Intermediate commit for AVR
[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
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
2323 /*-----------------------------------------------------------------*/
2324 /* genAnd  - code for and                                          */
2325 /*-----------------------------------------------------------------*/
2326 static void genAnd (iCode *ic, iCode *ifx)
2327 {
2328     operand *left, *right, *result;
2329     int size, offset=0;
2330     char *l;
2331
2332     aopOp((left = IC_LEFT(ic)),ic,FALSE);
2333     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2334     aopOp((result=IC_RESULT(ic)),ic,TRUE);
2335     
2336     size = AOP_SIZE(left);
2337     offset = 0;
2338     if (ifx) { /* used only for jumps */
2339         if (AOP_TYPE(right) == AOP_LIT) {
2340             int p2 = powof2((int) floatFromVal (AOP(right)->aopu.aop_lit));
2341             if (p2) { /* right side is a power of 2 */
2342                 l = aopGet(AOP(left),p2 / 8);
2343                 if (IC_TRUE(ifx)) {
2344                         emitcode("sbrc","%s,%d",l,(p2 % 8));
2345                         emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2346                 } else {
2347                         emitcode("sbrs","%s,%d",l,(p2 % 8));
2348                         emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2349                 }
2350             } else { /* right not power of two */
2351                     while (size--) {
2352                     }    
2353             }
2354         } else { /* right is not a literal */
2355         }
2356     } else { /* other jump -> result goes to register*/
2357     }
2358
2359 release :
2360     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2361     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2362     freeAsmop(result,NULL,ic,TRUE);     
2363 }
2364
2365 /*-----------------------------------------------------------------*/
2366 /* genOr  - code for or                                            */
2367 /*-----------------------------------------------------------------*/
2368 static void genOr (iCode *ic, iCode *ifx)
2369 {
2370     operand *left, *right, *result;
2371     int size, offset=0;
2372     unsigned long lit = 0L;
2373
2374     aopOp((left = IC_LEFT(ic)),ic,FALSE);
2375     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2376     aopOp((result=IC_RESULT(ic)),ic,TRUE);
2377
2378
2379 release :
2380     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2381     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2382     freeAsmop(result,NULL,ic,TRUE);     
2383 }
2384
2385 /*-----------------------------------------------------------------*/
2386 /* genXor - code for xclusive or                                   */
2387 /*-----------------------------------------------------------------*/
2388 static void genXor (iCode *ic, iCode *ifx)
2389 {
2390     operand *left, *right, *result;
2391     int size, offset=0;
2392     unsigned long lit = 0L;
2393
2394     aopOp((left = IC_LEFT(ic)),ic,FALSE);
2395     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2396     aopOp((result=IC_RESULT(ic)),ic,TRUE);
2397
2398
2399
2400 release :
2401     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2402     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2403     freeAsmop(result,NULL,ic,TRUE);     
2404 }
2405
2406 /*-----------------------------------------------------------------*/
2407 /* genInline - write the inline code out                           */
2408 /*-----------------------------------------------------------------*/
2409 static void genInline (iCode *ic)
2410 {
2411     char buffer[MAX_INLINEASM];
2412     char *bp = buffer;
2413     char *bp1= buffer;
2414     
2415     _G.inLine += (!options.asmpeep);
2416     strcpy(buffer,IC_INLINE(ic));
2417
2418     /* emit each line as a code */
2419     while (*bp) {
2420         if (*bp == '\n') {
2421             *bp++ = '\0';
2422             emitcode(bp1,"");
2423             bp1 = bp;
2424         } else {
2425             if (*bp == ':') {
2426                 bp++;
2427                 *bp = '\0';
2428                 bp++;
2429                 emitcode(bp1,"");
2430                 bp1 = bp;
2431             } else
2432                 bp++;
2433         }
2434     }
2435     if (bp1 != bp)
2436         emitcode(bp1,"");
2437     /*     emitcode("",buffer); */
2438     _G.inLine -= (!options.asmpeep);
2439 }
2440
2441 /*-----------------------------------------------------------------*/
2442 /* genRRC - rotate right with carry                                */
2443 /*-----------------------------------------------------------------*/
2444 static void genRRC (iCode *ic)
2445 {
2446     operand *left , *result ;
2447     int size, offset = 0;
2448     char *l;    
2449
2450     /* rotate right with carry */
2451     left = IC_LEFT(ic);
2452     result=IC_RESULT(ic);
2453     aopOp (left,ic,FALSE);
2454     aopOp (result,ic,FALSE);
2455
2456     /* move it to the result */
2457     size = AOP_SIZE(result);    
2458     offset = size - 1 ;
2459
2460
2461     freeAsmop(left,NULL,ic,TRUE);
2462     freeAsmop(result,NULL,ic,TRUE);
2463 }
2464
2465 /*-----------------------------------------------------------------*/
2466 /* genRLC - generate code for rotate left with carry               */
2467 /*-----------------------------------------------------------------*/
2468 static void genRLC (iCode *ic)
2469 {    
2470     operand *left , *result ;
2471     int size, offset = 0;
2472     char *l;    
2473
2474     /* rotate right with carry */
2475     left = IC_LEFT(ic);
2476     result=IC_RESULT(ic);
2477     aopOp (left,ic,FALSE);
2478     aopOp (result,ic,FALSE);
2479
2480
2481     freeAsmop(left,NULL,ic,TRUE);
2482     freeAsmop(result,NULL,ic,TRUE);
2483 }
2484
2485 /*-----------------------------------------------------------------*/
2486 /* genGetHbit - generates code get highest order bit               */
2487 /*-----------------------------------------------------------------*/
2488 static void genGetHbit (iCode *ic)
2489 {
2490     operand *left, *result;
2491     left = IC_LEFT(ic);
2492     result=IC_RESULT(ic);
2493     aopOp (left,ic,FALSE);
2494     aopOp (result,ic,FALSE);
2495
2496
2497     freeAsmop(left,NULL,ic,TRUE);
2498     freeAsmop(result,NULL,ic,TRUE);
2499 }
2500
2501 /*-----------------------------------------------------------------*/
2502 /* AccRol - rotate left accumulator by known count                 */
2503 /*-----------------------------------------------------------------*/
2504 static void AccRol (int shCount)
2505 {
2506     shCount &= 0x0007;              // shCount : 0..7
2507     switch(shCount){
2508         case 0 :
2509             break;
2510         case 1 :
2511             emitcode("rl","a");
2512             break;
2513         case 2 :
2514             emitcode("rl","a");
2515             emitcode("rl","a");
2516             break;
2517         case 3 :
2518             emitcode("swap","a");
2519             emitcode("rr","a");
2520             break;
2521         case 4 :
2522             emitcode("swap","a");
2523             break;
2524         case 5 :
2525             emitcode("swap","a");
2526             emitcode("rl","a");
2527             break;
2528         case 6 :
2529             emitcode("rr","a");
2530             emitcode("rr","a");
2531             break;
2532         case 7 :
2533             emitcode("rr","a");
2534             break;
2535     }
2536 }
2537
2538 /*-----------------------------------------------------------------*/
2539 /* AccLsh - left shift accumulator by known count                  */
2540 /*-----------------------------------------------------------------*/
2541 static void AccLsh (int shCount)
2542 {
2543     if(shCount != 0){
2544         if(shCount == 1)
2545             emitcode("add","a,acc");
2546         else 
2547             if(shCount == 2) {
2548             emitcode("add","a,acc");
2549             emitcode("add","a,acc");
2550         } else {
2551             /* rotate left accumulator */
2552             AccRol(shCount);
2553             /* and kill the lower order bits */
2554             emitcode("anl","a,#0x%02x", SLMask[shCount]);
2555         }
2556     }
2557 }
2558
2559 /*-----------------------------------------------------------------*/
2560 /* AccRsh - right shift accumulator by known count                 */
2561 /*-----------------------------------------------------------------*/
2562 static void AccRsh (int shCount)
2563 {
2564     if(shCount != 0){
2565         if(shCount == 1){
2566             CLRC;
2567             emitcode("rrc","a");
2568         } else {
2569             /* rotate right accumulator */
2570             AccRol(8 - shCount);
2571             /* and kill the higher order bits */
2572             emitcode("anl","a,#0x%02x", SRMask[shCount]);
2573         }
2574     }
2575 }
2576
2577 /*-----------------------------------------------------------------*/
2578 /* AccSRsh - signed right shift accumulator by known count                 */
2579 /*-----------------------------------------------------------------*/
2580 static void AccSRsh (int shCount)
2581 {
2582     symbol *tlbl ;
2583     if(shCount != 0){
2584         if(shCount == 1){
2585             emitcode("mov","c,acc.7");
2586             emitcode("rrc","a");
2587         } else if(shCount == 2){
2588             emitcode("mov","c,acc.7");
2589             emitcode("rrc","a");
2590             emitcode("mov","c,acc.7");
2591             emitcode("rrc","a");
2592         } else {
2593             tlbl = newiTempLabel(NULL);
2594             /* rotate right accumulator */
2595             AccRol(8 - shCount);
2596             /* and kill the higher order bits */
2597             emitcode("anl","a,#0x%02x", SRMask[shCount]);
2598             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
2599             emitcode("orl","a,#0x%02x",
2600                      (unsigned char)~SRMask[shCount]);
2601             emitcode("","%05d$:",tlbl->key+100);
2602         }
2603     }
2604 }
2605
2606 /*-----------------------------------------------------------------*/
2607 /* shiftR1Left2Result - shift right one byte from left to result   */
2608 /*-----------------------------------------------------------------*/
2609 static void shiftR1Left2Result (operand *left, int offl,
2610                                 operand *result, int offr,
2611                                 int shCount, int sign)
2612 {
2613     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
2614     /* shift right accumulator */
2615     if(sign)
2616         AccSRsh(shCount);
2617     else
2618         AccRsh(shCount);
2619     aopPut(AOP(result),"a",offr);
2620 }
2621
2622 /*-----------------------------------------------------------------*/
2623 /* shiftL1Left2Result - shift left one byte from left to result    */
2624 /*-----------------------------------------------------------------*/
2625 static void shiftL1Left2Result (operand *left, int offl,
2626                                 operand *result, int offr, int shCount)
2627 {
2628     char *l;
2629     l = aopGet(AOP(left),offl);
2630     MOVA(l);
2631     /* shift left accumulator */
2632     AccLsh(shCount);
2633     aopPut(AOP(result),"a",offr);
2634 }
2635
2636 /*-----------------------------------------------------------------*/
2637 /* movLeft2Result - move byte from left to result                  */
2638 /*-----------------------------------------------------------------*/
2639 static void movLeft2Result (operand *left, int offl,
2640                             operand *result, int offr, int sign)
2641 {
2642     char *l;
2643     if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
2644         l = aopGet(AOP(left),offl);
2645
2646         if (*l == '@' && (IS_AOP_PREG(result))) {
2647             emitcode("mov","a,%s",l);
2648             aopPut(AOP(result),"a",offr);
2649         } else {
2650             if(!sign)
2651                 aopPut(AOP(result),l,offr);
2652             else{
2653                 /* MSB sign in acc.7 ! */
2654                 if(getDataSize(left) == offl+1){
2655                     emitcode("mov","a,%s",l);
2656                     aopPut(AOP(result),"a",offr);
2657                 }
2658             }
2659         }
2660     }
2661 }
2662
2663 /*-----------------------------------------------------------------*/
2664 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
2665 /*-----------------------------------------------------------------*/
2666 static void AccAXRrl1 (char *x)
2667 {
2668     emitcode("rrc","a");
2669     emitcode("xch","a,%s", x);
2670     emitcode("rrc","a");
2671     emitcode("xch","a,%s", x);
2672 }
2673
2674 /*-----------------------------------------------------------------*/
2675 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
2676 /*-----------------------------------------------------------------*/
2677 static void AccAXLrl1 (char *x)
2678 {
2679     emitcode("xch","a,%s",x);
2680     emitcode("rlc","a");
2681     emitcode("xch","a,%s",x);
2682     emitcode("rlc","a");
2683 }
2684
2685 /*-----------------------------------------------------------------*/
2686 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
2687 /*-----------------------------------------------------------------*/
2688 static void AccAXLsh1 (char *x)
2689 {
2690     emitcode("xch","a,%s",x);
2691     emitcode("add","a,acc");
2692     emitcode("xch","a,%s",x);
2693     emitcode("rlc","a");
2694 }
2695
2696 /*-----------------------------------------------------------------*/
2697 /* AccAXLsh - left shift a:x by known count (0..7)                 */
2698 /*-----------------------------------------------------------------*/
2699 static void AccAXLsh (char *x, int shCount)
2700 {
2701     switch(shCount){
2702         case 0 :
2703             break;
2704         case 1 :
2705             AccAXLsh1(x);
2706             break;
2707         case 2 :
2708             AccAXLsh1(x);
2709             AccAXLsh1(x);
2710             break;
2711         case 3 :
2712         case 4 :
2713         case 5 :                        // AAAAABBB:CCCCCDDD
2714             AccRol(shCount);            // BBBAAAAA:CCCCCDDD
2715             emitcode("anl","a,#0x%02x",
2716                      SLMask[shCount]);  // BBB00000:CCCCCDDD
2717             emitcode("xch","a,%s",x);   // CCCCCDDD:BBB00000
2718             AccRol(shCount);            // DDDCCCCC:BBB00000
2719             emitcode("xch","a,%s",x);   // BBB00000:DDDCCCCC
2720             emitcode("xrl","a,%s",x);   // (BBB^DDD)CCCCC:DDDCCCCC
2721             emitcode("xch","a,%s",x);   // DDDCCCCC:(BBB^DDD)CCCCC
2722             emitcode("anl","a,#0x%02x",
2723                      SLMask[shCount]);  // DDD00000:(BBB^DDD)CCCCC
2724             emitcode("xch","a,%s",x);   // (BBB^DDD)CCCCC:DDD00000
2725             emitcode("xrl","a,%s",x);   // BBBCCCCC:DDD00000            
2726             break;
2727         case 6 :                        // AAAAAABB:CCCCCCDD
2728             emitcode("anl","a,#0x%02x",
2729                      SRMask[shCount]);  // 000000BB:CCCCCCDD
2730             emitcode("mov","c,acc.0");  // c = B
2731             emitcode("xch","a,%s",x);   // CCCCCCDD:000000BB
2732             AccAXRrl1(x);               // BCCCCCCD:D000000B
2733             AccAXRrl1(x);               // BBCCCCCC:DD000000
2734             break;
2735         case 7 :                        // a:x <<= 7
2736             emitcode("anl","a,#0x%02x",
2737                      SRMask[shCount]);  // 0000000B:CCCCCCCD
2738             emitcode("mov","c,acc.0");  // c = B
2739             emitcode("xch","a,%s",x);   // CCCCCCCD:0000000B
2740             AccAXRrl1(x);               // BCCCCCCC:D0000000
2741             break;
2742         default :
2743             break;
2744     }
2745 }
2746
2747 /*-----------------------------------------------------------------*/
2748 /* AccAXRsh - right shift a:x known count (0..7)                   */
2749 /*-----------------------------------------------------------------*/
2750 static void AccAXRsh (char *x, int shCount)
2751 {   
2752     switch(shCount){
2753         case 0 :
2754             break;
2755         case 1 :
2756             CLRC;
2757             AccAXRrl1(x);               // 0->a:x
2758             break;
2759         case 2 :
2760             CLRC;
2761             AccAXRrl1(x);               // 0->a:x
2762             CLRC;
2763             AccAXRrl1(x);               // 0->a:x
2764             break;
2765         case 3 :
2766         case 4 :
2767         case 5 :                        // AAAAABBB:CCCCCDDD = a:x
2768             AccRol(8 - shCount);        // BBBAAAAA:DDDCCCCC
2769             emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
2770             AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
2771             emitcode("anl","a,#0x%02x",
2772                      SRMask[shCount]);  // 000CCCCC:BBBAAAAA
2773             emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
2774             emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
2775             emitcode("anl","a,#0x%02x",
2776                      SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
2777             emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
2778             emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
2779             emitcode("xch","a,%s",x);   // 000AAAAA:BBBCCCCC
2780             break;
2781         case 6 :                        // AABBBBBB:CCDDDDDD
2782             emitcode("mov","c,acc.7");
2783             AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
2784             AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
2785             emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
2786             emitcode("anl","a,#0x%02x",
2787                      SRMask[shCount]);  // 000000AA:BBBBBBCC
2788             break;
2789         case 7 :                        // ABBBBBBB:CDDDDDDD
2790             emitcode("mov","c,acc.7");  // c = A
2791             AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
2792             emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
2793             emitcode("anl","a,#0x%02x",
2794                      SRMask[shCount]);  // 0000000A:BBBBBBBC
2795             break;
2796         default :
2797             break;
2798     }
2799 }
2800
2801 /*-----------------------------------------------------------------*/
2802 /* AccAXRshS - right shift signed a:x known count (0..7)           */
2803 /*-----------------------------------------------------------------*/
2804 static void AccAXRshS (char *x, int shCount)
2805 {   
2806     symbol *tlbl ;
2807     switch(shCount){
2808         case 0 :
2809             break;
2810         case 1 :
2811             emitcode("mov","c,acc.7");
2812             AccAXRrl1(x);               // s->a:x
2813             break;
2814         case 2 :
2815             emitcode("mov","c,acc.7");
2816             AccAXRrl1(x);               // s->a:x
2817             emitcode("mov","c,acc.7");
2818             AccAXRrl1(x);               // s->a:x
2819             break;
2820         case 3 :
2821         case 4 :
2822         case 5 :                        // AAAAABBB:CCCCCDDD = a:x
2823             tlbl = newiTempLabel(NULL);
2824             AccRol(8 - shCount);        // BBBAAAAA:CCCCCDDD
2825             emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
2826             AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
2827             emitcode("anl","a,#0x%02x",
2828                      SRMask[shCount]);  // 000CCCCC:BBBAAAAA
2829             emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
2830             emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
2831             emitcode("anl","a,#0x%02x",
2832                      SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
2833             emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
2834             emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
2835             emitcode("xch","a,%s",x);   // 000SAAAA:BBBCCCCC
2836             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); 
2837             emitcode("orl","a,#0x%02x",
2838                      (unsigned char)~SRMask[shCount]);  // 111AAAAA:BBBCCCCC
2839             emitcode("","%05d$:",tlbl->key+100);
2840             break;                      // SSSSAAAA:BBBCCCCC
2841         case 6 :                        // AABBBBBB:CCDDDDDD
2842             tlbl = newiTempLabel(NULL);
2843             emitcode("mov","c,acc.7");
2844             AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
2845             AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
2846             emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
2847             emitcode("anl","a,#0x%02x",
2848                      SRMask[shCount]);  // 000000AA:BBBBBBCC
2849             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); 
2850             emitcode("orl","a,#0x%02x",
2851                      (unsigned char)~SRMask[shCount]);  // 111111AA:BBBBBBCC
2852             emitcode("","%05d$:",tlbl->key+100);
2853             break;
2854         case 7 :                        // ABBBBBBB:CDDDDDDD
2855             tlbl = newiTempLabel(NULL);
2856             emitcode("mov","c,acc.7");  // c = A
2857             AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
2858             emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
2859             emitcode("anl","a,#0x%02x",
2860                      SRMask[shCount]);  // 0000000A:BBBBBBBC
2861             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); 
2862             emitcode("orl","a,#0x%02x",
2863                      (unsigned char)~SRMask[shCount]);  // 1111111A:BBBBBBBC
2864             emitcode("","%05d$:",tlbl->key+100);
2865             break;
2866         default :
2867             break;
2868     }
2869 }
2870
2871 /*-----------------------------------------------------------------*/
2872 /* shiftL2Left2Result - shift left two bytes from left to result   */
2873 /*-----------------------------------------------------------------*/
2874 static void shiftL2Left2Result (operand *left, int offl,
2875                                 operand *result, int offr, int shCount)
2876 {
2877     if(sameRegs(AOP(result), AOP(left)) &&
2878        ((offl + MSB16) == offr)){
2879         /* don't crash result[offr] */
2880             //  MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
2881         emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16));
2882     } else {
2883         movLeft2Result(left,offl, result, offr, 0);
2884         MOVA(aopGet(AOP(left),offl+MSB16));
2885     }
2886     /* ax << shCount (x = lsb(result))*/
2887     AccAXLsh( aopGet(AOP(result),offr) , shCount);
2888     aopPut(AOP(result),"a",offr+MSB16);
2889 }
2890
2891
2892 /*-----------------------------------------------------------------*/
2893 /* shiftR2Left2Result - shift right two bytes from left to result  */
2894 /*-----------------------------------------------------------------*/
2895 static void shiftR2Left2Result (operand *left, int offl,
2896                                 operand *result, int offr,
2897                                 int shCount, int sign)
2898 {
2899     if(sameRegs(AOP(result), AOP(left)) &&
2900        ((offl + MSB16) == offr)){
2901         /* don't crash result[offr] */
2902             //  MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
2903         emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16));
2904     } else {
2905         movLeft2Result(left,offl, result, offr, 0);
2906         //      MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
2907     }
2908     /* a:x >> shCount (x = lsb(result))*/
2909     if(sign)
2910         AccAXRshS( aopGet(AOP(result),offr) , shCount);
2911     else
2912         AccAXRsh( aopGet(AOP(result),offr) , shCount);
2913     if(getDataSize(result) > 1)
2914         aopPut(AOP(result),"a",offr+MSB16);
2915 }
2916
2917 /*-----------------------------------------------------------------*/
2918 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
2919 /*-----------------------------------------------------------------*/
2920 static void shiftLLeftOrResult (operand *left, int offl,
2921                                 operand *result, int offr, int shCount)
2922 {
2923         //    MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
2924     /* shift left accumulator */
2925     AccLsh(shCount);
2926     /* or with result */
2927     emitcode("orl","a,%s", aopGet(AOP(result),offr));
2928     /* back to result */
2929     aopPut(AOP(result),"a",offr);
2930 }
2931
2932 /*-----------------------------------------------------------------*/
2933 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
2934 /*-----------------------------------------------------------------*/
2935 static void shiftRLeftOrResult (operand *left, int offl,
2936                                 operand *result, int offr, int shCount)
2937 {
2938         //   MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
2939     /* shift right accumulator */
2940     AccRsh(shCount);
2941     /* or with result */
2942     emitcode("orl","a,%s", aopGet(AOP(result),offr));
2943     /* back to result */
2944     aopPut(AOP(result),"a",offr);
2945 }
2946
2947 /*-----------------------------------------------------------------*/
2948 /* genlshOne - left shift a one byte quantity by known count       */
2949 /*-----------------------------------------------------------------*/
2950 static void genlshOne (operand *result, operand *left, int shCount)
2951 {       
2952     shiftL1Left2Result(left, LSB, result, LSB, shCount);
2953 }
2954
2955 /*-----------------------------------------------------------------*/
2956 /* genlshTwo - left shift two bytes by known amount != 0           */
2957 /*-----------------------------------------------------------------*/
2958 static void genlshTwo (operand *result,operand *left, int shCount)
2959 {
2960     int size;
2961     
2962     size = getDataSize(result);
2963
2964     /* if shCount >= 8 */
2965     if (shCount >= 8) {
2966         shCount -= 8 ;
2967
2968         if (size > 1){
2969             if (shCount)
2970                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
2971             else 
2972                 movLeft2Result(left, LSB, result, MSB16, 0);
2973         }
2974         aopPut(AOP(result),zero,LSB);   
2975     }
2976
2977     /*  1 <= shCount <= 7 */
2978     else {  
2979         if(size == 1)
2980             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
2981         else 
2982             shiftL2Left2Result(left, LSB, result, LSB, shCount);
2983     }
2984 }
2985
2986 /*-----------------------------------------------------------------*/
2987 /* shiftLLong - shift left one long from left to result            */
2988 /* offl = LSB or MSB16                                             */
2989 /*-----------------------------------------------------------------*/
2990 static void shiftLLong (operand *left, operand *result, int offr )
2991 {
2992     char *l;
2993     int size = AOP_SIZE(result);
2994
2995     if(size >= LSB+offr){
2996         l = aopGet(AOP(left),LSB);
2997         MOVA(l);
2998         emitcode("add","a,acc");
2999         if (sameRegs(AOP(left),AOP(result)) && 
3000             size >= MSB16+offr && offr != LSB )
3001             emitcode("xch","a,%s",
3002                      aopGet(AOP(left),LSB+offr));
3003         else        
3004             aopPut(AOP(result),"a",LSB+offr);
3005     }
3006
3007     if(size >= MSB16+offr){
3008         if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
3009             l = aopGet(AOP(left),MSB16);
3010             MOVA(l);
3011         }
3012         emitcode("rlc","a");
3013         if (sameRegs(AOP(left),AOP(result)) && 
3014             size >= MSB24+offr && offr != LSB)
3015             emitcode("xch","a,%s",
3016                      aopGet(AOP(left),MSB16+offr));
3017         else        
3018             aopPut(AOP(result),"a",MSB16+offr);
3019     }
3020
3021     if(size >= MSB24+offr){
3022         if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
3023             l = aopGet(AOP(left),MSB24);
3024             //      MOVA(l);
3025         }
3026         emitcode("rlc","a");
3027         if (sameRegs(AOP(left),AOP(result)) && 
3028             size >= MSB32+offr && offr != LSB )
3029             emitcode("xch","a,%s",
3030                      aopGet(AOP(left),MSB24+offr));
3031         else        
3032             aopPut(AOP(result),"a",MSB24+offr);
3033     }
3034
3035     if(size > MSB32+offr){
3036         if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
3037             l = aopGet(AOP(left),MSB32);
3038             MOVA(l);    
3039         }
3040         emitcode("rlc","a");
3041         aopPut(AOP(result),"a",MSB32+offr);
3042     }
3043     if(offr != LSB)
3044         aopPut(AOP(result),zero,LSB);       
3045 }
3046
3047 /*-----------------------------------------------------------------*/
3048 /* genlshFour - shift four byte by a known amount != 0             */
3049 /*-----------------------------------------------------------------*/
3050 static void genlshFour (operand *result, operand *left, int shCount)
3051 {
3052     int size;
3053
3054     size = AOP_SIZE(result);
3055
3056     /* if shifting more that 3 bytes */
3057     if (shCount >= 24 ) {
3058         shCount -= 24;
3059         if (shCount)
3060             /* lowest order of left goes to the highest
3061             order of the destination */
3062             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
3063         else
3064             movLeft2Result(left, LSB, result, MSB32, 0);
3065         aopPut(AOP(result),zero,LSB);
3066         aopPut(AOP(result),zero,MSB16);
3067         aopPut(AOP(result),zero,MSB32);
3068         return;
3069     }
3070
3071     /* more than two bytes */
3072     else if ( shCount >= 16 ) {
3073         /* lower order two bytes goes to higher order two bytes */
3074         shCount -= 16;
3075         /* if some more remaining */
3076         if (shCount)
3077             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
3078         else {
3079             movLeft2Result(left, MSB16, result, MSB32, 0);
3080             movLeft2Result(left, LSB, result, MSB24, 0);
3081         }
3082         aopPut(AOP(result),zero,MSB16);
3083         aopPut(AOP(result),zero,LSB);
3084         return;
3085     }    
3086
3087     /* if more than 1 byte */
3088     else if ( shCount >= 8 ) {
3089         /* lower order three bytes goes to higher order  three bytes */
3090         shCount -= 8;
3091         if(size == 2){
3092             if(shCount)
3093                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
3094             else
3095                 movLeft2Result(left, LSB, result, MSB16, 0);
3096         }
3097         else{   /* size = 4 */
3098             if(shCount == 0){
3099                 movLeft2Result(left, MSB24, result, MSB32, 0);
3100                 movLeft2Result(left, MSB16, result, MSB24, 0);
3101                 movLeft2Result(left, LSB, result, MSB16, 0);
3102                 aopPut(AOP(result),zero,LSB);
3103             }
3104             else if(shCount == 1)
3105                 shiftLLong(left, result, MSB16);
3106             else{
3107                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
3108                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
3109                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
3110                 aopPut(AOP(result),zero,LSB);
3111             }
3112         }
3113     }
3114
3115     /* 1 <= shCount <= 7 */
3116     else if(shCount <= 2){
3117         shiftLLong(left, result, LSB);
3118         if(shCount == 2)
3119             shiftLLong(result, result, LSB);
3120     }
3121     /* 3 <= shCount <= 7, optimize */
3122     else{
3123         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
3124         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
3125         shiftL2Left2Result(left, LSB, result, LSB, shCount);
3126     }
3127 }
3128
3129 /*-----------------------------------------------------------------*/
3130 /* genLeftShiftLiteral - left shifting by known count              */
3131 /*-----------------------------------------------------------------*/
3132 static void genLeftShiftLiteral (operand *left,
3133                                  operand *right,
3134                                  operand *result,
3135                                  iCode *ic)
3136 {    
3137     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3138     int size;
3139
3140     freeAsmop(right,NULL,ic,TRUE);
3141
3142     aopOp(left,ic,FALSE);
3143     aopOp(result,ic,FALSE);
3144
3145     size = getSize(operandType(result));
3146
3147 #if VIEW_SIZE
3148     emitcode("; shift left ","result %d, left %d",size,
3149              AOP_SIZE(left));
3150 #endif
3151
3152     /* I suppose that the left size >= result size */
3153     if(shCount == 0){
3154         while(size--){
3155             movLeft2Result(left, size, result, size, 0);
3156         }
3157     }
3158
3159     else if(shCount >= (size * 8))
3160         while(size--)
3161             aopPut(AOP(result),zero,size);
3162     else{
3163         switch (size) {
3164             case 1:
3165                 genlshOne (result,left,shCount);
3166                 break;
3167
3168             case 2:
3169             case 3:
3170                 genlshTwo (result,left,shCount);
3171                 break;
3172
3173             case 4:
3174                 genlshFour (result,left,shCount);
3175                 break;
3176         }
3177     }
3178     freeAsmop(left,NULL,ic,TRUE);
3179     freeAsmop(result,NULL,ic,TRUE);
3180 }
3181
3182 /*-----------------------------------------------------------------*/
3183 /* genLeftShift - generates code for left shifting                 */
3184 /*-----------------------------------------------------------------*/
3185 static void genLeftShift (iCode *ic)
3186 {
3187     operand *left,*right, *result;
3188     int size, offset;
3189     char *l;
3190     symbol *tlbl , *tlbl1;
3191
3192     right = IC_RIGHT(ic);
3193     left  = IC_LEFT(ic);
3194     result = IC_RESULT(ic);
3195
3196     aopOp(right,ic,FALSE);
3197
3198     /* if the shift count is known then do it 
3199     as efficiently as possible */
3200     if (AOP_TYPE(right) == AOP_LIT) {
3201         genLeftShiftLiteral (left,right,result,ic);
3202         return ;
3203     }
3204
3205     /* shift count is unknown then we have to form 
3206     a loop get the loop count in B : Note: we take
3207     only the lower order byte since shifting
3208     more that 32 bits make no sense anyway, ( the
3209     largest size of an object can be only 32 bits ) */  
3210
3211     emitcode("mov","b,%s",aopGet(AOP(right),0));
3212     emitcode("inc","b");
3213     freeAsmop (right,NULL,ic,TRUE);
3214     aopOp(left,ic,FALSE);
3215     aopOp(result,ic,FALSE);
3216
3217     /* now move the left to the result if they are not the
3218     same */
3219     if (!sameRegs(AOP(left),AOP(result)) && 
3220         AOP_SIZE(result) > 1) {
3221
3222         size = AOP_SIZE(result);
3223         offset=0;
3224         while (size--) {
3225             l = aopGet(AOP(left),offset);
3226             if (*l == '@' && (IS_AOP_PREG(result))) {
3227
3228                 emitcode("mov","a,%s",l);
3229                 aopPut(AOP(result),"a",offset);
3230             } else
3231                 aopPut(AOP(result),l,offset);
3232             offset++;
3233         }
3234     }
3235
3236     tlbl = newiTempLabel(NULL);
3237     size = AOP_SIZE(result);
3238     offset = 0 ;   
3239     tlbl1 = newiTempLabel(NULL);
3240
3241     /* if it is only one byte then */
3242     if (size == 1) {
3243         symbol *tlbl1 = newiTempLabel(NULL);
3244
3245         l = aopGet(AOP(left),0);
3246         MOVA(l);
3247         emitcode("sjmp","%05d$",tlbl1->key+100); 
3248         emitcode("","%05d$:",tlbl->key+100);
3249         emitcode("add","a,acc");
3250         emitcode("","%05d$:",tlbl1->key+100);
3251         emitcode("djnz","b,%05d$",tlbl->key+100);      
3252         aopPut(AOP(result),"a",0);
3253         goto release ;
3254     }
3255     
3256     reAdjustPreg(AOP(result));    
3257     
3258     emitcode("sjmp","%05d$",tlbl1->key+100); 
3259     emitcode("","%05d$:",tlbl->key+100);    
3260     l = aopGet(AOP(result),offset);
3261     MOVA(l);
3262     emitcode("add","a,acc");         
3263     aopPut(AOP(result),"a",offset++);
3264     while (--size) {
3265         l = aopGet(AOP(result),offset);
3266         MOVA(l);
3267         emitcode("rlc","a");         
3268         aopPut(AOP(result),"a",offset++);
3269     }
3270     reAdjustPreg(AOP(result));
3271
3272     emitcode("","%05d$:",tlbl1->key+100);
3273     emitcode("djnz","b,%05d$",tlbl->key+100);
3274 release:
3275     freeAsmop(left,NULL,ic,TRUE);
3276     freeAsmop(result,NULL,ic,TRUE);
3277 }
3278
3279 /*-----------------------------------------------------------------*/
3280 /* genrshOne - right shift a one byte quantity by known count      */
3281 /*-----------------------------------------------------------------*/
3282 static void genrshOne (operand *result, operand *left,
3283                        int shCount, int sign)
3284 {
3285     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
3286 }
3287
3288 /*-----------------------------------------------------------------*/
3289 /* genrshTwo - right shift two bytes by known amount != 0          */
3290 /*-----------------------------------------------------------------*/
3291 static void genrshTwo (operand *result,operand *left,
3292                        int shCount, int sign)
3293 {
3294     /* if shCount >= 8 */
3295     if (shCount >= 8) {
3296         shCount -= 8 ;
3297         if (shCount)
3298             shiftR1Left2Result(left, MSB16, result, LSB,
3299                                shCount, sign);
3300         else 
3301             movLeft2Result(left, MSB16, result, LSB, sign);
3302         addSign(result, MSB16, sign);
3303     }
3304
3305     /*  1 <= shCount <= 7 */
3306     else
3307         shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
3308 }
3309
3310 /*-----------------------------------------------------------------*/
3311 /* shiftRLong - shift right one long from left to result           */
3312 /* offl = LSB or MSB16                                             */
3313 /*-----------------------------------------------------------------*/
3314 static void shiftRLong (operand *left, int offl,
3315                         operand *result, int sign)
3316 {
3317     if(!sign)
3318         emitcode("clr","c");
3319     MOVA(aopGet(AOP(left),MSB32));
3320     if(sign)
3321         emitcode("mov","c,acc.7");
3322     emitcode("rrc","a");
3323     aopPut(AOP(result),"a",MSB32-offl);
3324     if(offl == MSB16)
3325         /* add sign of "a" */
3326         addSign(result, MSB32, sign);
3327
3328     MOVA(aopGet(AOP(left),MSB24));
3329     emitcode("rrc","a");
3330     aopPut(AOP(result),"a",MSB24-offl);
3331
3332     MOVA(aopGet(AOP(left),MSB16));
3333     emitcode("rrc","a");
3334     aopPut(AOP(result),"a",MSB16-offl);
3335
3336     if(offl == LSB){
3337         MOVA(aopGet(AOP(left),LSB));
3338         emitcode("rrc","a");
3339         aopPut(AOP(result),"a",LSB);
3340     }
3341 }
3342
3343 /*-----------------------------------------------------------------*/
3344 /* genrshFour - shift four byte by a known amount != 0             */
3345 /*-----------------------------------------------------------------*/
3346 static void genrshFour (operand *result, operand *left,
3347                         int shCount, int sign)
3348 {
3349     /* if shifting more that 3 bytes */
3350     if(shCount >= 24 ) {
3351         shCount -= 24;
3352         if(shCount)
3353             shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
3354         else
3355             movLeft2Result(left, MSB32, result, LSB, sign);
3356         addSign(result, MSB16, sign);
3357     }
3358     else if(shCount >= 16){
3359         shCount -= 16;
3360         if(shCount)
3361             shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
3362         else{
3363             movLeft2Result(left, MSB24, result, LSB, 0);
3364             movLeft2Result(left, MSB32, result, MSB16, sign);
3365         }
3366         addSign(result, MSB24, sign);
3367     }
3368     else if(shCount >= 8){
3369         shCount -= 8;
3370         if(shCount == 1)
3371             shiftRLong(left, MSB16, result, sign);
3372         else if(shCount == 0){
3373             movLeft2Result(left, MSB16, result, LSB, 0);
3374             movLeft2Result(left, MSB24, result, MSB16, 0);
3375             movLeft2Result(left, MSB32, result, MSB24, sign);
3376             addSign(result, MSB32, sign);
3377         }
3378         else{
3379             shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
3380             shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
3381             /* the last shift is signed */
3382             shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
3383             addSign(result, MSB32, sign);
3384         }
3385     }
3386     else{   /* 1 <= shCount <= 7 */
3387         if(shCount <= 2){
3388             shiftRLong(left, LSB, result, sign);
3389             if(shCount == 2)
3390                 shiftRLong(result, LSB, result, sign);
3391         }
3392         else{
3393             shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
3394             shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
3395             shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
3396         }
3397     }
3398 }
3399
3400 /*-----------------------------------------------------------------*/
3401 /* genRightShiftLiteral - right shifting by known count            */
3402 /*-----------------------------------------------------------------*/
3403 static void genRightShiftLiteral (operand *left,
3404                                   operand *right,
3405                                   operand *result,
3406                                   iCode *ic,
3407                                   int sign)
3408 {    
3409     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3410     int size;
3411
3412     freeAsmop(right,NULL,ic,TRUE);
3413
3414     aopOp(left,ic,FALSE);
3415     aopOp(result,ic,FALSE);
3416
3417 #if VIEW_SIZE
3418     emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
3419              AOP_SIZE(left));
3420 #endif
3421
3422     size = getDataSize(left);
3423     /* test the LEFT size !!! */
3424
3425     /* I suppose that the left size >= result size */
3426     if(shCount == 0){
3427         size = getDataSize(result);
3428         while(size--)
3429             movLeft2Result(left, size, result, size, 0);
3430     }
3431
3432     else if(shCount >= (size * 8)){
3433         if(sign)
3434             /* get sign in acc.7 */
3435             MOVA(aopGet(AOP(left),size-1));
3436         addSign(result, LSB, sign);
3437     } else{
3438         switch (size) {
3439             case 1:
3440                 genrshOne (result,left,shCount,sign);
3441                 break;
3442
3443             case 2:
3444                 genrshTwo (result,left,shCount,sign);
3445                 break;
3446
3447             case 4:
3448                 genrshFour (result,left,shCount,sign);
3449                 break;
3450             default :
3451                 break;
3452         }
3453
3454         freeAsmop(left,NULL,ic,TRUE);
3455         freeAsmop(result,NULL,ic,TRUE);
3456     }
3457 }
3458
3459 /*-----------------------------------------------------------------*/
3460 /* genSignedRightShift - right shift of signed number              */
3461 /*-----------------------------------------------------------------*/
3462 static void genSignedRightShift (iCode *ic)
3463 {
3464     operand *right, *left, *result;
3465     int size, offset;
3466     char *l;
3467     symbol *tlbl, *tlbl1 ;
3468
3469     /* we do it the hard way put the shift count in b
3470     and loop thru preserving the sign */
3471
3472     right = IC_RIGHT(ic);
3473     left  = IC_LEFT(ic);
3474     result = IC_RESULT(ic);
3475
3476     aopOp(right,ic,FALSE);  
3477
3478
3479     if ( AOP_TYPE(right) == AOP_LIT) {
3480         genRightShiftLiteral (left,right,result,ic,1);
3481         return ;
3482     }
3483         /* shift count is unknown then we have to form 
3484        a loop get the loop count in B : Note: we take
3485        only the lower order byte since shifting
3486        more that 32 bits make no sense anyway, ( the
3487        largest size of an object can be only 32 bits ) */  
3488
3489     emitcode("mov","b,%s",aopGet(AOP(right),0));
3490     emitcode("inc","b");
3491     freeAsmop (right,NULL,ic,TRUE);
3492     aopOp(left,ic,FALSE);
3493     aopOp(result,ic,FALSE);
3494
3495     /* now move the left to the result if they are not the
3496     same */
3497     if (!sameRegs(AOP(left),AOP(result)) && 
3498         AOP_SIZE(result) > 1) {
3499
3500         size = AOP_SIZE(result);
3501         offset=0;
3502         while (size--) {
3503             l = aopGet(AOP(left),offset);
3504             if (*l == '@' && IS_AOP_PREG(result)) {
3505
3506                 emitcode("mov","a,%s",l);
3507                 aopPut(AOP(result),"a",offset);
3508             } else
3509                 aopPut(AOP(result),l,offset);
3510             offset++;
3511         }
3512     }
3513
3514     /* mov the highest order bit to OVR */    
3515     tlbl = newiTempLabel(NULL);
3516     tlbl1= newiTempLabel(NULL);
3517
3518     size = AOP_SIZE(result);
3519     offset = size - 1;
3520     emitcode("mov","a,%s",aopGet(AOP(left),offset));
3521     emitcode("rlc","a");
3522     emitcode("mov","ov,c");
3523     /* if it is only one byte then */
3524     if (size == 1) {
3525         l = aopGet(AOP(left),0);
3526         MOVA(l);
3527         emitcode("sjmp","%05d$",tlbl1->key+100);
3528         emitcode("","%05d$:",tlbl->key+100);
3529         emitcode("mov","c,ov");
3530         emitcode("rrc","a");
3531         emitcode("","%05d$:",tlbl1->key+100);
3532         emitcode("djnz","b,%05d$",tlbl->key+100);
3533         aopPut(AOP(result),"a",0);
3534         goto release ;
3535     }
3536
3537     reAdjustPreg(AOP(result));
3538     emitcode("sjmp","%05d$",tlbl1->key+100);
3539     emitcode("","%05d$:",tlbl->key+100);    
3540     emitcode("mov","c,ov");
3541     while (size--) {
3542         l = aopGet(AOP(result),offset);
3543         MOVA(l);
3544         emitcode("rrc","a");         
3545         aopPut(AOP(result),"a",offset--);
3546     }
3547     reAdjustPreg(AOP(result));
3548     emitcode("","%05d$:",tlbl1->key+100);
3549     emitcode("djnz","b,%05d$",tlbl->key+100);
3550
3551 release:
3552     freeAsmop(left,NULL,ic,TRUE);
3553     freeAsmop(result,NULL,ic,TRUE);
3554 }
3555
3556 /*-----------------------------------------------------------------*/
3557 /* genRightShift - generate code for right shifting                */
3558 /*-----------------------------------------------------------------*/
3559 static void genRightShift (iCode *ic)
3560 {
3561     operand *right, *left, *result;
3562     link *retype ;
3563     int size, offset;
3564     char *l;
3565     symbol *tlbl, *tlbl1 ;
3566
3567     /* if signed then we do it the hard way preserve the
3568     sign bit moving it inwards */
3569     retype = getSpec(operandType(IC_RESULT(ic)));
3570
3571     if (!SPEC_USIGN(retype)) {
3572         genSignedRightShift (ic);
3573         return ;
3574     }
3575
3576     /* signed & unsigned types are treated the same : i.e. the
3577     signed is NOT propagated inwards : quoting from the
3578     ANSI - standard : "for E1 >> E2, is equivalent to division
3579     by 2**E2 if unsigned or if it has a non-negative value,
3580     otherwise the result is implementation defined ", MY definition
3581     is that the sign does not get propagated */
3582
3583     right = IC_RIGHT(ic);
3584     left  = IC_LEFT(ic);
3585     result = IC_RESULT(ic);
3586
3587     aopOp(right,ic,FALSE);
3588
3589     /* if the shift count is known then do it 
3590     as efficiently as possible */
3591     if (AOP_TYPE(right) == AOP_LIT) {
3592         genRightShiftLiteral (left,right,result,ic, 0);
3593         return ;
3594     }
3595
3596     /* shift count is unknown then we have to form 
3597     a loop get the loop count in B : Note: we take
3598     only the lower order byte since shifting
3599     more that 32 bits make no sense anyway, ( the
3600     largest size of an object can be only 32 bits ) */  
3601
3602     emitcode("mov","b,%s",aopGet(AOP(right),0));
3603     emitcode("inc","b");
3604     freeAsmop (right,NULL,ic,TRUE);
3605     aopOp(left,ic,FALSE);
3606     aopOp(result,ic,FALSE);
3607
3608     /* now move the left to the result if they are not the
3609     same */
3610     if (!sameRegs(AOP(left),AOP(result)) && 
3611         AOP_SIZE(result) > 1) {
3612
3613         size = AOP_SIZE(result);
3614         offset=0;
3615         while (size--) {
3616             l = aopGet(AOP(left),offset);
3617             if (*l == '@' && IS_AOP_PREG(result)) {
3618
3619                 emitcode("mov","a,%s",l);
3620                 aopPut(AOP(result),"a",offset);
3621             } else
3622                 aopPut(AOP(result),l,offset);
3623             offset++;
3624         }
3625     }
3626
3627     tlbl = newiTempLabel(NULL);
3628     tlbl1= newiTempLabel(NULL);
3629     size = AOP_SIZE(result);
3630     offset = size - 1;
3631
3632     /* if it is only one byte then */
3633     if (size == 1) {
3634         l = aopGet(AOP(left),0);
3635         MOVA(l);
3636         emitcode("sjmp","%05d$",tlbl1->key+100);
3637         emitcode("","%05d$:",tlbl->key+100);
3638         CLRC;
3639         emitcode("rrc","a");
3640         emitcode("","%05d$:",tlbl1->key+100);
3641         emitcode("djnz","b,%05d$",tlbl->key+100);
3642         aopPut(AOP(result),"a",0);
3643         goto release ;
3644     }
3645
3646     reAdjustPreg(AOP(result));
3647     emitcode("sjmp","%05d$",tlbl1->key+100);
3648     emitcode("","%05d$:",tlbl->key+100);    
3649     CLRC;
3650     while (size--) {
3651         l = aopGet(AOP(result),offset);
3652         MOVA(l);
3653         emitcode("rrc","a");         
3654         aopPut(AOP(result),"a",offset--);
3655     }
3656     reAdjustPreg(AOP(result));
3657
3658     emitcode("","%05d$:",tlbl1->key+100);
3659     emitcode("djnz","b,%05d$",tlbl->key+100);
3660
3661 release:
3662     freeAsmop(left,NULL,ic,TRUE);
3663     freeAsmop(result,NULL,ic,TRUE);
3664 }
3665
3666 /*-----------------------------------------------------------------*/
3667 /* genUnpackBits - generates code for unpacking bits               */
3668 /*-----------------------------------------------------------------*/
3669 static void genUnpackBits (operand *result, char *rname, int ptype)
3670 {    
3671     int shCnt ;
3672     int rlen = 0 ;
3673     link *etype;
3674     int offset = 0 ;
3675
3676     etype = getSpec(operandType(result));
3677
3678     /* read the first byte  */
3679     switch (ptype) {
3680
3681     case POINTER:
3682     case IPOINTER:
3683         emitcode("mov","a,@%s",rname);
3684         break;
3685         
3686     case PPOINTER:
3687         emitcode("movx","a,@%s",rname);
3688         break;
3689         
3690     case FPOINTER:
3691         emitcode("movx","a,@dptr");
3692         break;
3693
3694     case CPOINTER:
3695         emitcode("clr","a");
3696         emitcode("movc","a","@a+dptr");
3697         break;
3698
3699     case GPOINTER:
3700         emitcode("lcall","__gptrget");
3701         break;
3702     }
3703
3704     /* if we have bitdisplacement then it fits   */
3705     /* into this byte completely or if length is */
3706     /* less than a byte                          */
3707     if ((shCnt = SPEC_BSTR(etype)) || 
3708         (SPEC_BLEN(etype) <= 8))  {
3709
3710         /* shift right acc */
3711         AccRsh(shCnt);
3712
3713         emitcode("anl","a,#0x%02x",
3714                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
3715         aopPut(AOP(result),"a",offset);
3716         return ;
3717     }
3718
3719     /* bit field did not fit in a byte  */
3720     rlen = SPEC_BLEN(etype) - 8;
3721     aopPut(AOP(result),"a",offset++);
3722
3723     while (1)  {
3724
3725         switch (ptype) {
3726         case POINTER:
3727         case IPOINTER:
3728             emitcode("inc","%s",rname);
3729             emitcode("mov","a,@%s",rname);
3730             break;
3731             
3732         case PPOINTER:
3733             emitcode("inc","%s",rname);
3734             emitcode("movx","a,@%s",rname);
3735             break;
3736
3737         case FPOINTER:
3738             emitcode("inc","dptr");
3739             emitcode("movx","a,@dptr");
3740             break;
3741             
3742         case CPOINTER:
3743             emitcode("clr","a");
3744             emitcode("inc","dptr");
3745             emitcode("movc","a","@a+dptr");
3746             break;
3747             
3748         case GPOINTER:
3749             emitcode("inc","dptr");
3750             emitcode("lcall","__gptrget");
3751             break;
3752         }
3753
3754         rlen -= 8;            
3755         /* if we are done */
3756         if ( rlen <= 0 )
3757             break ;
3758         
3759         aopPut(AOP(result),"a",offset++);
3760                               
3761     }
3762     
3763     if (rlen) {
3764         emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
3765         aopPut(AOP(result),"a",offset);        
3766     }
3767     
3768     return ;
3769 }
3770
3771
3772 /*-----------------------------------------------------------------*/
3773 /* genDataPointerGet - generates code when ptr offset is known     */
3774 /*-----------------------------------------------------------------*/
3775 static void genDataPointerGet (operand *left, 
3776                                operand *result, 
3777                                iCode *ic)
3778 {
3779     char *l;
3780     char buffer[256];
3781     int size , offset = 0;
3782     aopOp(result,ic,TRUE);
3783
3784     /* get the string representation of the name */
3785     l = aopGet(AOP(left),0);
3786     size = AOP_SIZE(result);
3787     while (size--) {
3788         if (offset)
3789             sprintf(buffer,"(%s + %d)",l+1,offset);
3790         else
3791             sprintf(buffer,"%s",l+1);
3792         aopPut(AOP(result),buffer,offset++);
3793     }
3794
3795     freeAsmop(left,NULL,ic,TRUE);
3796     freeAsmop(result,NULL,ic,TRUE);
3797 }
3798
3799 /*-----------------------------------------------------------------*/
3800 /* genNearPointerGet - emitcode for near pointer fetch             */
3801 /*-----------------------------------------------------------------*/
3802 static void genNearPointerGet (operand *left, 
3803                                operand *result, 
3804                                iCode *ic)
3805 {
3806     asmop *aop = NULL;
3807     regs *preg = NULL ;
3808     char *rname ;
3809     link *rtype, *retype;
3810     link *ltype = operandType(left);    
3811     char buffer[80];
3812
3813     rtype = operandType(result);
3814     retype= getSpec(rtype);
3815     
3816     aopOp(left,ic,FALSE);
3817     
3818     /* if left is rematerialisable and
3819        result is not bit variable type and
3820        the left is pointer to data space i.e
3821        lower 128 bytes of space */
3822     if (AOP_TYPE(left) == AOP_IMMD &&
3823         !IS_BITVAR(retype)         &&
3824         DCL_TYPE(ltype) == POINTER) {
3825         genDataPointerGet (left,result,ic);
3826         return ;
3827     }
3828     
3829         /* if the value is already in a pointer register
3830        then don't need anything more */
3831     if (!AOP_INPREG(AOP(left))) {
3832         /* otherwise get a free pointer register */
3833         aop = newAsmop(0);
3834         preg = getFreePtr(ic,&aop,FALSE,0);
3835         emitcode("mov","%s,%s",
3836                 preg->name,
3837                 aopGet(AOP(left),0));
3838         rname = preg->name ;
3839     } else
3840         rname = aopGet(AOP(left),0);
3841     
3842     freeAsmop(left,NULL,ic,TRUE);
3843     aopOp (result,ic,FALSE);
3844     
3845       /* if bitfield then unpack the bits */
3846     if (IS_BITVAR(retype)) 
3847         genUnpackBits (result,rname,POINTER);
3848     else {
3849         /* we have can just get the values */
3850         int size = AOP_SIZE(result);
3851         int offset = 0 ;        
3852         
3853         while (size--) {
3854             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
3855
3856                 emitcode("mov","a,@%s",rname);
3857                 aopPut(AOP(result),"a",offset);
3858             } else {
3859                 sprintf(buffer,"@%s",rname);
3860                 aopPut(AOP(result),buffer,offset);
3861             }
3862             offset++ ;
3863             if (size)
3864                 emitcode("inc","%s",rname);
3865         }
3866     }
3867
3868     /* now some housekeeping stuff */
3869     if (aop) {
3870         /* we had to allocate for this iCode */
3871         freeAsmop(NULL,aop,ic,TRUE);
3872     } else { 
3873         /* we did not allocate which means left
3874            already in a pointer register, then
3875            if size > 0 && this could be used again
3876            we have to point it back to where it 
3877            belongs */
3878         if (AOP_SIZE(result) > 1 &&
3879             !OP_SYMBOL(left)->remat &&
3880             ( OP_SYMBOL(left)->liveTo > ic->seq ||
3881               ic->depth )) {
3882             int size = AOP_SIZE(result) - 1;
3883             while (size--)
3884                 emitcode("dec","%s",rname);
3885         }
3886     }
3887
3888     /* done */
3889     freeAsmop(result,NULL,ic,TRUE);
3890      
3891 }
3892
3893 /*-----------------------------------------------------------------*/
3894 /* genPagedPointerGet - emitcode for paged pointer fetch           */
3895 /*-----------------------------------------------------------------*/
3896 static void genPagedPointerGet (operand *left, 
3897                                operand *result, 
3898                                iCode *ic)
3899 {
3900     asmop *aop = NULL;
3901     regs *preg = NULL ;
3902     char *rname ;
3903     link *rtype, *retype;    
3904
3905     rtype = operandType(result);
3906     retype= getSpec(rtype);
3907     
3908     aopOp(left,ic,FALSE);
3909
3910   /* if the value is already in a pointer register
3911        then don't need anything more */
3912     if (!AOP_INPREG(AOP(left))) {
3913         /* otherwise get a free pointer register */
3914         aop = newAsmop(0);
3915         preg = getFreePtr(ic,&aop,FALSE,0);
3916         emitcode("mov","%s,%s",
3917                 preg->name,
3918                 aopGet(AOP(left),0));
3919         rname = preg->name ;
3920     } else
3921         rname = aopGet(AOP(left),0);
3922     
3923     freeAsmop(left,NULL,ic,TRUE);
3924     aopOp (result,ic,FALSE);
3925
3926     /* if bitfield then unpack the bits */
3927     if (IS_BITVAR(retype)) 
3928         genUnpackBits (result,rname,PPOINTER);
3929     else {
3930         /* we have can just get the values */
3931         int size = AOP_SIZE(result);
3932         int offset = 0 ;        
3933         
3934         while (size--) {
3935             
3936             emitcode("movx","a,@%s",rname);
3937             aopPut(AOP(result),"a",offset);
3938             
3939             offset++ ;
3940             
3941             if (size)
3942                 emitcode("inc","%s",rname);
3943         }
3944     }
3945
3946     /* now some housekeeping stuff */
3947     if (aop) {
3948         /* we had to allocate for this iCode */
3949         freeAsmop(NULL,aop,ic,TRUE);
3950     } else { 
3951         /* we did not allocate which means left
3952            already in a pointer register, then
3953            if size > 0 && this could be used again
3954            we have to point it back to where it 
3955            belongs */
3956         if (AOP_SIZE(result) > 1 &&
3957             !OP_SYMBOL(left)->remat &&
3958             ( OP_SYMBOL(left)->liveTo > ic->seq ||
3959               ic->depth )) {
3960             int size = AOP_SIZE(result) - 1;
3961             while (size--)
3962                 emitcode("dec","%s",rname);
3963         }
3964     }
3965
3966     /* done */
3967     freeAsmop(result,NULL,ic,TRUE);
3968     
3969         
3970 }
3971
3972 /*-----------------------------------------------------------------*/
3973 /* genFarPointerGet - gget value from far space                    */
3974 /*-----------------------------------------------------------------*/
3975 static void genFarPointerGet (operand *left,
3976                               operand *result, iCode *ic)
3977 {
3978     int size, offset ;
3979     link *retype = getSpec(operandType(result));
3980
3981     aopOp(left,ic,FALSE);
3982
3983     /* if the operand is already in dptr 
3984     then we do nothing else we move the value to dptr */
3985     if (AOP_TYPE(left) != AOP_STR) {
3986         /* if this is remateriazable */
3987         if (AOP_TYPE(left) == AOP_IMMD)
3988             emitcode("mov","dptr,%s",aopGet(AOP(left),0));
3989         else { /* we need to get it byte by byte */
3990             emitcode("mov","dpl,%s",aopGet(AOP(left),0));
3991             emitcode("mov","dph,%s",aopGet(AOP(left),1));
3992             if (options.model == MODEL_FLAT24)
3993             {
3994                emitcode("mov", "dpx,%s",aopGet(AOP(left),2));
3995             }
3996         }
3997     }
3998     /* so dptr know contains the address */
3999     freeAsmop(left,NULL,ic,TRUE);
4000     aopOp(result,ic,FALSE);
4001
4002     /* if bit then unpack */
4003     if (IS_BITVAR(retype)) 
4004         genUnpackBits(result,"dptr",FPOINTER);
4005     else {
4006         size = AOP_SIZE(result);
4007         offset = 0 ;
4008
4009         while (size--) {
4010             emitcode("movx","a,@dptr");
4011             aopPut(AOP(result),"a",offset++);
4012             if (size)
4013                 emitcode("inc","dptr");
4014         }
4015     }
4016
4017     freeAsmop(result,NULL,ic,TRUE);
4018 }
4019
4020 /*-----------------------------------------------------------------*/
4021 /* emitcodePointerGet - gget value from code space                  */
4022 /*-----------------------------------------------------------------*/
4023 static void emitcodePointerGet (operand *left,
4024                                 operand *result, iCode *ic)
4025 {
4026     int size, offset ;
4027     link *retype = getSpec(operandType(result));
4028
4029     aopOp(left,ic,FALSE);
4030
4031     /* if the operand is already in dptr 
4032     then we do nothing else we move the value to dptr */
4033     if (AOP_TYPE(left) != AOP_STR) {
4034         /* if this is remateriazable */
4035         if (AOP_TYPE(left) == AOP_IMMD)
4036             emitcode("mov","dptr,%s",aopGet(AOP(left),0));
4037         else { /* we need to get it byte by byte */
4038             emitcode("mov","dpl,%s",aopGet(AOP(left),0));
4039             emitcode("mov","dph,%s",aopGet(AOP(left),1));
4040             if (options.model == MODEL_FLAT24)
4041             {
4042                emitcode("mov", "dpx,%s",aopGet(AOP(left),2));
4043             }
4044         }
4045     }
4046     /* so dptr know contains the address */
4047     freeAsmop(left,NULL,ic,TRUE);
4048     aopOp(result,ic,FALSE);
4049
4050     /* if bit then unpack */
4051     if (IS_BITVAR(retype)) 
4052         genUnpackBits(result,"dptr",CPOINTER);
4053     else {
4054         size = AOP_SIZE(result);
4055         offset = 0 ;
4056
4057         while (size--) {
4058             emitcode("clr","a");
4059             emitcode("movc","a,@a+dptr");
4060             aopPut(AOP(result),"a",offset++);
4061             if (size)
4062                 emitcode("inc","dptr");
4063         }
4064     }
4065
4066     freeAsmop(result,NULL,ic,TRUE);
4067 }
4068
4069 /*-----------------------------------------------------------------*/
4070 /* genGenPointerGet - gget value from generic pointer space        */
4071 /*-----------------------------------------------------------------*/
4072 static void genGenPointerGet (operand *left,
4073                               operand *result, iCode *ic)
4074 {
4075     int size, offset ;
4076     link *retype = getSpec(operandType(result));
4077
4078     aopOp(left,ic,FALSE);
4079
4080     /* if the operand is already in dptr 
4081     then we do nothing else we move the value to dptr */
4082     if (AOP_TYPE(left) != AOP_STR) {
4083         /* if this is remateriazable */
4084         if (AOP_TYPE(left) == AOP_IMMD) {
4085             emitcode("mov","dptr,%s",aopGet(AOP(left),0));
4086             emitcode("mov","b,#%d",pointerCode(retype));
4087         }
4088         else { /* we need to get it byte by byte */
4089             emitcode("mov","dpl,%s",aopGet(AOP(left),0));
4090             emitcode("mov","dph,%s",aopGet(AOP(left),1));
4091             if (options.model == MODEL_FLAT24)
4092             {
4093                emitcode("mov", "dpx,%s",aopGet(AOP(left),2));
4094                emitcode("mov","b,%s",aopGet(AOP(left),3));
4095             }
4096             else
4097             {
4098                 emitcode("mov","b,%s",aopGet(AOP(left),2));
4099             }
4100         }
4101     }
4102     /* so dptr know contains the address */
4103     freeAsmop(left,NULL,ic,TRUE);
4104     aopOp(result,ic,FALSE); 
4105
4106     /* if bit then unpack */
4107     if (IS_BITVAR(retype)) 
4108         genUnpackBits(result,"dptr",GPOINTER);
4109     else {
4110         size = AOP_SIZE(result);
4111         offset = 0 ;
4112
4113         while (size--) {
4114             emitcode("lcall","__gptrget");
4115             aopPut(AOP(result),"a",offset++);
4116             if (size)
4117                 emitcode("inc","dptr");
4118         }
4119     }
4120
4121     freeAsmop(result,NULL,ic,TRUE);
4122 }
4123
4124 /*-----------------------------------------------------------------*/
4125 /* genPointerGet - generate code for pointer get                   */
4126 /*-----------------------------------------------------------------*/
4127 static void genPointerGet (iCode *ic)
4128 {
4129     operand *left, *result ;
4130     link *type, *etype;
4131     int p_type;
4132
4133     left = IC_LEFT(ic);
4134     result = IC_RESULT(ic) ;
4135
4136     /* depending on the type of pointer we need to
4137     move it to the correct pointer register */
4138     type = operandType(left);
4139     etype = getSpec(type);
4140     /* if left is of type of pointer then it is simple */
4141     if (IS_PTR(type) && !IS_FUNC(type->next)) 
4142         p_type = DCL_TYPE(type);
4143     else {
4144         /* we have to go by the storage class */
4145         p_type = PTR_TYPE(SPEC_OCLS(etype));
4146
4147 /*      if (SPEC_OCLS(etype)->codesp ) { */
4148 /*          p_type = CPOINTER ;  */
4149 /*      } */
4150 /*      else */
4151 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
4152 /*              p_type = FPOINTER ; */
4153 /*          else */
4154 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
4155 /*                  p_type = PPOINTER; */
4156 /*              else */
4157 /*                  if (SPEC_OCLS(etype) == idata ) */
4158 /*                      p_type = IPOINTER; */
4159 /*                  else */
4160 /*                      p_type = POINTER ; */
4161     }
4162
4163     /* now that we have the pointer type we assign
4164     the pointer values */
4165     switch (p_type) {
4166
4167     case POINTER:       
4168     case IPOINTER:
4169         genNearPointerGet (left,result,ic);
4170         break;
4171
4172     case PPOINTER:
4173         genPagedPointerGet(left,result,ic);
4174         break;
4175
4176     case FPOINTER:
4177         genFarPointerGet (left,result,ic);
4178         break;
4179
4180     case CPOINTER:
4181         emitcodePointerGet (left,result,ic);
4182         break;
4183
4184     case GPOINTER:
4185         genGenPointerGet (left,result,ic);
4186         break;
4187     }
4188
4189 }
4190
4191 /*-----------------------------------------------------------------*/
4192 /* genPackBits - generates code for packed bit storage             */
4193 /*-----------------------------------------------------------------*/
4194 static void genPackBits (link    *etype ,
4195                          operand *right ,
4196                          char *rname, int p_type)
4197 {
4198     int shCount = 0 ;
4199     int offset = 0  ;
4200     int rLen = 0 ;
4201     int blen, bstr ;   
4202     char *l ;
4203
4204     blen = SPEC_BLEN(etype);
4205     bstr = SPEC_BSTR(etype);
4206
4207     l = aopGet(AOP(right),offset++);
4208     MOVA(l);   
4209
4210     /* if the bit lenth is less than or    */
4211     /* it exactly fits a byte then         */
4212     if (SPEC_BLEN(etype) <= 8 )  {
4213         shCount = SPEC_BSTR(etype) ;
4214
4215         /* shift left acc */
4216         AccLsh(shCount);
4217
4218         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
4219
4220
4221             switch (p_type) {
4222                 case POINTER:
4223                     emitcode ("mov","b,a");
4224                     emitcode("mov","a,@%s",rname);
4225                     break;
4226
4227                 case FPOINTER:
4228                     emitcode ("mov","b,a");
4229                     emitcode("movx","a,@dptr");
4230                     break;
4231
4232                 case GPOINTER:
4233                     emitcode ("push","b");
4234                     emitcode ("push","acc");
4235                     emitcode ("lcall","__gptrget");
4236                     emitcode ("pop","b");
4237                     break;
4238             }
4239
4240             emitcode ("anl","a,#0x%02x",(unsigned char)
4241                       ((unsigned char)(0xFF << (blen+bstr)) | 
4242                        (unsigned char)(0xFF >> (8-bstr)) ) );
4243             emitcode ("orl","a,b");
4244             if (p_type == GPOINTER)
4245                 emitcode("pop","b");
4246         }
4247     }
4248
4249     switch (p_type) {
4250         case POINTER:
4251             emitcode("mov","@%s,a",rname);
4252             break;
4253
4254         case FPOINTER:
4255             emitcode("movx","@dptr,a");
4256             break;
4257
4258         case GPOINTER:
4259             emitcode("lcall","__gptrput");
4260             break;
4261     }
4262
4263     /* if we r done */
4264     if ( SPEC_BLEN(etype) <= 8 )
4265         return ;
4266
4267     emitcode("inc","%s",rname);
4268     rLen = SPEC_BLEN(etype) ;     
4269
4270     /* now generate for lengths greater than one byte */
4271     while (1) {
4272
4273         l = aopGet(AOP(right),offset++);
4274
4275         rLen -= 8 ;
4276         if (rLen <= 0 )
4277             break ;
4278
4279         switch (p_type) {
4280             case POINTER:
4281                 if (*l == '@') {
4282                     MOVA(l);
4283                     emitcode("mov","@%s,a",rname);
4284                 } else
4285                     emitcode("mov","@%s,%s",rname,l);
4286                 break;
4287
4288             case FPOINTER:
4289                 MOVA(l);
4290                 emitcode("movx","@dptr,a");
4291                 break;
4292
4293             case GPOINTER:
4294                 MOVA(l);
4295                 emitcode("lcall","__gptrput");
4296                 break;  
4297         }   
4298         emitcode ("inc","%s",rname);
4299     }
4300
4301     MOVA(l);
4302
4303     /* last last was not complete */
4304     if (rLen)   {
4305         /* save the byte & read byte */
4306         switch (p_type) {
4307             case POINTER:
4308                 emitcode ("mov","b,a");
4309                 emitcode("mov","a,@%s",rname);
4310                 break;
4311
4312             case FPOINTER:
4313                 emitcode ("mov","b,a");
4314                 emitcode("movx","a,@dptr");
4315                 break;
4316
4317             case GPOINTER:
4318                 emitcode ("push","b");
4319                 emitcode ("push","acc");
4320                 emitcode ("lcall","__gptrget");
4321                 emitcode ("pop","b");
4322                 break;
4323         }
4324
4325         emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
4326         emitcode ("orl","a,b");
4327     }
4328
4329     if (p_type == GPOINTER)
4330         emitcode("pop","b");
4331
4332     switch (p_type) {
4333
4334     case POINTER:
4335         emitcode("mov","@%s,a",rname);
4336         break;
4337         
4338     case FPOINTER:
4339         emitcode("movx","@dptr,a");
4340         break;
4341         
4342     case GPOINTER:
4343         emitcode("lcall","__gptrput");
4344         break;                  
4345     }
4346 }
4347 /*-----------------------------------------------------------------*/
4348 /* genDataPointerSet - remat pointer to data space                 */
4349 /*-----------------------------------------------------------------*/
4350 static void genDataPointerSet(operand *right,
4351                               operand *result,
4352                               iCode *ic)
4353 {
4354     int size, offset = 0 ;
4355     char *l, buffer[256];
4356
4357     aopOp(right,ic,FALSE);
4358     
4359     l = aopGet(AOP(result),0);
4360     size = AOP_SIZE(right);
4361     while (size--) {
4362         if (offset)
4363             sprintf(buffer,"(%s + %d)",l+1,offset);
4364         else
4365             sprintf(buffer,"%s",l+1);
4366         emitcode("mov","%s,%s",buffer,
4367                  aopGet(AOP(right),offset++));
4368     }
4369
4370     freeAsmop(right,NULL,ic,TRUE);
4371     freeAsmop(result,NULL,ic,TRUE);
4372 }
4373
4374 /*-----------------------------------------------------------------*/
4375 /* genNearPointerSet - emitcode for near pointer put                */
4376 /*-----------------------------------------------------------------*/
4377 static void genNearPointerSet (operand *right,
4378                                operand *result, 
4379                                iCode *ic)
4380 {
4381     asmop *aop = NULL;
4382     regs *preg = NULL ;
4383     char *rname , *l;
4384     link *retype;
4385     link *ptype = operandType(result);
4386     
4387     retype= getSpec(operandType(right));
4388
4389     aopOp(result,ic,FALSE);
4390     
4391     /* if the result is rematerializable &
4392        in data space & not a bit variable */
4393     if (AOP_TYPE(result) == AOP_IMMD &&
4394         DCL_TYPE(ptype) == POINTER   &&
4395         !IS_BITVAR(retype)) {
4396         genDataPointerSet (right,result,ic);
4397         return;
4398     }
4399
4400     /* if the value is already in a pointer register
4401     then don't need anything more */
4402     if (!AOP_INPREG(AOP(result))) {
4403         /* otherwise get a free pointer register */
4404         aop = newAsmop(0);
4405         preg = getFreePtr(ic,&aop,FALSE,0);
4406         emitcode("mov","%s,%s",
4407                  preg->name,
4408                  aopGet(AOP(result),0));
4409         rname = preg->name ;
4410     } else
4411         rname = aopGet(AOP(result),0);
4412
4413     freeAsmop(result,NULL,ic,TRUE);
4414     aopOp (right,ic,FALSE);
4415
4416     /* if bitfield then unpack the bits */
4417     if (IS_BITVAR(retype)) 
4418         genPackBits (retype,right,rname,POINTER);
4419     else {
4420         /* we have can just get the values */
4421         int size = AOP_SIZE(right);
4422         int offset = 0 ;    
4423
4424         while (size--) {
4425             l = aopGet(AOP(right),offset);
4426             if (*l == '@' ) {
4427                 MOVA(l);
4428                 emitcode("mov","@%s,a",rname);
4429             } else
4430                 emitcode("mov","@%s,%s",rname,l);
4431             if (size)
4432                 emitcode("inc","%s",rname);
4433             offset++;
4434         }
4435     }
4436
4437     /* now some housekeeping stuff */
4438     if (aop) {
4439         /* we had to allocate for this iCode */
4440         freeAsmop(NULL,aop,ic,TRUE);
4441     } else { 
4442         /* we did not allocate which means left
4443         already in a pointer register, then
4444         if size > 0 && this could be used again
4445         we have to point it back to where it 
4446         belongs */
4447         if (AOP_SIZE(right) > 1 &&
4448             !OP_SYMBOL(result)->remat &&
4449             ( OP_SYMBOL(result)->liveTo > ic->seq ||
4450               ic->depth )) {
4451             int size = AOP_SIZE(right) - 1;
4452             while (size--)
4453                 emitcode("dec","%s",rname);
4454         }
4455     }
4456
4457     /* done */
4458     freeAsmop(right,NULL,ic,TRUE);
4459
4460
4461 }
4462
4463 /*-----------------------------------------------------------------*/
4464 /* genPagedPointerSet - emitcode for Paged pointer put             */
4465 /*-----------------------------------------------------------------*/
4466 static void genPagedPointerSet (operand *right,
4467                                operand *result, 
4468                                iCode *ic)
4469 {
4470     asmop *aop = NULL;
4471     regs *preg = NULL ;
4472     char *rname , *l;
4473     link *retype;
4474        
4475     retype= getSpec(operandType(right));
4476     
4477     aopOp(result,ic,FALSE);
4478     
4479     /* if the value is already in a pointer register
4480        then don't need anything more */
4481     if (!AOP_INPREG(AOP(result))) {
4482         /* otherwise get a free pointer register */
4483         aop = newAsmop(0);
4484         preg = getFreePtr(ic,&aop,FALSE,0);
4485         emitcode("mov","%s,%s",
4486                 preg->name,
4487                 aopGet(AOP(result),0));
4488         rname = preg->name ;
4489     } else
4490         rname = aopGet(AOP(result),0);
4491     
4492     freeAsmop(result,NULL,ic,TRUE);
4493     aopOp (right,ic,FALSE);
4494
4495     /* if bitfield then unpack the bits */
4496     if (IS_BITVAR(retype)) 
4497         genPackBits (retype,right,rname,PPOINTER);
4498     else {
4499         /* we have can just get the values */
4500         int size = AOP_SIZE(right);
4501         int offset = 0 ;        
4502         
4503         while (size--) {
4504             l = aopGet(AOP(right),offset);
4505             
4506             MOVA(l);
4507             emitcode("movx","@%s,a",rname);
4508
4509             if (size)
4510                 emitcode("inc","%s",rname);
4511
4512             offset++;
4513         }
4514     }
4515     
4516     /* now some housekeeping stuff */
4517     if (aop) {
4518         /* we had to allocate for this iCode */
4519         freeAsmop(NULL,aop,ic,TRUE);
4520     } else { 
4521         /* we did not allocate which means left
4522            already in a pointer register, then
4523            if size > 0 && this could be used again
4524            we have to point it back to where it 
4525            belongs */
4526         if (AOP_SIZE(right) > 1 &&
4527             !OP_SYMBOL(result)->remat &&
4528             ( OP_SYMBOL(result)->liveTo > ic->seq ||
4529               ic->depth )) {
4530             int size = AOP_SIZE(right) - 1;
4531             while (size--)
4532                 emitcode("dec","%s",rname);
4533         }
4534     }
4535
4536     /* done */
4537     freeAsmop(right,NULL,ic,TRUE);
4538     
4539         
4540 }
4541
4542 /*-----------------------------------------------------------------*/
4543 /* genFarPointerSet - set value from far space                     */
4544 /*-----------------------------------------------------------------*/
4545 static void genFarPointerSet (operand *right,
4546                               operand *result, iCode *ic)
4547 {
4548     int size, offset ;
4549     link *retype = getSpec(operandType(right));
4550
4551     aopOp(result,ic,FALSE);
4552
4553     /* if the operand is already in dptr 
4554     then we do nothing else we move the value to dptr */
4555     if (AOP_TYPE(result) != AOP_STR) {
4556         /* if this is remateriazable */
4557         if (AOP_TYPE(result) == AOP_IMMD)
4558             emitcode("mov","dptr,%s",aopGet(AOP(result),0));
4559         else { /* we need to get it byte by byte */
4560             emitcode("mov","dpl,%s",aopGet(AOP(result),0));
4561             emitcode("mov","dph,%s",aopGet(AOP(result),1));
4562             if (options.model == MODEL_FLAT24)
4563             {
4564                emitcode("mov", "dpx,%s",aopGet(AOP(result),2));
4565             }
4566         }
4567     }
4568     /* so dptr know contains the address */
4569     freeAsmop(result,NULL,ic,TRUE);
4570     aopOp(right,ic,FALSE);
4571
4572     /* if bit then unpack */
4573     if (IS_BITVAR(retype)) 
4574         genPackBits(retype,right,"dptr",FPOINTER);
4575     else {
4576         size = AOP_SIZE(right);
4577         offset = 0 ;
4578
4579         while (size--) {
4580             char *l = aopGet(AOP(right),offset++);
4581             MOVA(l);
4582             emitcode("movx","@dptr,a");
4583             if (size)
4584                 emitcode("inc","dptr");
4585         }
4586     }
4587
4588     freeAsmop(right,NULL,ic,TRUE);
4589 }
4590
4591 /*-----------------------------------------------------------------*/
4592 /* genGenPointerSet - set value from generic pointer space         */
4593 /*-----------------------------------------------------------------*/
4594 static void genGenPointerSet (operand *right,
4595                               operand *result, iCode *ic)
4596 {
4597     int size, offset ;
4598     link *retype = getSpec(operandType(right));
4599
4600     aopOp(result,ic,FALSE);
4601
4602     /* if the operand is already in dptr 
4603     then we do nothing else we move the value to dptr */
4604     if (AOP_TYPE(result) != AOP_STR) {
4605         /* if this is remateriazable */
4606         if (AOP_TYPE(result) == AOP_IMMD) {
4607             emitcode("mov","dptr,%s",aopGet(AOP(result),0));
4608             emitcode("mov","b,%s + 1",aopGet(AOP(result),0));
4609         }
4610         else { /* we need to get it byte by byte */
4611             emitcode("mov","dpl,%s",aopGet(AOP(result),0));
4612             emitcode("mov","dph,%s",aopGet(AOP(result),1));
4613             if (options.model == MODEL_FLAT24)
4614             {
4615                emitcode("mov", "dpx,%s",aopGet(AOP(result),2));
4616                emitcode("mov","b,%s",aopGet(AOP(result),3));
4617             }
4618             else
4619             {
4620                 emitcode("mov","b,%s",aopGet(AOP(result),2));
4621             }
4622         }
4623     }
4624     /* so dptr know contains the address */
4625     freeAsmop(result,NULL,ic,TRUE);
4626     aopOp(right,ic,FALSE);
4627
4628     /* if bit then unpack */
4629     if (IS_BITVAR(retype)) 
4630         genPackBits(retype,right,"dptr",GPOINTER);
4631     else {
4632         size = AOP_SIZE(right);
4633         offset = 0 ;
4634
4635         while (size--) {
4636             char *l = aopGet(AOP(right),offset++);
4637             MOVA(l);
4638             emitcode("lcall","__gptrput");
4639             if (size)
4640                 emitcode("inc","dptr");
4641         }
4642     }
4643
4644     freeAsmop(right,NULL,ic,TRUE);
4645 }
4646
4647 /*-----------------------------------------------------------------*/
4648 /* genPointerSet - stores the value into a pointer location        */
4649 /*-----------------------------------------------------------------*/
4650 static void genPointerSet (iCode *ic)
4651 {    
4652     operand *right, *result ;
4653     link *type, *etype;
4654     int p_type;
4655
4656     right = IC_RIGHT(ic);
4657     result = IC_RESULT(ic) ;
4658
4659     /* depending on the type of pointer we need to
4660     move it to the correct pointer register */
4661     type = operandType(result);
4662     etype = getSpec(type);
4663     /* if left is of type of pointer then it is simple */
4664     if (IS_PTR(type) && !IS_FUNC(type->next)) {
4665         p_type = DCL_TYPE(type);
4666     }
4667     else {
4668         /* we have to go by the storage class */
4669         p_type = PTR_TYPE(SPEC_OCLS(etype));
4670
4671 /*      if (SPEC_OCLS(etype)->codesp ) { */
4672 /*          p_type = CPOINTER ;  */
4673 /*      } */
4674 /*      else */
4675 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
4676 /*              p_type = FPOINTER ; */
4677 /*          else */
4678 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
4679 /*                  p_type = PPOINTER ; */
4680 /*              else */
4681 /*                  if (SPEC_OCLS(etype) == idata ) */
4682 /*                      p_type = IPOINTER ; */
4683 /*                  else */
4684 /*                      p_type = POINTER ; */
4685     }
4686
4687     /* now that we have the pointer type we assign
4688     the pointer values */
4689     switch (p_type) {
4690
4691     case POINTER:
4692     case IPOINTER:
4693         genNearPointerSet (right,result,ic);
4694         break;
4695
4696     case PPOINTER:
4697         genPagedPointerSet (right,result,ic);
4698         break;
4699
4700     case FPOINTER:
4701         genFarPointerSet (right,result,ic);
4702         break;
4703
4704     case GPOINTER:
4705         genGenPointerSet (right,result,ic);
4706         break;
4707     }
4708
4709 }
4710
4711 /*-----------------------------------------------------------------*/
4712 /* genIfx - generate code for Ifx statement                        */
4713 /*-----------------------------------------------------------------*/
4714 static void genIfx (iCode *ic, iCode *popIc)
4715 {
4716     operand *cond = IC_COND(ic);
4717     int isbit =0;
4718
4719     aopOp(cond,ic,FALSE);
4720
4721     /* get the value into acc */
4722     if (AOP_TYPE(cond) != AOP_CRY)
4723         toBoolean(cond,"",0);
4724     else
4725         isbit = 1;
4726     /* the result is now in the accumulator */
4727     freeAsmop(cond,NULL,ic,TRUE);
4728
4729     /* if there was something to be popped then do it */
4730     if (popIc)
4731         genIpop(popIc);
4732
4733     /* if the condition is  a bit variable */
4734 /*     if (isbit && IS_ITEMP(cond) && SPIL_LOC(cond)) { */
4735 /*      //      genIfxJump(ic,SPIL_LOC(cond)->rname); */
4736 /*     } */
4737 /*     else */
4738 /*      if (isbit && !IS_ITEMP(cond)) */
4739 /*              //          genIfxJump(ic,OP_SYMBOL(cond)->rname); */
4740 /*      else */
4741 /*              // genIfxJump(ic,"a"); */
4742
4743     ic->generated = 1;
4744 }
4745
4746 /*-----------------------------------------------------------------*/
4747 /* genAddrOf - generates code for address of                       */
4748 /*-----------------------------------------------------------------*/
4749 static void genAddrOf (iCode *ic)
4750 {
4751     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
4752     int size, offset ;
4753
4754     aopOp(IC_RESULT(ic),ic,FALSE);
4755
4756     /* if the operand is on the stack then we 
4757     need to get the stack offset of this
4758     variable */
4759     if (sym->onStack) {
4760         /* if it has an offset then we need to compute
4761         it */
4762         if (sym->stack) {
4763             emitcode("mov","a,_bp");
4764             emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
4765             aopPut(AOP(IC_RESULT(ic)),"a",0);       
4766         } else {
4767             /* we can just move _bp */
4768             aopPut(AOP(IC_RESULT(ic)),"_bp",0);
4769         }
4770         /* fill the result with zero */
4771         size = AOP_SIZE(IC_RESULT(ic)) - 1;
4772         
4773         
4774         if (options.stack10bit && size < (FPTRSIZE - 1))
4775         {
4776             fprintf(stderr, 
4777                     "*** warning: pointer to stack var truncated.\n");
4778         }
4779         
4780         offset = 1;
4781         while (size--)
4782         {
4783             /* Yuck! */
4784             if (options.stack10bit && offset == 2)
4785             {
4786                 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
4787             }
4788             else
4789             {
4790                 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
4791             }
4792         }
4793
4794         goto release;
4795     }
4796
4797     /* object not on stack then we need the name */
4798     size = AOP_SIZE(IC_RESULT(ic));
4799     offset = 0;
4800
4801     while (size--) {
4802         char s[SDCC_NAME_MAX];
4803         if (offset) 
4804             sprintf(s,"#(%s >> %d)",
4805                     sym->rname,
4806                     offset*8);
4807         else
4808             sprintf(s,"#%s",sym->rname);
4809         aopPut(AOP(IC_RESULT(ic)),s,offset++);
4810     }
4811
4812 release:
4813     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
4814
4815 }
4816
4817 /*-----------------------------------------------------------------*/
4818 /* genFarFarAssign - assignment when both are in far space         */
4819 /*-----------------------------------------------------------------*/
4820 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
4821 {
4822     int size = AOP_SIZE(right);
4823     int offset = 0;
4824     char *l ;
4825     /* first push the right side on to the stack */
4826     while (size--) {
4827         l = aopGet(AOP(right),offset++);
4828         MOVA(l);
4829         emitcode ("push","acc");
4830     }
4831     
4832     freeAsmop(right,NULL,ic,FALSE);
4833     /* now assign DPTR to result */
4834     aopOp(result,ic,FALSE);
4835     size = AOP_SIZE(result);
4836     while (size--) {
4837         emitcode ("pop","acc");
4838         aopPut(AOP(result),"a",--offset);
4839     }
4840     freeAsmop(result,NULL,ic,FALSE);
4841         
4842 }
4843
4844 /*-----------------------------------------------------------------*/
4845 /* genAssign - generate code for assignment                        */
4846 /*-----------------------------------------------------------------*/
4847 static void genAssign (iCode *ic)
4848 {
4849     operand *result, *right;
4850     int size, offset ;
4851         unsigned long lit = 0L;
4852
4853     result = IC_RESULT(ic);
4854     right  = IC_RIGHT(ic) ;
4855
4856     /* if they are the same */
4857     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
4858         return ;
4859
4860     aopOp(right,ic,FALSE);
4861     
4862     /* special case both in far space */
4863     if (AOP_TYPE(right) == AOP_DPTR &&
4864         IS_TRUE_SYMOP(result)       &&
4865         isOperandInFarSpace(result)) {
4866         
4867         genFarFarAssign (result,right,ic);
4868         return ;
4869     }
4870
4871     aopOp(result,ic,TRUE);
4872
4873     /* if they are the same registers */
4874     if (sameRegs(AOP(right),AOP(result)))
4875         goto release;
4876
4877     /* if the result is a bit */
4878     if (AOP_TYPE(result) == AOP_CRY) {
4879
4880         /* if the right size is a literal then
4881         we know what the value is */
4882         if (AOP_TYPE(right) == AOP_LIT) {
4883             if (((int) operandLitValue(right))) 
4884                 aopPut(AOP(result),one,0);
4885             else
4886                 aopPut(AOP(result),zero,0);
4887             goto release;
4888         }
4889
4890         /* the right is also a bit variable */
4891         if (AOP_TYPE(right) == AOP_CRY) {
4892             emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4893             aopPut(AOP(result),"c",0);
4894             goto release ;
4895         }
4896
4897         /* we need to or */
4898         toBoolean(right,"",0);
4899         aopPut(AOP(result),"a",0);
4900         goto release ;
4901     }
4902
4903     /* bit variables done */
4904     /* general case */
4905     size = AOP_SIZE(result);
4906     offset = 0 ;
4907     if(AOP_TYPE(right) == AOP_LIT)
4908         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4909     if((size > 1) &&
4910        (AOP_TYPE(result) != AOP_REG) &&
4911        (AOP_TYPE(right) == AOP_LIT) &&
4912        !IS_FLOAT(operandType(right)) &&
4913        (lit < 256L)){
4914         emitcode("clr","a");
4915         while (size--) {
4916             if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
4917                 aopPut(AOP(result),"a",size);
4918             else
4919                 aopPut(AOP(result),
4920                        aopGet(AOP(right),size),
4921                        size);
4922         }
4923     } else {
4924         while (size--) {
4925             aopPut(AOP(result),
4926                    aopGet(AOP(right),offset),
4927                    offset);
4928             offset++;
4929         }
4930     }
4931     
4932 release:
4933     freeAsmop (right,NULL,ic,FALSE);
4934     freeAsmop (result,NULL,ic,TRUE);
4935 }   
4936
4937 /*-----------------------------------------------------------------*/
4938 /* genJumpTab - genrates code for jump table                       */
4939 /*-----------------------------------------------------------------*/
4940 static void genJumpTab (iCode *ic)
4941 {
4942     symbol *jtab;
4943     char *l;
4944
4945     aopOp(IC_JTCOND(ic),ic,FALSE);
4946     /* get the condition into accumulator */
4947     l = aopGet(AOP(IC_JTCOND(ic)),0);
4948     MOVA(l);
4949     /* multiply by three */
4950     emitcode("add","a,acc");
4951     emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0));
4952     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
4953
4954     jtab = newiTempLabel(NULL);
4955     emitcode("mov","dptr,#%05d$",jtab->key+100);
4956     emitcode("jmp","@a+dptr");
4957     emitcode("","%05d$:",jtab->key+100);
4958     /* now generate the jump labels */
4959     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
4960          jtab = setNextItem(IC_JTLABELS(ic)))
4961         emitcode("ljmp","%05d$",jtab->key+100);
4962
4963 }
4964
4965 /*-----------------------------------------------------------------*/
4966 /* genCast - gen code for casting                                  */
4967 /*-----------------------------------------------------------------*/
4968 static void genCast (iCode *ic)
4969 {
4970     operand *result = IC_RESULT(ic);
4971     link *ctype = operandType(IC_LEFT(ic));
4972     link *rtype = operandType(IC_RIGHT(ic));
4973     operand *right = IC_RIGHT(ic);
4974     int size, offset ;
4975
4976     /* if they are equivalent then do nothing */
4977     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
4978         return ;
4979
4980     aopOp(right,ic,FALSE) ;
4981     aopOp(result,ic,FALSE);
4982
4983     /* if the result is a bit */
4984     if (AOP_TYPE(result) == AOP_CRY) {
4985         /* if the right size is a literal then
4986         we know what the value is */
4987         if (AOP_TYPE(right) == AOP_LIT) {
4988             if (((int) operandLitValue(right))) 
4989                 aopPut(AOP(result),one,0);
4990             else
4991                 aopPut(AOP(result),zero,0);
4992
4993             goto release;
4994         }
4995
4996         /* the right is also a bit variable */
4997         if (AOP_TYPE(right) == AOP_CRY) {
4998             emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4999             aopPut(AOP(result),"c",0);
5000             goto release ;
5001         }
5002
5003         /* we need to or */
5004         toBoolean(right,"",0);
5005         aopPut(AOP(result),"a",0);
5006         goto release ;
5007     }
5008
5009     /* if they are the same size : or less */
5010     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
5011
5012         /* if they are in the same place */
5013         if (sameRegs(AOP(right),AOP(result)))
5014             goto release;
5015
5016         /* if they in different places then copy */
5017         size = AOP_SIZE(result);
5018         offset = 0 ;
5019         while (size--) {
5020             aopPut(AOP(result),
5021                    aopGet(AOP(right),offset),
5022                    offset);
5023             offset++;
5024         }
5025         goto release;
5026     }
5027
5028
5029     /* if the result is of type pointer */
5030     if (IS_PTR(ctype)) {
5031
5032         int p_type;
5033         link *type = operandType(right);
5034         link *etype = getSpec(type);
5035
5036         /* pointer to generic pointer */
5037         if (IS_GENPTR(ctype)) {
5038             char *l = zero;
5039             
5040             if (IS_PTR(type)) 
5041                 p_type = DCL_TYPE(type);
5042             else {
5043                 /* we have to go by the storage class */
5044                 p_type = PTR_TYPE(SPEC_OCLS(etype));
5045             }
5046                 
5047             /* the first two bytes are known */
5048             size = GPTRSIZE - 1; 
5049             offset = 0 ;
5050             while (size--) {
5051                 aopPut(AOP(result),
5052                        aopGet(AOP(right),offset),
5053                        offset);
5054                 offset++;
5055             }
5056             /* the last byte depending on type */
5057             switch (p_type) {
5058             case IPOINTER:
5059             case POINTER:
5060                 l = zero;
5061                 break;
5062             case FPOINTER:
5063                 l = one;
5064                 break;
5065             case CPOINTER:
5066                 l = "#0x02";
5067                 break;                          
5068             case PPOINTER:
5069                 l = "#0x03";
5070                 break;
5071                 
5072             default:
5073                 /* this should never happen */
5074                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
5075                        "got unknown pointer type");
5076                 exit(1);
5077             }
5078             aopPut(AOP(result),l, GPTRSIZE - 1);            
5079             goto release ;
5080         }
5081         
5082         /* just copy the pointers */
5083         size = AOP_SIZE(result);
5084         offset = 0 ;
5085         while (size--) {
5086             aopPut(AOP(result),
5087                    aopGet(AOP(right),offset),
5088                    offset);
5089             offset++;
5090         }
5091         goto release ;
5092     }
5093     
5094     /* so we now know that the size of destination is greater
5095     than the size of the source */
5096     /* we move to result for the size of source */
5097     size = AOP_SIZE(right);
5098     offset = 0 ;
5099     while (size--) {
5100         aopPut(AOP(result),
5101                aopGet(AOP(right),offset),
5102                offset);
5103         offset++;
5104     }
5105
5106     /* now depending on the sign of the source && destination */
5107     size = AOP_SIZE(result) - AOP_SIZE(right);
5108     /* if unsigned or not an integral type */
5109     if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
5110         while (size--)
5111             aopPut(AOP(result),zero,offset++);
5112     } else {
5113         /* we need to extend the sign :{ */
5114         char *l = aopGet(AOP(right),AOP_SIZE(right) - 1);
5115         MOVA(l);
5116         emitcode("rlc","a");
5117         emitcode("subb","a,acc");
5118         while (size--)
5119             aopPut(AOP(result),"a",offset++);   
5120     }
5121
5122     /* we are done hurray !!!! */
5123
5124 release:
5125     freeAsmop(right,NULL,ic,TRUE);
5126     freeAsmop(result,NULL,ic,TRUE);
5127
5128 }
5129
5130 /*-----------------------------------------------------------------*/
5131 /* genDjnz - generate decrement & jump if not zero instrucion      */
5132 /*-----------------------------------------------------------------*/
5133 static int genDjnz (iCode *ic, iCode *ifx)
5134 {
5135     symbol *lbl, *lbl1;
5136     if (!ifx)
5137         return 0;
5138     
5139     /* if the if condition has a false label
5140        then we cannot save */
5141     if (IC_FALSE(ifx))
5142         return 0;
5143
5144     /* if the minus is not of the form 
5145        a = a - 1 */
5146     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
5147         !IS_OP_LITERAL(IC_RIGHT(ic)))
5148         return 0;
5149
5150     if (operandLitValue(IC_RIGHT(ic)) != 1)
5151         return 0;
5152
5153     /* if the size of this greater than one then no
5154        saving */
5155     if (getSize(operandType(IC_RESULT(ic))) > 1)
5156         return 0;
5157
5158     /* otherwise we can save BIG */
5159     lbl = newiTempLabel(NULL);
5160     lbl1= newiTempLabel(NULL);
5161
5162     aopOp(IC_RESULT(ic),ic,FALSE);
5163     
5164     if (IS_AOP_PREG(IC_RESULT(ic))) {
5165         emitcode("dec","%s",
5166                  aopGet(AOP(IC_RESULT(ic)),0));
5167         emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0));
5168         emitcode("jnz","%05d$",lbl->key+100);
5169     } else {    
5170         emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0),
5171                   lbl->key+100);
5172     }
5173     emitcode ("sjmp","%05d$",lbl1->key+100);
5174     emitcode ("","%05d$:",lbl->key+100);
5175     emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
5176     emitcode ("","%05d$:",lbl1->key+100);
5177     
5178     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
5179     ifx->generated = 1;
5180     return 1;
5181 }
5182
5183 static char *recvregs[8] = 
5184 {
5185         "r16","r17","r18","r19","r20","r21","r22","r23"
5186 };
5187 static recvCnt = 0;
5188
5189 /*-----------------------------------------------------------------*/
5190 /* genReceive - generate code for a receive iCode                  */
5191 /*-----------------------------------------------------------------*/
5192 static void genReceive (iCode *ic)
5193 {    
5194         int size , offset =0;
5195         aopOp(IC_RESULT(ic),ic,FALSE);  
5196         size = AOP_SIZE(IC_RESULT(ic));
5197         while (size--) {
5198                 aopPut(AOP(IC_RESULT(ic)),recvregs[recvCnt++],offset);
5199                 offset++;
5200         }
5201         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
5202 }
5203
5204 /*-----------------------------------------------------------------*/
5205 /* gen51Code - generate code for 8051 based controllers            */
5206 /*-----------------------------------------------------------------*/
5207 void genAVRCode (iCode *lic)
5208 {
5209     iCode *ic;
5210     int cln = 0;
5211
5212     lineHead = lineCurr = NULL;
5213     recvCnt =0;
5214     /* print the allocation information */
5215     if (allocInfo)
5216         printAllocInfo( currFunc, codeOutFile);
5217     /* if debug information required */
5218 /*     if (options.debug && currFunc) { */
5219     if (currFunc) {
5220         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
5221         _G.debugLine = 1;
5222         if (IS_STATIC(currFunc->etype))
5223             emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name); 
5224         else
5225             emitcode("","G$%s$0$0 ==.",currFunc->name);
5226         _G.debugLine = 0;
5227     }
5228     /* stack pointer name */
5229     if (options.useXstack)
5230         spname = "_spx";
5231     else
5232         spname = "sp";
5233     
5234  
5235     for (ic = lic ; ic ; ic = ic->next ) {
5236         
5237         if ( cln != ic->lineno ) {
5238             if ( options.debug ) {
5239                 _G.debugLine = 1;
5240                 emitcode("","C$%s$%d$%d$%d ==.",
5241                          ic->filename,ic->lineno,
5242                          ic->level,ic->block);
5243                 _G.debugLine = 0;
5244             }
5245             emitcode(";","%s %d",ic->filename,ic->lineno);
5246             cln = ic->lineno ;
5247         }
5248         /* if the result is marked as
5249            spilt and rematerializable or code for
5250            this has already been generated then
5251            do nothing */
5252         if (resultRemat(ic) || ic->generated ) 
5253             continue ;
5254         
5255         /* depending on the operation */
5256         switch (ic->op) {
5257         case '!' :
5258             genNot(ic);
5259             break;
5260             
5261         case '~' :
5262             genCpl(ic);
5263             break;
5264             
5265         case UNARYMINUS:
5266             genUminus (ic);
5267             break;
5268             
5269         case IPUSH:
5270             genIpush (ic);
5271             break;
5272             
5273         case IPOP:
5274             /* IPOP happens only when trying to restore a 
5275                spilt live range, if there is an ifx statement
5276                following this pop then the if statement might
5277                be using some of the registers being popped which
5278                would destory the contents of the register so
5279                we need to check for this condition and handle it */
5280             if (ic->next            && 
5281                 ic->next->op == IFX &&
5282                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
5283                 genIfx (ic->next,ic);
5284             else
5285                 genIpop (ic);
5286             break; 
5287             
5288         case CALL:
5289             genCall (ic);
5290             break;
5291             
5292         case PCALL:
5293             genPcall (ic);
5294             break;
5295             
5296         case FUNCTION:
5297             genFunction (ic);
5298             break;
5299             
5300         case ENDFUNCTION:
5301             genEndFunction (ic);
5302             break;
5303             
5304         case RETURN:
5305             genRet (ic);
5306             break;
5307             
5308         case LABEL:
5309             genLabel (ic);
5310             break;
5311             
5312         case GOTO:
5313             genGoto (ic);
5314             break;
5315             
5316         case '+' :
5317             genPlus (ic) ;
5318             break;
5319             
5320         case '-' :
5321             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
5322                 genMinus (ic);
5323             break;
5324             
5325         case '*' :
5326             genMult (ic);
5327             break;
5328             
5329         case '/' :
5330             genDiv (ic) ;
5331             break;
5332             
5333         case '%' :
5334             genMod (ic);
5335             break;
5336             
5337         case '>' :
5338             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
5339             break;
5340             
5341         case '<' :
5342             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
5343             break;
5344             
5345         case LE_OP:
5346             genCmpLe (ic,ifxForOp(IC_RESULT(ic),ic));
5347             break;
5348
5349         case GE_OP:
5350             genCmpGe (ic,ifxForOp(IC_RESULT(ic),ic));
5351             break;
5352
5353         case NE_OP:
5354             genCmpNe (ic,ifxForOp(IC_RESULT(ic),ic));       
5355             break;      
5356             
5357         case EQ_OP:
5358             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
5359             break;          
5360             
5361         case AND_OP:
5362             genAndOp (ic);
5363             break;
5364             
5365         case OR_OP:
5366             genOrOp (ic);
5367             break;
5368             
5369         case '^' :
5370             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
5371             break;
5372             
5373         case '|' :
5374                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
5375             break;
5376             
5377         case BITWISEAND:
5378             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
5379             break;
5380             
5381         case INLINEASM:
5382             genInline (ic);
5383             break;
5384             
5385         case RRC:
5386             genRRC (ic);
5387             break;
5388             
5389         case RLC:
5390             genRLC (ic);
5391             break;
5392             
5393         case GETHBIT:
5394             genGetHbit (ic);
5395             break;
5396             
5397         case LEFT_OP:
5398             genLeftShift (ic);
5399             break;
5400             
5401         case RIGHT_OP:
5402             genRightShift (ic);
5403             break;
5404             
5405         case GET_VALUE_AT_ADDRESS:
5406             genPointerGet(ic);
5407             break;
5408             
5409         case '=' :
5410             if (POINTER_SET(ic))
5411                 genPointerSet(ic);
5412             else
5413                 genAssign(ic);
5414             break;
5415             
5416         case IFX:
5417             genIfx (ic,NULL);
5418             break;
5419             
5420         case ADDRESS_OF:
5421             genAddrOf (ic);
5422             break;
5423             
5424         case JUMPTABLE:
5425             genJumpTab (ic);
5426             break;
5427             
5428         case CAST:
5429             genCast (ic);
5430             break;
5431             
5432         case RECEIVE:
5433             genReceive(ic);
5434             break;
5435             
5436         case SEND:
5437             addSet(&_G.sendSet,ic);
5438             break;
5439
5440         default :
5441             ic = ic;
5442             /*      piCode(ic,stdout); */
5443             
5444         }
5445     }
5446     
5447
5448     /* now we are ready to call the 
5449        peep hole optimizer */
5450     if (!options.nopeep)
5451         peepHole (&lineHead);
5452
5453     /* now do the actual printing */
5454     printLine (lineHead,codeOutFile);    
5455     return;
5456 }