Some more AVR intermediate commit
[fw/sdcc] / src / avr / gen.c
1 /*-------------------------------------------------------------------------
2   avrgen.c - source file for code generation for ATMEL AVR
3   
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (2000)
5   
6   This program is free software; you can redistribute it and/or modify it
7   under the terms of the GNU General Public License as published by the
8   Free Software Foundation; either version 2, or (at your option) any
9   later version.
10   
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15   
16   You should have received a copy of the GNU General Public License
17   along with this program; if not, write to the Free Software
18   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19   
20   In other words, you are welcome to use, share and improve this program.
21   You are forbidden to forbid anyone else to use, share and improve
22   what you give them.   Help stamp out software-hoarding!
23   
24
25 -------------------------------------------------------------------------*/
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <ctype.h>
31 #include "SDCCglobl.h"
32
33 #ifdef HAVE_SYS_ISA_DEFS_H
34 #include <sys/isa_defs.h>
35 #else
36 #ifdef HAVE_ENDIAN_H
37 #include <endian.h>
38 #else
39 #ifndef __BORLANDC__
40 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
41 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
42 #endif
43 #endif
44 #endif
45
46 #include "common.h"
47 #include "SDCCpeeph.h"
48 #include "ralloc.h"
49 #include "gen.h"
50
51 char *aopLiteral (value *val, int offset);
52 extern int allocInfo;
53
54 /* this is the down and dirty file with all kinds of 
55    kludgy & hacky stuff. This is what it is all about
56    CODE GENERATION for a specific MCU . some of the
57    routines may be reusable, will have to see */
58
59 static char *zero = "0x00";
60 static char *one  = "0x01";
61 static char *spname ;
62
63 char *fReturnAVR[] = {"r16","r17","r18","r19" };
64 unsigned fAVRReturnSize = 4; /* shared with ralloc.c */
65 char **fAVRReturn = fReturnAVR;
66
67 static short rbank = -1;
68 static char *larray[4] = {"lo8","hi8","hlo8","hhi8"};
69 static char *tscr[4] = {"r0","r1","r24","r25"};
70 static struct {
71         short xPushed;
72         short zPushed;
73         short accInUse;
74         short inLine;
75         short debugLine;
76         short nRegsSaved;
77         set *sendSet;
78 } _G;
79
80 extern int avr_ptrRegReq ;
81 extern int avr_nRegs;
82 extern FILE *codeOutFile;
83 static void saverbank (int, iCode *,bool);
84 #define RESULTONSTACK(x) \
85                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
86                          IC_RESULT(x)->aop->type == AOP_STK )
87
88 #define MOVR0(x) if (strcmp(x,"r0")) emitcode("mov","r0,%s",x);
89 #define CLRC    emitcode("clc","")
90 #define SETC    emitcode("stc","")
91 #define MOVA(x)
92 #define IS_REGIDX(a,r) (a->type == AOP_REG && a->aopu.aop_reg[0]->rIdx == r)
93
94 static lineNode *lineHead = NULL;
95 static lineNode *lineCurr = NULL;
96
97 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
98                                    0xE0, 0xC0, 0x80, 0x00};
99 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
100                                    0x07, 0x03, 0x01, 0x00};
101
102 #define LSB     0
103 #define MSB16   1
104 #define MSB24   2
105 #define MSB32   3
106
107 /*-----------------------------------------------------------------*/
108 /* emitcode - writes the code into a file : for now it is simple    */
109 /*-----------------------------------------------------------------*/
110 static void emitcode (char *inst,char *fmt, ...)
111 {
112         va_list ap;
113         char lb[MAX_INLINEASM];  
114         char *lbp = lb;
115
116         va_start(ap,fmt);   
117
118         if (inst && *inst) {
119                 if (fmt && *fmt)
120                         sprintf(lb,"%s\t",inst);
121                 else
122                         sprintf(lb,"%s",inst);
123                 vsprintf(lb+(strlen(lb)),fmt,ap);
124         }  else
125                 vsprintf(lb,fmt,ap);
126
127         while (isspace(*lbp)) lbp++;
128
129         if (lbp && *lbp) 
130                 lineCurr = (lineCurr ?
131                             connectLine(lineCurr,newLineNode(lb)) :
132                             (lineHead = newLineNode(lb)));
133         lineCurr->isInline = _G.inLine;
134         lineCurr->isDebug  = _G.debugLine;
135         va_end(ap);
136 }
137
138 /*-----------------------------------------------------------------*/
139 /* getFreePtr - returns X or Z whichever is free or can be pushed  */
140 /*-----------------------------------------------------------------*/
141 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result, bool zonly)
142 {
143         bool xiu = FALSE , ziu = FALSE;
144         bool xou = FALSE , zou = FALSE;
145
146         /* the logic: if x & z used in the instruction
147            then we are in trouble otherwise */
148
149         /* first check if x & z are used by this
150            instruction, in which case we are in trouble */
151         if ((xiu = bitVectBitValue(ic->rUsed,X_IDX)) &&
152             (ziu = bitVectBitValue(ic->rUsed,Z_IDX))) 
153                 {
154                         goto endOfWorld;      
155                 }
156
157         xou = bitVectBitValue(ic->rMask,X_IDX);
158         zou = bitVectBitValue(ic->rMask,Z_IDX);
159
160         /* if no usage of Z then return it */
161         if (!ziu && !zou) {
162                 ic->rUsed = bitVectSetBit(ic->rUsed,Z_IDX);
163                 (*aopp)->type = AOP_Z;
164
165                 (*aopp)->aop_ptr2 = avr_regWithIdx(R31_IDX);
166                 return (*aopp)->aopu.aop_ptr = avr_regWithIdx(R30_IDX);
167         }    
168
169         /* if no usage of X then return it */
170         if (!xiu && !xou && !zonly) {
171                 ic->rUsed = bitVectSetBit(ic->rUsed,X_IDX);
172                 (*aopp)->type = AOP_X;
173         
174                 (*aopp)->aop_ptr2 = avr_regWithIdx(R27_IDX);
175                 return (*aopp)->aopu.aop_ptr = avr_regWithIdx(R26_IDX);
176         }
177
178         /* if z not used then */
179
180         if (!ziu) {
181                 /* push it if not already pushed */
182                 if (!_G.zPushed) {
183                         emitcode ("push","%s",
184                                   avr_regWithIdx(R30_IDX)->dname);
185                         emitcode ("push","%s",
186                                   avr_regWithIdx(R31_IDX)->dname);
187                         _G.zPushed++ ;
188                 }
189         
190                 ic->rUsed = bitVectSetBit(ic->rUsed,Z_IDX);
191                 (*aopp)->type = AOP_Z;
192                 (*aopp)->aop_ptr2 = avr_regWithIdx(R31_IDX);
193                 return (*aopp)->aopu.aop_ptr = avr_regWithIdx(R30_IDX);
194         }
195
196         /* now we know they both have usage */
197         /* if x not used in this instruction */
198         if (!xiu && !zonly) {
199                 /* push it if not already pushed */
200                 if (!_G.xPushed) {
201                         emitcode ("push","%s",
202                                   avr_regWithIdx(R26_IDX)->dname);
203                         emitcode ("push","%s",
204                                   avr_regWithIdx(R27_IDX)->dname);
205                         _G.xPushed++ ;
206                 }
207         
208                 ic->rUsed = bitVectSetBit(ic->rUsed,X_IDX);
209                 (*aopp)->type = AOP_X;
210
211                 (*aopp)->aop_ptr2 = avr_regWithIdx(R27_IDX);
212                 return (*aopp)->aopu.aop_ptr = avr_regWithIdx(R26_IDX);
213         }
214
215
216         endOfWorld :
217                 /* I said end of world but not quite end of world yet */
218                 /* if this is a result then we can push it on the stack*/
219                 if (result) {
220                         (*aopp)->type = AOP_STK;    
221                         return NULL;
222                 }
223
224         piCode(ic,stdout);
225         /* other wise this is true end of the world */
226         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
227                "getFreePtr should never reach here");
228         exit(0);
229 }
230
231 /*-----------------------------------------------------------------*/
232 /* newAsmop - creates a new asmOp                                  */
233 /*-----------------------------------------------------------------*/
234 static asmop *newAsmop (short type)
235 {
236         asmop *aop;
237
238         ALLOC(aop,sizeof(asmop));
239         aop->type = type;
240         return aop;
241 }
242
243 /*-----------------------------------------------------------------*/
244 /* pointerCode - returns the code for a pointer type               */
245 /*-----------------------------------------------------------------*/
246 static int pointerCode (link *etype)
247 {
248
249         return PTR_TYPE(SPEC_OCLS(etype));
250
251 }
252
253 /*-----------------------------------------------------------------*/
254 /* aopForSym - for a true symbol                                   */
255 /*-----------------------------------------------------------------*/
256 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
257 {
258         asmop *aop;
259         memmap *space= SPEC_OCLS(sym->etype);
260
261         /* if already has one */
262         if (sym->aop)
263                 return sym->aop;
264
265         /* assign depending on the storage class */
266         /* if it is on the stack */
267         if (sym->onStack) {
268                 sym->aop = aop = newAsmop(0);
269                 aop->size = getSize(sym->type);
270
271                 /* we can use std / ldd instruction */
272                 if (sym->stack > 0 && (sym->stack + getSize(sym->type) - 1) <= 63) {
273                         aop->type = AOP_STK_D;
274                         aop->aopu.aop_stk = sym->stack;
275                         return aop;
276                 }
277
278                 /* otherwise get a free pointer register X/Z */
279                 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result,FALSE);
280
281                 /* now assign the address of the variable to 
282                    the pointer register */
283                 if (aop->type != AOP_STK) {
284                         emitcode("movw","%s,r28",aop->aopu.aop_ptr->name);
285                         if (sym->stack < 0) {
286                                 if ((sym->stack - _G.nRegsSaved) > -63) {
287                                         emitcode("sbiw","%s,0x%02x",
288                                                  aop->aopu.aop_ptr->name,
289                                                  (sym->stack - _G.nRegsSaved));
290                                 } else {
291                                         emitcode("subi","%s,lo8(%d)", aop->aopu.aop_ptr->name,
292                                                  sym->stack - _G.nRegsSaved);
293                                         emitcode("sbci","%s,hi8(%d)",aop->aop_ptr2->name,
294                                                  sym->stack - _G.nRegsSaved);
295                                 }
296                         } else {
297                                 if (sym->stack <= 63) {
298                                         emitcode("adiw","%s,0x%02x",aop->aopu.aop_ptr->name,sym->stack);
299                                 } else {
300                                         emitcode("subi","%s,lo8(-%d)",aop->aopu.aop_ptr->name,sym->stack);
301                                         emitcode("sbci","%s,hi8(-%d)",aop->aop_ptr2->name,sym->stack); 
302                                 }
303                         }
304                 }
305                 return aop;
306         }
307     
308         /* if in bit space */
309         if (IN_BITSPACE(space)) {
310                 sym->aop = aop = newAsmop (AOP_CRY);
311                 aop->aopu.aop_dir = sym->rname ;
312                 aop->size = getSize(sym->type);
313                 return aop;
314         }
315         /* if it is in direct space */
316         if (IN_DIRSPACE(space)) {
317                 sym->aop = aop = newAsmop (AOP_DIR);
318                 aop->aopu.aop_dir = sym->rname ;
319                 aop->size = getSize(sym->type);
320                 return aop;
321         }
322
323         /* special case for a function */
324         if (IS_FUNC(sym->type)) {   
325                 sym->aop = aop = newAsmop(AOP_IMMD);    
326                 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
327                 strcpy(aop->aopu.aop_immd,sym->rname);
328                 aop->size = FPTRSIZE; 
329                 return aop;
330         }
331
332         /* only remaining is code / eeprom which will need pointer reg */
333         /* if it is in code space */
334         if (IN_CODESPACE(space))
335                 aop->code = 1;
336
337         sym->aop = aop = newAsmop(0);
338         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result,aop->code);
339         aop->size = getSize(sym->type);
340         emitcode ("ldi","%s,lo8(%s)",aop->aopu.aop_ptr->name,sym->rname);
341         emitcode ("ldi","%s,hi8(%s)",aop->aop_ptr2);
342
343         return aop;     
344 }
345
346 /*-----------------------------------------------------------------*/
347 /* aopForRemat - rematerialzes an object                           */
348 /*-----------------------------------------------------------------*/
349 static asmop *aopForRemat (symbol *sym)
350 {
351         iCode *ic = sym->rematiCode;
352         asmop *aop = newAsmop(AOP_IMMD);
353         int val = 0;
354
355         for (;;) {
356                 if (ic->op == '+')
357                         val += operandLitValue(IC_RIGHT(ic));
358                 else if (ic->op == '-')
359                         val -= operandLitValue(IC_RIGHT(ic));
360                 else
361                         break;
362         
363                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
364         }
365
366         if (val)
367                 sprintf(buffer,"(%s %c 0x%04x)",
368                         OP_SYMBOL(IC_LEFT(ic))->rname, 
369                         val >= 0 ? '+' : '-',
370                         abs(val) & 0xffff);
371         else
372                 strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
373
374         ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
375         strcpy(aop->aopu.aop_immd,buffer);    
376         return aop;        
377 }
378
379 /*-----------------------------------------------------------------*/
380 /* regsInCommon - two operands have some registers in common       */
381 /*-----------------------------------------------------------------*/
382 static bool regsInCommon (operand *op1, operand *op2)
383 {
384         symbol *sym1, *sym2;
385         int i;
386
387         /* if they have registers in common */
388         if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
389                 return FALSE ;
390
391         sym1 = OP_SYMBOL(op1);
392         sym2 = OP_SYMBOL(op2);
393
394         if (sym1->nRegs == 0 || sym2->nRegs == 0)
395                 return FALSE ;
396
397         for (i = 0 ; i < sym1->nRegs ; i++) {
398                 int j;
399                 if (!sym1->regs[i])
400                         continue ;
401
402                 for (j = 0 ; j < sym2->nRegs ;j++ ) {
403                         if (!sym2->regs[j])
404                                 continue ;
405
406                         if (sym2->regs[j] == sym1->regs[i])
407                                 return TRUE ;
408                 }
409         }
410
411         return FALSE ;
412 }
413
414 /*-----------------------------------------------------------------*/
415 /* operandsEqu - equivalent                                        */
416 /*-----------------------------------------------------------------*/
417 static bool operandsEqu ( operand *op1, operand *op2)
418 {
419         symbol *sym1, *sym2;
420
421         /* if they not symbols */
422         if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
423                 return FALSE;
424
425         sym1 = OP_SYMBOL(op1);
426         sym2 = OP_SYMBOL(op2);
427
428         /* if both are itemps & one is spilt
429            and the other is not then false */
430         if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
431             sym1->isspilt != sym2->isspilt )
432                 return FALSE ;
433
434         /* if they are the same */
435         if (sym1 == sym2)
436                 return TRUE ;
437
438         if (strcmp(sym1->rname,sym2->rname) == 0)
439                 return TRUE;
440
441
442         /* if left is a tmp & right is not */
443         if (IS_ITEMP(op1)  && 
444             !IS_ITEMP(op2) &&
445             sym1->isspilt  &&
446             (sym1->usl.spillLoc == sym2))
447                 return TRUE;
448
449         if (IS_ITEMP(op2)  && 
450             !IS_ITEMP(op1) &&
451             sym2->isspilt  &&
452             sym1->level > 0 &&
453             (sym2->usl.spillLoc == sym1))
454                 return TRUE ;
455
456         return FALSE ;
457 }
458
459 /*-----------------------------------------------------------------*/
460 /* sameRegs - two asmops have the same registers                   */
461 /*-----------------------------------------------------------------*/
462 static bool sameRegs (asmop *aop1, asmop *aop2 )
463 {
464         int i;
465
466         if (aop1 == aop2)
467                 return TRUE ;
468
469         if (aop1->type != AOP_REG ||
470             aop2->type != AOP_REG )
471                 return FALSE ;
472
473         if (aop1->size != aop2->size )
474                 return FALSE ;
475
476         for (i = 0 ; i < aop1->size ; i++ )
477                 if (aop1->aopu.aop_reg[i] !=
478                     aop2->aopu.aop_reg[i] )
479                         return FALSE ;
480
481         return TRUE ;
482 }
483
484 /*-----------------------------------------------------------------*/
485 /* isRegPair - for size 2 if this operand has a register pair      */
486 /*-----------------------------------------------------------------*/
487 static int isRegPair (asmop *aop)
488 {
489         if (!aop || aop->size != 2) return 0;
490         if (aop->type == AOP_X || aop->type == AOP_Z) return 1;
491         if (aop->type != AOP_REG) return 0;
492         if ((aop->aopu.aop_reg[1]->rIdx - 
493              aop->aopu.aop_reg[0]->rIdx) == 1) return 1;
494         return 0;
495 }
496
497 /*-----------------------------------------------------------------*/
498 /* aopOp - allocates an asmop for an operand  :                    */
499 /*-----------------------------------------------------------------*/
500 static void aopOp (operand *op, iCode *ic, bool result)
501 {
502         asmop *aop;
503         symbol *sym;
504         int i;
505
506         if (!op)
507                 return ;
508
509         /* if this a literal */
510         if (IS_OP_LITERAL(op)) {
511                 op->aop = aop = newAsmop(AOP_LIT);
512                 aop->aopu.aop_lit = op->operand.valOperand;
513                 aop->size = getSize(operandType(op));
514                 return;
515         }
516
517         /* if already has a asmop then continue */
518         if (op->aop)
519                 return ;
520
521         /* if the underlying symbol has a aop */
522         if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
523                 op->aop = OP_SYMBOL(op)->aop;
524                 return;
525         }
526
527         /* if this is a true symbol */
528         if (IS_TRUE_SYMOP(op)) {    
529                 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
530                 return ;
531         }
532
533         /* this is a temporary : this has
534            only four choices :
535            a) register
536            b) spillocation
537            c) rematerialize 
538            d) conditional   
539            e) can be a return use only */
540
541         sym = OP_SYMBOL(op);
542
543
544         /* if the type is a conditional */
545         if (sym->regType == REG_CND) {
546                 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
547                 aop->size = 0;
548                 return;
549         }
550
551         /* if it is spilt then two situations
552            a) is rematerialize 
553            b) has a spill location */
554         if (sym->isspilt || sym->nRegs == 0) {
555
556                 /* rematerialize it NOW */
557                 if (sym->remat) {
558                         sym->aop = op->aop = aop =
559                                 aopForRemat (sym);
560                         aop->size = getSize(sym->type);
561                         return;
562                 }
563
564                 if (sym->accuse) {
565                         assert("ACC_USE cannot happen in AVR\n");
566                 }
567
568                 if (sym->ruonly ) {
569                         int i;
570                         aop = op->aop = sym->aop = newAsmop(AOP_STR);
571                         aop->size = getSize(sym->type);
572                         for ( i = 0 ; i < fAVRReturnSize ; i++ )
573                                 aop->aopu.aop_str[i] = fAVRReturn[i];
574                         return;
575                 }
576
577                 /* else spill location  */
578                 sym->aop = op->aop = aop = 
579                         aopForSym(ic,sym->usl.spillLoc,result);
580                 aop->size = getSize(sym->type);
581                 return;
582         }
583
584         /* must be in a register */
585         sym->aop = op->aop = aop = newAsmop(AOP_REG);
586         aop->size = sym->nRegs;
587         for ( i = 0 ; i < sym->nRegs ;i++)
588                 aop->aopu.aop_reg[i] = sym->regs[i];
589 }
590
591 /*-----------------------------------------------------------------*/
592 /* freeAsmop - free up the asmop given to an operand               */
593 /*----------------------------------------------------------------*/
594 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
595 {   
596         asmop *aop ;
597
598         if (!op)
599                 aop = aaop;
600         else 
601                 aop = op->aop;
602
603         if (!aop)
604                 return ;
605
606         if (aop->freed)
607                 goto dealloc; 
608
609         aop->freed = 1;
610
611         /* depending on the asmop type only three cases need work AOP_RO
612            , AOP_R1 && AOP_STK */
613         switch (aop->type) {
614         case AOP_X :
615                 if (_G.xPushed ) {
616                         if (pop) {
617                                 emitcode ("pop","r26");
618                                 emitcode ("pop","r27");
619                                 _G.xPushed--;
620                         }
621                 }
622                 bitVectUnSetBit(ic->rUsed,X_IDX);
623                 break;
624
625         case AOP_Z :
626                 if (_G.zPushed ) {
627                         if (pop) {
628                                 emitcode ("pop","r30");
629                                 emitcode ("pop","r31");
630                                 _G.zPushed--;
631                         }
632                 }
633                 bitVectUnSetBit(ic->rUsed,Z_IDX);          
634                 break;
635
636         case AOP_STK :
637                 {
638                         int sz = aop->size;    
639                         int stk = aop->aopu.aop_stk + aop->size;
640                         bitVectUnSetBit(ic->rUsed,X_IDX);
641                         bitVectUnSetBit(ic->rUsed,Z_IDX);          
642
643                         getFreePtr(ic,&aop,FALSE,0);
644             
645                         emitcode ("movw","%s,r28");
646                         if (stk) {
647                                 if (stk <= 63 && stk > 0) {
648                                         emitcode ("adiw","%s,0x%02x",aop->aopu.aop_ptr->name,stk+1);
649                                 } else {
650                                         emitcode ("subi","%s,lo8(%d)",aop->aopu.aop_ptr->name,-(stk+1));
651                                         emitcode ("sbci","%s,hi8(%d)",aop->aop_ptr2->name,-(stk+1));
652                                 }
653                         }
654
655                         while (sz--) {
656                                 emitcode("pop","r24");
657                                 emitcode("st","-%s,r24",aop->type == AOP_X ? "X" : "Z");
658                                 if (!sz) break;
659                         }
660                         op->aop = aop;
661                         freeAsmop(op,NULL,ic,TRUE);
662                         if (_G.xPushed) {
663                                 emitcode("pop","r26");
664                                 emitcode("pop","r27");
665                                 _G.xPushed--;
666                         }
667
668                         if (_G.zPushed) {
669                                 emitcode("pop","r30");
670                                 emitcode("pop","r31");
671                                 _G.zPushed--;
672                         }       
673                 }
674         }
675
676  dealloc:
677         /* all other cases just dealloc */
678         if (op ) {
679                 op->aop = NULL;
680                 if (IS_SYMOP(op)) {
681                         OP_SYMBOL(op)->aop = NULL;    
682                         /* if the symbol has a spill */
683                         if (SPIL_LOC(op))
684                                 SPIL_LOC(op)->aop = NULL;
685                 }
686         }
687 }
688
689 /*-----------------------------------------------------------------*/
690 /* aopGet - for fetching value of the aop                          */
691 /*-----------------------------------------------------------------*/
692 static char *aopGet (asmop *aop, int offset)
693 {
694         char *s = buffer ;
695         char *rs;
696
697         /* offset is greater than
698            size then zero */
699         if (offset > (aop->size - 1) &&
700             aop->type != AOP_LIT)
701                 return zero;
702
703         /* depending on type */
704         switch (aop->type) {
705         
706         case AOP_X:
707                 if (offset > aop->coff) {
708                         emitcode ("adiw","%s,%d",aop->aopu.aop_ptr->name,offset - aop->coff);  
709                 }
710         
711                 if (offset < aop->coff) {
712                         emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,aop->coff - offset);
713                 }
714         
715                 aop->coff = offset ;
716                 emitcode("ld","%s,x",
717                          (rs = ((offset & 1) ? "r25" : "r24")));
718                 return rs;
719
720         case AOP_Z:
721                 if (aop->code) {
722                         if (offset > aop->coff) {
723                                 emitcode("adiw","r30,%d",offset - aop->coff);
724                         } else {
725                                 emitcode("sbiw","r30,%d",aop->coff - offset);
726                         }
727                         emitcode("lpm","%s,z",(rs = ((offset & 1) ? "r25" : "r24")));
728                 } else {
729                         /* we can use lds */
730                         if (offset  > aop->coff) {
731                                 emitcode ("ldd","%s,z+%d",(rs = ((offset & 1) ? "r25" : "r24")),
732                                           offset - aop->coff);
733                         } else {
734                                 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,aop->coff - offset);
735                                 aop->coff = offset;
736                                 emitcode ("ld","%s,z",(rs = ((offset & 1) ? "r25" : "r24")));
737                         }
738                 }
739                 return rs;
740
741         case AOP_IMMD:
742         
743                 emitcode ("lds","%s,(%s)+%d",
744                           (rs = ((offset & 1) ? "r25" : "r24")),
745                           aop->aopu.aop_immd, offset);
746                 return rs;
747         
748         case AOP_DIR:
749                 emitcode ("lds","%s,(%s)+%d",
750                           (rs = ((offset & 1) ? "r25" : "r24")),
751                           aop->aopu.aop_dir, offset);
752                 return rs;
753         
754         case AOP_REG:
755                 return aop->aopu.aop_reg[offset]->name;
756         
757         case AOP_CRY:
758                 assert("cannot be in bit space AOP_CRY\n");
759                 break;
760
761         case AOP_LIT:
762                 s = aopLiteral(aop->aopu.aop_lit,offset);
763                 emitcode("ldi","%s,lo8(%s)",(rs = ((offset & 1)?"r24" : "r25")),s);
764                 return rs;
765
766         case AOP_STR:
767                 aop->coff = offset ;
768                 return aop->aopu.aop_str[offset];
769         
770         case AOP_STK_D:
771                 emitcode ("ldd","%s,Y+%d",
772                           (rs = ((offset & 1) ? "r25" : "r24")),                  
773                           aop->aopu.aop_stk+offset);
774                 return rs;
775         }
776
777         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
778                "aopget got unsupported aop->type");
779         exit(0);
780 }
781 /*-----------------------------------------------------------------*/
782 /* aopPut - puts a string for a aop                                */
783 /*-----------------------------------------------------------------*/
784 static void aopPut (asmop *aop, char *s, int offset)
785 {
786         char *d = buffer ;
787
788         if (aop->size && offset > ( aop->size - 1)) {
789                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
790                        "aopPut got offset > aop->size");
791                 exit(0);
792         }
793
794         /* will assign value to value */
795         /* depending on where it is ofcourse */
796         switch (aop->type) {
797         case AOP_DIR:
798                 if (offset) {
799                         sprintf(d,"(%s)+%d", aop->aopu.aop_dir,offset);
800                 }
801                 else {
802                         sprintf(d,"%s",aop->aopu.aop_dir);
803                 }
804         
805                 emitcode("sts","%s,%s",d,s);
806                 break;
807         
808         case AOP_REG:
809                 if (toupper(*s) != 'R') {
810                         if (s == zero) {
811                                 emitcode("clr","%s",aop->aopu.aop_reg[offset]->name);
812                         } else {
813                                 emitcode("ldi","r25,%s",s);
814                                 emitcode("mov","%s,r35",aop->aopu.aop_reg[offset]->name);
815                         }
816                 } else {
817                         if (strcmp( aop->aopu.aop_reg[offset]->name,s)) {
818                                 emitcode("mov","%s,%s", aop->aopu.aop_reg[offset]->name,s);
819                         }
820                 }
821                 break;
822         
823         case AOP_X:
824                 if (offset > aop->coff) {
825                         emitcode ("adiw","%s,%d",aop->aopu.aop_ptr->name,offset - aop->coff);  
826                 }
827         
828                 if (offset < aop->coff) {
829                         emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,aop->coff - offset);
830                 }
831         
832                 aop->coff = offset ;
833                 emitcode("st","x,%s", s);
834                 break;
835         
836         case AOP_Z:
837                 if (aop->code) {
838                         if (offset > aop->coff) {
839                                 emitcode("adiw","r30,%d",offset - aop->coff);
840                         } else {
841                                 emitcode("sbiw","r30,%d",aop->coff - offset);
842                         }
843                         emitcode("lpm","%s,z",s);
844                 } else {
845                         /* we can use lds */
846                         if (offset  > aop->coff) {
847                                 emitcode ("sdd","z+%d,%s",offset - aop->coff,s);
848                         } else {
849                                 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,aop->coff - offset);
850                                 aop->coff = offset;
851                                 emitcode ("ld","%s,z",s);
852                         }
853                 }
854                 break;
855         
856         case AOP_STK:
857                 emitcode("push","%s",s);        
858                 break;
859         
860         case AOP_CRY:
861                 /* if used only for a condition code check */
862                 assert(toupper(*s) == 'R');
863                 if (offset == 0) {
864                         emitcode("xrl","r0,r0");
865                         emitcode("cpi","%s,0",s);
866                 }
867                 else {
868                         emitcode("cpc","r0,%s",s);
869                 }
870                 break;
871         
872         case AOP_STR:
873                 aop->coff = offset;
874                 if (strcmp(aop->aopu.aop_str[offset],s))
875                         emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
876                 break;
877
878         case AOP_STK_D:
879                 emitcode ("std","y+%d,%s",offset,s);
880                 break;
881
882         default :
883                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
884                        "aopPut got unsupported aop->type");
885                 exit(0);    
886         }    
887
888 }
889
890 /*-----------------------------------------------------------------*/
891 /* reAdjustPreg - points a register back to where it should        */
892 /*-----------------------------------------------------------------*/
893 static void reAdjustPreg (asmop *aop)
894 {
895         int size ;
896
897         aop->coff = 0;
898         if ((size = aop->size) <= 1)
899                 return ;
900         size-- ;
901         switch (aop->type) {
902         case AOP_X :
903         case AOP_Z :
904                 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,size);
905                 break;          
906         }
907
908 }
909
910 #define AOP(op) op->aop
911 #define AOP_TYPE(op) AOP(op)->type
912 #define AOP_SIZE(op) AOP(op)->size
913 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_X || \
914                        AOP_TYPE(x) == AOP_Z))
915 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                      \
916                       (x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) || \
917                       x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) )))
918
919 /*-----------------------------------------------------------------*/
920 /* genNotFloat - generates not for float operations                */
921 /*-----------------------------------------------------------------*/
922 static void genNotFloat (operand *op, operand *res)
923 {
924         int size, offset;
925         char *l;
926         symbol *tlbl ;
927
928         /* we will put 127 in the first byte of 
929            the result */
930         aopPut(AOP(res),"127",0);
931         size = AOP_SIZE(op) - 1;
932         offset = 1;
933
934         l = aopGet(op->aop,offset++);
935         MOVR0(l);    
936
937         while(size--) {
938                 emitcode("or","R0,%s", aopGet(op->aop, offset++));
939         }
940         tlbl = newiTempLabel(NULL);
941
942         tlbl = newiTempLabel(NULL);
943         aopPut(res->aop,zero,1);
944         emitcode("cpi","r0,0");
945         emitcode("breq","L%05d",tlbl->key);
946         aopPut(res->aop,one,1);
947         emitcode("","L%05d:",tlbl->key);
948
949         size = res->aop->size - 2;
950         offset = 2;    
951         /* put zeros in the rest */
952         while (size--) 
953                 aopPut(res->aop,zero,offset++);
954 }
955
956 /*-----------------------------------------------------------------*/
957 /* opIsGptr: returns non-zero if the passed operand is             */   
958 /* a generic pointer type.                                         */
959 /*-----------------------------------------------------------------*/ 
960 static int opIsGptr(operand *op)
961 {
962         link *type = operandType(op);
963     
964         if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
965                 {
966                         return 1;
967                 }
968         return 0;        
969 }
970
971 /*-----------------------------------------------------------------*/
972 /* getDataSize - get the operand data size                         */
973 /*-----------------------------------------------------------------*/
974 static int getDataSize(operand *op)
975 {
976         int size;
977         size = AOP_SIZE(op);
978         if (size == GPTRSIZE)
979                 {
980                         link *type = operandType(op);
981                         if (IS_GENPTR(type))
982                                 {
983                                         /* generic pointer; arithmetic operations
984                                          * should ignore the high byte (pointer type).
985                                          */
986                                         size--;
987                                 }
988                 }
989         return size;
990 }
991
992 /*-----------------------------------------------------------------*/
993 /* outAcc - output Acc                                             */
994 /*-----------------------------------------------------------------*/
995 static void outAcc(operand *result)
996 {
997         int size, offset;
998         size = getDataSize(result);
999         if(size){
1000                 aopPut(AOP(result),"r0",0);
1001                 size--;
1002                 offset = 1;
1003                 /* unsigned or positive */
1004                 while(size--){
1005                         aopPut(AOP(result),zero,offset++);
1006                 }
1007         }
1008 }
1009
1010 /*-----------------------------------------------------------------*/
1011 /* outBitC - output a bit C                                        */
1012 /*-----------------------------------------------------------------*/
1013 static void outBitC(operand *result)
1014 {
1015         emitcode("clr","r0");
1016         emitcode("rol","r0");
1017         outAcc(result);
1018 }
1019
1020 /*-----------------------------------------------------------------*/
1021 /* toBoolean - emit code for orl a,operator(sizeop)                */
1022 /*-----------------------------------------------------------------*/
1023 static void toBoolean(operand *oper, char *r, bool clr)
1024 {
1025         int size = AOP_SIZE(oper) ;
1026         int offset = 0;
1027         if (clr) emitcode ("clr","%s",r);
1028         while (size--) 
1029                 emitcode("or","%s,%s",r,aopGet(AOP(oper),offset++));
1030 }
1031
1032
1033 /*-----------------------------------------------------------------*/
1034 /* genNot - generate code for ! operation                          */
1035 /*-----------------------------------------------------------------*/
1036 static void genNot (iCode *ic)
1037 {
1038         symbol *tlbl;
1039         link *optype = operandType(IC_LEFT(ic));
1040         int size, offset = 1;
1041
1042         /* assign asmOps to operand & result */
1043         aopOp (IC_LEFT(ic),ic,FALSE);
1044         aopOp (IC_RESULT(ic),ic,TRUE);
1045
1046         /* if type float then do float */
1047         if (IS_FLOAT(optype)) {
1048                 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1049                 goto release;
1050         }
1051         emitcode("clr","r0");
1052         tlbl = newiTempLabel(NULL);
1053         size = AOP_SIZE(IC_LEFT(ic));
1054         offset = 0;
1055         if (size == 1) {
1056                 emitcode("cpse","%s,r0",aopGet(AOP(IC_LEFT(ic)),0));
1057         }
1058         else {
1059                 while (size--) {
1060                         if (offset) emitcode("cpc","%s,r0",aopGet(AOP(IC_LEFT(ic)),offset));
1061                         else emitcode("cpi","%s,0",aopGet(AOP(IC_LEFT(ic)),offset));
1062                         offset++;
1063                 }
1064                 emitcode("bne","L%05d",tlbl->key);
1065         }
1066         emitcode("ldi","r0,1");
1067         emitcode("","L%05d:",tlbl->key);
1068         aopPut(AOP(IC_RESULT(ic)),"r0",0);
1069         size = AOP_SIZE(IC_RESULT(ic)) -1;
1070         offset = 1;
1071         while (size--) aopPut(AOP(IC_RESULT(ic)),zero,offset++);
1072     
1073
1074  release:    
1075         /* release the aops */
1076         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1077         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1078 }
1079
1080
1081 /*-----------------------------------------------------------------*/
1082 /* genCpl - generate code for complement                           */
1083 /*-----------------------------------------------------------------*/
1084 static void genCpl (iCode *ic)
1085 {
1086         int offset = 0;
1087         int size ;
1088         int samer;
1089
1090         /* assign asmOps to operand & result */
1091         aopOp (IC_LEFT(ic),ic,FALSE);
1092         aopOp (IC_RESULT(ic),ic,TRUE);
1093         samer = sameRegs(AOP(IC_LEFT(ic)),AOP(IC_RESULT(ic)));
1094         size = AOP_SIZE(IC_RESULT(ic));
1095         while (size--) {
1096                 char *l = aopGet(AOP(IC_LEFT(ic)),offset);
1097                 if (samer) {
1098                         emitcode ("com","%s",l);
1099                 } else {
1100                         aopPut(AOP(IC_RESULT(ic)),l,offset);
1101                         emitcode ("com","%s",aopGet(AOP(IC_RESULT(ic)),offset));
1102                 }
1103                 offset++;
1104         }
1105
1106         /* release the aops */
1107         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1108         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1109 }
1110
1111 /*-----------------------------------------------------------------*/
1112 /* genUminusFloat - unary minus for floating points                */
1113 /*-----------------------------------------------------------------*/
1114 static void genUminusFloat(operand *op,operand *result)
1115 {
1116         int size ,offset =0 ;
1117         char *l;
1118         /* for this we just need to flip the 
1119            first it then copy the rest in place */
1120         size = AOP_SIZE(op) - 1;
1121         l = aopGet(AOP(op),3);
1122     
1123         emitcode("ldi","r24,0x80");
1124         if (sameRegs(AOP(op),AOP(result))) {
1125                 emitcode("eor","%s,r24",l);
1126         } else {
1127                 aopPut(AOP(result),l,3);
1128                 emitcode("eor","%s,r24",aopGet(AOP(result),3));
1129         }
1130         while(size--) {
1131                 aopPut(AOP(result), aopGet(AOP(op),offset), offset);
1132                 offset++;
1133         }          
1134 }
1135
1136 /*-----------------------------------------------------------------*/
1137 /* genUminus - unary minus code generation                         */
1138 /*-----------------------------------------------------------------*/
1139 static void genUminus (iCode *ic)
1140 {
1141         int offset ,size ;
1142         link *optype, *rtype;
1143         int samer ;
1144
1145         /* assign asmops */
1146         aopOp(IC_LEFT(ic),ic,FALSE);
1147         aopOp(IC_RESULT(ic),ic,TRUE);
1148
1149         optype = operandType(IC_LEFT(ic));
1150         rtype = operandType(IC_RESULT(ic));
1151
1152         /* if float then do float stuff */
1153         if (IS_FLOAT(optype)) {
1154                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1155                 goto release;
1156         }
1157
1158         /* otherwise subtract from zero */
1159         size = AOP_SIZE(IC_LEFT(ic));
1160         offset = 0 ;
1161         samer = sameRegs(AOP(IC_LEFT(ic)),AOP(IC_RESULT(ic)));
1162         if (size == 1) {
1163                 if (samer) {
1164                         emitcode("neg","%s",aopGet(AOP(IC_LEFT(ic)),0));
1165                 } else {
1166                         aopPut(AOP(IC_RESULT(ic)),aopGet(AOP(IC_LEFT(ic)),0),0);
1167                         emitcode("neg","%s",aopGet(AOP(IC_RESULT(ic)),0));
1168                 }
1169         } else {
1170                 offset = size - 1;
1171                 while(size--) {
1172                         char *l = aopGet(AOP(IC_LEFT(ic)),offset);
1173                         if (!samer) {
1174                                 aopPut(AOP(IC_RESULT(ic)),l,offset);
1175                                 l = aopGet(AOP(IC_RESULT(ic)),offset);
1176                         }
1177                         if (offset) emitcode("com","%s",l);
1178                         else emitcode("neg","%s",l);
1179                         offset--;
1180                 }
1181                 size = AOP_SIZE(IC_LEFT(ic)) -1;
1182                 offset = 1 ;
1183                 while (size--) {
1184                         emitcode("sbci","%s,lo8(-1)",aopGet(AOP(IC_RESULT(ic)),offset++));
1185                 }
1186         }
1187
1188         /* if any remaining bytes in the result */
1189         /* we just need to propagate the sign   */
1190         if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1191                 symbol *tlbl = newiTempLabel(NULL);
1192                 emitcode("clr","r0");
1193                 emitcode("brcc","L%05d",tlbl->key);
1194                 emitcode("com","r0");
1195                 emitcode("","L%05d:",tlbl->key);
1196                 while (size--) 
1197                         aopPut(AOP(IC_RESULT(ic)),"r0",offset++);
1198         }       
1199
1200  release:
1201         /* release the aops */
1202         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1203         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
1204 }
1205
1206 /*-----------------------------------------------------------------*/
1207 /* assignResultValue -                                             */
1208 /*-----------------------------------------------------------------*/
1209 static void assignResultValue(operand * oper)
1210 {
1211         int offset = 0;
1212         int size = AOP_SIZE(oper);
1213         while (size--) {
1214                 aopPut(AOP(oper),fAVRReturn[offset],offset);
1215                 offset++;
1216         }
1217 }
1218
1219 /*-----------------------------------------------------------------*/
1220 /* saveZreg - if indirect call then save z-pointer register        */
1221 /*-----------------------------------------------------------------*/
1222 static void saveZreg (iCode *ic)
1223 {
1224         /* only if live accross this call */
1225         if (ic->regsSaved == 0 && 
1226             (bitVectBitValue(ic->rMask,R30_IDX) ||
1227              bitVectBitValue(ic->rMask,R31_IDX))) {
1228                 ic->regsSaved = 1;
1229                 emitcode("push","r30");
1230                 emitcode("push","r31");
1231         }
1232 }
1233
1234 /*-----------------------------------------------------------------*/
1235 /* popZreg - restore values of zreg                                */
1236 /*-----------------------------------------------------------------*/
1237 static void popZreg (iCode *ic)
1238 {
1239         if (ic->regsSaved) {
1240                 emitcode ("pop","r31");
1241                 emitcode ("pop","r30");
1242         }
1243 }
1244
1245 /*-----------------------------------------------------------------*/
1246 /* genIpush - genrate code for pushing this gets a little complex  */
1247 /*-----------------------------------------------------------------*/
1248 static void genIpush (iCode *ic)
1249 {
1250         int size, offset = 0 ;
1251         char *l;
1252
1253
1254         if (!ic->parmPush) {
1255                 /* and the item is spilt then do nothing */
1256                 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1257                         return ;
1258         } else {
1259                 iCode *lic ; 
1260                 for (lic = ic->next ; lic ; lic = lic->next) 
1261                         if (lic->op == PCALL) break;
1262                 if (lic) saveZreg(lic);
1263         }
1264
1265         /* this is a paramter push */
1266         aopOp(IC_LEFT(ic),ic,FALSE);
1267         size = AOP_SIZE(IC_LEFT(ic));
1268         while (size--) {
1269                 l = aopGet(AOP(IC_LEFT(ic)),offset++);
1270                 emitcode("push","%s",l);
1271         }       
1272
1273         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1274 }
1275
1276 /*-----------------------------------------------------------------*/
1277 /* genIpop - recover the registers: can happen only for spilling   */
1278 /*-----------------------------------------------------------------*/
1279 static void genIpop (iCode *ic)
1280 {
1281         int size,offset ;
1282
1283
1284         /* if the temp was not pushed then */
1285         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1286                 return ;
1287
1288         aopOp(IC_LEFT(ic),ic,FALSE);
1289         size = AOP_SIZE(IC_LEFT(ic));
1290         offset = (size-1);
1291         while (size--) 
1292                 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--));
1293
1294         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1295 }
1296
1297 /*-----------------------------------------------------------------*/
1298 /* genCall - generates a call statement                            */
1299 /*-----------------------------------------------------------------*/
1300 static void genCall (iCode *ic)
1301 {
1302
1303         /* if send set is not empty the assign */
1304         if (_G.sendSet) {
1305                 iCode *sic ;
1306
1307                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
1308                      sic = setNextItem(_G.sendSet)) {
1309                         int size, offset = 0;
1310                         aopOp(IC_LEFT(sic),sic,FALSE);
1311                         size = AOP_SIZE(IC_LEFT(sic));
1312                         while (size--) {
1313                                 char *l = aopGet(AOP(IC_LEFT(sic)),offset);
1314                                 if (strcmp(l,fAVRReturn[offset]))
1315                                         emitcode("mov","%s,%s",
1316                                                  fAVRReturn[offset],
1317                                                  l);
1318                                 offset++;
1319                         }
1320                         freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1321                 }
1322                 _G.sendSet = NULL;
1323         }
1324         /* make the call */
1325         emitcode("call","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1326                               OP_SYMBOL(IC_LEFT(ic))->rname :
1327                               OP_SYMBOL(IC_LEFT(ic))->name));
1328
1329         /* if we need assign a result value */
1330         if ((IS_ITEMP(IC_RESULT(ic)) && 
1331              (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1332               OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1333             IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1334
1335                 aopOp(IC_RESULT(ic),ic,FALSE);
1336                 assignResultValue(IC_RESULT(ic));
1337                 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1338         }
1339
1340         /* adjust the stack for parameters if required */
1341         if (IC_LEFT(ic)->parmBytes) {
1342                 if (IC_LEFT(ic)->parmBytes > 63) {
1343                         emitcode("sbiw","r28,%d",IC_LEFT(ic)->parmBytes);
1344                 } else {
1345                         emitcode("subi","r28,lo8(%d)",IC_LEFT(ic)->parmBytes);
1346                         emitcode("sbci","r29,hi8(%d)",IC_LEFT(ic)->parmBytes);
1347                 }
1348         }
1349
1350 }
1351
1352 /*-----------------------------------------------------------------*/
1353 /* genPcall - generates a call by pointer statement                */
1354 /*-----------------------------------------------------------------*/
1355 static void genPcall (iCode *ic)
1356 {
1357
1358         if (!ic->regsSaved) saveZreg(ic);
1359
1360         aopOp(IC_LEFT(ic),ic,FALSE);
1361         emitcode("mov","r30",aopGet(AOP(IC_LEFT(ic)),0));
1362         emitcode("mov","r31",aopGet(AOP(IC_RIGHT(ic)),0));
1363         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
1364
1365         /* if send set is not empty the assign */
1366         if (_G.sendSet) {
1367                 iCode *sic ;
1368
1369                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
1370                      sic = setNextItem(_G.sendSet)) {
1371                         int size, offset = 0;
1372                         aopOp(IC_LEFT(sic),sic,FALSE);
1373                         size = AOP_SIZE(IC_LEFT(sic));
1374                         while (size--) {
1375                                 char *l = aopGet(AOP(IC_LEFT(sic)),offset);
1376                                 if (strcmp(l,fAVRReturn[offset]))
1377                                         emitcode("mov","%s,%s",
1378                                                  fAVRReturn[offset],
1379                                                  l);
1380                                 offset++;
1381                         }
1382                         freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1383                 }
1384                 _G.sendSet = NULL;
1385         }
1386
1387         emitcode("icall","");
1388
1389         /* if we need assign a result value */
1390         if ((IS_ITEMP(IC_RESULT(ic)) &&
1391              (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1392               OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
1393             IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1394
1395                 aopOp(IC_RESULT(ic),ic,FALSE);
1396
1397                 assignResultValue(IC_RESULT(ic));
1398                 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1399         }
1400
1401         /* adjust the stack for parameters if 
1402            required */
1403         if (IC_LEFT(ic)->parmBytes) {
1404                 int i;
1405                 if (IC_LEFT(ic)->parmBytes > 3) {
1406                         emitcode("mov","a,%s",spname);
1407                         emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1408                         emitcode("mov","%s,a",spname);
1409                 } else 
1410                         for ( i = 0 ; i <  IC_LEFT(ic)->parmBytes ;i++)
1411                                 emitcode("dec","%s",spname);
1412
1413         }
1414
1415         /* adjust the stack for parameters if required */
1416         if (IC_LEFT(ic)->parmBytes) {
1417                 if (IC_LEFT(ic)->parmBytes > 63) {
1418                         emitcode("sbiw","r28,%d",IC_LEFT(ic)->parmBytes);
1419                 } else {
1420                         emitcode("subi","r28,lo8(%d)",IC_LEFT(ic)->parmBytes);
1421                         emitcode("sbci","r29,hi8(%d)",IC_LEFT(ic)->parmBytes);
1422                 }
1423         }
1424         if (ic->regsSaved) popZreg(ic);
1425 }
1426
1427 /*-----------------------------------------------------------------*/
1428 /* resultRemat - result  is rematerializable                       */
1429 /*-----------------------------------------------------------------*/
1430 static int resultRemat (iCode *ic)
1431 {
1432         if (SKIP_IC(ic) || ic->op == IFX)
1433                 return 0;
1434
1435         if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1436                 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1437                 if (sym->remat && !POINTER_SET(ic)) 
1438                         return 1;
1439         }
1440
1441         return 0;
1442 }
1443
1444 #ifdef __BORLANDC__
1445 #define STRCASECMP stricmp
1446 #else
1447 #define STRCASECMP strcasecmp
1448 #endif
1449
1450 /*-----------------------------------------------------------------*/
1451 /* inExcludeList - return 1 if the string is in exclude Reg list   */
1452 /*-----------------------------------------------------------------*/
1453 static bool inExcludeList(char *s)
1454 {
1455         int i =0;
1456     
1457         if (options.excludeRegs[i] &&
1458             STRCASECMP(options.excludeRegs[i],"none") == 0)
1459                 return FALSE ;
1460
1461         for ( i = 0 ; options.excludeRegs[i]; i++) {
1462                 if (options.excludeRegs[i] &&
1463                     STRCASECMP(s,options.excludeRegs[i]) == 0)
1464                         return TRUE;
1465         }
1466         return FALSE ;
1467 }
1468
1469 /*-----------------------------------------------------------------*/
1470 /* genFunction - generated code for function entry                 */
1471 /*-----------------------------------------------------------------*/
1472 static void genFunction (iCode *ic)
1473 {
1474         symbol *sym;
1475         link *fetype;
1476         int i = 0;
1477
1478         _G.nRegsSaved = 0;
1479         /* create the function header */
1480         emitcode(";","-----------------------------------------");
1481         emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1482         emitcode(";","-----------------------------------------");
1483
1484         emitcode("","%s:",sym->rname);
1485         fetype = getSpec(operandType(IC_LEFT(ic)));
1486
1487         /* if critical function then turn interrupts off */
1488         if (SPEC_CRTCL(fetype))
1489                 emitcode("cli","");
1490
1491         if (IS_ISR(sym->etype)) {
1492         }
1493
1494         /* save the preserved registers that are used in this function */
1495         for (i = R2_IDX ; i <= R15_IDX ; i++ ) {
1496                 if (bitVectBitValue(sym->regsUsed,i)) {
1497                         _G.nRegsSaved++;
1498                         emitcode("push","%s",avr_regWithIdx(i)->name);
1499                 }
1500         }
1501         /* now for the pointer registers */
1502         if (bitVectBitValue(sym->regsUsed,R26_IDX)) {
1503                 _G.nRegsSaved++;
1504                 emitcode("push","r26");
1505         }
1506         if (bitVectBitValue(sym->regsUsed,R27_IDX)) {
1507                 _G.nRegsSaved++;
1508                 emitcode("push","r27");
1509         }
1510         if (bitVectBitValue(sym->regsUsed,R30_IDX)) {
1511                 _G.nRegsSaved++;
1512                 emitcode("push","r30");
1513         }
1514         if (bitVectBitValue(sym->regsUsed,R31_IDX)) {
1515                 _G.nRegsSaved++;
1516                 emitcode("push","r31");
1517         }
1518         /* adjust the stack for the function */
1519         if (sym->stack) {
1520                 emitcode ("push","r28");
1521                 emitcode ("push","r29");
1522                 emitcode ("in","r28,__SP_L__");
1523                 emitcode ("in","r29,__SP_H__");
1524                 if (sym->stack <= 63) {
1525                         emitcode("sbiw","r28,%d",sym->stack);
1526                 } else {
1527                         emitcode ("subi","r28,lo8(%d)",sym->stack);
1528                         emitcode ("sbci","r29,hi8(%d)",sym->stack);
1529                 }
1530                 emitcode("out","__SP_L__,r28");
1531                 emitcode("out","__SP_H__,r29");
1532         }
1533 }
1534
1535 /*-----------------------------------------------------------------*/
1536 /* genEndFunction - generates epilogue for functions               */
1537 /*-----------------------------------------------------------------*/
1538 static void genEndFunction (iCode *ic)
1539 {
1540         symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1541         int i;
1542
1543         /* restore stack pointer */
1544         if (sym->stack) {
1545                 if (sym->stack <= 63) {
1546                         emitcode("adiw","r28,%d",sym->stack);
1547                 } else {
1548                         emitcode ("subi","r28,lo8(-%d)",sym->stack);
1549                         emitcode ("sbci","r29,hi8(-%d)",sym->stack);
1550                 }
1551                 emitcode("out","__SP_L__,r28");
1552                 emitcode("out","__SP_H__,r29");
1553
1554                 /* pop frame pointer */
1555                 emitcode ("pop","r29");
1556                 emitcode ("pop","r28");
1557         }
1558         /* restore preserved registers */
1559         if (bitVectBitValue(sym->regsUsed,R31_IDX)) {
1560                 _G.nRegsSaved--;
1561                 emitcode("pop","r31");
1562         }
1563         if (bitVectBitValue(sym->regsUsed,R30_IDX)) {
1564                 _G.nRegsSaved--;
1565                 emitcode("pop","r30");
1566         }
1567         if (bitVectBitValue(sym->regsUsed,R27_IDX)) {
1568                 _G.nRegsSaved--;
1569                 emitcode("push","r27");
1570         }
1571         if (bitVectBitValue(sym->regsUsed,R26_IDX)) {
1572                 _G.nRegsSaved--;
1573                 emitcode("push","r26");
1574         }
1575         for (i = R15_IDX ; i >= R2_IDX ; i-- ) {
1576                 if (bitVectBitValue(sym->regsUsed,i)) {
1577                         _G.nRegsSaved--;
1578                         emitcode("pop","%s",avr_regWithIdx(i)->name);
1579                 }
1580         }
1581
1582         if (SPEC_CRTCL(sym->etype))
1583                 emitcode("sti","");
1584
1585         if (IS_ISR(sym->etype)) {
1586                 emitcode("rti","");
1587         } else {
1588                 emitcode("ret","");
1589         }
1590
1591 }
1592
1593 /*-----------------------------------------------------------------*/
1594 /* genRet - generate code for return statement                     */
1595 /*-----------------------------------------------------------------*/
1596 static void genRet (iCode *ic)
1597 {
1598         int size,offset = 0 ;
1599     
1600         /* if we have no return value then
1601            just generate the "ret" */
1602         if (!IC_LEFT(ic)) 
1603                 goto jumpret;       
1604     
1605         /* we have something to return then
1606            move the return value into place */
1607         aopOp(IC_LEFT(ic),ic,FALSE);
1608         size = AOP_SIZE(IC_LEFT(ic));
1609     
1610         while (size--) {
1611                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
1612                         emitcode("ldi","%s,%s(%d)",fAVRReturn[offset],larray[offset],
1613                                  (int)floatFromVal (AOP(IC_LEFT(ic))->aopu.aop_lit),offset);
1614                 } else {                
1615                         char *l ;
1616                         l = aopGet(AOP(IC_LEFT(ic)),offset);
1617                         if (strcmp(fAVRReturn[offset],l))
1618                                 emitcode("mov","%s,%s",fAVRReturn[offset],l);
1619                 }
1620                 offset++;
1621         }    
1622
1623         freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
1624     
1625  jumpret:
1626         /* generate a jump to the return label
1627            if the next is not the return statement */
1628         if (!(ic->next && ic->next->op == LABEL &&
1629               IC_LABEL(ic->next) == returnLabel))
1630         
1631                 emitcode("rjmp","L%05d",returnLabel->key);
1632     
1633 }
1634
1635 /*-----------------------------------------------------------------*/
1636 /* genLabel - generates a label                                    */
1637 /*-----------------------------------------------------------------*/
1638 static void genLabel (iCode *ic)
1639 {
1640         /* special case never generate */
1641         if (IC_LABEL(ic) == entryLabel)
1642                 return ;
1643
1644         emitcode("","L%05d:",IC_LABEL(ic)->key);
1645 }
1646
1647 /*-----------------------------------------------------------------*/
1648 /* genGoto - generates a ljmp                                      */
1649 /*-----------------------------------------------------------------*/
1650 static void genGoto (iCode *ic)
1651 {
1652         emitcode ("rjmp","L%05d:",(IC_LABEL(ic)->key+100));
1653 }
1654
1655 /*-----------------------------------------------------------------*/
1656 /* findLabelBackwards: walks back through the iCode chain looking  */
1657 /* for the given label. Returns number of iCode instructions       */
1658 /* between that label and given ic.                                */
1659 /* Returns zero if label not found.                                */
1660 /*-----------------------------------------------------------------*/
1661 static int findLabelBackwards(iCode *ic, int key)
1662 {
1663         int count = 0;
1664     
1665         while (ic->prev)
1666                 {
1667                         ic = ic->prev;
1668                         count++;
1669         
1670                         if (ic->op == LABEL && IC_LABEL(ic)->key == key)
1671                                 {
1672                                         /* printf("findLabelBackwards = %d\n", count); */
1673                                         return count;
1674                                 }
1675                 }
1676     
1677         return 0;
1678 }
1679
1680 /*-----------------------------------------------------------------*/
1681 /* genPlusIncr :- does addition with increment if possible         */
1682 /*-----------------------------------------------------------------*/
1683 static bool genPlusIncr (iCode *ic)
1684 {
1685         unsigned int icount ;
1686     
1687         /* will try to generate an increment */
1688         /* if the right side is not a literal 
1689            we cannot */
1690         if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1691                 return FALSE ;
1692     
1693         icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
1694     
1695         /* if the sizes are greater than 2 or they are not the same regs
1696            then we cannot */
1697         if (!sameRegs(AOP(IC_LEFT(ic)),AOP(IC_RESULT(ic))))
1698                 return FALSE ;
1699     
1700         /* so we know LEFT & RESULT in the same registers and add
1701            amount <= 63 */
1702         /* for short & char types */
1703         if (AOP_SIZE(IC_RESULT(ic)) < 2) {
1704                 if (icount == 1) {
1705                         emitcode("inc","%s",aopGet(AOP(IC_LEFT(ic)),0));
1706                         return TRUE;
1707                 } 
1708                 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_LEFT(ic)),0),-icount);
1709                 return TRUE;
1710         }
1711
1712         if (AOP_SIZE(IC_RESULT(ic)) <= 3) {
1713                 /* if register pair and starts with 26/30 then adiw */
1714                 if (isRegPair(AOP(IC_RESULT(ic))) && icount > 0 && icount < 64 &&
1715                     ( IS_REGIDX(AOP(IC_RESULT(ic)),R26_IDX) ||
1716                       IS_REGIDX(AOP(IC_RESULT(ic)),R30_IDX) )) {
1717                         emitcode("adiw","%s,%d",aopGet(AOP(IC_RESULT(ic)),0),icount);
1718                         return TRUE;
1719                 }
1720     
1721                 /* use subi */
1722                 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_RESULT(ic)),0),-icount);
1723                 emitcode("sbci","%s,hi8(%d)",aopGet(AOP(IC_RESULT(ic)),1),-icount);
1724                 return TRUE;
1725         }
1726
1727         /* for 32 bit longs */
1728         emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_RESULT(ic)),0),-icount);
1729         emitcode("sbci","%s,hi8(%d)",aopGet(AOP(IC_RESULT(ic)),1),-icount);
1730         emitcode("sbci","%s,hlo8(%d)",aopGet(AOP(IC_RESULT(ic)),2),-icount);
1731         emitcode("sbci","%s,hhi8(%d)",aopGet(AOP(IC_RESULT(ic)),3),-icount);
1732         return TRUE;
1733    
1734 }
1735
1736 /* This is the pure and virtuous version of this code.
1737  * I'm pretty certain it's right, but not enough to toss the old 
1738  * code just yet...
1739  */
1740 static void adjustArithmeticResult  (iCode *ic)
1741 {
1742         if (opIsGptr(IC_RESULT(ic)) &&
1743             opIsGptr(IC_LEFT(ic))   &&
1744             !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1745                 {
1746                         aopPut(AOP(IC_RESULT(ic)),
1747                                aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1),
1748                                GPTRSIZE - 1);
1749                 }
1750
1751         if (opIsGptr(IC_RESULT(ic)) &&
1752             opIsGptr(IC_RIGHT(ic))   &&
1753             !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
1754                 {
1755                         aopPut(AOP(IC_RESULT(ic)),
1756                                aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1),
1757                                GPTRSIZE - 1);
1758                 }
1759
1760         if (opIsGptr(IC_RESULT(ic))        &&
1761             AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE   &&
1762             AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE  &&
1763             !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
1764             !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
1765                 char buffer[5];
1766                 sprintf(buffer,"%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
1767                 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
1768         }
1769 }
1770
1771 /*-----------------------------------------------------------------*/
1772 /* genPlus - generates code for addition                           */
1773 /*-----------------------------------------------------------------*/
1774 static void genPlus (iCode *ic)
1775 {
1776         int size, offset = 0;
1777         int samer;
1778         char *l;
1779
1780         /* special cases :- */
1781
1782         aopOp (IC_LEFT(ic),ic,FALSE);
1783         aopOp (IC_RIGHT(ic),ic,FALSE);
1784         aopOp (IC_RESULT(ic),ic,TRUE);
1785
1786         /* if I can do an increment instead
1787            of add then GOOD for ME */
1788         if (genPlusIncr (ic) == TRUE)
1789                 goto release;   
1790
1791         size = getDataSize(IC_RESULT(ic));
1792         samer = sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic)));
1793
1794         while(size--) {
1795                 if (!samer) 
1796                         aopPut(AOP(IC_RESULT(ic)),aopGet(AOP(IC_LEFT(ic)),offset),offset);
1797
1798                 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
1799
1800                         if(offset == 0) l = "add";
1801                         else l = "adc";
1802
1803                         emitcode(l,"%s,%s",aopGet(AOP(IC_RESULT(ic)),offset),
1804                                  aopGet(AOP(IC_RIGHT(ic)),offset));
1805                 } else {
1806                         if (offset == 0) l = "subi";
1807                         else l = "sbci";
1808
1809                         emitcode(l,"%s,%s(-%d)",aopGet(AOP(IC_RESULT(ic)),offset),
1810                                  larray[offset],
1811                                  (int)floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
1812                 }
1813                 offset++;
1814         }
1815
1816         adjustArithmeticResult(ic);
1817
1818  release:
1819         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1820         freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1821         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1822 }
1823
1824 /*-----------------------------------------------------------------*/
1825 /* genMinusDec :- does subtraction with deccrement if possible     */
1826 /*-----------------------------------------------------------------*/
1827 static bool genMinusDec (iCode *ic)
1828 {
1829         unsigned int icount ;
1830     
1831         /* will try to generate an increment */
1832         /* if the right side is not a literal 
1833            we cannot */
1834         if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1835                 return FALSE ;
1836     
1837         icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
1838     
1839         /* if the sizes are greater than 2 or they are not the same regs
1840            then we cannot */
1841         if (!sameRegs(AOP(IC_LEFT(ic)),AOP(IC_RIGHT(ic))))
1842                 return FALSE ;
1843     
1844         /* so we know LEFT & RESULT in the same registers and add
1845            amount <= 63 */
1846         /* for short & char types */
1847         if (AOP_SIZE(IC_RESULT(ic)) < 2) {
1848                 if (icount == 1) {
1849                         emitcode("dec","%s",aopGet(AOP(IC_LEFT(ic)),0));
1850                         return TRUE;
1851                 } 
1852                 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_LEFT(ic)),0),icount);
1853                 return TRUE;
1854         }
1855
1856         if (AOP_SIZE(IC_RESULT(ic)) <= 3) {
1857                 /* if register pair and starts with 26/30 then adiw */
1858                 if (isRegPair(AOP(IC_RESULT(ic))) && icount > 0 && icount < 64 &&
1859                     ( IS_REGIDX(AOP(IC_RESULT(ic)),R26_IDX) ||
1860                       IS_REGIDX(AOP(IC_RESULT(ic)),R30_IDX) )) {
1861                         emitcode("sbiw","%s,%d",aopGet(AOP(IC_RESULT(ic)),0),icount);
1862                         return TRUE;
1863                 }
1864     
1865                 /* use subi */
1866                 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_RESULT(ic)),0),icount);
1867                 emitcode("sbci","%s,hi8(%d)",aopGet(AOP(IC_RESULT(ic)),1),icount);
1868                 return TRUE;
1869         }
1870         /* for 32 bit longs */
1871         emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_RESULT(ic)),0),icount);
1872         emitcode("sbci","%s,hi8(%d)",aopGet(AOP(IC_RESULT(ic)),1),icount);
1873         emitcode("sbci","%s,hlo8(%d)",aopGet(AOP(IC_RESULT(ic)),2),icount);
1874         emitcode("sbci","%s,hhi8(%d)",aopGet(AOP(IC_RESULT(ic)),3),icount);
1875         return TRUE;
1876
1877 }
1878
1879 /*-----------------------------------------------------------------*/
1880 /* addSign - complete with sign                                    */
1881 /*-----------------------------------------------------------------*/
1882 static void addSign(operand *result, int offset, int sign)
1883 {
1884         int size = (getDataSize(result) - offset);
1885         if(size > 0){
1886                 if(sign){
1887                         emitcode("rlc","a");
1888                         emitcode("subb","a,acc");
1889                         while(size--)
1890                                 aopPut(AOP(result),"a",offset++); 
1891                 } else
1892                         while(size--)
1893                                 aopPut(AOP(result),zero,offset++);
1894         }
1895 }
1896
1897 /*-----------------------------------------------------------------*/
1898 /* genMinus - generates code for subtraction                       */
1899 /*-----------------------------------------------------------------*/
1900 static void genMinus (iCode *ic)
1901 {
1902         int size, offset = 0, samer;
1903         char *l;
1904
1905         aopOp (IC_LEFT(ic),ic,FALSE);
1906         aopOp (IC_RIGHT(ic),ic,FALSE);
1907         aopOp (IC_RESULT(ic),ic,TRUE);
1908     
1909         /* if I can do an decrement instead
1910            of subtract then GOOD for ME */
1911         if (genMinusDec (ic) == TRUE)
1912                 goto release;   
1913     
1914         size = getDataSize(IC_RESULT(ic));   
1915         samer = sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic)));
1916         while (size--) {
1917                 if (!samer) 
1918                         aopPut(AOP(IC_RESULT(ic)),aopGet(AOP(IC_LEFT(ic)),offset),offset);
1919
1920                 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
1921
1922                         if(offset == 0) l = "sub";
1923                         else l = "sbc";
1924
1925                         emitcode(l,"%s,%s",aopGet(AOP(IC_RESULT(ic)),offset),
1926                                  aopGet(AOP(IC_RIGHT(ic)),offset));
1927                 } else {
1928                         if (offset == 0) l = "subi";
1929                         else l = "sbci";
1930
1931                         emitcode(l,"%s,%s(%d)",aopGet(AOP(IC_RESULT(ic)),offset),
1932                                  larray[offset],
1933                                  (int)floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
1934                 }
1935                 offset++;
1936         }
1937
1938         adjustArithmeticResult(ic);
1939     
1940  release:
1941         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1942         freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1943         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1944 }
1945
1946 /*-----------------------------------------------------------------*/
1947 /* genMultOneByte : 8 bit multiplication & division                */
1948 /*-----------------------------------------------------------------*/
1949 static void genMultOneByte (operand *left,
1950                             operand *right,
1951                             operand *result)
1952 {
1953         link *opetype = operandType(result);
1954         symbol *lbl ;
1955         int size,offset;
1956     
1957         /* (if two literals, the value is computed before) */
1958         /* if one literal, literal on the right */
1959         if (AOP_TYPE(left) == AOP_LIT){
1960                 operand *t = right;
1961                 right = left;
1962                 left = t;
1963         }
1964     
1965         size = AOP_SIZE(result);
1966
1967         if (SPEC_USIGN(opetype)) {
1968                 emitcode("mul","%s,%s", aopGet(AOP(left),0),aopGet(AOP(right),0));
1969         } else {
1970                 emitcode("muls","%s,%s", aopGet(AOP(left),0),
1971                          aopGet(AOP(right),0));
1972         }
1973         aopPut(AOP(result),"r0",0);
1974         if (size > 1){
1975                 aopPut(AOP(result),"r1",1);
1976                 offset = 2;
1977                 size -= 2;
1978                 if (SPEC_USIGN(opetype)) {
1979                         while(size--) {
1980                                 aopPut(AOP(result),zero,offset++);
1981                         }
1982                 } else {
1983                         if (size) {
1984                                 lbl = newiTempLabel(NULL);
1985                                 emitcode("ldi","r24,0");
1986                                 emitcode("brcc","L%05d",lbl->key);
1987                                 emitcode("ldi","r24,lo8(-1)");
1988                                 emitcode("","L%05d:",lbl->key);
1989                                 while (size--) aopPut(AOP(result),"r24",offset++);
1990                         }
1991                 }
1992         }
1993         return;
1994 }
1995
1996 /*-----------------------------------------------------------------*/
1997 /* genMult - generates code for multiplication                     */
1998 /*-----------------------------------------------------------------*/
1999 static void genMult (iCode *ic)
2000 {
2001         operand *left = IC_LEFT(ic);
2002         operand *right = IC_RIGHT(ic);
2003         operand *result= IC_RESULT(ic);   
2004
2005         /* assign the amsops */
2006         aopOp (left,ic,FALSE);
2007         aopOp (right,ic,FALSE);
2008         aopOp (result,ic,TRUE);
2009
2010         /* if both are of size == 1 */
2011         if (AOP_SIZE(left) == 1 &&
2012             AOP_SIZE(right) == 1 ) {
2013                 genMultOneByte(left,right,result);
2014                 goto release ;
2015         }
2016
2017         /* should have been converted to function call */       
2018         assert(1) ;
2019
2020         release :
2021                 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2022         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2023         freeAsmop(result,NULL,ic,TRUE); 
2024 }
2025
2026 /*-----------------------------------------------------------------*/
2027 /* genDiv - generates code for division                            */
2028 /*-----------------------------------------------------------------*/
2029 static void genDiv (iCode *ic)
2030 {
2031         /* should have been converted to function call */
2032         assert(1);
2033 }
2034
2035 /*-----------------------------------------------------------------*/
2036 /* genMod - generates code for division                            */
2037 /*-----------------------------------------------------------------*/
2038 static void genMod (iCode *ic)
2039 {
2040         /* should have been converted to function call */
2041         assert(1);
2042
2043 }
2044
2045 enum {
2046         AVR_EQ = 0,
2047         AVR_NE,
2048         AVR_LT,
2049         AVR_GE
2050 };
2051
2052 /*-----------------------------------------------------------------*/
2053 /* revavrcnd - reverse a conditional for avr                       */
2054 /*-----------------------------------------------------------------*/
2055 static int revavrcnd(int type)
2056 {
2057         static struct {
2058                 int type, rtype;
2059         } rar[] = { { AVR_EQ, AVR_NE}, {AVR_LT, AVR_GE}};
2060         int i;
2061
2062         for (i = 0 ; i < (sizeof(rar)/sizeof(rar[0]));i++) {
2063                 if (rar[i].type == type) return rar[i].rtype;
2064                 if (rar[i].rtype== type) return rar[i].type;
2065         }
2066         assert(1); /* cannot happen */
2067 }
2068
2069 static char *br_name[4] = {"breq","brne","brlt","brge"};
2070 static char *br_uname[4]= {"breq","brne","brlo","brcc"};
2071
2072 /*-----------------------------------------------------------------*/
2073 /* genBranch - generate the branch instruction                     */
2074 /*-----------------------------------------------------------------*/
2075 static void genBranch (iCode *ifx, int br_type, int sign)
2076 {
2077         int tj = (IC_TRUE(ifx) ? 1 : 0) ;
2078
2079         if (tj) { /* if true jump */
2080                 char *nm = (sign ? br_name[br_type] : br_uname[br_type]);
2081                 emitcode(nm,"L%05d",IC_TRUE(ifx)->key);
2082         } else { /* if false jump */
2083                 int rtype = revavrcnd(br_type);
2084                 char *nm = (sign ? br_name[rtype] : br_uname[rtype]);
2085                 emitcode(nm,"L%05d",IC_FALSE(ifx)->key);
2086         }
2087         ifx->generated = 1;
2088 }
2089
2090 /*-----------------------------------------------------------------*/
2091 /* genCmp - compare & jump                                         */
2092 /*-----------------------------------------------------------------*/
2093 static void genCmp (iCode *ic, iCode *ifx, int br_type)
2094 {
2095         operand *left, *right, *result;
2096         link *letype , *retype;
2097         symbol *lbl;
2098         int sign, size, offset =0;
2099
2100         left = IC_LEFT(ic);
2101         right= IC_RIGHT(ic);
2102         result = IC_RESULT(ic);
2103
2104         letype = getSpec(operandType(left));
2105         retype =getSpec(operandType(right));
2106         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2107
2108         /* assign the amsops */
2109         aopOp (left,ic,FALSE);
2110         aopOp (right,ic,FALSE);
2111         aopOp (result,ic,TRUE);
2112         size = AOP_SIZE(left);
2113
2114         if (ifx) {
2115                 if (size == 1) {
2116                         if (AOP_TYPE(right) == AOP_LIT) {
2117                                 emitcode("cpi","%s,lo8(%d)",aopGet(AOP(left),0),
2118                                          (int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
2119                                 genBranch(ifx,br_type,sign);
2120                         } else { /* right != literal */
2121                                 emitcode("cp","%s,%s",aopGet(AOP(left),0),aopGet(AOP(right),0));
2122                                 genBranch(ifx,br_type,sign);
2123                         }
2124                 } else { /* size != 1 */
2125                         while (size--) {
2126                                 if (offset == 0) 
2127                                         emitcode("cp","%s,%s",aopGet(AOP(left),0),aopGet(AOP(right),0));
2128                                 else
2129                                         emitcode("cpc","%s,%s",aopGet(AOP(left),offset),aopGet(AOP(right),offset));
2130                                 offset++;
2131                         }
2132                         genBranch(ifx,br_type,sign);
2133                 }
2134         } else { /* no ifx */
2135                 emitcode("clr","r0");
2136                 while (size--) {
2137                         if (offset == 0) 
2138                                 emitcode("cp","%s,%s",aopGet(AOP(left),0),aopGet(AOP(right),0));
2139                         else
2140                                 emitcode("cpc","%s,%s",aopGet(AOP(left),offset),aopGet(AOP(right),offset));
2141                         offset++;
2142                 }
2143                 lbl = newiTempLabel(NULL);
2144                 br_type = revavrcnd(br_type);
2145                 if (sign) emitcode(br_uname[br_type],"L%05d",lbl->key);
2146                 else emitcode(br_name[br_type],"L%05d",lbl->key);
2147                 emitcode("inc","r0");
2148                 emitcode("","L%05d:",lbl->key);
2149                 aopPut(AOP(result),"r0",0);
2150                 size = AOP_SIZE(result) - 1;
2151                 offset = 1;
2152                 while (size--) aopPut(AOP(result),zero,offset++);
2153         }
2154
2155         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2156         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2157         freeAsmop(result,NULL,ic,TRUE); 
2158 }
2159
2160 /*-----------------------------------------------------------------*/
2161 /* genCmpGt :- greater than comparison                             */
2162 /*-----------------------------------------------------------------*/
2163 static void genCmpGt (iCode *ic, iCode *ifx)
2164 {
2165         /* should have transformed by the parser */
2166         assert(1);
2167 }
2168
2169 /*-----------------------------------------------------------------*/
2170 /* genCmpLt - less than comparisons                                */
2171 /*-----------------------------------------------------------------*/
2172 static void genCmpLt (iCode *ic, iCode *ifx)
2173 {
2174         genCmp(ic,ifx,AVR_LT);
2175 }
2176
2177 /*-----------------------------------------------------------------*/
2178 /* genCmpEq - generates code for equal to                          */
2179 /*-----------------------------------------------------------------*/
2180 static void genCmpEq (iCode *ic, iCode *ifx)
2181 {
2182         genCmp(ic,ifx,AVR_EQ);
2183 }
2184
2185 /*-----------------------------------------------------------------*/
2186 /* genCmpNe - generates code for not equal to                      */
2187 /*-----------------------------------------------------------------*/
2188 static void genCmpNe (iCode *ic, iCode *ifx)
2189 {
2190         genCmp(ic,ifx,AVR_NE);
2191 }
2192
2193 /*-----------------------------------------------------------------*/
2194 /* genCmpGe - generates code for greater than equal to             */
2195 /*-----------------------------------------------------------------*/
2196 static void genCmpGe (iCode *ic, iCode *ifx)
2197 {
2198         genCmp(ic,ifx,AVR_GE);
2199 }
2200
2201 /*-----------------------------------------------------------------*/
2202 /* genCmpLe - generates code for less than equal to                */
2203 /*-----------------------------------------------------------------*/
2204 static void genCmpLe (iCode *ic, iCode *ifx)
2205 {
2206         operand *left = IC_LEFT(ic);
2207         operand *right= IC_RIGHT(ic);
2208     
2209         IC_RIGHT(ic) = left;
2210         IC_LEFT(ic)  = right;
2211         genCmp(ic,ifx,AVR_GE);
2212 }
2213
2214 /*-----------------------------------------------------------------*/
2215 /* ifxForOp - returns the icode containing the ifx for operand     */
2216 /*-----------------------------------------------------------------*/
2217 static iCode *ifxForOp ( operand *op, iCode *ic )
2218 {
2219         /* if true symbol then needs to be assigned */
2220         if (IS_TRUE_SYMOP(op))
2221                 return NULL ;
2222
2223     /* if this has register type condition and
2224     the next instruction is ifx with the same operand
2225     and live to of the operand is upto the ifx only then */
2226         if (ic->next &&
2227             ic->next->op == IFX &&
2228             IC_COND(ic->next)->key == op->key &&
2229             OP_SYMBOL(op)->liveTo <= ic->next->seq )
2230                 return ic->next;
2231
2232         return NULL;
2233 }
2234 /*-----------------------------------------------------------------*/
2235 /* genAndOp - for && operation                                     */
2236 /*-----------------------------------------------------------------*/
2237 static void genAndOp (iCode *ic)
2238 {
2239         operand *left,*right, *result;
2240         symbol *tlbl;
2241         int size , offset;
2242
2243         /* note here that && operations that are in an
2244            if statement are taken away by backPatchLabels
2245            only those used in arthmetic operations remain */
2246         aopOp((left=IC_LEFT(ic)),ic,FALSE);
2247         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2248         aopOp((result=IC_RESULT(ic)),ic,FALSE);
2249
2250         tlbl = newiTempLabel(NULL);
2251         toBoolean(left,"r0",TRUE);    
2252         toBoolean(right,"r1",TRUE);
2253         emitcode("and","r0,r1");
2254         emitcode("ldi","r24,1");
2255         emitcode("breq","L%05d",tlbl->key);
2256         emitcode("dec","r24");
2257         emitcode("","L%05d:",tlbl->key);
2258         aopPut(AOP(result),"r24",0);
2259         size = AOP_SIZE(result) -1;
2260         offset = 1;
2261         while (size--) aopPut(AOP(result),zero,offset++);
2262     
2263         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2264         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2265         freeAsmop(result,NULL,ic,TRUE);
2266 }
2267
2268
2269 /*-----------------------------------------------------------------*/
2270 /* genOrOp - for || operation                                      */
2271 /*-----------------------------------------------------------------*/
2272 static void genOrOp (iCode *ic)
2273 {
2274         operand *left,*right, *result;
2275         symbol *tlbl;
2276         int size , offset;
2277
2278         /* note here that || operations that are in an
2279            if statement are taken away by backPatchLabels
2280            only those used in arthmetic operations remain */
2281         aopOp((left=IC_LEFT(ic)),ic,FALSE);
2282         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2283         aopOp((result=IC_RESULT(ic)),ic,FALSE);
2284
2285         tlbl = newiTempLabel(NULL);
2286         toBoolean(left,"r0",TRUE);    
2287         toBoolean(right,"r0",FALSE);
2288         emitcode("ldi","r24,1");
2289         emitcode("breq","L%05d",tlbl->key);
2290         emitcode("dec","r24");
2291         emitcode("","L%05d:",tlbl->key);
2292         aopPut(AOP(result),"r24",0);
2293         size = AOP_SIZE(result) -1;
2294         offset = 1;
2295         while (size--) aopPut(AOP(result),zero,offset++);
2296
2297         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2298         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2299         freeAsmop(result,NULL,ic,TRUE);            
2300 }
2301
2302 /*-----------------------------------------------------------------*/
2303 /* isLiteralBit - test if lit == 2^n                               */
2304 /*-----------------------------------------------------------------*/
2305 static int isLiteralBit(unsigned long lit)
2306 {
2307         unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
2308                                 0x100L,0x200L,0x400L,0x800L,
2309                                 0x1000L,0x2000L,0x4000L,0x8000L,
2310                                 0x10000L,0x20000L,0x40000L,0x80000L,
2311                                 0x100000L,0x200000L,0x400000L,0x800000L,
2312                                 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
2313                                 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
2314         int idx;
2315     
2316         for(idx = 0; idx < 32; idx++)
2317                 if(lit == pw[idx])
2318                         return idx+1;
2319         return 0;
2320 }
2321
2322 enum { AVR_AND = 0, AVR_OR, AVR_XOR };
2323 static char *bopnames_lit[] = {"andi","ori"};
2324 static char *bopnames[] = {"and","or","eor"};
2325 /*-----------------------------------------------------------------*/
2326 /* genBitWise - generate bitwise operations                        */
2327 /*-----------------------------------------------------------------*/
2328 static void genBitWise(iCode *ic, iCode *ifx, int bitop)
2329 {
2330         operand *left, *right, *result;
2331         int size, offset=0;
2332         char *l;
2333         symbol *lbl, *lbl1;
2334         int samerl, samerr ;
2335
2336         aopOp((left = IC_LEFT(ic)),ic,FALSE);
2337         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2338         aopOp((result=IC_RESULT(ic)),ic,TRUE);
2339     
2340         size = AOP_SIZE(left);
2341         offset = 0;
2342         if (ifx) { /* used only for jumps */
2343                 if (AOP_TYPE(right) == AOP_LIT && 
2344                     (bitop == AVR_AND || bitop == AVR_OR)) {
2345                         int lit = (int) floatFromVal (AOP(right)->aopu.aop_lit);
2346                         int p2 = powof2(lit);
2347                         if (bitop == AVR_AND && p2) { /* right side is a power of 2 */
2348                                 l = aopGet(AOP(left),p2 / 8);
2349                                 if (IC_TRUE(ifx)) {
2350                                         emitcode("sbrc","%s,%d",l,(p2 % 8));
2351                                         emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2352                                 } else {
2353                                         emitcode("sbrs","%s,%d",l,(p2 % 8));
2354                                         emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2355                                 }
2356                         } else { /* right not power of two */
2357                                 int eh = OP_SYMBOL(left)->liveTo <= ic->seq;
2358                                 if (size == 1) {
2359                                         if (eh) {
2360                                                 emitcode(bopnames_lit[bitop],"%s,lo8(%d)",
2361                                                          aopGet(AOP(IC_LEFT(ic)),0), lit);
2362                                         } else {
2363                                                 MOVR0(aopGet(AOP(IC_LEFT(ic)),0));
2364                                                 emitcode(bopnames_lit[bitop],"r0,lo8(%d)",lit);
2365                                         }
2366                                         lbl = newiTempLabel(NULL);
2367                                         if (IC_TRUE(ifx)) {
2368                                                 emitcode("breq","L%05d",lbl->key);
2369                                                 emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2370                                         } else {                                        
2371                                                 emitcode("brne","L%05d",lbl->key);
2372                                                 emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2373                                         }
2374                                         emitcode("","L%05d:",lbl->key);
2375                                 } else if (size == 2) {
2376                                         emitcode("mov","r24,%s",aopGet(AOP(IC_LEFT(ic)),0));
2377                                         emitcode("mov","r25,%s",aopGet(AOP(IC_LEFT(ic)),1));
2378                                         emitcode(bopnames_lit[bitop],"r24,lo8(%d)",lit);
2379                                         emitcode(bopnames_lit[bitop],"r25,hi8(%d)",lit);
2380                                         emitcode("sbiw","r24,0");
2381                                         lbl = newiTempLabel(NULL);
2382                                         if (IC_TRUE(ifx)) {
2383                                                 emitcode("breq","L%05d",lbl->key);
2384                                                 emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2385                                         } else {                                        
2386                                                 emitcode("brne","L%05d",lbl->key);
2387                                                 emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2388                                         }
2389                                         emitcode("","L%05d:",lbl->key);                                 
2390                                 } else {                                        
2391                                         lbl = newiTempLabel(NULL);
2392                                         lbl1 = newiTempLabel(NULL);                                     
2393                                         while (size--) {
2394                                                 if (eh) {
2395                                                         emitcode(bopnames_lit[bitop],"%s,lo8(%d)",
2396                                                          aopGet(AOP(IC_LEFT(ic)),offset), lit);
2397                                                 } else {
2398                                                         MOVR0(aopGet(AOP(IC_LEFT(ic)),offset));
2399                                                         emitcode("andi","r0,lo8(%d)",lit);
2400                                                 }
2401                                                 emitcode("brne","L%05d",lbl->key);
2402                                                 offset++;
2403                                         }
2404                                         /* all are zero */
2405                                         if (IC_FALSE(ifx)) emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2406                                         else emitcode("rjmp","L%05d",lbl1->key);
2407                                         emitcode("","L%05d:",lbl->key);
2408                                         /* not zero */
2409                                         if (IC_TRUE(ifx)) emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2410                                         emitcode("","L%05d:",lbl1->key);
2411                                         
2412                                 }
2413                         }
2414                 } else { /* right is not a literal */
2415                         int eh = OP_SYMBOL(left)->liveTo <= ic->seq;
2416                         int reh = OP_SYMBOL(right)->liveTo <= ic->seq;
2417                         if (size == 1) {
2418                                 if (eh) {
2419                                         emitcode(bopnames[bitop],"%s,%s",
2420                                                  aopGet(AOP(IC_LEFT(ic)),0),
2421                                                  aopGet(AOP(IC_RIGHT(ic)),0));
2422                                 } else if (reh) {
2423                                         emitcode(bopnames[bitop],"%s,%s",
2424                                                  aopGet(AOP(IC_RIGHT(ic)),0),
2425                                                  aopGet(AOP(IC_LEFT(ic)),0));
2426                                 } else {
2427                                         MOVR0(aopGet(AOP(IC_LEFT(ic)),0));
2428                                         emitcode(bopnames[bitop],"r0,%s",aopGet(AOP(IC_RIGHT(ic)),0));
2429                                 }
2430                                 lbl = newiTempLabel(NULL);
2431                                 if (IC_TRUE(ifx)) {
2432                                         emitcode("breq","L%05d",lbl->key);
2433                                         emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2434                                 } else {                                        
2435                                         emitcode("brne","L%05d",lbl->key);
2436                                         emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2437                                 }
2438                                 emitcode("","L%05d:",lbl->key);
2439                         } else if (size == 2) {
2440                                 emitcode("mov","r24,%s",aopGet(AOP(IC_LEFT(ic)),0));
2441                                 emitcode("mov","r25,%s",aopGet(AOP(IC_LEFT(ic)),1));
2442                                 emitcode(bopnames[bitop],"r24,%s",aopGet(AOP(IC_RIGHT(ic)),0));
2443                                 emitcode(bopnames[bitop],"r25,%s",aopGet(AOP(IC_RIGHT(ic)),1));
2444                                 emitcode("sbiw","r24,0");
2445                                 lbl = newiTempLabel(NULL);
2446                                 if (IC_TRUE(ifx)) {
2447                                         emitcode("breq","L%05d",lbl->key);
2448                                         emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2449                                 } else {                                        
2450                                         emitcode("brne","L%05d",lbl->key);
2451                                         emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2452                                 }
2453                                 emitcode("","L%05d:",lbl->key);                                 
2454                         } else {                                        
2455                                 lbl = newiTempLabel(NULL);
2456                                 lbl1 = newiTempLabel(NULL);                                     
2457                                 while (size--) {
2458                                         if (eh) {
2459                                                 emitcode(bopnames[bitop],"%s,%s",
2460                                                          aopGet(AOP(IC_LEFT(ic)),offset),
2461                                                          aopGet(AOP(IC_RIGHT(ic)),offset));
2462                                         } else if (reh) {
2463                                                 emitcode(bopnames[bitop],"%s,%s",
2464                                                          aopGet(AOP(IC_RIGHT(ic)),offset),
2465                                                          aopGet(AOP(IC_LEFT(ic)),offset));
2466                                         } else {
2467                                                 MOVR0(aopGet(AOP(IC_LEFT(ic)),offset));
2468                                                 emitcode(bopnames[bitop],"r0,%s",aopGet(AOP(IC_RIGHT(ic)),offset));
2469                                         }
2470                                         emitcode("brne","L%05d",lbl->key);
2471                                         offset++;
2472                                 }
2473                                 /* all are zero */
2474                                 if (IC_FALSE(ifx)) emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2475                                 else emitcode("rjmp","L%05d",lbl1->key);
2476                                 emitcode("","L%05d:",lbl->key);
2477                                 /* not zero */
2478                                 if (IC_TRUE(ifx)) emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2479                                 emitcode("","L%05d:",lbl1->key);
2480                                 
2481                         }
2482                 }
2483                 goto release ;
2484         }
2485
2486         /* result needs to go a register */
2487         samerl = sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic)));
2488         samerr = sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)));
2489         while (size--) {
2490                 if (samerl) {
2491                         if (AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT && (bitop == AVR_AND || bitop == AVR_OR)) {
2492                                 emitcode(bopnames_lit[bitop],"%s,%s(%d)",aopGet(AOP(IC_LEFT(ic)),offset),
2493                                          larray[offset],(int) floatFromVal (AOP(right)->aopu.aop_lit));
2494                         } else {
2495                                 emitcode(bopnames[bitop],"%s,%s",aopGet(AOP(IC_LEFT(ic)),offset),
2496                                          aopGet(AOP(IC_RIGHT(ic)),offset));
2497                         }
2498                 } else if (samerr) {
2499                         emitcode(bopnames[bitop],"%s,%s",aopGet(AOP(IC_RIGHT(ic)),offset),
2500                                  aopGet(AOP(IC_LEFT(ic)),offset));
2501                 } else {
2502                         aopPut(AOP(IC_RESULT(ic)),aopGet(AOP(IC_LEFT(ic)),offset),offset);
2503                         emitcode(bopnames[bitop],aopGet(AOP(IC_RESULT(ic)),offset),
2504                                  aopGet(AOP(IC_RIGHT(ic)),offset));
2505                 }
2506                 offset++;
2507         }
2508 release :
2509         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2510         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2511         freeAsmop(result,NULL,ic,TRUE);     
2512 }
2513
2514 /*-----------------------------------------------------------------*/
2515 /* genAnd  - code for and                                          */
2516 /*-----------------------------------------------------------------*/
2517 static void genAnd (iCode *ic, iCode *ifx)
2518 {
2519         genBitWise(ic,ifx,AVR_AND);
2520 }
2521
2522 /*-----------------------------------------------------------------*/
2523 /* genOr  - code for or                                            */
2524 /*-----------------------------------------------------------------*/
2525 static void genOr (iCode *ic, iCode *ifx)
2526 {
2527         genBitWise(ic,ifx,AVR_OR);
2528 }
2529
2530 /*-----------------------------------------------------------------*/
2531 /* genXor - code for xclusive or                                   */
2532 /*-----------------------------------------------------------------*/
2533 static void genXor (iCode *ic, iCode *ifx)
2534 {
2535         genBitWise(ic,ifx,AVR_XOR);
2536 }
2537
2538 /*-----------------------------------------------------------------*/
2539 /* genInline - write the inline code out                           */
2540 /*-----------------------------------------------------------------*/
2541 static void genInline (iCode *ic)
2542 {
2543         char buffer[MAX_INLINEASM];
2544         char *bp = buffer;
2545         char *bp1= buffer;
2546     
2547         _G.inLine += (!options.asmpeep);
2548         strcpy(buffer,IC_INLINE(ic));
2549
2550         /* emit each line as a code */
2551         while (*bp) {
2552                 if (*bp == '\n') {
2553                         *bp++ = '\0';
2554                         emitcode(bp1,"");
2555                         bp1 = bp;
2556                 } else {
2557                         if (*bp == ':') {
2558                                 bp++;
2559                                 *bp = '\0';
2560                                 bp++;
2561                                 emitcode(bp1,"");
2562                                 bp1 = bp;
2563                         } else
2564                                 bp++;
2565                 }
2566         }
2567         if (bp1 != bp)
2568                 emitcode(bp1,"");
2569         /*     emitcode("",buffer); */
2570         _G.inLine -= (!options.asmpeep);
2571 }
2572
2573 /*-----------------------------------------------------------------*/
2574 /* genRotC - rotate right/left with carry , lr = 1 rotate right    */
2575 /*-----------------------------------------------------------------*/
2576 static void genRotC (iCode *ic, int lr)
2577 {
2578         operand *left , *result ;
2579         int size, offset = 0;
2580         char *l;    
2581
2582         /* rotate right with carry */
2583         left = IC_LEFT(ic);
2584         result=IC_RESULT(ic);
2585         aopOp (left,ic,FALSE);
2586         aopOp (result,ic,FALSE);
2587
2588         /* move it to the result */
2589         size = AOP_SIZE(result);    
2590         if (!sameRegs(AOP(left),AOP(result))) {
2591                 offset = 0;
2592                 while (size--) {
2593                         aopPut(AOP(result),
2594                                aopGet(AOP(left),offset),
2595                                offset);
2596                         offset++;
2597                 }
2598                 size = AOP_SIZE(result);
2599         }
2600         if (lr) offset = size - 1;
2601         else offset = 0;
2602         
2603         CLRC;
2604         emitcode ("sbrc","%s,%d",aopGet(AOP(result),offset),
2605                   (lr ? 0 : 7));
2606         emitcode("sec","");
2607                   
2608         while (size--) {
2609                 emitcode((lr ? "ror" : "rol"),"%s",aopGet(AOP(result),offset));
2610                 if (lr) offset--;
2611                 else offset++;
2612         }
2613         freeAsmop(left,NULL,ic,TRUE);
2614         freeAsmop(result,NULL,ic,TRUE);
2615 }
2616
2617 /*-----------------------------------------------------------------*/
2618 /* genRRC - rotate right with carry                                */
2619 /*-----------------------------------------------------------------*/
2620 static void genRRC (iCode *ic)
2621 {
2622         genRotC(ic,1);
2623 }
2624
2625 /*-----------------------------------------------------------------*/
2626 /* genRLC - generate code for rotate left with carry               */
2627 /*-----------------------------------------------------------------*/
2628 static void genRLC (iCode *ic)
2629 {    
2630         genRotC(ic,0);
2631 }
2632
2633 /*-----------------------------------------------------------------*/
2634 /* genGetHbit - generates code get highest order bit               */
2635 /*-----------------------------------------------------------------*/
2636 static void genGetHbit (iCode *ic)
2637 {
2638         operand *left, *result;
2639         int size, offset ;
2640
2641         left = IC_LEFT(ic);
2642         result=IC_RESULT(ic);
2643         aopOp (left,ic,FALSE);
2644         aopOp (result,ic,FALSE);
2645
2646         size = AOP_SIZE(result);
2647         if (!sameRegs(AOP(left),AOP(result))) {
2648                 emitcode("clr","%s",aopGet(AOP(result),size -1));
2649                 emitcode("sbrc","%s,7",aopGet(AOP(left),size -1));
2650                 emitcode("subi","%s,lo8(-1)",aopGet(AOP(result),size-1));
2651         } else {
2652                 emitcode("clr","r0");
2653                 emitcode("sbrc","%s,7",aopGet(AOP(left),size-1));
2654                 emitcode("subi","r0,lo8(-1)");
2655                 aopPut(AOP(result),"r0",0);
2656         }
2657         offset = 1;
2658         size --;        
2659         while (size--) {
2660                 emitcode("clr",aopGet(AOP(result),offset++));
2661         }
2662         freeAsmop(left,NULL,ic,TRUE);
2663         freeAsmop(result,NULL,ic,TRUE);
2664 }
2665
2666 /*-----------------------------------------------------------------*/
2667 /* genShiftLeftLit - shift left by a known amount                  */
2668 /*-----------------------------------------------------------------*/
2669 static void genShiftLeftLit (iCode *ic)
2670 {
2671         operand *left,*right, *result;
2672         int size , shCount, offset =0;
2673         int lByteZ=0;
2674
2675         right = IC_RIGHT(ic);
2676         left  = IC_LEFT(ic);
2677         result = IC_RESULT(ic);
2678
2679         aopOp(left,ic,FALSE);
2680         aopOp(result,ic,FALSE);
2681         size = AOP_SIZE(result);
2682         shCount = (int)floatFromVal (AOP(right)->aopu.aop_lit);
2683
2684         if (shCount > (size*8 -1)) {
2685                 while (size--) aopPut(AOP(result),zero,offset++);
2686                 goto release;
2687         }
2688         switch(size) {
2689         case 1:
2690                 if (!sameRegs(AOP(left),AOP(result)))
2691                         aopPut(AOP(result),aopGet(AOP(left),0),0);
2692                 if (shCount >= 4) {
2693                         emitcode("swap","%s",aopGet(AOP(result),0));
2694                         emitcode("andi","%s,0xf0");
2695                         shCount -= 4;
2696                 }
2697                 if (shCount == 1) {
2698                         emitcode("add","%s,%s",aopGet(AOP(result),0),aopGet(AOP(result),0));
2699                         shCount--;
2700                 }
2701                 while (shCount--)
2702                         emitcode("lsl","%s",aopGet(AOP(result),0));
2703                 break;
2704         case 2:
2705                 if (shCount >= 12) {
2706                         aopPut(AOP(result),aopGet(AOP(left),0),1);
2707                         aopPut(AOP(result),zero,0);
2708                         emitcode("swap","%s",aopGet(AOP(result),1));
2709                         emitcode("andi","%s,0xf0",aopGet(AOP(result),1));
2710                         shCount -= 12;
2711                         lByteZ = 1;
2712                 }
2713                 if (shCount >= 8) {
2714                         aopPut(AOP(result),aopGet(AOP(left),0),1);
2715                         aopPut(AOP(result),zero,0);
2716                         shCount -= 8;
2717                         lByteZ = 1;
2718                 }
2719                 if (shCount >= 4) {
2720                         if (lByteZ) {
2721                                 emitcode("swap","%s",aopGet(AOP(result),1));
2722                                 emitcode("andi","%s,0xf0",aopGet(AOP(result),1));
2723                                 shCount -= 4;                           
2724                         } else {
2725                                 int ssh;
2726                                 shCount -= 4;
2727                                 ssh = shCount;
2728                                 if (sameRegs(AOP(left),AOP(result))) {
2729                                         emitcode("mov","r1,%s",aopGet(AOP(left),0));
2730                                         emitcode("swap","%s",aopGet(AOP(left),0));
2731                                         emitcode("andi","%s,0xf0",aopGet(AOP(left),0));
2732                                         emitcode("andi","r1,0x0f");
2733                                         while(shCount--) {
2734                                                 emitcode("lsl","%s",aopGet(AOP(left),0));
2735                                                 emitcode("lsl","r1");
2736                                         }
2737                                         emitcode("swap","%s",aopGet(AOP(result),1));
2738                                         emitcode("andi","%s,0xf0",aopGet(AOP(result),1));
2739                                         while (ssh--) emitcode("lsl","%s",aopGet(AOP(result),1));
2740                                         emitcode("or","%s,r1",aopGet(AOP(result),1));
2741                                         shCount =0;
2742                                 } else {
2743                                         MOVR0(aopGet(AOP(left),0));
2744                                         emitcode("mov","r1,r0");
2745                                         emitcode("swap","r0");
2746                                         emitcode("andi","r0,0xf0");
2747                                         emitcode("andi","r1,0x0f");
2748                                         while(shCount--) {
2749                                                 emitcode("lsl","r0");
2750                                                 emitcode("lsl","r1");
2751                                         }
2752                                         aopPut(AOP(result),"r0",0);
2753                                         aopPut(AOP(result),aopGet(AOP(left),1),1);
2754                                         emitcode("swap","%s",aopGet(AOP(result),1));
2755                                         emitcode("andi","%s,0xf0",aopGet(AOP(result),1));
2756                                         while (ssh--) emitcode("lsl","%s",aopGet(AOP(result),1));
2757                                         emitcode("or","%s,r1",aopGet(AOP(result),1));
2758                                         shCount =0;
2759                                 }
2760                         }
2761                 }
2762                 if (!lByteZ && !sameRegs(AOP(result),AOP(left)) && shCount) {
2763                         offset = 0;
2764                         while(size--) {
2765                                 aopPut(AOP(result),aopGet(AOP(left),offset),offset);
2766                                 offset++;
2767                         }
2768                 }
2769                 while (shCount--) {
2770                         if (lByteZ) {
2771                                 emitcode("lsl","%s",aopGet(AOP(result),1));
2772                         } else {
2773                                 emitcode("lsl","%s",aopGet(AOP(result),0));
2774                                 emitcode("rol","%s",aopGet(AOP(result),1));
2775                         }
2776                 }
2777                 break;
2778         case 3:
2779                 assert("shifting generic pointer ?\n");
2780                 break;
2781         case 4:
2782                 /* 32 bits we do only byte boundaries */
2783                 if (shCount >= 24) {
2784                         aopPut(AOP(result),aopGet(AOP(left),0),3);
2785                         aopPut(AOP(result),zero,2);
2786                         aopPut(AOP(result),zero,1);
2787                         aopPut(AOP(result),zero,0);
2788                         lByteZ = 3;
2789                         shCount -= 24;
2790                 }
2791                 if (shCount >= 16) {
2792                         aopPut(AOP(result),aopGet(AOP(left),0),3);
2793                         aopPut(AOP(result),aopGet(AOP(left),1),2);
2794                         aopPut(AOP(result),zero,1);
2795                         aopPut(AOP(result),zero,0);
2796                         lByteZ = 2;
2797                         shCount -= 16;
2798                 }
2799                 if (shCount >= 8) {
2800                         aopPut(AOP(result),aopGet(AOP(left),0),3);
2801                         aopPut(AOP(result),aopGet(AOP(left),1),2);
2802                         aopPut(AOP(result),aopGet(AOP(left),2),1);
2803                         aopPut(AOP(result),zero,0);
2804                         shCount -= 8;
2805                         lByteZ = 1;
2806                 }
2807                 if (!lByteZ && !sameRegs(AOP(left),AOP(right))) {
2808                         offset = 0;
2809                         while (size--) {
2810                                 aopPut(AOP(result),aopGet(AOP(left),offset),offset);
2811                                 offset++;
2812                         }
2813                         offset = 0;
2814                         size = AOP_SIZE(result);
2815                 }
2816                 if (shCount) {
2817                         switch (lByteZ) {
2818                         case 0:
2819                                 while (shCount--) {
2820                                         emitcode("lsl","%s",aopGet(AOP(result),0));
2821                                         emitcode("rol","%s",aopGet(AOP(result),1));
2822                                         emitcode("rol","%s",aopGet(AOP(result),2));
2823                                         emitcode("rol","%s",aopGet(AOP(result),3));
2824                                 }
2825                                 break;
2826                         case 1:
2827                                 while (shCount--) {
2828                                         emitcode("lsl","%s",aopGet(AOP(result),1));
2829                                         emitcode("rol","%s",aopGet(AOP(result),2));
2830                                         emitcode("rol","%s",aopGet(AOP(result),3));
2831                                 }
2832                                 break;
2833                         case 2:
2834                                 while (shCount--) {
2835                                         emitcode("lsl","%s",aopGet(AOP(result),2));
2836                                         emitcode("rol","%s",aopGet(AOP(result),3));
2837                                 }
2838                                 break;
2839                         case 3:
2840                                 while (shCount--) {
2841                                         emitcode("lsl","%s",aopGet(AOP(result),3));
2842                                 }
2843                                 break;
2844                         }
2845                 }
2846
2847         }
2848
2849  release:       
2850         freeAsmop(left,NULL,ic,TRUE);
2851         freeAsmop(right,NULL,ic,TRUE);
2852         freeAsmop(result,NULL,ic,TRUE);
2853 }
2854
2855 /*-----------------------------------------------------------------*/
2856 /* genLeftShift - generates code for left shifting                 */
2857 /*-----------------------------------------------------------------*/
2858 static void genLeftShift (iCode *ic)
2859 {
2860         operand *left,*right, *result;
2861         int size, offset;
2862         char *l;
2863         symbol *tlbl , *tlbl1;
2864
2865         right = IC_RIGHT(ic);
2866         left  = IC_LEFT(ic);
2867         result = IC_RESULT(ic);
2868
2869         aopOp(right,ic,FALSE);
2870
2871         if (AOP_TYPE(right) == AOP_LIT) {
2872                 genShiftLeftLit(ic);
2873                 return ;
2874         }
2875
2876         /* unknown count */
2877         aopOp(left,ic,FALSE);
2878         aopOp(result,ic,FALSE);
2879         size = AOP_SIZE(result);
2880         offset = 0;
2881         if (AOP_SIZE(right) > 1) {
2882                 if (isRegPair(AOP(right))) {
2883                         emitcode("movw","r24,%s",aopGet(AOP(right),0));
2884                 } else {
2885                         emitcode("mov","r24,%s",aopGet(AOP(right),0));
2886                         emitcode("mov","r25,%s",aopGet(AOP(right),1));
2887                 }
2888         } else {
2889                 emitcode("mov","r24,%s",aopGet(AOP(right),0));
2890         }
2891         if (!sameRegs(AOP(left),AOP(result))) {
2892                 while (size--) {
2893                         aopPut(AOP(result),aopGet(AOP(left),offset),offset);
2894                         offset++;
2895                 }
2896                 size = AOP_SIZE(result);
2897         }
2898         tlbl = newiTempLabel(NULL);
2899         emitcode("","L%05d:",tlbl->key);
2900         offset = 0;
2901         while (size--) {
2902                 if (offset) emitcode("rol","%s",aopGet(AOP(result),offset));
2903                 else emitcode("lsl","%s",aopGet(AOP(result),0));
2904                 offset++;
2905         }
2906         if (AOP_SIZE(right) > 1) emitcode("sbiw","r24,1");
2907         else emitcode("dec","r24");
2908         emitcode("brne","L%05d",tlbl->key);
2909         
2910  release:
2911         freeAsmop(left,NULL,ic,TRUE);
2912         freeAsmop(right,NULL,ic,TRUE);
2913         freeAsmop(result,NULL,ic,TRUE);
2914 }
2915
2916 /*-----------------------------------------------------------------*/
2917 /* genRightShift - generate code for right shifting                */
2918 /*-----------------------------------------------------------------*/
2919 static void genRightShift (iCode *ic)
2920 {
2921         operand *right, *left, *result;
2922         link *retype ;
2923         int size, offset;
2924         char *l;
2925         symbol *tlbl, *tlbl1 ;
2926
2927
2928  release:
2929         freeAsmop(left,NULL,ic,TRUE);
2930         freeAsmop(result,NULL,ic,TRUE);
2931 }
2932
2933 /*-----------------------------------------------------------------*/
2934 /* genUnpackBits - generates code for unpacking bits               */
2935 /*-----------------------------------------------------------------*/
2936 static void genUnpackBits (operand *result, char *rname, int ptype)
2937 {    
2938         int shCnt ;
2939         int rlen = 0 ;
2940         link *etype;
2941         int offset = 0 ;
2942
2943         etype = getSpec(operandType(result));
2944
2945         /* read the first byte  */
2946         switch (ptype) {
2947
2948         case POINTER:
2949         case IPOINTER:
2950                 emitcode("mov","a,@%s",rname);
2951                 break;
2952         
2953         case PPOINTER:
2954                 emitcode("movx","a,@%s",rname);
2955                 break;
2956         
2957         case FPOINTER:
2958                 emitcode("movx","a,@dptr");
2959                 break;
2960
2961         case CPOINTER:
2962                 emitcode("clr","a");
2963                 emitcode("movc","a","@a+dptr");
2964                 break;
2965
2966         case GPOINTER:
2967                 emitcode("lcall","__gptrget");
2968                 break;
2969         }
2970
2971         /* if we have bitdisplacement then it fits   */
2972         /* into this byte completely or if length is */
2973         /* less than a byte                          */
2974         if ((shCnt = SPEC_BSTR(etype)) || 
2975             (SPEC_BLEN(etype) <= 8))  {
2976
2977                                 /* shift right acc */
2978                 //              AccRsh(shCnt);
2979
2980                 emitcode("anl","a,#0x%02x",
2981                          ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
2982                 aopPut(AOP(result),"a",offset);
2983                 return ;
2984         }
2985
2986         /* bit field did not fit in a byte  */
2987         rlen = SPEC_BLEN(etype) - 8;
2988         aopPut(AOP(result),"a",offset++);
2989
2990         while (1)  {
2991
2992                 switch (ptype) {
2993                 case POINTER:
2994                 case IPOINTER:
2995                         emitcode("inc","%s",rname);
2996                         emitcode("mov","a,@%s",rname);
2997                         break;
2998             
2999                 case PPOINTER:
3000                         emitcode("inc","%s",rname);
3001                         emitcode("movx","a,@%s",rname);
3002                         break;
3003
3004                 case FPOINTER:
3005                         emitcode("inc","dptr");
3006                         emitcode("movx","a,@dptr");
3007                         break;
3008             
3009                 case CPOINTER:
3010                         emitcode("clr","a");
3011                         emitcode("inc","dptr");
3012                         emitcode("movc","a","@a+dptr");
3013                         break;
3014             
3015                 case GPOINTER:
3016                         emitcode("inc","dptr");
3017                         emitcode("lcall","__gptrget");
3018                         break;
3019                 }
3020
3021                 rlen -= 8;            
3022                                 /* if we are done */
3023                 if ( rlen <= 0 )
3024                         break ;
3025         
3026                 aopPut(AOP(result),"a",offset++);
3027                               
3028         }
3029     
3030         if (rlen) {
3031                 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
3032                 aopPut(AOP(result),"a",offset);        
3033         }
3034     
3035         return ;
3036 }
3037
3038
3039 /*-----------------------------------------------------------------*/
3040 /* genDataPointerGet - generates code when ptr offset is known     */
3041 /*-----------------------------------------------------------------*/
3042 static void genDataPointerGet (operand *left, 
3043                                operand *result, 
3044                                iCode *ic)
3045 {
3046         char *l;
3047         char buffer[256];
3048         int size , offset = 0;
3049         aopOp(result,ic,TRUE);
3050
3051         /* get the string representation of the name */
3052         l = aopGet(AOP(left),0);
3053         size = AOP_SIZE(result);
3054         while (size--) {
3055                 if (offset)
3056                         sprintf(buffer,"(%s + %d)",l+1,offset);
3057                 else
3058                         sprintf(buffer,"%s",l+1);
3059                 aopPut(AOP(result),buffer,offset++);
3060         }
3061
3062         freeAsmop(left,NULL,ic,TRUE);
3063         freeAsmop(result,NULL,ic,TRUE);
3064 }
3065
3066 /*-----------------------------------------------------------------*/
3067 /* genNearPointerGet - emitcode for near pointer fetch             */
3068 /*-----------------------------------------------------------------*/
3069 static void genNearPointerGet (operand *left, 
3070                                operand *result, 
3071                                iCode *ic)
3072 {
3073         asmop *aop = NULL;
3074         regs *preg = NULL ;
3075         char *rname ;
3076         link *rtype, *retype;
3077         link *ltype = operandType(left);    
3078         char buffer[80];
3079
3080         rtype = operandType(result);
3081         retype= getSpec(rtype);
3082     
3083         aopOp(left,ic,FALSE);
3084     
3085         /* if left is rematerialisable and
3086            result is not bit variable type and
3087            the left is pointer to data space i.e
3088            lower 128 bytes of space */
3089         if (AOP_TYPE(left) == AOP_IMMD &&
3090             !IS_BITVAR(retype)         &&
3091             DCL_TYPE(ltype) == POINTER) {
3092                 genDataPointerGet (left,result,ic);
3093                 return ;
3094         }
3095     
3096         /* if the value is already in a pointer register
3097            then don't need anything more */
3098         if (!AOP_INPREG(AOP(left))) {
3099                                 /* otherwise get a free pointer register */
3100                 aop = newAsmop(0);
3101                 preg = getFreePtr(ic,&aop,FALSE,0);
3102                 emitcode("mov","%s,%s",
3103                          preg->name,
3104                          aopGet(AOP(left),0));
3105                 rname = preg->name ;
3106         } else
3107                 rname = aopGet(AOP(left),0);
3108     
3109         freeAsmop(left,NULL,ic,TRUE);
3110         aopOp (result,ic,FALSE);
3111     
3112         /* if bitfield then unpack the bits */
3113         if (IS_BITVAR(retype)) 
3114                 genUnpackBits (result,rname,POINTER);
3115         else {
3116                                 /* we have can just get the values */
3117                 int size = AOP_SIZE(result);
3118                 int offset = 0 ;        
3119         
3120                 while (size--) {
3121                         if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
3122
3123                                 emitcode("mov","a,@%s",rname);
3124                                 aopPut(AOP(result),"a",offset);
3125                         } else {
3126                                 sprintf(buffer,"@%s",rname);
3127                                 aopPut(AOP(result),buffer,offset);
3128                         }
3129                         offset++ ;
3130                         if (size)
3131                                 emitcode("inc","%s",rname);
3132                 }
3133         }
3134
3135         /* now some housekeeping stuff */
3136         if (aop) {
3137                                 /* we had to allocate for this iCode */
3138                 freeAsmop(NULL,aop,ic,TRUE);
3139         } else { 
3140                                 /* we did not allocate which means left
3141                                    already in a pointer register, then
3142                                    if size > 0 && this could be used again
3143                                    we have to point it back to where it 
3144                                    belongs */
3145                 if (AOP_SIZE(result) > 1 &&
3146                     !OP_SYMBOL(left)->remat &&
3147                     ( OP_SYMBOL(left)->liveTo > ic->seq ||
3148                       ic->depth )) {
3149                         int size = AOP_SIZE(result) - 1;
3150                         while (size--)
3151                                 emitcode("dec","%s",rname);
3152                 }
3153         }
3154
3155         /* done */
3156         freeAsmop(result,NULL,ic,TRUE);
3157      
3158 }
3159
3160 /*-----------------------------------------------------------------*/
3161 /* genPagedPointerGet - emitcode for paged pointer fetch           */
3162 /*-----------------------------------------------------------------*/
3163 static void genPagedPointerGet (operand *left, 
3164                                 operand *result, 
3165                                 iCode *ic)
3166 {
3167         asmop *aop = NULL;
3168         regs *preg = NULL ;
3169         char *rname ;
3170         link *rtype, *retype;    
3171
3172         rtype = operandType(result);
3173         retype= getSpec(rtype);
3174     
3175         aopOp(left,ic,FALSE);
3176
3177         /* if the value is already in a pointer register
3178            then don't need anything more */
3179         if (!AOP_INPREG(AOP(left))) {
3180                                 /* otherwise get a free pointer register */
3181                 aop = newAsmop(0);
3182                 preg = getFreePtr(ic,&aop,FALSE,0);
3183                 emitcode("mov","%s,%s",
3184                          preg->name,
3185                          aopGet(AOP(left),0));
3186                 rname = preg->name ;
3187         } else
3188                 rname = aopGet(AOP(left),0);
3189     
3190         freeAsmop(left,NULL,ic,TRUE);
3191         aopOp (result,ic,FALSE);
3192
3193         /* if bitfield then unpack the bits */
3194         if (IS_BITVAR(retype)) 
3195                 genUnpackBits (result,rname,PPOINTER);
3196         else {
3197                                 /* we have can just get the values */
3198                 int size = AOP_SIZE(result);
3199                 int offset = 0 ;        
3200         
3201                 while (size--) {
3202             
3203                         emitcode("movx","a,@%s",rname);
3204                         aopPut(AOP(result),"a",offset);
3205             
3206                         offset++ ;
3207             
3208                         if (size)
3209                                 emitcode("inc","%s",rname);
3210                 }
3211         }
3212
3213         /* now some housekeeping stuff */
3214         if (aop) {
3215                                 /* we had to allocate for this iCode */
3216                 freeAsmop(NULL,aop,ic,TRUE);
3217         } else { 
3218                                 /* we did not allocate which means left
3219                                    already in a pointer register, then
3220                                    if size > 0 && this could be used again
3221                                    we have to point it back to where it 
3222                                    belongs */
3223                 if (AOP_SIZE(result) > 1 &&
3224                     !OP_SYMBOL(left)->remat &&
3225                     ( OP_SYMBOL(left)->liveTo > ic->seq ||
3226                       ic->depth )) {
3227                         int size = AOP_SIZE(result) - 1;
3228                         while (size--)
3229                                 emitcode("dec","%s",rname);
3230                 }
3231         }
3232
3233         /* done */
3234         freeAsmop(result,NULL,ic,TRUE);
3235     
3236         
3237 }
3238
3239 /*-----------------------------------------------------------------*/
3240 /* genFarPointerGet - gget value from far space                    */
3241 /*-----------------------------------------------------------------*/
3242 static void genFarPointerGet (operand *left,
3243                               operand *result, iCode *ic)
3244 {
3245         int size, offset ;
3246         link *retype = getSpec(operandType(result));
3247
3248         aopOp(left,ic,FALSE);
3249
3250         /* if the operand is already in dptr 
3251            then we do nothing else we move the value to dptr */
3252         if (AOP_TYPE(left) != AOP_STR) {
3253                                 /* if this is remateriazable */
3254                 if (AOP_TYPE(left) == AOP_IMMD)
3255                         emitcode("mov","dptr,%s",aopGet(AOP(left),0));
3256                 else { /* we need to get it byte by byte */
3257                         emitcode("mov","dpl,%s",aopGet(AOP(left),0));
3258                         emitcode("mov","dph,%s",aopGet(AOP(left),1));
3259                         if (options.model == MODEL_FLAT24)
3260                                 {
3261                                         emitcode("mov", "dpx,%s",aopGet(AOP(left),2));
3262                                 }
3263                 }
3264         }
3265         /* so dptr know contains the address */
3266         freeAsmop(left,NULL,ic,TRUE);
3267         aopOp(result,ic,FALSE);
3268
3269         /* if bit then unpack */
3270         if (IS_BITVAR(retype)) 
3271                 genUnpackBits(result,"dptr",FPOINTER);
3272         else {
3273                 size = AOP_SIZE(result);
3274                 offset = 0 ;
3275
3276                 while (size--) {
3277                         emitcode("movx","a,@dptr");
3278                         aopPut(AOP(result),"a",offset++);
3279                         if (size)
3280                                 emitcode("inc","dptr");
3281                 }
3282         }
3283
3284         freeAsmop(result,NULL,ic,TRUE);
3285 }
3286
3287 /*-----------------------------------------------------------------*/
3288 /* emitcodePointerGet - gget value from code space                  */
3289 /*-----------------------------------------------------------------*/
3290 static void emitcodePointerGet (operand *left,
3291                                 operand *result, iCode *ic)
3292 {
3293         int size, offset ;
3294         link *retype = getSpec(operandType(result));
3295
3296         aopOp(left,ic,FALSE);
3297
3298         /* if the operand is already in dptr 
3299            then we do nothing else we move the value to dptr */
3300         if (AOP_TYPE(left) != AOP_STR) {
3301                                 /* if this is remateriazable */
3302                 if (AOP_TYPE(left) == AOP_IMMD)
3303                         emitcode("mov","dptr,%s",aopGet(AOP(left),0));
3304                 else { /* we need to get it byte by byte */
3305                         emitcode("mov","dpl,%s",aopGet(AOP(left),0));
3306                         emitcode("mov","dph,%s",aopGet(AOP(left),1));
3307                         if (options.model == MODEL_FLAT24)
3308                                 {
3309                                         emitcode("mov", "dpx,%s",aopGet(AOP(left),2));
3310                                 }
3311                 }
3312         }
3313         /* so dptr know contains the address */
3314         freeAsmop(left,NULL,ic,TRUE);
3315         aopOp(result,ic,FALSE);
3316
3317         /* if bit then unpack */
3318         if (IS_BITVAR(retype)) 
3319                 genUnpackBits(result,"dptr",CPOINTER);
3320         else {
3321                 size = AOP_SIZE(result);
3322                 offset = 0 ;
3323
3324                 while (size--) {
3325                         emitcode("clr","a");
3326                         emitcode("movc","a,@a+dptr");
3327                         aopPut(AOP(result),"a",offset++);
3328                         if (size)
3329                                 emitcode("inc","dptr");
3330                 }
3331         }
3332
3333         freeAsmop(result,NULL,ic,TRUE);
3334 }
3335
3336 /*-----------------------------------------------------------------*/
3337 /* genGenPointerGet - gget value from generic pointer space        */
3338 /*-----------------------------------------------------------------*/
3339 static void genGenPointerGet (operand *left,
3340                               operand *result, iCode *ic)
3341 {
3342         int size, offset ;
3343         link *retype = getSpec(operandType(result));
3344
3345         aopOp(left,ic,FALSE);
3346
3347         /* if the operand is already in dptr 
3348            then we do nothing else we move the value to dptr */
3349         if (AOP_TYPE(left) != AOP_STR) {
3350                                 /* if this is remateriazable */
3351                 if (AOP_TYPE(left) == AOP_IMMD) {
3352                         emitcode("mov","dptr,%s",aopGet(AOP(left),0));
3353                         emitcode("mov","b,#%d",pointerCode(retype));
3354                 }
3355                 else { /* we need to get it byte by byte */
3356                         emitcode("mov","dpl,%s",aopGet(AOP(left),0));
3357                         emitcode("mov","dph,%s",aopGet(AOP(left),1));
3358                         if (options.model == MODEL_FLAT24)
3359                                 {
3360                                         emitcode("mov", "dpx,%s",aopGet(AOP(left),2));
3361                                         emitcode("mov","b,%s",aopGet(AOP(left),3));
3362                                 }
3363                         else
3364                                 {
3365                                         emitcode("mov","b,%s",aopGet(AOP(left),2));
3366                                 }
3367                 }
3368         }
3369         /* so dptr know contains the address */
3370         freeAsmop(left,NULL,ic,TRUE);
3371         aopOp(result,ic,FALSE); 
3372
3373         /* if bit then unpack */
3374         if (IS_BITVAR(retype)) 
3375                 genUnpackBits(result,"dptr",GPOINTER);
3376         else {
3377                 size = AOP_SIZE(result);
3378                 offset = 0 ;
3379
3380                 while (size--) {
3381                         emitcode("lcall","__gptrget");
3382                         aopPut(AOP(result),"a",offset++);
3383                         if (size)
3384                                 emitcode("inc","dptr");
3385                 }
3386         }
3387
3388         freeAsmop(result,NULL,ic,TRUE);
3389 }
3390
3391 /*-----------------------------------------------------------------*/
3392 /* genPointerGet - generate code for pointer get                   */
3393 /*-----------------------------------------------------------------*/
3394 static void genPointerGet (iCode *ic)
3395 {
3396         operand *left, *result ;
3397         link *type, *etype;
3398         int p_type;
3399
3400         left = IC_LEFT(ic);
3401         result = IC_RESULT(ic) ;
3402
3403         /* depending on the type of pointer we need to
3404            move it to the correct pointer register */
3405         type = operandType(left);
3406         etype = getSpec(type);
3407         /* if left is of type of pointer then it is simple */
3408         if (IS_PTR(type) && !IS_FUNC(type->next)) 
3409                 p_type = DCL_TYPE(type);
3410         else {
3411                                 /* we have to go by the storage class */
3412                 p_type = PTR_TYPE(SPEC_OCLS(etype));
3413
3414                                 /*      if (SPEC_OCLS(etype)->codesp ) { */
3415                                 /*          p_type = CPOINTER ;  */
3416                                 /*      } */
3417                                 /*      else */
3418                                 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
3419                                 /*              p_type = FPOINTER ; */
3420                                 /*          else */
3421                                 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
3422                                 /*                  p_type = PPOINTER; */
3423                                 /*              else */
3424                                 /*                  if (SPEC_OCLS(etype) == idata ) */
3425                                 /*                      p_type = IPOINTER; */
3426                                 /*                  else */
3427                                 /*                      p_type = POINTER ; */
3428         }
3429
3430         /* now that we have the pointer type we assign
3431            the pointer values */
3432         switch (p_type) {
3433
3434         case POINTER:   
3435         case IPOINTER:
3436                 genNearPointerGet (left,result,ic);
3437                 break;
3438
3439         case PPOINTER:
3440                 genPagedPointerGet(left,result,ic);
3441                 break;
3442
3443         case FPOINTER:
3444                 genFarPointerGet (left,result,ic);
3445                 break;
3446
3447         case CPOINTER:
3448                 emitcodePointerGet (left,result,ic);
3449                 break;
3450
3451         case GPOINTER:
3452                 genGenPointerGet (left,result,ic);
3453                 break;
3454         }
3455
3456 }
3457
3458 /*-----------------------------------------------------------------*/
3459 /* genPackBits - generates code for packed bit storage             */
3460 /*-----------------------------------------------------------------*/
3461 static void genPackBits (link    *etype ,
3462                          operand *right ,
3463                          char *rname, int p_type)
3464 {
3465         int shCount = 0 ;
3466         int offset = 0  ;
3467         int rLen = 0 ;
3468         int blen, bstr ;   
3469         char *l ;
3470
3471         blen = SPEC_BLEN(etype);
3472         bstr = SPEC_BSTR(etype);
3473
3474         l = aopGet(AOP(right),offset++);
3475         MOVA(l);   
3476
3477         /* if the bit lenth is less than or    */
3478         /* it exactly fits a byte then         */
3479         if (SPEC_BLEN(etype) <= 8 )  {
3480                 shCount = SPEC_BSTR(etype) ;
3481
3482                                 /* shift left acc */
3483                 //              AccLsh(shCount);
3484
3485                 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
3486
3487
3488                         switch (p_type) {
3489                         case POINTER:
3490                                 emitcode ("mov","b,a");
3491                                 emitcode("mov","a,@%s",rname);
3492                                 break;
3493
3494                         case FPOINTER:
3495                                 emitcode ("mov","b,a");
3496                                 emitcode("movx","a,@dptr");
3497                                 break;
3498
3499                         case GPOINTER:
3500                                 emitcode ("push","b");
3501                                 emitcode ("push","acc");
3502                                 emitcode ("lcall","__gptrget");
3503                                 emitcode ("pop","b");
3504                                 break;
3505                         }
3506
3507                         emitcode ("anl","a,#0x%02x",(unsigned char)
3508                                   ((unsigned char)(0xFF << (blen+bstr)) | 
3509                                    (unsigned char)(0xFF >> (8-bstr)) ) );
3510                         emitcode ("orl","a,b");
3511                         if (p_type == GPOINTER)
3512                                 emitcode("pop","b");
3513                 }
3514         }
3515
3516         switch (p_type) {
3517         case POINTER:
3518                 emitcode("mov","@%s,a",rname);
3519                 break;
3520
3521         case FPOINTER:
3522                 emitcode("movx","@dptr,a");
3523                 break;
3524
3525         case GPOINTER:
3526                 emitcode("lcall","__gptrput");
3527                 break;
3528         }
3529
3530         /* if we r done */
3531         if ( SPEC_BLEN(etype) <= 8 )
3532                 return ;
3533
3534         emitcode("inc","%s",rname);
3535         rLen = SPEC_BLEN(etype) ;     
3536
3537         /* now generate for lengths greater than one byte */
3538         while (1) {
3539
3540                 l = aopGet(AOP(right),offset++);
3541
3542                 rLen -= 8 ;
3543                 if (rLen <= 0 )
3544                         break ;
3545
3546                 switch (p_type) {
3547                 case POINTER:
3548                         if (*l == '@') {
3549                                 MOVA(l);
3550                                 emitcode("mov","@%s,a",rname);
3551                         } else
3552                                 emitcode("mov","@%s,%s",rname,l);
3553                         break;
3554
3555                 case FPOINTER:
3556                         MOVA(l);
3557                         emitcode("movx","@dptr,a");
3558                         break;
3559
3560                 case GPOINTER:
3561                         MOVA(l);
3562                         emitcode("lcall","__gptrput");
3563                         break;  
3564                 }   
3565                 emitcode ("inc","%s",rname);
3566         }
3567
3568         MOVA(l);
3569
3570         /* last last was not complete */
3571         if (rLen)   {
3572                                 /* save the byte & read byte */
3573                 switch (p_type) {
3574                 case POINTER:
3575                         emitcode ("mov","b,a");
3576                         emitcode("mov","a,@%s",rname);
3577                         break;
3578
3579                 case FPOINTER:
3580                         emitcode ("mov","b,a");
3581                         emitcode("movx","a,@dptr");
3582                         break;
3583
3584                 case GPOINTER:
3585                         emitcode ("push","b");
3586                         emitcode ("push","acc");
3587                         emitcode ("lcall","__gptrget");
3588                         emitcode ("pop","b");
3589                         break;
3590                 }
3591
3592                 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
3593                 emitcode ("orl","a,b");
3594         }
3595
3596         if (p_type == GPOINTER)
3597                 emitcode("pop","b");
3598
3599         switch (p_type) {
3600
3601         case POINTER:
3602                 emitcode("mov","@%s,a",rname);
3603                 break;
3604         
3605         case FPOINTER:
3606                 emitcode("movx","@dptr,a");
3607                 break;
3608         
3609         case GPOINTER:
3610                 emitcode("lcall","__gptrput");
3611                 break;                  
3612         }
3613 }
3614 /*-----------------------------------------------------------------*/
3615 /* genDataPointerSet - remat pointer to data space                 */
3616 /*-----------------------------------------------------------------*/
3617 static void genDataPointerSet(operand *right,
3618                               operand *result,
3619                               iCode *ic)
3620 {
3621         int size, offset = 0 ;
3622         char *l, buffer[256];
3623
3624         aopOp(right,ic,FALSE);
3625     
3626         l = aopGet(AOP(result),0);
3627         size = AOP_SIZE(right);
3628         while (size--) {
3629                 if (offset)
3630                         sprintf(buffer,"(%s + %d)",l+1,offset);
3631                 else
3632                         sprintf(buffer,"%s",l+1);
3633                 emitcode("mov","%s,%s",buffer,
3634                          aopGet(AOP(right),offset++));
3635         }
3636
3637         freeAsmop(right,NULL,ic,TRUE);
3638         freeAsmop(result,NULL,ic,TRUE);
3639 }
3640
3641 /*-----------------------------------------------------------------*/
3642 /* genNearPointerSet - emitcode for near pointer put                */
3643 /*-----------------------------------------------------------------*/
3644 static void genNearPointerSet (operand *right,
3645                                operand *result, 
3646                                iCode *ic)
3647 {
3648         asmop *aop = NULL;
3649         regs *preg = NULL ;
3650         char *rname , *l;
3651         link *retype;
3652         link *ptype = operandType(result);
3653     
3654         retype= getSpec(operandType(right));
3655
3656         aopOp(result,ic,FALSE);
3657     
3658         /* if the result is rematerializable &
3659            in data space & not a bit variable */
3660         if (AOP_TYPE(result) == AOP_IMMD &&
3661             DCL_TYPE(ptype) == POINTER   &&
3662             !IS_BITVAR(retype)) {
3663                 genDataPointerSet (right,result,ic);
3664                 return;
3665         }
3666
3667         /* if the value is already in a pointer register
3668            then don't need anything more */
3669         if (!AOP_INPREG(AOP(result))) {
3670                                 /* otherwise get a free pointer register */
3671                 aop = newAsmop(0);
3672                 preg = getFreePtr(ic,&aop,FALSE,0);
3673                 emitcode("mov","%s,%s",
3674                          preg->name,
3675                          aopGet(AOP(result),0));
3676                 rname = preg->name ;
3677         } else
3678                 rname = aopGet(AOP(result),0);
3679
3680         freeAsmop(result,NULL,ic,TRUE);
3681         aopOp (right,ic,FALSE);
3682
3683         /* if bitfield then unpack the bits */
3684         if (IS_BITVAR(retype)) 
3685                 genPackBits (retype,right,rname,POINTER);
3686         else {
3687                                 /* we have can just get the values */
3688                 int size = AOP_SIZE(right);
3689                 int offset = 0 ;    
3690
3691                 while (size--) {
3692                         l = aopGet(AOP(right),offset);
3693                         if (*l == '@' ) {
3694                                 MOVA(l);
3695                                 emitcode("mov","@%s,a",rname);
3696                         } else
3697                                 emitcode("mov","@%s,%s",rname,l);
3698                         if (size)
3699                                 emitcode("inc","%s",rname);
3700                         offset++;
3701                 }
3702         }
3703
3704         /* now some housekeeping stuff */
3705         if (aop) {
3706                                 /* we had to allocate for this iCode */
3707                 freeAsmop(NULL,aop,ic,TRUE);
3708         } else { 
3709                                 /* we did not allocate which means left
3710                                    already in a pointer register, then
3711                                    if size > 0 && this could be used again
3712                                    we have to point it back to where it 
3713                                    belongs */
3714                 if (AOP_SIZE(right) > 1 &&
3715                     !OP_SYMBOL(result)->remat &&
3716                     ( OP_SYMBOL(result)->liveTo > ic->seq ||
3717                       ic->depth )) {
3718                         int size = AOP_SIZE(right) - 1;
3719                         while (size--)
3720                                 emitcode("dec","%s",rname);
3721                 }
3722         }
3723
3724         /* done */
3725         freeAsmop(right,NULL,ic,TRUE);
3726
3727
3728 }
3729
3730 /*-----------------------------------------------------------------*/
3731 /* genPagedPointerSet - emitcode for Paged pointer put             */
3732 /*-----------------------------------------------------------------*/
3733 static void genPagedPointerSet (operand *right,
3734                                 operand *result, 
3735                                 iCode *ic)
3736 {
3737         asmop *aop = NULL;
3738         regs *preg = NULL ;
3739         char *rname , *l;
3740         link *retype;
3741        
3742         retype= getSpec(operandType(right));
3743     
3744         aopOp(result,ic,FALSE);
3745     
3746         /* if the value is already in a pointer register
3747            then don't need anything more */
3748         if (!AOP_INPREG(AOP(result))) {
3749                                 /* otherwise get a free pointer register */
3750                 aop = newAsmop(0);
3751                 preg = getFreePtr(ic,&aop,FALSE,0);
3752                 emitcode("mov","%s,%s",
3753                          preg->name,
3754                          aopGet(AOP(result),0));
3755                 rname = preg->name ;
3756         } else
3757                 rname = aopGet(AOP(result),0);
3758     
3759         freeAsmop(result,NULL,ic,TRUE);
3760         aopOp (right,ic,FALSE);
3761
3762         /* if bitfield then unpack the bits */
3763         if (IS_BITVAR(retype)) 
3764                 genPackBits (retype,right,rname,PPOINTER);
3765         else {
3766                                 /* we have can just get the values */
3767                 int size = AOP_SIZE(right);
3768                 int offset = 0 ;        
3769         
3770                 while (size--) {
3771                         l = aopGet(AOP(right),offset);
3772             
3773                         MOVA(l);
3774                         emitcode("movx","@%s,a",rname);
3775
3776                         if (size)
3777                                 emitcode("inc","%s",rname);
3778
3779                         offset++;
3780                 }
3781         }
3782     
3783         /* now some housekeeping stuff */
3784         if (aop) {
3785                                 /* we had to allocate for this iCode */
3786                 freeAsmop(NULL,aop,ic,TRUE);
3787         } else { 
3788                                 /* we did not allocate which means left
3789                                    already in a pointer register, then
3790                                    if size > 0 && this could be used again
3791                                    we have to point it back to where it 
3792                                    belongs */
3793                 if (AOP_SIZE(right) > 1 &&
3794                     !OP_SYMBOL(result)->remat &&
3795                     ( OP_SYMBOL(result)->liveTo > ic->seq ||
3796                       ic->depth )) {
3797                         int size = AOP_SIZE(right) - 1;
3798                         while (size--)
3799                                 emitcode("dec","%s",rname);
3800                 }
3801         }
3802
3803         /* done */
3804         freeAsmop(right,NULL,ic,TRUE);
3805     
3806         
3807 }
3808
3809 /*-----------------------------------------------------------------*/
3810 /* genFarPointerSet - set value from far space                     */
3811 /*-----------------------------------------------------------------*/
3812 static void genFarPointerSet (operand *right,
3813                               operand *result, iCode *ic)
3814 {
3815         int size, offset ;
3816         link *retype = getSpec(operandType(right));
3817
3818         aopOp(result,ic,FALSE);
3819
3820         /* if the operand is already in dptr 
3821            then we do nothing else we move the value to dptr */
3822         if (AOP_TYPE(result) != AOP_STR) {
3823                                 /* if this is remateriazable */
3824                 if (AOP_TYPE(result) == AOP_IMMD)
3825                         emitcode("mov","dptr,%s",aopGet(AOP(result),0));
3826                 else { /* we need to get it byte by byte */
3827                         emitcode("mov","dpl,%s",aopGet(AOP(result),0));
3828                         emitcode("mov","dph,%s",aopGet(AOP(result),1));
3829                         if (options.model == MODEL_FLAT24)
3830                                 {
3831                                         emitcode("mov", "dpx,%s",aopGet(AOP(result),2));
3832                                 }
3833                 }
3834         }
3835         /* so dptr know contains the address */
3836         freeAsmop(result,NULL,ic,TRUE);
3837         aopOp(right,ic,FALSE);
3838
3839         /* if bit then unpack */
3840         if (IS_BITVAR(retype)) 
3841                 genPackBits(retype,right,"dptr",FPOINTER);
3842         else {
3843                 size = AOP_SIZE(right);
3844                 offset = 0 ;
3845
3846                 while (size--) {
3847                         char *l = aopGet(AOP(right),offset++);
3848                         MOVA(l);
3849                         emitcode("movx","@dptr,a");
3850                         if (size)
3851                                 emitcode("inc","dptr");
3852                 }
3853         }
3854
3855         freeAsmop(right,NULL,ic,TRUE);
3856 }
3857
3858 /*-----------------------------------------------------------------*/
3859 /* genGenPointerSet - set value from generic pointer space         */
3860 /*-----------------------------------------------------------------*/
3861 static void genGenPointerSet (operand *right,
3862                               operand *result, iCode *ic)
3863 {
3864         int size, offset ;
3865         link *retype = getSpec(operandType(right));
3866
3867         aopOp(result,ic,FALSE);
3868
3869         /* if the operand is already in dptr 
3870            then we do nothing else we move the value to dptr */
3871         if (AOP_TYPE(result) != AOP_STR) {
3872                                 /* if this is remateriazable */
3873                 if (AOP_TYPE(result) == AOP_IMMD) {
3874                         emitcode("mov","dptr,%s",aopGet(AOP(result),0));
3875                         emitcode("mov","b,%s + 1",aopGet(AOP(result),0));
3876                 }
3877                 else { /* we need to get it byte by byte */
3878                         emitcode("mov","dpl,%s",aopGet(AOP(result),0));
3879                         emitcode("mov","dph,%s",aopGet(AOP(result),1));
3880                         if (options.model == MODEL_FLAT24)
3881                                 {
3882                                         emitcode("mov", "dpx,%s",aopGet(AOP(result),2));
3883                                         emitcode("mov","b,%s",aopGet(AOP(result),3));
3884                                 }
3885                         else
3886                                 {
3887                                         emitcode("mov","b,%s",aopGet(AOP(result),2));
3888                                 }
3889                 }
3890         }
3891         /* so dptr know contains the address */
3892         freeAsmop(result,NULL,ic,TRUE);
3893         aopOp(right,ic,FALSE);
3894
3895         /* if bit then unpack */
3896         if (IS_BITVAR(retype)) 
3897                 genPackBits(retype,right,"dptr",GPOINTER);
3898         else {
3899                 size = AOP_SIZE(right);
3900                 offset = 0 ;
3901
3902                 while (size--) {
3903                         char *l = aopGet(AOP(right),offset++);
3904                         MOVA(l);
3905                         emitcode("lcall","__gptrput");
3906                         if (size)
3907                                 emitcode("inc","dptr");
3908                 }
3909         }
3910
3911         freeAsmop(right,NULL,ic,TRUE);
3912 }
3913
3914 /*-----------------------------------------------------------------*/
3915 /* genPointerSet - stores the value into a pointer location        */
3916 /*-----------------------------------------------------------------*/
3917 static void genPointerSet (iCode *ic)
3918 {    
3919         operand *right, *result ;
3920         link *type, *etype;
3921         int p_type;
3922
3923         right = IC_RIGHT(ic);
3924         result = IC_RESULT(ic) ;
3925
3926         /* depending on the type of pointer we need to
3927            move it to the correct pointer register */
3928         type = operandType(result);
3929         etype = getSpec(type);
3930         /* if left is of type of pointer then it is simple */
3931         if (IS_PTR(type) && !IS_FUNC(type->next)) {
3932                 p_type = DCL_TYPE(type);
3933         }
3934         else {
3935                                 /* we have to go by the storage class */
3936                 p_type = PTR_TYPE(SPEC_OCLS(etype));
3937
3938                                 /*      if (SPEC_OCLS(etype)->codesp ) { */
3939                                 /*          p_type = CPOINTER ;  */
3940                                 /*      } */
3941                                 /*      else */
3942                                 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
3943                                 /*              p_type = FPOINTER ; */
3944                                 /*          else */
3945                                 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
3946                                 /*                  p_type = PPOINTER ; */
3947                                 /*              else */
3948                                 /*                  if (SPEC_OCLS(etype) == idata ) */
3949                                 /*                      p_type = IPOINTER ; */
3950                                 /*                  else */
3951                                 /*                      p_type = POINTER ; */
3952         }
3953
3954         /* now that we have the pointer type we assign
3955            the pointer values */
3956         switch (p_type) {
3957
3958         case POINTER:
3959         case IPOINTER:
3960                 genNearPointerSet (right,result,ic);
3961                 break;
3962
3963         case PPOINTER:
3964                 genPagedPointerSet (right,result,ic);
3965                 break;
3966
3967         case FPOINTER:
3968                 genFarPointerSet (right,result,ic);
3969                 break;
3970
3971         case GPOINTER:
3972                 genGenPointerSet (right,result,ic);
3973                 break;
3974         }
3975
3976 }
3977
3978 /*-----------------------------------------------------------------*/
3979 /* genIfx - generate code for Ifx statement                        */
3980 /*-----------------------------------------------------------------*/
3981 static void genIfx (iCode *ic, iCode *popIc)
3982 {
3983         operand *cond = IC_COND(ic);
3984         int isbit =0;
3985
3986         aopOp(cond,ic,FALSE);
3987
3988         /* get the value into acc */
3989         if (AOP_TYPE(cond) != AOP_CRY)
3990                 toBoolean(cond,"",0);
3991         else
3992                 isbit = 1;
3993         /* the result is now in the accumulator */
3994         freeAsmop(cond,NULL,ic,TRUE);
3995
3996         /* if there was something to be popped then do it */
3997         if (popIc)
3998                 genIpop(popIc);
3999
4000         /* if the condition is  a bit variable */
4001         /*     if (isbit && IS_ITEMP(cond) && SPIL_LOC(cond)) { */
4002         /*      //      genIfxJump(ic,SPIL_LOC(cond)->rname); */
4003                         /*     } */
4004                         /*     else */
4005                         /*      if (isbit && !IS_ITEMP(cond)) */
4006                         /*              //          genIfxJump(ic,OP_SYMBOL(cond)->rname); */
4007                         /*      else */
4008                         /*              // genIfxJump(ic,"a"); */
4009
4010                         ic->generated = 1;
4011 }
4012
4013 /*-----------------------------------------------------------------*/
4014 /* genAddrOf - generates code for address of                       */
4015 /*-----------------------------------------------------------------*/
4016 static void genAddrOf (iCode *ic)
4017 {
4018         symbol *sym = OP_SYMBOL(IC_LEFT(ic));
4019         int size, offset ;
4020
4021         aopOp(IC_RESULT(ic),ic,FALSE);
4022
4023         /* if the operand is on the stack then we 
4024            need to get the stack offset of this
4025            variable */
4026         if (sym->onStack) {
4027                                 /* if it has an offset then we need to compute
4028                                    it */
4029                 if (sym->stack) {
4030                         emitcode("mov","a,_bp");
4031                         emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
4032                         aopPut(AOP(IC_RESULT(ic)),"a",0);       
4033                 } else {
4034                         /* we can just move _bp */
4035                         aopPut(AOP(IC_RESULT(ic)),"_bp",0);
4036                 }
4037                                 /* fill the result with zero */
4038                 size = AOP_SIZE(IC_RESULT(ic)) - 1;
4039         
4040         
4041                 if (options.stack10bit && size < (FPTRSIZE - 1))
4042                         {
4043                                 fprintf(stderr, 
4044                                         "*** warning: pointer to stack var truncated.\n");
4045                         }
4046         
4047                 offset = 1;
4048                 while (size--)
4049                         {
4050                                 /* Yuck! */
4051                                 if (options.stack10bit && offset == 2)
4052                                         {
4053                                                 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
4054                                         }
4055                                 else
4056                                         {
4057                                                 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
4058                                         }
4059                         }
4060
4061                 goto release;
4062         }
4063
4064         /* object not on stack then we need the name */
4065         size = AOP_SIZE(IC_RESULT(ic));
4066         offset = 0;
4067
4068         while (size--) {
4069                 char s[SDCC_NAME_MAX];
4070                 if (offset) 
4071                         sprintf(s,"#(%s >> %d)",
4072                                 sym->rname,
4073                                 offset*8);
4074                 else
4075                         sprintf(s,"#%s",sym->rname);
4076                 aopPut(AOP(IC_RESULT(ic)),s,offset++);
4077         }
4078
4079  release:
4080         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
4081
4082 }
4083
4084 /*-----------------------------------------------------------------*/
4085 /* genFarFarAssign - assignment when both are in far space         */
4086 /*-----------------------------------------------------------------*/
4087 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
4088 {
4089         int size = AOP_SIZE(right);
4090         int offset = 0;
4091         char *l ;
4092         /* first push the right side on to the stack */
4093         while (size--) {
4094                 l = aopGet(AOP(right),offset++);
4095                 MOVA(l);
4096                 emitcode ("push","acc");
4097         }
4098     
4099         freeAsmop(right,NULL,ic,FALSE);
4100         /* now assign DPTR to result */
4101         aopOp(result,ic,FALSE);
4102         size = AOP_SIZE(result);
4103         while (size--) {
4104                 emitcode ("pop","acc");
4105                 aopPut(AOP(result),"a",--offset);
4106         }
4107         freeAsmop(result,NULL,ic,FALSE);
4108         
4109 }
4110
4111 /*-----------------------------------------------------------------*/
4112 /* genAssign - generate code for assignment                        */
4113 /*-----------------------------------------------------------------*/
4114 static void genAssign (iCode *ic)
4115 {
4116         operand *result, *right;
4117         int size, offset ;
4118         unsigned long lit = 0L;
4119
4120         result = IC_RESULT(ic);
4121         right  = IC_RIGHT(ic) ;
4122
4123         /* if they are the same */
4124         if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
4125                 return ;
4126
4127         aopOp(right,ic,FALSE);
4128     
4129         /* special case both in far space */
4130         if (AOP_TYPE(right) == AOP_DPTR &&
4131             IS_TRUE_SYMOP(result)       &&
4132             isOperandInFarSpace(result)) {
4133         
4134                 genFarFarAssign (result,right,ic);
4135                 return ;
4136         }
4137
4138         aopOp(result,ic,TRUE);
4139
4140         /* if they are the same registers */
4141         if (sameRegs(AOP(right),AOP(result)))
4142                 goto release;
4143
4144         /* if the result is a bit */
4145         if (AOP_TYPE(result) == AOP_CRY) {
4146
4147                                 /* if the right size is a literal then
4148                                    we know what the value is */
4149                 if (AOP_TYPE(right) == AOP_LIT) {
4150                         if (((int) operandLitValue(right))) 
4151                                 aopPut(AOP(result),one,0);
4152                         else
4153                                 aopPut(AOP(result),zero,0);
4154                         goto release;
4155                 }
4156
4157                                 /* the right is also a bit variable */
4158                 if (AOP_TYPE(right) == AOP_CRY) {
4159                         emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4160                         aopPut(AOP(result),"c",0);
4161                         goto release ;
4162                 }
4163
4164                                 /* we need to or */
4165                 toBoolean(right,"",0);
4166                 aopPut(AOP(result),"a",0);
4167                 goto release ;
4168         }
4169
4170         /* bit variables done */
4171         /* general case */
4172         size = AOP_SIZE(result);
4173         offset = 0 ;
4174         if(AOP_TYPE(right) == AOP_LIT)
4175                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4176         if((size > 1) &&
4177            (AOP_TYPE(result) != AOP_REG) &&
4178            (AOP_TYPE(right) == AOP_LIT) &&
4179            !IS_FLOAT(operandType(right)) &&
4180            (lit < 256L)){
4181                 emitcode("clr","a");
4182                 while (size--) {
4183                         if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
4184                                 aopPut(AOP(result),"a",size);
4185                         else
4186                                 aopPut(AOP(result),
4187                                        aopGet(AOP(right),size),
4188                                        size);
4189                 }
4190         } else {
4191                 while (size--) {
4192                         aopPut(AOP(result),
4193                                aopGet(AOP(right),offset),
4194                                offset);
4195                         offset++;
4196                 }
4197         }
4198     
4199  release:
4200         freeAsmop (right,NULL,ic,FALSE);
4201         freeAsmop (result,NULL,ic,TRUE);
4202 }   
4203
4204 /*-----------------------------------------------------------------*/
4205 /* genJumpTab - genrates code for jump table                       */
4206 /*-----------------------------------------------------------------*/
4207 static void genJumpTab (iCode *ic)
4208 {
4209         symbol *jtab;
4210         char *l;
4211
4212         aopOp(IC_JTCOND(ic),ic,FALSE);
4213         /* get the condition into accumulator */
4214         l = aopGet(AOP(IC_JTCOND(ic)),0);
4215         MOVA(l);
4216         /* multiply by three */
4217         emitcode("add","a,acc");
4218         emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0));
4219         freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
4220
4221         jtab = newiTempLabel(NULL);
4222         emitcode("mov","dptr,#%05d$",jtab->key+100);
4223         emitcode("jmp","@a+dptr");
4224         emitcode("","%05d$:",jtab->key+100);
4225         /* now generate the jump labels */
4226         for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
4227              jtab = setNextItem(IC_JTLABELS(ic)))
4228                 emitcode("ljmp","%05d$",jtab->key+100);
4229
4230 }
4231
4232 /*-----------------------------------------------------------------*/
4233 /* genCast - gen code for casting                                  */
4234 /*-----------------------------------------------------------------*/
4235 static void genCast (iCode *ic)
4236 {
4237         operand *result = IC_RESULT(ic);
4238         link *ctype = operandType(IC_LEFT(ic));
4239         link *rtype = operandType(IC_RIGHT(ic));
4240         operand *right = IC_RIGHT(ic);
4241         int size, offset ;
4242
4243         /* if they are equivalent then do nothing */
4244         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
4245                 return ;
4246
4247         aopOp(right,ic,FALSE) ;
4248         aopOp(result,ic,FALSE);
4249
4250         /* if the result is a bit */
4251         if (AOP_TYPE(result) == AOP_CRY) {
4252                                 /* if the right size is a literal then
4253                                    we know what the value is */
4254                 if (AOP_TYPE(right) == AOP_LIT) {
4255                         if (((int) operandLitValue(right))) 
4256                                 aopPut(AOP(result),one,0);
4257                         else
4258                                 aopPut(AOP(result),zero,0);
4259
4260                         goto release;
4261                 }
4262
4263                                 /* the right is also a bit variable */
4264                 if (AOP_TYPE(right) == AOP_CRY) {
4265                         emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4266                         aopPut(AOP(result),"c",0);
4267                         goto release ;
4268                 }
4269
4270                                 /* we need to or */
4271                 toBoolean(right,"",0);
4272                 aopPut(AOP(result),"a",0);
4273                 goto release ;
4274         }
4275
4276         /* if they are the same size : or less */
4277         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
4278
4279                                 /* if they are in the same place */
4280                 if (sameRegs(AOP(right),AOP(result)))
4281                         goto release;
4282
4283                                 /* if they in different places then copy */
4284                 size = AOP_SIZE(result);
4285                 offset = 0 ;
4286                 while (size--) {
4287                         aopPut(AOP(result),
4288                                aopGet(AOP(right),offset),
4289                                offset);
4290                         offset++;
4291                 }
4292                 goto release;
4293         }
4294
4295
4296         /* if the result is of type pointer */
4297         if (IS_PTR(ctype)) {
4298
4299                 int p_type;
4300                 link *type = operandType(right);
4301                 link *etype = getSpec(type);
4302
4303                                 /* pointer to generic pointer */
4304                 if (IS_GENPTR(ctype)) {
4305                         char *l = zero;
4306             
4307                         if (IS_PTR(type)) 
4308                                 p_type = DCL_TYPE(type);
4309                         else {
4310                                 /* we have to go by the storage class */
4311                                 p_type = PTR_TYPE(SPEC_OCLS(etype));
4312                         }
4313                 
4314                         /* the first two bytes are known */
4315                         size = GPTRSIZE - 1; 
4316                         offset = 0 ;
4317                         while (size--) {
4318                                 aopPut(AOP(result),
4319                                        aopGet(AOP(right),offset),
4320                                        offset);
4321                                 offset++;
4322                         }
4323                         /* the last byte depending on type */
4324                         switch (p_type) {
4325                         case IPOINTER:
4326                         case POINTER:
4327                                 l = zero;
4328                                 break;
4329                         case FPOINTER:
4330                                 l = one;
4331                                 break;
4332                         case CPOINTER:
4333                                 l = "#0x02";
4334                                 break;                          
4335                         case PPOINTER:
4336                                 l = "#0x03";
4337                                 break;
4338                 
4339                         default:
4340                                 /* this should never happen */
4341                                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
4342                                        "got unknown pointer type");
4343                                 exit(1);
4344                         }
4345                         aopPut(AOP(result),l, GPTRSIZE - 1);        
4346                         goto release ;
4347                 }
4348         
4349                                 /* just copy the pointers */
4350                 size = AOP_SIZE(result);
4351                 offset = 0 ;
4352                 while (size--) {
4353                         aopPut(AOP(result),
4354                                aopGet(AOP(right),offset),
4355                                offset);
4356                         offset++;
4357                 }
4358                 goto release ;
4359         }
4360     
4361         /* so we now know that the size of destination is greater
4362            than the size of the source */
4363         /* we move to result for the size of source */
4364         size = AOP_SIZE(right);
4365         offset = 0 ;
4366         while (size--) {
4367                 aopPut(AOP(result),
4368                        aopGet(AOP(right),offset),
4369                        offset);
4370                 offset++;
4371         }
4372
4373         /* now depending on the sign of the source && destination */
4374         size = AOP_SIZE(result) - AOP_SIZE(right);
4375         /* if unsigned or not an integral type */
4376         if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
4377                 while (size--)
4378                         aopPut(AOP(result),zero,offset++);
4379         } else {
4380                                 /* we need to extend the sign :{ */
4381                 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1);
4382                 MOVA(l);
4383                 emitcode("rlc","a");
4384                 emitcode("subb","a,acc");
4385                 while (size--)
4386                         aopPut(AOP(result),"a",offset++);   
4387         }
4388
4389         /* we are done hurray !!!! */
4390
4391  release:
4392         freeAsmop(right,NULL,ic,TRUE);
4393         freeAsmop(result,NULL,ic,TRUE);
4394
4395 }
4396
4397 /*-----------------------------------------------------------------*/
4398 /* genDjnz - generate decrement & jump if not zero instrucion      */
4399 /*-----------------------------------------------------------------*/
4400 static int genDjnz (iCode *ic, iCode *ifx)
4401 {
4402         symbol *lbl, *lbl1;
4403         if (!ifx)
4404                 return 0;
4405     
4406         /* if the if condition has a false label
4407            then we cannot save */
4408         if (IC_FALSE(ifx))
4409                 return 0;
4410
4411         /* if the minus is not of the form 
4412            a = a - 1 */
4413         if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
4414             !IS_OP_LITERAL(IC_RIGHT(ic)))
4415                 return 0;
4416
4417         if (operandLitValue(IC_RIGHT(ic)) != 1)
4418                 return 0;
4419
4420         /* if the size of this greater than one then no
4421            saving */
4422         if (getSize(operandType(IC_RESULT(ic))) > 1)
4423                 return 0;
4424
4425         /* otherwise we can save BIG */
4426         lbl = newiTempLabel(NULL);
4427         lbl1= newiTempLabel(NULL);
4428
4429         aopOp(IC_RESULT(ic),ic,FALSE);
4430     
4431         if (IS_AOP_PREG(IC_RESULT(ic))) {
4432                 emitcode("dec","%s",
4433                          aopGet(AOP(IC_RESULT(ic)),0));
4434                 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0));
4435                 emitcode("jnz","%05d$",lbl->key+100);
4436         } else {        
4437                 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0),
4438                           lbl->key+100);
4439         }
4440         emitcode ("sjmp","%05d$",lbl1->key+100);
4441         emitcode ("","%05d$:",lbl->key+100);
4442         emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4443         emitcode ("","%05d$:",lbl1->key+100);
4444     
4445         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
4446         ifx->generated = 1;
4447         return 1;
4448 }
4449
4450 static char *recvregs[8] = 
4451 {
4452         "r16","r17","r18","r19","r20","r21","r22","r23"
4453 };
4454 static recvCnt = 0;
4455
4456 /*-----------------------------------------------------------------*/
4457 /* genReceive - generate code for a receive iCode                  */
4458 /*-----------------------------------------------------------------*/
4459 static void genReceive (iCode *ic)
4460 {    
4461         int size , offset =0;
4462         aopOp(IC_RESULT(ic),ic,FALSE);  
4463         size = AOP_SIZE(IC_RESULT(ic));
4464         while (size--) {
4465                 aopPut(AOP(IC_RESULT(ic)),recvregs[recvCnt++],offset);
4466                 offset++;
4467         }
4468         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
4469 }
4470
4471 /*-----------------------------------------------------------------*/
4472 /* gen51Code - generate code for 8051 based controllers            */
4473 /*-----------------------------------------------------------------*/
4474 void genAVRCode (iCode *lic)
4475 {
4476         iCode *ic;
4477         int cln = 0;
4478
4479         lineHead = lineCurr = NULL;
4480         recvCnt =0;
4481         /* print the allocation information */
4482         if (allocInfo)
4483                 printAllocInfo( currFunc, codeOutFile);
4484         /* if debug information required */
4485         /*     if (options.debug && currFunc) { */
4486         if (currFunc) {
4487                 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
4488                 _G.debugLine = 1;
4489                 if (IS_STATIC(currFunc->etype))
4490                         emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name); 
4491                 else
4492                         emitcode("","G$%s$0$0 ==.",currFunc->name);
4493                 _G.debugLine = 0;
4494         }
4495         /* stack pointer name */
4496         if (options.useXstack)
4497                 spname = "_spx";
4498         else
4499                 spname = "sp";
4500     
4501  
4502         for (ic = lic ; ic ; ic = ic->next ) {
4503         
4504                 if ( cln != ic->lineno ) {
4505                         if ( options.debug ) {
4506                                 _G.debugLine = 1;
4507                                 emitcode("","C$%s$%d$%d$%d ==.",
4508                                          ic->filename,ic->lineno,
4509                                          ic->level,ic->block);
4510                                 _G.debugLine = 0;
4511                         }
4512                         emitcode(";","%s %d",ic->filename,ic->lineno);
4513                         cln = ic->lineno ;
4514                 }
4515                                 /* if the result is marked as
4516                                    spilt and rematerializable or code for
4517                                    this has already been generated then
4518                                    do nothing */
4519                 if (resultRemat(ic) || ic->generated ) 
4520                         continue ;
4521         
4522                                 /* depending on the operation */
4523                 switch (ic->op) {
4524                 case '!' :
4525                         genNot(ic);
4526                         break;
4527             
4528                 case '~' :
4529                         genCpl(ic);
4530                         break;
4531             
4532                 case UNARYMINUS:
4533                         genUminus (ic);
4534                         break;
4535             
4536                 case IPUSH:
4537                         genIpush (ic);
4538                         break;
4539             
4540                 case IPOP:
4541                         /* IPOP happens only when trying to restore a 
4542                            spilt live range, if there is an ifx statement
4543                            following this pop then the if statement might
4544                            be using some of the registers being popped which
4545                            would destory the contents of the register so
4546                            we need to check for this condition and handle it */
4547                         if (ic->next            && 
4548                             ic->next->op == IFX &&
4549                             regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
4550                                 genIfx (ic->next,ic);
4551                         else
4552                                 genIpop (ic);
4553                         break; 
4554             
4555                 case CALL:
4556                         genCall (ic);
4557                         break;
4558             
4559                 case PCALL:
4560                         genPcall (ic);
4561                         break;
4562             
4563                 case FUNCTION:
4564                         genFunction (ic);
4565                         break;
4566             
4567                 case ENDFUNCTION:
4568                         genEndFunction (ic);
4569                         break;
4570             
4571                 case RETURN:
4572                         genRet (ic);
4573                         break;
4574             
4575                 case LABEL:
4576                         genLabel (ic);
4577                         break;
4578             
4579                 case GOTO:
4580                         genGoto (ic);
4581                         break;
4582             
4583                 case '+' :
4584                         genPlus (ic) ;
4585                         break;
4586             
4587                 case '-' :
4588                         if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
4589                                 genMinus (ic);
4590                         break;
4591             
4592                 case '*' :
4593                         genMult (ic);
4594                         break;
4595             
4596                 case '/' :
4597                         genDiv (ic) ;
4598                         break;
4599             
4600                 case '%' :
4601                         genMod (ic);
4602                         break;
4603             
4604                 case '>' :
4605                         genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                     
4606                         break;
4607             
4608                 case '<' :
4609                         genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
4610                         break;
4611             
4612                 case LE_OP:
4613                         genCmpLe (ic,ifxForOp(IC_RESULT(ic),ic));
4614                         break;
4615
4616                 case GE_OP:
4617                         genCmpGe (ic,ifxForOp(IC_RESULT(ic),ic));
4618                         break;
4619
4620                 case NE_OP:
4621                         genCmpNe (ic,ifxForOp(IC_RESULT(ic),ic));           
4622                         break;  
4623             
4624                 case EQ_OP:
4625                         genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
4626                         break;      
4627             
4628                 case AND_OP:
4629                         genAndOp (ic);
4630                         break;
4631             
4632                 case OR_OP:
4633                         genOrOp (ic);
4634                         break;
4635             
4636                 case '^' :
4637                         genXor (ic,ifxForOp(IC_RESULT(ic),ic));
4638                         break;
4639             
4640                 case '|' :
4641                         genOr (ic,ifxForOp(IC_RESULT(ic),ic));
4642                         break;
4643             
4644                 case BITWISEAND:
4645                         genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
4646                         break;
4647             
4648                 case INLINEASM:
4649                         genInline (ic);
4650                         break;
4651             
4652                 case RRC:
4653                         genRRC (ic);
4654                         break;
4655             
4656                 case RLC:
4657                         genRLC (ic);
4658                         break;
4659             
4660                 case GETHBIT:
4661                         genGetHbit (ic);
4662                         break;
4663             
4664                 case LEFT_OP:
4665                         genLeftShift (ic);
4666                         break;
4667             
4668                 case RIGHT_OP:
4669                         genRightShift (ic);
4670                         break;
4671             
4672                 case GET_VALUE_AT_ADDRESS:
4673                         genPointerGet(ic);
4674                         break;
4675             
4676                 case '=' :
4677                         if (POINTER_SET(ic))
4678                                 genPointerSet(ic);
4679                         else
4680                                 genAssign(ic);
4681                         break;
4682             
4683                 case IFX:
4684                         genIfx (ic,NULL);
4685                         break;
4686             
4687                 case ADDRESS_OF:
4688                         genAddrOf (ic);
4689                         break;
4690             
4691                 case JUMPTABLE:
4692                         genJumpTab (ic);
4693                         break;
4694             
4695                 case CAST:
4696                         genCast (ic);
4697                         break;
4698             
4699                 case RECEIVE:
4700                         genReceive(ic);
4701                         break;
4702             
4703                 case SEND:
4704                         addSet(&_G.sendSet,ic);
4705                         break;
4706
4707                 default :
4708                         ic = ic;
4709                         /*      piCode(ic,stdout); */
4710             
4711                 }
4712         }
4713     
4714
4715         /* now we are ready to call the 
4716            peep hole optimizer */
4717         if (!options.nopeep)
4718                 peepHole (&lineHead);
4719
4720         /* now do the actual printing */
4721         printLine (lineHead,codeOutFile);    
4722         return;
4723 }