Another 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 fReturnSize = 4; /* shared with ralloc.c */
65 char **fReturn = fReturnAVR;
66
67 static short rbank = -1;
68
69 static struct {
70     short xPushed;
71     short zPushed;
72     short accInUse;
73     short inLine;
74     short debugLine;
75     short nRegsSaved;
76     set *sendSet;
77 } _G;
78
79 extern int avr_ptrRegReq ;
80 extern int avr_nRegs;
81 extern FILE *codeOutFile;
82 static void saverbank (int, iCode *,bool);
83 #define RESULTONSTACK(x) \
84                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
85                          IC_RESULT(x)->aop->type == AOP_STK )
86
87 #define MOVR0(x) if (strcmp(x,"r0")) emitcode("mov","r0,%s",x);
88 #define CLRC    emitcode("clc")
89 #define SETC    emitcode("stc")
90 #define IS_REGIDX(a,r) (a->type == AOP_REG && aop->aopu.aop_reg[0]->rIdx == r)
91
92 static lineNode *lineHead = NULL;
93 static lineNode *lineCurr = NULL;
94
95 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
96 0xE0, 0xC0, 0x80, 0x00};
97 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
98 0x07, 0x03, 0x01, 0x00};
99
100 #define LSB     0
101 #define MSB16   1
102 #define MSB24   2
103 #define MSB32   3
104
105 /*-----------------------------------------------------------------*/
106 /* emitcode - writes the code into a file : for now it is simple    */
107 /*-----------------------------------------------------------------*/
108 static void emitcode (char *inst,char *fmt, ...)
109 {
110     va_list ap;
111     char lb[MAX_INLINEASM];  
112     char *lbp = lb;
113
114     va_start(ap,fmt);   
115
116     if (inst && *inst) {
117         if (fmt && *fmt)
118             sprintf(lb,"%s\t",inst);
119         else
120             sprintf(lb,"%s",inst);
121         vsprintf(lb+(strlen(lb)),fmt,ap);
122     }  else
123         vsprintf(lb,fmt,ap);
124
125     while (isspace(*lbp)) lbp++;
126
127     if (lbp && *lbp) 
128         lineCurr = (lineCurr ?
129                     connectLine(lineCurr,newLineNode(lb)) :
130                     (lineHead = newLineNode(lb)));
131     lineCurr->isInline = _G.inLine;
132     lineCurr->isDebug  = _G.debugLine;
133     va_end(ap);
134 }
135
136 /*-----------------------------------------------------------------*/
137 /* getFreePtr - returns X or Z whichever is free or can be pushed  */
138 /*-----------------------------------------------------------------*/
139 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result, bool zonly)
140 {
141     bool xiu = FALSE , ziu = FALSE;
142     bool xou = FALSE , zou = FALSE;
143
144     /* the logic: if x & z used in the instruction
145     then we are in trouble otherwise */
146
147     /* first check if x & z are used by this
148     instruction, in which case we are in trouble */
149     if ((xiu = bitVectBitValue(ic->rUsed,X_IDX)) &&
150         (ziu = bitVectBitValue(ic->rUsed,Z_IDX))) 
151     {
152         goto endOfWorld;      
153     }
154
155     xou = bitVectBitValue(ic->rMask,X_IDX);
156     zou = bitVectBitValue(ic->rMask,Z_IDX);
157
158     /* if no usage of Z then return it */
159     if (!ziu && !zou) {
160         ic->rUsed = bitVectSetBit(ic->rUsed,Z_IDX);
161         (*aopp)->type = AOP_Z;
162
163         (*aopp)->aop_ptr2 = avr_regWithIdx(R31_IDX);
164         return (*aopp)->aopu.aop_ptr = avr_regWithIdx(R30_IDX);
165     }    
166
167     /* if no usage of X then return it */
168     if (!xiu && !xou && !zonly) {
169         ic->rUsed = bitVectSetBit(ic->rUsed,X_IDX);
170         (*aopp)->type = AOP_X;
171         
172         (*aopp)->aop_ptr2 = avr_regWithIdx(R27_IDX);
173         return (*aopp)->aopu.aop_ptr = avr_regWithIdx(R26_IDX);
174     }
175
176     /* if z not used then */
177
178     if (!ziu) {
179         /* push it if not already pushed */
180         if (!_G.zPushed) {
181             emitcode ("push","%s",
182                       avr_regWithIdx(R30_IDX)->dname);
183             emitcode ("push","%s",
184                       avr_regWithIdx(R31_IDX)->dname);
185             _G.zPushed++ ;
186         }
187         
188         ic->rUsed = bitVectSetBit(ic->rUsed,Z_IDX);
189         (*aopp)->type = AOP_Z;
190         (*aopp)->aop_ptr2 = avr_regWithIdx(R31_IDX);
191         return (*aopp)->aopu.aop_ptr = avr_regWithIdx(R30_IDX);
192     }
193
194     /* now we know they both have usage */
195     /* if x not used in this instruction */
196     if (!xiu && !zonly) {
197         /* push it if not already pushed */
198         if (!_G.xPushed) {
199             emitcode ("push","%s",
200                       avr_regWithIdx(R26_IDX)->dname);
201             emitcode ("push","%s",
202                       avr_regWithIdx(R27_IDX)->dname);
203             _G.xPushed++ ;
204         }
205         
206         ic->rUsed = bitVectSetBit(ic->rUsed,X_IDX);
207         (*aopp)->type = AOP_X;
208
209         (*aopp)->aop_ptr2 = avr_regWithIdx(R27_IDX);
210         return (*aopp)->aopu.aop_ptr = avr_regWithIdx(R26_IDX);
211     }
212
213
214 endOfWorld :
215     /* I said end of world but not quite end of world yet */
216     /* if this is a result then we can push it on the stack*/
217     if (result) {
218         (*aopp)->type = AOP_STK;    
219         return NULL;
220     }
221
222     piCode(ic,stdout);
223     /* other wise this is true end of the world */
224     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
225            "getFreePtr should never reach here");
226     exit(0);
227 }
228
229 /*-----------------------------------------------------------------*/
230 /* newAsmop - creates a new asmOp                                  */
231 /*-----------------------------------------------------------------*/
232 static asmop *newAsmop (short type)
233 {
234     asmop *aop;
235
236     ALLOC(aop,sizeof(asmop));
237     aop->type = type;
238     return aop;
239 }
240
241 /*-----------------------------------------------------------------*/
242 /* pointerCode - returns the code for a pointer type               */
243 /*-----------------------------------------------------------------*/
244 static int pointerCode (link *etype)
245 {
246
247     return PTR_TYPE(SPEC_OCLS(etype));
248
249 }
250
251 /*-----------------------------------------------------------------*/
252 /* aopForSym - for a true symbol                                   */
253 /*-----------------------------------------------------------------*/
254 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
255 {
256     asmop *aop;
257     memmap *space= SPEC_OCLS(sym->etype);
258
259     /* if already has one */
260     if (sym->aop)
261         return sym->aop;
262
263     /* assign depending on the storage class */
264     /* if it is on the stack */
265     if (sym->onStack) {
266         sym->aop = aop = newAsmop(0);
267         aop->size = getSize(sym->type);
268
269         /* we can use std / ldd instruction */
270         if (sym->stack > 0 && (sym->stack + getSize(sym->type) - 1) <= 63) {
271             aop->type = AOP_STK_D;
272             aop->aopu.aop_stk = sym->stack;
273             return aop;
274         }
275
276         /* otherwise get a free pointer register X/Z */
277         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result,FALSE);
278
279         /* now assign the address of the variable to 
280            the pointer register */
281         if (aop->type != AOP_STK) {
282             emitcode("movw","%s,r28",aop->aopu.aop_ptr->name);
283             if (sym->stack < 0) {
284                 if ((sym->stack - _G.nRegsSaved) > -63) {
285                     emitcode("sbiw","%s,0x%02x",
286                              aop->aopu.aop_ptr->name,
287                              (sym->stack - _G.nRegsSaved));
288                 } else {
289                     emitcode("subi","%s,lo8(%d)", aop->aopu.aop_ptr->name,
290                              sym->stack - _G.nRegsSaved);
291                     emitcode("sbci","%s,hi8(%d)",aop->aop_ptr2->name,
292                              sym->stack - _G.nRegsSaved);
293                 }
294             } else {
295                 if (sym->stack <= 63) {
296                     emitcode("adiw","%s,0x%02x",aop->aopu.aop_ptr->name,sym->stack);
297                 } else {
298                     emitcode("subi","%s,lo8(-%d)",aop->aopu.aop_ptr->name,sym->stack);
299                     emitcode("sbci","%s,hi8(-%d)",aop->aop_ptr2->name,sym->stack); 
300                 }
301             }
302         }
303         return aop;
304     }
305     
306     /* if in bit space */
307     if (IN_BITSPACE(space)) {
308         sym->aop = aop = newAsmop (AOP_CRY);
309         aop->aopu.aop_dir = sym->rname ;
310         aop->size = getSize(sym->type);
311         return aop;
312     }
313     /* if it is in direct space */
314     if (IN_DIRSPACE(space)) {
315         sym->aop = aop = newAsmop (AOP_DIR);
316         aop->aopu.aop_dir = sym->rname ;
317         aop->size = getSize(sym->type);
318         return aop;
319     }
320
321     /* special case for a function */
322     if (IS_FUNC(sym->type)) {   
323         sym->aop = aop = newAsmop(AOP_IMMD);    
324         ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
325         strcpy(aop->aopu.aop_immd,sym->rname);
326         aop->size = FPTRSIZE; 
327         return aop;
328     }
329
330     /* only remaining is code / eeprom which will need pointer reg */
331     /* if it is in code space */
332     if (IN_CODESPACE(space))
333         aop->code = 1;
334
335     sym->aop = aop = newAsmop(0);
336     aop->aopu.aop_ptr = getFreePtr(ic,&aop,result,aop->code);
337     aop->size = getSize(sym->type);
338     emitcode ("ldi","%s,lo8(%s)",aop->aopu.aop_ptr->name,sym->rname);
339     emircode ("ldi","%s,hi8(%s)",aop->aop_ptr2);
340
341     return aop;     
342 }
343
344 /*-----------------------------------------------------------------*/
345 /* aopForRemat - rematerialzes an object                           */
346 /*-----------------------------------------------------------------*/
347 static asmop *aopForRemat (symbol *sym)
348 {
349     iCode *ic = sym->rematiCode;
350     asmop *aop = newAsmop(AOP_IMMD);
351     int val = 0;
352
353     for (;;) {
354         if (ic->op == '+')
355             val += operandLitValue(IC_RIGHT(ic));
356         else if (ic->op == '-')
357             val -= operandLitValue(IC_RIGHT(ic));
358         else
359             break;
360         
361         ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
362     }
363
364     if (val)
365         sprintf(buffer,"(%s %c 0x%04x)",
366                 OP_SYMBOL(IC_LEFT(ic))->rname, 
367                 val >= 0 ? '+' : '-',
368                 abs(val) & 0xffff);
369     else
370         strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
371
372     ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
373     strcpy(aop->aopu.aop_immd,buffer);    
374     return aop;        
375 }
376
377 /*-----------------------------------------------------------------*/
378 /* regsInCommon - two operands have some registers in common       */
379 /*-----------------------------------------------------------------*/
380 static bool regsInCommon (operand *op1, operand *op2)
381 {
382     symbol *sym1, *sym2;
383     int i;
384
385     /* if they have registers in common */
386     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
387         return FALSE ;
388
389     sym1 = OP_SYMBOL(op1);
390     sym2 = OP_SYMBOL(op2);
391
392     if (sym1->nRegs == 0 || sym2->nRegs == 0)
393         return FALSE ;
394
395     for (i = 0 ; i < sym1->nRegs ; i++) {
396         int j;
397         if (!sym1->regs[i])
398             continue ;
399
400         for (j = 0 ; j < sym2->nRegs ;j++ ) {
401             if (!sym2->regs[j])
402                 continue ;
403
404             if (sym2->regs[j] == sym1->regs[i])
405                 return TRUE ;
406         }
407     }
408
409     return FALSE ;
410 }
411
412 /*-----------------------------------------------------------------*/
413 /* operandsEqu - equivalent                                        */
414 /*-----------------------------------------------------------------*/
415 static bool operandsEqu ( operand *op1, operand *op2)
416 {
417     symbol *sym1, *sym2;
418
419     /* if they not symbols */
420     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
421         return FALSE;
422
423     sym1 = OP_SYMBOL(op1);
424     sym2 = OP_SYMBOL(op2);
425
426     /* if both are itemps & one is spilt
427        and the other is not then false */
428     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
429         sym1->isspilt != sym2->isspilt )
430         return FALSE ;
431
432     /* if they are the same */
433     if (sym1 == sym2)
434         return TRUE ;
435
436     if (strcmp(sym1->rname,sym2->rname) == 0)
437         return TRUE;
438
439
440     /* if left is a tmp & right is not */
441     if (IS_ITEMP(op1)  && 
442         !IS_ITEMP(op2) &&
443         sym1->isspilt  &&
444         (sym1->usl.spillLoc == sym2))
445         return TRUE;
446
447     if (IS_ITEMP(op2)  && 
448         !IS_ITEMP(op1) &&
449         sym2->isspilt  &&
450         sym1->level > 0 &&
451         (sym2->usl.spillLoc == sym1))
452         return TRUE ;
453
454     return FALSE ;
455 }
456
457 /*-----------------------------------------------------------------*/
458 /* sameRegs - two asmops have the same registers                   */
459 /*-----------------------------------------------------------------*/
460 static bool sameRegs (asmop *aop1, asmop *aop2 )
461 {
462     int i;
463
464     if (aop1 == aop2)
465         return TRUE ;
466
467     if (aop1->type != AOP_REG ||
468         aop2->type != AOP_REG )
469         return FALSE ;
470
471     if (aop1->size != aop2->size )
472         return FALSE ;
473
474     for (i = 0 ; i < aop1->size ; i++ )
475         if (aop1->aopu.aop_reg[i] !=
476             aop2->aopu.aop_reg[i] )
477             return FALSE ;
478
479     return TRUE ;
480 }
481
482 /*-----------------------------------------------------------------*/
483 /* isRegPair - for size 2 if this operand has a register pair      */
484 /*-----------------------------------------------------------------*/
485 static int isRegPair (aop *aopp)
486 {
487     if (!aop || aop->size != 2) return 0;
488     if (aop->type == AOP_X || aop->type == AOP_Y) return 1;
489     if (aop->type != AOP_REG) return 0;
490     if ((aop->aopu.aop_reg[1]->rIdx - 
491          aop->aopu.aop_reg[0]->rIdx) == 1) return 1;
492     return 0;
493 }
494
495 /*-----------------------------------------------------------------*/
496 /* aopOp - allocates an asmop for an operand  :                    */
497 /*-----------------------------------------------------------------*/
498 static void aopOp (operand *op, iCode *ic, bool result)
499 {
500     asmop *aop;
501     symbol *sym;
502     int i;
503
504     if (!op)
505         return ;
506
507     /* if this a literal */
508     if (IS_OP_LITERAL(op)) {
509         op->aop = aop = newAsmop(AOP_LIT);
510         aop->aopu.aop_lit = op->operand.valOperand;
511         aop->size = getSize(operandType(op));
512         return;
513     }
514
515     /* if already has a asmop then continue */
516     if (op->aop)
517         return ;
518
519     /* if the underlying symbol has a aop */
520     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
521         op->aop = OP_SYMBOL(op)->aop;
522         return;
523     }
524
525     /* if this is a true symbol */
526     if (IS_TRUE_SYMOP(op)) {    
527         op->aop = aopForSym(ic,OP_SYMBOL(op),result);
528         return ;
529     }
530
531     /* this is a temporary : this has
532     only four choices :
533     a) register
534     b) spillocation
535     c) rematerialize 
536     d) conditional   
537     e) can be a return use only */
538
539     sym = OP_SYMBOL(op);
540
541
542     /* if the type is a conditional */
543     if (sym->regType == REG_CND) {
544         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
545         aop->size = 0;
546         return;
547     }
548
549     /* if it is spilt then two situations
550     a) is rematerialize 
551     b) has a spill location */
552     if (sym->isspilt || sym->nRegs == 0) {
553
554         /* rematerialize it NOW */
555         if (sym->remat) {
556             sym->aop = op->aop = aop =
557                                       aopForRemat (sym);
558             aop->size = getSize(sym->type);
559             return;
560         }
561
562         if (sym->accuse) {
563                 assert("ACC_USE cannot happen in AVR\n");
564         }
565
566         if (sym->ruonly ) {
567             int i;
568             aop = op->aop = sym->aop = newAsmop(AOP_STR);
569             aop->size = getSize(sym->type);
570             for ( i = 0 ; i < fReturnSize ; i++ )
571                 aop->aopu.aop_str[i] = fReturn[i];
572             return;
573         }
574
575         /* else spill location  */
576         sym->aop = op->aop = aop = 
577                                   aopForSym(ic,sym->usl.spillLoc,result);
578         aop->size = getSize(sym->type);
579         return;
580     }
581
582     /* must be in a register */
583     sym->aop = op->aop = aop = newAsmop(AOP_REG);
584     aop->size = sym->nRegs;
585     for ( i = 0 ; i < sym->nRegs ;i++)
586         aop->aopu.aop_reg[i] = sym->regs[i];
587 }
588
589 /*-----------------------------------------------------------------*/
590 /* freeAsmop - free up the asmop given to an operand               */
591 /*----------------------------------------------------------------*/
592 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
593 {   
594     asmop *aop ;
595
596     if (!op)
597         aop = aaop;
598     else 
599         aop = op->aop;
600
601     if (!aop)
602         return ;
603
604     if (aop->freed)
605         goto dealloc; 
606
607     aop->freed = 1;
608
609     /* depending on the asmop type only three cases need work AOP_RO
610        , AOP_R1 && AOP_STK */
611     switch (aop->type) {
612         case AOP_X :
613             if (_G.xPushed ) {
614                 if (pop) {
615                     emitcode ("pop","r26");
616                     emitcode ("pop","r27");
617                     _G.xPushed--;
618                 }
619             }
620             bitVectUnSetBit(ic->rUsed,X_IDX);
621             break;
622
623         case AOP_Z :
624             if (_G.zPushed ) {
625                 if (pop) {
626                     emitcode ("pop","r30");
627                     emitcode ("pop","r31");
628                     _G.zPushed--;
629                 }
630             }
631             bitVectUnSetBit(ic->rUsed,Z_IDX);          
632             break;
633
634         case AOP_STK :
635         {
636             int sz = aop->size;    
637             int stk = aop->aopu.aop_stk + aop->size;
638             bitVectUnSetBit(ic->rUsed,X_IDX);
639             bitVectUnSetBit(ic->rUsed,Z_IDX);          
640
641             getFreePtr(ic,&aop,FALSE,0);
642             
643             emitcode ("movw","%s,r28");
644             if (stk) {
645                 if (stk <= 63 && stk > 0) {
646                     emitcode ("adiw","%s,0x%02x",aop->aopu.aop_ptr->name,stk+1);
647                 } else {
648                     emitcode ("subi","%s,lo8(%d)",aop->aopu.aop_ptr->name,-(stk+1));
649                     emitcode ("sbci","%s,hi8(%d)",aop->aop_ptr2->name,-(stk+1));
650                 }
651             }
652
653             while (sz--) {
654                 emitcode("pop","r24");
655                 emitcode("st","-%s,r24",aop->type == AOP_X ? "X" : "Z");
656                 if (!sz) break;
657             }
658             op->aop = aop;
659             freeAsmop(op,NULL,ic,TRUE);
660             if (_G.xPushed) {
661                 emitcode("pop","r26");
662                 emitcode("pop","r27");
663                 _G.xPushed--;
664             }
665
666             if (_G.zPushed) {
667                 emitcode("pop","r30");
668                 emitcode("pop","r31");
669                 _G.zPushed--;
670             }       
671         }
672     }
673
674 dealloc:
675     /* all other cases just dealloc */
676     if (op ) {
677         op->aop = NULL;
678         if (IS_SYMOP(op)) {
679             OP_SYMBOL(op)->aop = NULL;    
680             /* if the symbol has a spill */
681             if (SPIL_LOC(op))
682                 SPIL_LOC(op)->aop = NULL;
683         }
684     }
685 }
686
687 /*-----------------------------------------------------------------*/
688 /* aopGet - for fetching value of the aop                          */
689 /*-----------------------------------------------------------------*/
690 static char *aopGet (asmop *aop, int offset)
691 {
692     char *s = buffer ;
693     char *rs;
694
695     /* offset is greater than
696     size then zero */
697     if (offset > (aop->size - 1) &&
698         aop->type != AOP_LIT)
699         return zero;
700
701     /* depending on type */
702     switch (aop->type) {
703         
704     case AOP_X:
705         if (offset > aop->coff) {
706             emitcode ("adiw","%s,%d",aop->aopu.aop_ptr->name,offset - aop->coff);  
707         }
708         
709         if (offset < aop->coff) {
710             emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,aop->coff - offset);
711         }
712         
713         aop->coff = offset ;
714         emitcode("ld","%s,x",
715                      (rs = ((offset & 1) ? "r25" : "r24")));
716         return rs;
717
718     case AOP_Z:
719         if (aop->code) {
720             if (offset > aop->coff) {
721                 emitcode("adiw","r30,%d",offset - aop->coff);
722             } else {
723                 emitcode("sbiw","r30,%d",aop->coff - offset);
724             }
725             emitcode("lpm","%s,z",(rs = ((offset & 1) ? "r25" : "r24")));
726         } else {
727             /* we can use lds */
728             if (offset  > aop->coff) {
729                 emitcode ("ldd","%s,z+%d",(rs = ((offset & 1) ? "r25" : "r24")),
730                           offset - aop->coff);
731             } else {
732                 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,aop->coff - offset);
733                 aop->coff = offset;
734                 emitcode ("ld","%s,z",(rs = ((offset & 1) ? "r25" : "r24")));
735             }
736         }
737         return rs;
738
739     case AOP_IMMD:
740         
741         emitcode ("lds","%s,(%s)+%d",
742                   (rs = ((offset & 1) ? "r25" : "r24")),
743                   aop->aopu.aop_immd, offset);
744         return rs;
745         
746     case AOP_DIR:
747         emitcode ("lds","%s,(%s)+%d",
748                   (rs = ((offset & 1) ? "r25" : "r24")),
749                   aop->aopu.aop_dir, offset);
750         return rs;
751         
752     case AOP_REG:
753         return aop->aopu.aop_reg[offset]->name;
754         
755     case AOP_CRY:
756         assert("cannot be in bit space AOP_CRY\n");
757         break;
758
759     case AOP_LIT:
760         s = aopLiteral(aop->aopu.aop_lit,offset);
761         emitcode("ldi","%s,lo8(%s)",(rs = ((offset & 1)?"r24" : "r25")),s);
762         return rs;
763
764     case AOP_STR:
765         aop->coff = offset ;
766         return aop->aopu.aop_str[offset];
767         
768     case AOP_STK_D:
769         emitcode ("ldd","%s,Y+%d",
770                   (rs = ((offset & 1) ? "r25" : "r24")),                  
771                   aop->aopu.aop_stk+offset);
772         return rs;
773     }
774
775     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
776            "aopget got unsupported aop->type");
777     exit(0);
778 }
779 /*-----------------------------------------------------------------*/
780 /* aopPut - puts a string for a aop                                */
781 /*-----------------------------------------------------------------*/
782 static void aopPut (asmop *aop, char *s, int offset)
783 {
784     char *d = buffer ;
785     symbol *lbl ;
786
787     if (aop->size && offset > ( aop->size - 1)) {
788         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
789                "aopPut got offset > aop->size");
790         exit(0);
791     }
792
793     /* will assign value to value */
794     /* depending on where it is ofcourse */
795     switch (aop->type) {
796     case AOP_DIR:
797         if (offset) {
798             sprintf(d,"(%s)+%d", aop->aopu.aop_dir,offset);
799         }
800         else {
801             sprintf(d,"%s",aop->aopu.aop_dir);
802         }
803         
804         emitcode("sts","%s,%s",d,s);
805         break;
806         
807     case AOP_REG:
808         if (toupper(*s) != 'R') {
809             if (s == zero) {
810                 emitcode("clr","%s",aop->aopu.aop_reg[offset]->name);
811             } else {
812                 emitcode("ldi","r25,%s",s);
813                 emitcode("mov","%s,r35",aop->aopu.aop_reg[offset]->name);
814             }
815         } else {
816             if (strcmp( aop->aopu.aop_reg[offset]->name,s)) {
817                 emitcode("mov","%s,%s", aop->aopu.aop_reg[offset]->name,s);
818             }
819         }
820         break;
821         
822     case AOP_X:
823         if (offset > aop->coff) {
824             emitcode ("adiw","%s,%d",aop->aopu.aop_ptr->name,offset - aop->coff);  
825         }
826         
827         if (offset < aop->coff) {
828             emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,aop->coff - offset);
829         }
830         
831         aop->coff = offset ;
832         emitcode("st","x,%s", s);
833         break;
834         
835     case AOP_Z:
836         if (aop->code) {
837             if (offset > aop->coff) {
838                 emitcode("adiw","r30,%d",offset - aop->coff);
839             } else {
840                 emitcode("sbiw","r30,%d",aop->coff - offset);
841             }
842             emitcode("lpm","%s,z",s);
843         } else {
844             /* we can use lds */
845             if (offset  > aop->coff) {
846                 emitcode ("sdd","z+%d,%s",offset - aop->coff,s);
847             } else {
848                 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,aop->coff - offset);
849                 aop->coff = offset;
850                 emitcode ("ld","%s,z",s);
851             }
852         }
853         break;
854         
855     case AOP_STK:
856         emitcode("push","%s",s);        
857         break;
858         
859     case AOP_CRY:
860         /* if used only for a condition code check */
861         assert(toupper(*s) == 'R');
862         if (offset == 0) {
863             emitcode("xrl","r0,r0");
864             emitcode("cpi","%s,0",s);
865         }
866         else {
867             emitcode("cpc","r0,%s",s);
868         }
869         break;
870         
871     case AOP_STR:
872         aop->coff = offset;
873         if (strcmp(aop->aopu.aop_str[offset],s))
874             emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
875         break;
876
877     case AOP_STK_D:
878         emitcode ("std","y+%d,%s",offset,s);
879         break;
880
881     default :
882         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
883                "aopPut got unsupported aop->type");
884         exit(0);    
885     }    
886
887 }
888
889 /*-----------------------------------------------------------------*/
890 /* reAdjustPreg - points a register back to where it should        */
891 /*-----------------------------------------------------------------*/
892 static void reAdjustPreg (asmop *aop)
893 {
894     int size ;
895
896     aop->coff = 0;
897     if ((size = aop->size) <= 1)
898         return ;
899     size-- ;
900     switch (aop->type) {
901         case AOP_X :
902         case AOP_Z :
903             emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,size);
904             break;          
905     }
906
907 }
908
909 #define AOP(op) op->aop
910 #define AOP_TYPE(op) AOP(op)->type
911 #define AOP_SIZE(op) AOP(op)->size
912 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_X || \
913                        AOP_TYPE(x) == AOP_Z))
914 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                      \
915                       (x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) || \
916                       x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) )))
917
918 /*-----------------------------------------------------------------*/
919 /* genNotFloat - generates not for float operations                */
920 /*-----------------------------------------------------------------*/
921 static void genNotFloat (operand *op, operand *res)
922 {
923     int size, offset;
924     char *l;
925     symbol *tlbl ;
926
927     /* we will put 127 in the first byte of 
928     the result */
929     aopPut(AOP(res),"127",0);
930     size = AOP_SIZE(op) - 1;
931     offset = 1;
932
933     l = aopGet(op->aop,offset++);
934     MOVR0(l);    
935
936     while(size--) {
937         emitcode("or","R0,%s", aopGet(op->aop, offset++);
938     }
939     tlbl = newiTempLabel(NULL);
940
941     tlbl = newiTempLabel(NULL);
942     aopPut(res->aop,zero,1);
943     emitcode("cpi","r0,0");
944     emitcode("breq","L%05d",tlbl->key);
945     aopPut(res->aop,one,1);
946     emitcode("","L%05d:",tlbl->key);
947
948     size = res->aop->size - 2;
949     offset = 2;    
950     /* put zeros in the rest */
951     while (size--) 
952         aopPut(res->aop,zero,offset++);
953 }
954
955 /*-----------------------------------------------------------------*/
956 /* opIsGptr: returns non-zero if the passed operand is             */   
957 /* a generic pointer type.                                         */
958 /*-----------------------------------------------------------------*/ 
959 static int opIsGptr(operand *op)
960 {
961     link *type = operandType(op);
962     
963     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
964     {
965         return 1;
966     }
967     return 0;        
968 }
969
970 /*-----------------------------------------------------------------*/
971 /* getDataSize - get the operand data size                         */
972 /*-----------------------------------------------------------------*/
973 static int getDataSize(operand *op)
974 {
975     int size;
976     size = AOP_SIZE(op);
977     if (size == GPTRSIZE)
978     {
979         link *type = operandType(op);
980         if (IS_GENPTR(type))
981         {
982             /* generic pointer; arithmetic operations
983              * should ignore the high byte (pointer type).
984              */
985             size--;
986         }
987     }
988     return size;
989 }
990
991 /*-----------------------------------------------------------------*/
992 /* outAcc - output Acc                                             */
993 /*-----------------------------------------------------------------*/
994 static void outAcc(operand *result)
995 {
996     int size, offset;
997     size = getDataSize(result);
998     if(size){
999         aopPut(AOP(result),"r0",0);
1000         size--;
1001         offset = 1;
1002         /* unsigned or positive */
1003         while(size--){
1004             aopPut(AOP(result),zero,offset++);
1005         }
1006     }
1007 }
1008
1009 /*-----------------------------------------------------------------*/
1010 /* outBitC - output a bit C                                        */
1011 /*-----------------------------------------------------------------*/
1012 static void outBitC(operand *result)
1013 {
1014     emitcode("clr","r0");
1015     emitcode("rol","r0");
1016     outAcc(result);
1017 }
1018
1019 /*-----------------------------------------------------------------*/
1020 /* toBoolean - emit code for orl a,operator(sizeop)                */
1021 /*-----------------------------------------------------------------*/
1022 static void toBoolean(operand *oper, char *r, bool clr)
1023 {
1024     int size = AOP_SIZE(oper) ;
1025     int offset = 0;
1026     if (clr) emitcode ("clr","%s",r);
1027     while (size--) 
1028         emitcode("or","%s,%s",r,aopGet(AOP(oper),offset++));
1029 }
1030
1031
1032 /*-----------------------------------------------------------------*/
1033 /* genNot - generate code for ! operation                          */
1034 /*-----------------------------------------------------------------*/
1035 static void genNot (iCode *ic)
1036 {
1037     symbol *tlbl;
1038     link *optype = operandType(IC_LEFT(ic));
1039     int size, offset = 1;
1040
1041     /* assign asmOps to operand & result */
1042     aopOp (IC_LEFT(ic),ic,FALSE);
1043     aopOp (IC_RESULT(ic),ic,TRUE);
1044
1045     /* if type float then do float */
1046     if (IS_FLOAT(optype)) {
1047         genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1048         goto release;
1049     }
1050     emitcode("clr","r24");
1051     tlbl = newiTempLabel(NULL);
1052     toBoolean(IC_LEFT(ic),"r0",TRUE);
1053     emitcode("bne","L%05d",tlbl->key);
1054     emitcode("ldi","r24,1");
1055     emitcode("","L%05d:",tlbl->key);
1056     aopPut(AOP(IC_RESULT(ic)),"r24",0);
1057     size = AOP_SIZE(IC_RESULT(ic)) -1;
1058     while (size--) aopPut(AOP(IC_RESULT(ic)),zero,offset++);
1059     
1060
1061 release:    
1062     /* release the aops */
1063     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1064     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1065 }
1066
1067
1068 /*-----------------------------------------------------------------*/
1069 /* genCpl - generate code for complement                           */
1070 /*-----------------------------------------------------------------*/
1071 static void genCpl (iCode *ic)
1072 {
1073     int offset = 0;
1074     int size ;
1075     int samer;
1076
1077     /* assign asmOps to operand & result */
1078     aopOp (IC_LEFT(ic),ic,FALSE);
1079     aopOp (IC_RESULT(ic),ic,TRUE);
1080     samer = sameRegs(AOP(IC_LEFT(ic),AOP(IC_RESULT(ic))));
1081     size = AOP_SIZE(IC_RESULT(ic));
1082     while (size--) {
1083         char *l = aopGet(AOP(IC_LEFT(ic)),offset);
1084         if (samer) {
1085             emitcode ("com","%s",l);
1086         } else {
1087             aopPut(AOP(IC_RESULT(ic)),l,offset);
1088             emitcode ("com","%s",aopGet(AOP(IC_RESULT(ic)),offset++));
1089         }
1090     }
1091
1092
1093 release:
1094     /* release the aops */
1095     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1096     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1097 }
1098
1099 /*-----------------------------------------------------------------*/
1100 /* genUminusFloat - unary minus for floating points                */
1101 /*-----------------------------------------------------------------*/
1102 static void genUminusFloat(operand *op,operand *result)
1103 {
1104     int size ,offset =0 ;
1105     char *l;
1106     /* for this we just need to flip the 
1107     first it then copy the rest in place */
1108     size = AOP_SIZE(op) - 1;
1109     l = aopGet(AOP(op),3);
1110     
1111     emitcode("ldi","r24,0x80");
1112     if (sameRegs(AOP(op),AOP(result))) {
1113         emitcode("eor","%s,r24",l);
1114     } else {
1115         aopPut(AOP(result),l,3);
1116         emitcode("eor","%s,r24",aopGet(AOP(result),3));
1117     }
1118     while(size--) {
1119         aopPut(AOP(result), aopGet(AOP(op),offset), offset);
1120         offset++;
1121     }          
1122 }
1123
1124 /*-----------------------------------------------------------------*/
1125 /* genUminus - unary minus code generation                         */
1126 /*-----------------------------------------------------------------*/
1127 static void genUminus (iCode *ic)
1128 {
1129     int offset ,size ;
1130     link *optype, *rtype;
1131     int samer ;
1132
1133     /* assign asmops */
1134     aopOp(IC_LEFT(ic),ic,FALSE);
1135     aopOp(IC_RESULT(ic),ic,TRUE);
1136
1137     optype = operandType(IC_LEFT(ic));
1138     rtype = operandType(IC_RESULT(ic));
1139
1140     /* if float then do float stuff */
1141     if (IS_FLOAT(optype)) {
1142         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1143         goto release;
1144     }
1145
1146     /* otherwise subtract from zero */
1147     size = AOP_SIZE(IC_LEFT(ic));
1148     offset = 0 ;
1149     samer = sameRegs(AOP(IC_LEFT(ic)),AOP(IC_RESULT(ic)));
1150     CLRC;
1151     while(size--) {
1152         char *l = aopGet(AOP(IC_LEFT(ic)),offset);
1153         if (samer) {
1154             emitcode("clr","r0");
1155             emitcode("sbc","r0,%s",l);
1156             aopPut(AOP(IC_RESULT(ic)),"r0",offset++);
1157         } else {
1158             char *s;
1159             emitcode("clr","%s",s=aopGet(IC_RESULT(ic),offset++));
1160             emitcode("sbc","%s,%s",s,l);
1161         }
1162     }
1163
1164     /* if any remaining bytes in the result */
1165     /* we just need to propagate the sign   */
1166     if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1167         symbol *tlbl = newiTempLabel(NULL);
1168         emitcode("clr","r0");
1169         emitcode("brcc","L%05d",tlbl->key);
1170         emitcode("com","r0");
1171         emitcode("","L%05d:",tlbl->key);
1172         while (size--) 
1173             aopPut(AOP(IC_RESULT(ic)),"r0",offset++);
1174     }       
1175
1176 release:
1177     /* release the aops */
1178     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1179     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
1180 }
1181
1182 /*-----------------------------------------------------------------*/
1183 /* assignResultValue -                                             */
1184 /*-----------------------------------------------------------------*/
1185 static void assignResultValue(operand * oper)
1186 {
1187         int offset = 0;
1188         int size = AOP_SIZE(oper);
1189         while (size--) {
1190                 aopPut(AOP(oper),fReturn[offset],offset);
1191                 offset++;
1192         }
1193 }
1194
1195 /*-----------------------------------------------------------------*/
1196 /* saveZreg - if indirect call then save z-pointer register        */
1197 /*-----------------------------------------------------------------*/
1198 static void saveZreg (iCode *ic)
1199 {
1200         /* only if live accross this call */
1201         if (ic->regSaved == 0 && 
1202             (bitVectBitValue(ic->rMask,R30_IDX) ||
1203             bitVectBitValue(ic->rMask,R31_IDX))) {
1204             ic->regsSaved = 1;
1205             emitcode("push","r30");
1206             emitcode("push","r31");
1207         }
1208 }
1209
1210 /*-----------------------------------------------------------------*/
1211 /* popZreg - restore values of zreg                                */
1212 /*-----------------------------------------------------------------*/
1213 static void popZreg (iCode *ic)
1214 {
1215     if (ic->regsSaved) {
1216         emitcode ("pop","r31");
1217         emitcode ("pop","r30");
1218     }
1219 }
1220
1221 /*-----------------------------------------------------------------*/
1222 /* genIpush - genrate code for pushing this gets a little complex  */
1223 /*-----------------------------------------------------------------*/
1224 static void genIpush (iCode *ic)
1225 {
1226     int size, offset = 0 ;
1227     char *l;
1228
1229
1230     if (!ic->parmPush) {
1231         /* and the item is spilt then do nothing */
1232         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1233             return ;
1234     } else {
1235             iCode *lic ; 
1236             for (lic = ic->next ; lic ; lic = lic->next) 
1237                     if (lic->op == PCALL) break;
1238             if (lic) saveZreg(lic);
1239     }
1240
1241     /* this is a paramter push */
1242     aopOp(IC_LEFT(ic),ic,FALSE);
1243     size = AOP_SIZE(IC_LEFT(ic));
1244     while (size--) {
1245         l = aopGet(AOP(IC_LEFT(ic)),offset++);
1246         emitcode("push","%s",l);
1247     }       
1248
1249     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1250 }
1251
1252 /*-----------------------------------------------------------------*/
1253 /* genIpop - recover the registers: can happen only for spilling   */
1254 /*-----------------------------------------------------------------*/
1255 static void genIpop (iCode *ic)
1256 {
1257     int size,offset ;
1258
1259
1260     /* if the temp was not pushed then */
1261     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1262         return ;
1263
1264     aopOp(IC_LEFT(ic),ic,FALSE);
1265     size = AOP_SIZE(IC_LEFT(ic));
1266     offset = (size-1);
1267     while (size--) 
1268         emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--));
1269
1270     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1271 }
1272
1273 /*-----------------------------------------------------------------*/
1274 /* genCall - generates a call statement                            */
1275 /*-----------------------------------------------------------------*/
1276 static void genCall (iCode *ic)
1277 {
1278     link *detype;   
1279
1280     /* if send set is not empty the assign */
1281     if (_G.sendSet) {
1282         iCode *sic ;
1283
1284         for (sic = setFirstItem(_G.sendSet) ; sic ; 
1285              sic = setNextItem(_G.sendSet)) {
1286             int size, offset = 0;
1287             aopOp(IC_LEFT(sic),sic,FALSE);
1288             size = AOP_SIZE(IC_LEFT(sic));
1289             while (size--) {
1290                 char *l = aopGet(AOP(IC_LEFT(sic)),offset);
1291                 if (strcmp(l,fReturn[offset]))
1292                     emitcode("mov","%s,%s",
1293                              fReturn[offset],
1294                              l);
1295                 offset++;
1296             }
1297             freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1298         }
1299         _G.sendSet = NULL;
1300     }
1301     /* make the call */
1302     emitcode("call","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1303                            OP_SYMBOL(IC_LEFT(ic))->rname :
1304                            OP_SYMBOL(IC_LEFT(ic))->name));
1305
1306     /* if we need assign a result value */
1307     if ((IS_ITEMP(IC_RESULT(ic)) && 
1308          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1309           OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1310         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1311
1312         aopOp(IC_RESULT(ic),ic,FALSE);
1313         assignResultValue(IC_RESULT(ic));
1314         freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1315     }
1316
1317     /* adjust the stack for parameters if required */
1318     if (IC_LEFT(ic)->parmBytes) {
1319         if (IC_LEFT(ic)->parmBytes > 63) {
1320             emitcode("sbiw","r28,%d",IC_LEFT(ic)->parmBytes);
1321         } else {
1322             emitcode("subi","r28,lo8(%d)",IC_LEFT(ic)->parmBytes);
1323             emitcode("sbci","r29,hi8(%d)",IC_LEFT(ic)->parmBytes);
1324         }
1325     }
1326
1327 }
1328
1329 /*-----------------------------------------------------------------*/
1330 /* genPcall - generates a call by pointer statement                */
1331 /*-----------------------------------------------------------------*/
1332 static void genPcall (iCode *ic)
1333 {
1334     link *detype;
1335
1336     if (!ic->regsSaved) saveZreg(ic);
1337
1338     aopOp(IC_LEFT(ic),ic,FALSE);
1339     emitcode("mov","r30",aopGet(AOP(IC_LEFT(ic)),0));
1340     emitcode("mov","r31",aopGet(AOP(IC_RIGHT(ic)),0));
1341     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
1342
1343     /* if send set is not empty the assign */
1344     if (_G.sendSet) {
1345         iCode *sic ;
1346
1347         for (sic = setFirstItem(_G.sendSet) ; sic ; 
1348              sic = setNextItem(_G.sendSet)) {
1349             int size, offset = 0;
1350             aopOp(IC_LEFT(sic),sic,FALSE);
1351             size = AOP_SIZE(IC_LEFT(sic));
1352             while (size--) {
1353                 char *l = aopGet(AOP(IC_LEFT(sic)),offset);
1354                 if (strcmp(l,fReturn[offset]))
1355                     emitcode("mov","%s,%s",
1356                              fReturn[offset],
1357                              l);
1358                 offset++;
1359             }
1360             freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1361         }
1362         _G.sendSet = NULL;
1363     }
1364
1365     emitcode("icall","");
1366
1367     /* if we need assign a result value */
1368     if ((IS_ITEMP(IC_RESULT(ic)) &&
1369          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1370           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
1371         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1372
1373         aopOp(IC_RESULT(ic),ic,FALSE);
1374
1375         assignResultValue(IC_RESULT(ic));
1376         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1377     }
1378
1379     /* adjust the stack for parameters if 
1380     required */
1381     if (IC_LEFT(ic)->parmBytes) {
1382         int i;
1383         if (IC_LEFT(ic)->parmBytes > 3) {
1384             emitcode("mov","a,%s",spname);
1385             emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1386             emitcode("mov","%s,a",spname);
1387         } else 
1388             for ( i = 0 ; i <  IC_LEFT(ic)->parmBytes ;i++)
1389                 emitcode("dec","%s",spname);
1390
1391     }
1392
1393     /* adjust the stack for parameters if required */
1394     if (IC_LEFT(ic)->parmBytes) {
1395         if (IC_LEFT(ic)->parmBytes > 63) {
1396             emitcode("sbiw","r28,%d",IC_LEFT(ic)->parmBytes);
1397         } else {
1398             emitcode("subi","r28,lo8(%d)",IC_LEFT(ic)->parmBytes);
1399             emitcode("sbci","r29,hi8(%d)",IC_LEFT(ic)->parmBytes);
1400         }
1401     }
1402     if (ic->regsSaved) popZregs(ic);
1403 }
1404
1405 /*-----------------------------------------------------------------*/
1406 /* resultRemat - result  is rematerializable                       */
1407 /*-----------------------------------------------------------------*/
1408 static int resultRemat (iCode *ic)
1409 {
1410     if (SKIP_IC(ic) || ic->op == IFX)
1411         return 0;
1412
1413     if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1414         symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1415         if (sym->remat && !POINTER_SET(ic)) 
1416             return 1;
1417     }
1418
1419     return 0;
1420 }
1421
1422 #ifdef __BORLANDC__
1423 #define STRCASECMP stricmp
1424 #else
1425 #define STRCASECMP strcasecmp
1426 #endif
1427
1428 /*-----------------------------------------------------------------*/
1429 /* inExcludeList - return 1 if the string is in exclude Reg list   */
1430 /*-----------------------------------------------------------------*/
1431 static bool inExcludeList(char *s)
1432 {
1433     int i =0;
1434     
1435     if (options.excludeRegs[i] &&
1436     STRCASECMP(options.excludeRegs[i],"none") == 0)
1437         return FALSE ;
1438
1439     for ( i = 0 ; options.excludeRegs[i]; i++) {
1440         if (options.excludeRegs[i] &&
1441         STRCASECMP(s,options.excludeRegs[i]) == 0)
1442             return TRUE;
1443     }
1444     return FALSE ;
1445 }
1446
1447 /*-----------------------------------------------------------------*/
1448 /* genFunction - generated code for function entry                 */
1449 /*-----------------------------------------------------------------*/
1450 static void genFunction (iCode *ic)
1451 {
1452     symbol *sym;
1453     link *fetype;
1454     int i = 0;
1455
1456     _G.nRegsSaved = 0;
1457     /* create the function header */
1458     emitcode(";","-----------------------------------------");
1459     emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1460     emitcode(";","-----------------------------------------");
1461
1462     emitcode("","%s:",sym->rname);
1463     fetype = getSpec(operandType(IC_LEFT(ic)));
1464
1465     /* if critical function then turn interrupts off */
1466     if (SPEC_CRTCL(fetype))
1467         emitcode("cli");
1468
1469     if (IS_ISR(sym->etype)) {
1470     }
1471
1472     /* save the preserved registers that are used in this function */
1473     for (i = R2_IDX ; i <= R15_IDX ; i++ ) {
1474         if (bitVectBitValue(sym->regsUsed,i)) {
1475             _G.nRegsSaved++;
1476             emitcode("push","%s",avr_regWithIdx(i)->name);
1477         }
1478     }
1479     /* now for the pointer registers */
1480     if (bitVectBitValue(sym->regsUsed,R26_IDX)) {
1481         _G.nRegsSaved++;
1482         emitcode("push","r26");
1483     }
1484     if (bitVectBitValue(sym->regsUsed,R27_IDX)) {
1485         _G.nRegsSaved++;
1486         emitcode("push","r27");
1487     }
1488     if (bitVectBitValue(sym->regsUsed,R30_IDX)) {
1489         _G.nRegsSaved++;
1490         emitcode("push","r30");
1491     }
1492     if (bitVectBitValue(sym->regsUsed,R31_IDX)) {
1493         _G.nRegsSaved++;
1494         emitcode("push","r31");
1495     }
1496     /* adjust the stack for the function */
1497     if (sym->stack) {
1498         emitcode ("push","r28");
1499         emitcode ("push","r29");
1500         emitcode ("in","r28,__SP_L__");
1501         emitcode ("in","r29,__SP_H__");
1502         if (sym->stack <= 63) {
1503             emitcode("sbiw","r28,%d",sym->stack);
1504         } else {
1505             emitcode ("subi","r28,lo8(%d)",sym->stack);
1506             emitcode ("sbci","r29,hi8(%d)",sym->stack);
1507         }
1508         emitcode("out","__SP_L__,r28");
1509         emitcode("out","__SP_H__,r29");
1510     }
1511 }
1512
1513 /*-----------------------------------------------------------------*/
1514 /* genEndFunction - generates epilogue for functions               */
1515 /*-----------------------------------------------------------------*/
1516 static void genEndFunction (iCode *ic)
1517 {
1518     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1519
1520     /* restore stack pointer */
1521     if (sym->stack <= 63) {
1522         emitcode("adiw","r28,%d",sym->stack);
1523     } else {
1524         emitcode ("subi","r28,lo8(-%d)",sym->stack);
1525         emitcode ("sbci","r29,hi8(-%d)",sym->stack);
1526     }
1527     emitcode("out","__SP_L__,r28");
1528     emitcode("out","__SP_H__,r29");
1529
1530     /* pop frame pointer */
1531     emitcode ("pop","r29");
1532     emitcode ("pop","r28");
1533
1534     /* restore preserved registers */
1535     if (bitVectBitValue(sym->regsUsed,R31_IDX)) {
1536         _G.nRegsSaved--;
1537         emitcode("pop","r31");
1538     }
1539     if (bitVectBitValue(sym->regsUsed,R30_IDX)) {
1540         _G.nRegsSaved--;
1541         emitcode("pop","r30");
1542     }
1543     if (bitVectBitValue(sym->regsUsed,R27_IDX)) {
1544         _G.nRegsSaved--;
1545         emitcode("push","r27");
1546     }
1547     if (bitVectBitValue(sym->regsUsed,R26_IDX)) {
1548         _G.nRegsSaved--;
1549         emitcode("push","r26");
1550     }
1551     for (i = R15_IDX ; i >= R2_IDX ; i-- ) {
1552         if (bitVectBitValue(sym->regsUsed,i)) {
1553             _G.nRegsSaved--;
1554             emitcode("pop","%s",avr_regWithIdx(i)->name);
1555         }
1556     }
1557
1558     if (IS_ISR(sym->etype)) {
1559     }
1560
1561     if (SPEC_CRTCL(fetype))
1562         emitcode("sti");
1563 }
1564
1565 /*-----------------------------------------------------------------*/
1566 /* genRet - generate code for return statement                     */
1567 /*-----------------------------------------------------------------*/
1568 static void genRet (iCode *ic)
1569 {
1570     int size,offset = 0 , pushed = 0;
1571     
1572     /* if we have no return value then
1573        just generate the "ret" */
1574     if (!IC_LEFT(ic)) 
1575         goto jumpret;       
1576     
1577     /* we have something to return then
1578        move the return value into place */
1579     aopOp(IC_LEFT(ic),ic,FALSE);
1580     size = AOP_SIZE(IC_LEFT(ic));
1581     
1582     while (size--) {
1583         char *l ;
1584         l = aopGet(AOP(IC_LEFT(ic)),offset);
1585         if (strcmp(fReturn[offset],l))
1586             emitcode("mov","%s,%s",fReturn[offset++],l);
1587     }    
1588
1589     freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
1590     
1591  jumpret:
1592         /* generate a jump to the return label
1593            if the next is not the return statement */
1594     if (!(ic->next && ic->next->op == LABEL &&
1595           IC_LABEL(ic->next) == returnLabel))
1596         
1597         emitcode("rjmp","L%05d",returnLabel->key);
1598     
1599 }
1600
1601 /*-----------------------------------------------------------------*/
1602 /* genLabel - generates a label                                    */
1603 /*-----------------------------------------------------------------*/
1604 static void genLabel (iCode *ic)
1605 {
1606     /* special case never generate */
1607     if (IC_LABEL(ic) == entryLabel)
1608         return ;
1609
1610     emitcode("","L%05d:",IC_LABEL(ic)->key);
1611 }
1612
1613 /*-----------------------------------------------------------------*/
1614 /* genGoto - generates a ljmp                                      */
1615 /*-----------------------------------------------------------------*/
1616 static void genGoto (iCode *ic)
1617 {
1618     emitcode ("rjmp","L%05d:",(IC_LABEL(ic)->key+100));
1619 }
1620
1621 /*-----------------------------------------------------------------*/
1622 /* findLabelBackwards: walks back through the iCode chain looking  */
1623 /* for the given label. Returns number of iCode instructions       */
1624 /* between that label and given ic.                                */
1625 /* Returns zero if label not found.                                */
1626 /*-----------------------------------------------------------------*/
1627 static int findLabelBackwards(iCode *ic, int key)
1628 {
1629     int count = 0;
1630     
1631     while (ic->prev)
1632     {
1633         ic = ic->prev;
1634         count++;
1635         
1636         if (ic->op == LABEL && IC_LABEL(ic)->key == key)
1637         {
1638             /* printf("findLabelBackwards = %d\n", count); */
1639             return count;
1640         }
1641     }
1642     
1643     return 0;
1644 }
1645
1646 /*-----------------------------------------------------------------*/
1647 /* genPlusIncr :- does addition with increment if possible         */
1648 /*-----------------------------------------------------------------*/
1649 static bool genPlusIncr (iCode *ic)
1650 {
1651     unsigned int icount ;
1652     
1653     /* will try to generate an increment */
1654     /* if the right side is not a literal 
1655        we cannot */
1656     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1657         return FALSE ;
1658     
1659     icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
1660     
1661     /* if the sizes are greater than 2 or they are not the same regs
1662        then we cannot */
1663     if (AOP_SIZE(IC_RESULT(ic)) > 2 ||
1664         AOP_SIZE(IC_LEFT(ic)) > 2   ||
1665         !sameRegs(AOP(IC_LEFT(ic)),AOP(IC_RIGHT(ic))))
1666         return FALSE ;
1667     
1668     /* so we know LEFT & RESULT in the same registers and add
1669        amount <= 63 */
1670     /* for short & char types */
1671     if (AOP_SIZE(IC_RESULT(ic)) < 2) {
1672         if (icount == 1) {
1673             emitcode("inc","%s",aopGet(AOP(IC_LEFT(ic)),0));
1674             return TRUE;
1675         } 
1676         emicode("subi","%s,lo8(%d)",aopGet(AOP(IC_LEFT(ic)),0),-icount);
1677         return TRUE;
1678     }
1679
1680     /* if register pair and starts with 26/30 then adiw */
1681     if (isRegPair(AOP(IC_RESULT(ic))) && icount > 0 && icount < 64 &&
1682         ( IS_REGIDX(AOP(IC_RESULT(ic)),R26_IDX) ||
1683           IS_REGIDX(AOP(IC_RESULT(ic)),R30_IDX) )) {
1684         emitcode("adiw","%s,%d",aopGet(AOP(IC_RESULT(ic)),0),icount);
1685         return TRUE;
1686     }
1687     
1688     /* use subi */
1689     emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_RESULT(ic)),0),-icount);
1690     emitcode("sbci","%s,hi8(%d)",aopGet(AOP(IC_RESULT(ic)),1),-icount);
1691     return TRUE;
1692 }
1693
1694 /* This is the pure and virtuous version of this code.
1695  * I'm pretty certain it's right, but not enough to toss the old 
1696  * code just yet...
1697  */
1698 static void adjustArithmeticResult(iCode *ic)
1699 {
1700     if (opIsGptr(IC_RESULT(ic)) &&
1701         opIsGptr(IC_LEFT(ic))   &&
1702         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1703     {
1704         aopPut(AOP(IC_RESULT(ic)),
1705                aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1),
1706                GPTRSIZE - 1);
1707     }
1708
1709     if (opIsGptr(IC_RESULT(ic)) &&
1710         opIsGptr(IC_RIGHT(ic))   &&
1711         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
1712     {
1713         aopPut(AOP(IC_RESULT(ic)),
1714                aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1),
1715                GPTRSIZE - 1);
1716     }
1717
1718     if (opIsGptr(IC_RESULT(ic))            &&
1719         AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE   &&
1720         AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE  &&
1721          !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
1722          !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
1723          char buffer[5];
1724          sprintf(buffer,"%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
1725          aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
1726      }
1727 }
1728
1729 /*-----------------------------------------------------------------*/
1730 /* genPlus - generates code for addition                           */
1731 /*-----------------------------------------------------------------*/
1732 static void genPlus (iCode *ic)
1733 {
1734     int size, offset = 0;
1735
1736     /* special cases :- */
1737
1738     aopOp (IC_LEFT(ic),ic,FALSE);
1739     aopOp (IC_RIGHT(ic),ic,FALSE);
1740     aopOp (IC_RESULT(ic),ic,TRUE);
1741
1742     /* if I can do an increment instead
1743     of add then GOOD for ME */
1744     if (genPlusIncr (ic) == TRUE)
1745         goto release;   
1746
1747     size = getDataSize(IC_RESULT(ic));
1748
1749     while(size--){
1750         aopPut(AOP(IC_RESULT(ic)),aopGet(AOP(IC_RIGHT(ic)),offset),offset);
1751         if(offset == 0)
1752             emitcode("add","%s,%s",aopGet(AOP(IC_RESULT(ic)),offset),
1753                      aopGet(AOP(IC_LEFT(ic)),offset));
1754         else
1755             emitcode("adc","%s,%s",aopGet(AOP(IC_RESULT(ic)),offset),
1756                      aopGet(AOP(IC_LEFT(ic)),offset));
1757         }
1758     }
1759
1760     adjustArithmeticResult(ic);
1761
1762 release:
1763     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1764     freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1765     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1766 }
1767
1768 /*-----------------------------------------------------------------*/
1769 /* genMinusDec :- does subtraction with deccrement if possible     */
1770 /*-----------------------------------------------------------------*/
1771 static bool genMinusDec (iCode *ic)
1772 {
1773     unsigned int icount ;
1774     
1775     /* will try to generate an increment */
1776     /* if the right side is not a literal 
1777        we cannot */
1778     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1779         return FALSE ;
1780     
1781     icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
1782     
1783     /* if the sizes are greater than 2 or they are not the same regs
1784        then we cannot */
1785     if (AOP_SIZE(IC_RESULT(ic)) > 2 ||
1786         AOP_SIZE(IC_LEFT(ic)) > 2   ||
1787         !sameRegs(AOP(IC_LEFT(ic)),AOP(IC_RIGHT(ic))))
1788         return FALSE ;
1789     
1790     /* so we know LEFT & RESULT in the same registers and add
1791        amount <= 63 */
1792     /* for short & char types */
1793     if (AOP_SIZE(IC_RESULT(ic)) < 2) {
1794         if (icount == 1) {
1795             emitcode("dec","%s",aopGet(AOP(IC_LEFT(ic)),0));
1796             return TRUE;
1797         } 
1798         emicode("subi","%s,lo8(%d)",aopGet(AOP(IC_LEFT(ic)),0),icount);
1799         return TRUE;
1800     }
1801
1802     /* if register pair and starts with 26/30 then adiw */
1803     if (isRegPair(AOP(IC_RESULT(ic))) && icount > 0 && icount < 64 &&
1804         ( IS_REGIDX(AOP(IC_RESULT(ic)),R26_IDX) ||
1805           IS_REGIDX(AOP(IC_RESULT(ic)),R30_IDX) )) {
1806         emitcode("sbiw","%s,%d",aopGet(AOP(IC_RESULT(ic)),0),icount);
1807         return TRUE;
1808     }
1809     
1810     /* use subi */
1811     emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_RESULT(ic)),0),icount);
1812     emitcode("sbci","%s,hi8(%d)",aopGet(AOP(IC_RESULT(ic)),1),icount);
1813     return TRUE;
1814 }
1815
1816 /*-----------------------------------------------------------------*/
1817 /* addSign - complete with sign                                    */
1818 /*-----------------------------------------------------------------*/
1819 static void addSign(operand *result, int offset, int sign)
1820 {
1821     int size = (getDataSize(result) - offset);
1822     if(size > 0){
1823         if(sign){
1824             emitcode("rlc","a");
1825             emitcode("subb","a,acc");
1826             while(size--)
1827                 aopPut(AOP(result),"a",offset++); 
1828         } else
1829             while(size--)
1830                 aopPut(AOP(result),zero,offset++);
1831     }
1832 }
1833
1834 /*-----------------------------------------------------------------*/
1835 /* genMinus - generates code for subtraction                       */
1836 /*-----------------------------------------------------------------*/
1837 static void genMinus (iCode *ic)
1838 {
1839     int size, offset = 0;
1840     unsigned long lit = 0L;
1841     
1842     aopOp (IC_LEFT(ic),ic,FALSE);
1843     aopOp (IC_RIGHT(ic),ic,FALSE);
1844     aopOp (IC_RESULT(ic),ic,TRUE);
1845     
1846     /* if I can do an decrement instead
1847        of subtract then GOOD for ME */
1848     if (genMinusDec (ic) == TRUE)
1849         goto release;   
1850     
1851     size = getDataSize(IC_RESULT(ic));   
1852     
1853     while (size--) {
1854         aopPut(AOP(IC_RESULT(ic)),aopGet(AOP(IC_RIGHT(ic)),offset),offset);
1855         if(offset == 0)
1856             emitcode("sub","%s,%s",aopGet(AOP(IC_RESULT(ic)),offset),
1857                      aopGet(AOP(IC_LEFT(ic)),offset));
1858         else
1859             emitcode("sbc","%s,%s",aopGet(AOP(IC_RESULT(ic)),offset),
1860                      aopGet(AOP(IC_LEFT(ic)),offset));
1861     }
1862
1863     adjustArithmeticResult(ic);
1864     
1865  release:
1866     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1867     freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1868     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1869 }
1870
1871 /*-----------------------------------------------------------------*/
1872 /* genMultOneByte : 8 bit multiplication & division                */
1873 /*-----------------------------------------------------------------*/
1874 static void genMultOneByte (operand *left,
1875                             operand *right,
1876                             operand *result)
1877 {
1878     link *opetype = operandType(result);
1879     char *l ;
1880     symbol *lbl ;
1881     int size,offset;
1882     
1883     /* (if two literals, the value is computed before) */
1884     /* if one literal, literal on the right */
1885     if (AOP_TYPE(left) == AOP_LIT){
1886         operand *t = right;
1887         right = left;
1888         left = t;
1889     }
1890     
1891     size = AOP_SIZE(result);
1892
1893     if (SPEC_USIGN(opetype)) {
1894         emitcode("mul","%s,%s",
1895                  aopGet(IC_LEFT(ic),0),
1896                  aopGet(IC_RIGHT(ic),0));
1897     } else {
1898         emitcode("muls","%s,%s",
1899                  aopGet(IC_LEFT(ic),0),
1900                  aopGet(IC_RIGHT(ic),0));
1901     }
1902     aopPut(AOP(IC_RESULT(ic)),"r0",0);
1903     if (size > 1){
1904         aopPut(AOP(IC_RESULT(ic)),"r1",1);
1905         offset = 2;
1906         size -= 2;
1907         if (SPEC_USIGN(opetype)) {
1908             while(size--) {
1909                 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
1910             }
1911         } else {
1912             lbl = newiTempLabel(NULL);
1913             emitcode("ldi","r24,0");
1914             emitcode("brcc","L%05d",lbl->key);
1915             emitcode("ldi","r24,lo8(-1)");
1916             emitcode("","L%05d:",lbl->key);
1917             while (size--) aopPut(AOP(IC_RESULT(ic)),"r24",offset++);
1918         }
1919     }
1920     return;
1921 }
1922
1923 /*-----------------------------------------------------------------*/
1924 /* genMult - generates code for multiplication                     */
1925 /*-----------------------------------------------------------------*/
1926 static void genMult (iCode *ic)
1927 {
1928     operand *left = IC_LEFT(ic);
1929     operand *right = IC_RIGHT(ic);
1930     operand *result= IC_RESULT(ic);   
1931
1932     /* assign the amsops */
1933     aopOp (left,ic,FALSE);
1934     aopOp (right,ic,FALSE);
1935     aopOp (result,ic,TRUE);
1936
1937     /* if both are of size == 1 */
1938     if (AOP_SIZE(left) == 1 &&
1939         AOP_SIZE(right) == 1 ) {
1940         genMultOneByte(left,right,result);
1941         goto release ;
1942     }
1943
1944     /* should have been converted to function call */       
1945     assert(1) ;
1946
1947 release :
1948     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1949     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1950     freeAsmop(result,NULL,ic,TRUE); 
1951 }
1952
1953 /*-----------------------------------------------------------------*/
1954 /* genDiv - generates code for division                            */
1955 /*-----------------------------------------------------------------*/
1956 static void genDiv (iCode *ic)
1957 {
1958     /* should have been converted to function call */
1959     assert(1);
1960 }
1961
1962 /*-----------------------------------------------------------------*/
1963 /* genMod - generates code for division                            */
1964 /*-----------------------------------------------------------------*/
1965 static void genMod (iCode *ic)
1966 {
1967     /* should have been converted to function call */
1968     assert(1);
1969
1970 }
1971
1972 enum {
1973     AVR_EQ = 0,
1974     AVR_NE,
1975     AVR_LT,
1976     AVR_GE
1977 };
1978
1979 /*-----------------------------------------------------------------*/
1980 /* revavrcnd - reverse a conditional for avr                       */
1981 /*-----------------------------------------------------------------*/
1982 static int revavrcnd(int type)
1983 {
1984     static struct {
1985         int type, rtype;
1986     } rar[] = { { AVR_EQ, AVR_NE}, {AVR_LT, AVR_GE}};
1987     int i;
1988
1989     for (i = 0 ; i < (sizeof(rar)/sizeof(rar[0]));i++) {
1990         if (rar[i].type == type) return rar[i].rtype;
1991         if (rar[i].rtype== type) return rar[i].type;
1992     }
1993     assert(1); /* cannot happen */
1994 }
1995
1996 static char *br_name[4] = {"breq","brne","brlt","brge"};
1997 static char *br_uname[4]= {"breq","brne","brlo","brcc"};
1998
1999 /*-----------------------------------------------------------------*/
2000 /* genBranch - generate the branch instruction                     */
2001 /*-----------------------------------------------------------------*/
2002 static void genBranch (iCode *ifx, int br_type, int sign)
2003 {
2004     int tj = (IC_TRUE(ifx) ? 1 : 0) ;
2005
2006     if (tj) { /* if true jump */
2007         char *nm = (sign ? br_name[br_type] : br_uname[br_type]);
2008         emitcode(nm,"L%05d",IC_TRUE(ifx)->key);
2009     } else { /* if false jump */
2010         int rtype = revavrcnd(br_type);
2011         char *nm = (sign ? br_name[rtype] : br_uname[rtype]);
2012         emitcode(nm,"L%05d",IC_FALSE(ifx)->key);
2013     }
2014     ifx->generated = 1;
2015 }
2016
2017 /*-----------------------------------------------------------------*/
2018 /* genCmp - compare & jump                                         */
2019 /*-----------------------------------------------------------------*/
2020 static void genCmp (iCode *ic, iCode *ifx, int br_type)
2021 {
2022     operand *left, *right, *result;
2023     link *letype , *retype;
2024     symbol *lbl;
2025     int sign, size, offset =0;
2026
2027     left = IC_LEFT(ic);
2028     right= IC_RIGHT(ic);
2029     result = IC_RESULT(ic);
2030
2031     letype = getSpec(operandType(left));
2032     retype =getSpec(operandType(right));
2033     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2034
2035     /* assign the amsops */
2036     aopOp (left,ic,FALSE);
2037     aopOp (right,ic,FALSE);
2038     aopOp (result,ic,TRUE);
2039     size = AOP_SIZE(AOP(left));
2040
2041     if (ifx) {
2042         if (size == 1) {
2043             if (AOP_TYPE(AOP(right)) == AOP_LIT) {
2044                 emitcode("cpi","%s,lo8(%d)",aopGet(AOP(left),0),
2045                          (int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
2046                 genBranch(ifx,br_type);
2047             } else { /* right != literal */
2048                 emitcode("cp","%s,%s",aopGet(AOP(left),0),aopGet(AOP(right),0));
2049                 genBranch(ifx,br_type);
2050         } else { /* size != 1 */
2051             while (size--) {
2052                 if (offset = 0) 
2053                     emitcode("cp","%s,%s",aopGet(AOP(left),0),aopGet(AOP(right),0));
2054                 else
2055                     emitcode("cpc","%s,%s",aopGet(AOP(left),offset),aopGet(AOP(right),offset));
2056                 offset++;
2057             }
2058             genBranch(ifx,br_type);
2059         }
2060     } else { /* no ifx */
2061         emitCode("clr","r0");
2062         while (size--) {
2063             if (offset = 0) 
2064                 emitcode("cp","%s,%s",aopGet(AOP(left),0),aopGet(AOP(right),0));
2065             else
2066                 emitcode("cpc","%s,%s",aopGet(AOP(left),offset),aopGet(AOP(right),offset));
2067             offset++;
2068         }
2069         lbl = newiTempLabel(NULL);
2070         br_type = revavrcnd(br_type);
2071         if (sign) emitcode(br_uname[br_type],"L%05d",lbl->key);
2072         else emitcode(br_name[br_type],"L%05d",lbl->key);
2073         emitcode("inc","r0");
2074         emitcode("","L%05d:",lbl->key);
2075         aopPut(AOP(result),"r0",0);
2076         size = AOP_SIZE(AOP(result)) - 1;
2077         offset = 1;
2078         while (size--) aopPut(AOP(result),zero,offset++);
2079     }
2080
2081     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2082     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2083     freeAsmop(result,NULL,ic,TRUE); 
2084 }
2085
2086 /*-----------------------------------------------------------------*/
2087 /* genCmpGt :- greater than comparison                             */
2088 /*-----------------------------------------------------------------*/
2089 static void genCmpGt (iCode *ic, iCode *ifx)
2090 {
2091     /* should have transformed by the parser */
2092     assert(1);
2093 }
2094
2095 /*-----------------------------------------------------------------*/
2096 /* genCmpLt - less than comparisons                                */
2097 /*-----------------------------------------------------------------*/
2098 static void genCmpLt (iCode *ic, iCode *ifx)
2099 {
2100     genCmp(ic,ifx,AVR_LT);
2101 }
2102
2103 /*-----------------------------------------------------------------*/
2104 /* genCmpEq - generates code for equal to                          */
2105 /*-----------------------------------------------------------------*/
2106 static void genCmpEq (iCode *ic, iCode *ifx)
2107 {
2108     genCmp(ic,ifx,AVR_EQ);
2109 }
2110
2111 /*-----------------------------------------------------------------*/
2112 /* genCmpNe - generates code for not equal to                      */
2113 /*-----------------------------------------------------------------*/
2114 static void genCmpNe (iCode *ic, iCode *ifx)
2115 {
2116     genCmp(ic,ifx,AVR_NE);
2117 }
2118
2119 /*-----------------------------------------------------------------*/
2120 /* genCmpGe - generates code for greater than equal to             */
2121 /*-----------------------------------------------------------------*/
2122 static void genCmpGe (iCode *ic, iCode *ifx)
2123 {
2124     genCmp(ic,ifx,AVR_GE);
2125 }
2126
2127 /*-----------------------------------------------------------------*/
2128 /* genCmpLe - generates code for less than equal to                */
2129 /*-----------------------------------------------------------------*/
2130 static void genCmpLe (iCode *ic, iCode *ifx)
2131 {
2132     operand *left = IC_LEFT(ic);
2133     operand *right= IC_RIGHT(ic);
2134     
2135     IC_RIGHT(ic) = left;
2136     IC_LEFT(ic)  = right;
2137     gemCmp(ic,ifx,AVR_GE);
2138 }
2139
2140 /*-----------------------------------------------------------------*/
2141 /* ifxForOp - returns the icode containing the ifx for operand     */
2142 /*-----------------------------------------------------------------*/
2143 static iCode *ifxForOp ( operand *op, iCode *ic )
2144 {
2145     /* if true symbol then needs to be assigned */
2146     if (IS_TRUE_SYMOP(op))
2147         return NULL ;
2148
2149     /* if this has register type condition and
2150     the next instruction is ifx with the same operand
2151     and live to of the operand is upto the ifx only then */
2152     if (ic->next &&
2153         ic->next->op == IFX &&
2154         IC_COND(ic->next)->key == op->key &&
2155         OP_SYMBOL(op)->liveTo <= ic->next->seq )
2156         return ic->next;
2157
2158     return NULL;
2159 }
2160 /*-----------------------------------------------------------------*/
2161 /* genAndOp - for && operation                                     */
2162 /*-----------------------------------------------------------------*/
2163 static void genAndOp (iCode *ic)
2164 {
2165     operand *left,*right, *result;
2166     symbol *tlbl;
2167     int size , offset;
2168
2169     /* note here that && operations that are in an
2170     if statement are taken away by backPatchLabels
2171     only those used in arthmetic operations remain */
2172     aopOp((left=IC_LEFT(ic)),ic,FALSE);
2173     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2174     aopOp((result=IC_RESULT(ic)),ic,FALSE);
2175
2176     tlbl = newitempLabel(NULL);
2177     toBoolean(left,"r0",TRUE);    
2178     toBoolean(right,"r1",TRUE);
2179     emitcode("and","r0,r1");
2180     emitcode("ldi","r24,1");
2181     emitcode("breq","L%05d",tlbl->key);
2182     emitcode("dec","r24");
2183     emicode("","L%05d:",tlbl->key);
2184     aopPut(AOP(result),"r24",0);
2185     size = AOP_SIZE(AOP(result)) -1;
2186     offset = 1;
2187     while (size--) aopPut(AOP(result),zero,offset++);
2188     
2189     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2190     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2191     freeAsmop(result,NULL,ic,TRUE);
2192 }
2193
2194
2195 /*-----------------------------------------------------------------*/
2196 /* genOrOp - for || operation                                      */
2197 /*-----------------------------------------------------------------*/
2198 static void genOrOp (iCode *ic)
2199 {
2200     operand *left,*right, *result;
2201     symbol *tlbl;
2202     int size , offset;
2203
2204     /* note here that || operations that are in an
2205     if statement are taken away by backPatchLabels
2206     only those used in arthmetic operations remain */
2207     aopOp((left=IC_LEFT(ic)),ic,FALSE);
2208     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2209     aopOp((result=IC_RESULT(ic)),ic,FALSE);
2210
2211     tlbl = newitempLabel(NULL);
2212     toBoolean(left,"r0",TRUE);    
2213     toBoolean(right,"r0",FALSE);
2214     emitcode("ldi","r24,1");
2215     emitcode("breq","L%05d",tlbl->key);
2216     emitcode("dec","r24");
2217     emicode("","L%05d:",tlbl->key);
2218     aopPut(AOP(result),"r24",0);
2219     size = AOP_SIZE(AOP(result)) -1;
2220     offset = 1;
2221     while (size--) aopPut(AOP(result),zero,offset++);
2222
2223     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2224     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2225     freeAsmop(result,NULL,ic,TRUE);            
2226 }
2227
2228 /*-----------------------------------------------------------------*/
2229 /* isLiteralBit - test if lit == 2^n                               */
2230 /*-----------------------------------------------------------------*/
2231 static int isLiteralBit(unsigned long lit)
2232 {
2233     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
2234     0x100L,0x200L,0x400L,0x800L,
2235     0x1000L,0x2000L,0x4000L,0x8000L,
2236     0x10000L,0x20000L,0x40000L,0x80000L,
2237     0x100000L,0x200000L,0x400000L,0x800000L,
2238     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
2239     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
2240     int idx;
2241     
2242     for(idx = 0; idx < 32; idx++)
2243         if(lit == pw[idx])
2244             return idx+1;
2245     return 0;
2246 }
2247
2248
2249 /*-----------------------------------------------------------------*/
2250 /* genAnd  - code for and                                          */
2251 /*-----------------------------------------------------------------*/
2252 static void genAnd (iCode *ic, iCode *ifx)
2253 {
2254     operand *left, *right, *result;
2255     int size, offset=0;
2256     char *l;
2257     unsigned long lit = 0L;
2258
2259     aopOp((left = IC_LEFT(ic)),ic,FALSE);
2260     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2261     aopOp((result=IC_RESULT(ic)),ic,TRUE);
2262
2263     if (ifx) { /* used only for jumps */
2264         if (AOP_TYPE(AOP(right)) == AOP_LIT) {
2265             int p2 = powof2((int) floatFromVal (AOP(right)->aopu.aop_lit));
2266             if (p2) { /* right side is a power of 2 */
2267                 l = aopGet(AOP(left),p2 / 8);
2268                 if (IC_TRUE(ifx)) {
2269                         emitcode("sbrc","%s,%d",l,p2 % 8);
2270                         emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2271                 } else {
2272                         emitcode("sbrs","%s,%d",l,p2 % 8);
2273                         emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2274                 }
2275             } else { /* right not power of two */
2276                     emitcode
2277             }
2278         } else { /* right is not a literal */
2279         }
2280     } else { /* other jump -> result goes to register*/
2281     }
2282
2283 release :
2284     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2285     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2286     freeAsmop(result,NULL,ic,TRUE);     
2287 }
2288
2289 /*-----------------------------------------------------------------*/
2290 /* genOr  - code for or                                            */
2291 /*-----------------------------------------------------------------*/
2292 static void genOr (iCode *ic, iCode *ifx)
2293 {
2294     operand *left, *right, *result;
2295     int size, offset=0;
2296     unsigned long lit = 0L;
2297
2298     aopOp((left = IC_LEFT(ic)),ic,FALSE);
2299     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2300     aopOp((result=IC_RESULT(ic)),ic,TRUE);
2301
2302 #ifdef DEBUG_TYPE
2303     emitcode("","; Type res[%d] = l[%d]&r[%d]",
2304              AOP_TYPE(result),
2305              AOP_TYPE(left), AOP_TYPE(right));
2306     emitcode("","; Size res[%d] = l[%d]&r[%d]",
2307              AOP_SIZE(result),
2308              AOP_SIZE(left), AOP_SIZE(right));
2309 #endif
2310
2311     /* if left is a literal & right is not then exchange them */
2312     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2313         AOP_NEEDSACC(left)) {
2314         operand *tmp = right ;
2315         right = left;
2316         left = tmp;
2317     }
2318
2319     /* if result = right then exchange them */
2320     if(sameRegs(AOP(result),AOP(right))){
2321         operand *tmp = right ;
2322         right = left;
2323         left = tmp;
2324     }
2325
2326     /* if right is bit then exchange them */
2327     if (AOP_TYPE(right) == AOP_CRY &&
2328         AOP_TYPE(left) != AOP_CRY){
2329         operand *tmp = right ;
2330         right = left;
2331         left = tmp;
2332     }
2333     if(AOP_TYPE(right) == AOP_LIT)
2334         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2335
2336     size = AOP_SIZE(result);
2337
2338     // if(bit | yy)
2339     // xx = bit | yy;
2340     if (AOP_TYPE(left) == AOP_CRY){
2341         if(AOP_TYPE(right) == AOP_LIT){
2342             // c = bit & literal;
2343             if(lit){
2344                 // lit != 0 => result = 1
2345                 if(AOP_TYPE(result) == AOP_CRY){
2346                     if(size)
2347                         emitcode("setb","%s",AOP(result)->aopu.aop_dir);
2348                     else if(ifx)
2349                         continueIfTrue(ifx);
2350                     goto release;
2351                 }
2352                 emitcode("setb","c");
2353             } else {
2354                 // lit == 0 => result = left
2355                 if(size && sameRegs(AOP(result),AOP(left)))
2356                     goto release;
2357                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2358             }
2359         } else {
2360             if (AOP_TYPE(right) == AOP_CRY){
2361                 // c = bit | bit;
2362                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
2363                 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
2364             }
2365             else{
2366                 // c = bit | val;
2367                 symbol *tlbl = newiTempLabel(NULL);
2368                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
2369                     emitcode("setb","c");
2370                 emitcode("jb","%s,%05d$",
2371                          AOP(left)->aopu.aop_dir,tlbl->key+100);
2372                 toBoolean(right);
2373                 emitcode("jnz","%05d$",tlbl->key+100);
2374                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
2375                     jmpTrueOrFalse(ifx, tlbl);
2376                     goto release;
2377                 } else {
2378                     CLRC;
2379                     emitcode("","%05d$:",tlbl->key+100);
2380                 }
2381             }
2382         }
2383         // bit = c
2384         // val = c
2385         if(size)
2386             outBitC(result);
2387         // if(bit | ...)
2388         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
2389             genIfxJump(ifx, "c");           
2390         goto release ;
2391     }
2392
2393     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
2394     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
2395     if((AOP_TYPE(right) == AOP_LIT) &&
2396        (AOP_TYPE(result) == AOP_CRY) &&
2397        (AOP_TYPE(left) != AOP_CRY)){
2398         if(lit){
2399             // result = 1
2400             if(size)
2401                 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
2402             else 
2403                 continueIfTrue(ifx);
2404             goto release;
2405         } else {
2406             // lit = 0, result = boolean(left)
2407             if(size)
2408                 emitcode("setb","c");
2409             toBoolean(right);
2410             if(size){
2411                 symbol *tlbl = newiTempLabel(NULL);
2412                 emitcode("jnz","%05d$",tlbl->key+100);
2413                 CLRC;
2414                 emitcode("","%05d$:",tlbl->key+100);
2415             } else {
2416                 genIfxJump (ifx,"a");
2417                 goto release;
2418             }
2419         }
2420         outBitC(result);
2421         goto release ;
2422     }
2423
2424     /* if left is same as result */
2425     if(sameRegs(AOP(result),AOP(left))){
2426         for(;size--; offset++) {
2427             if(AOP_TYPE(right) == AOP_LIT){
2428                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2429                     continue;
2430                 else 
2431                     if (IS_AOP_PREG(left)) {
2432                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2433                         emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
2434                         aopPut(AOP(result),"a",offset);
2435                     } else
2436                         emitcode("orl","%s,%s",
2437                                  aopGet(AOP(left),offset,FALSE,TRUE),
2438                                  aopGet(AOP(right),offset,FALSE,FALSE));
2439             } else {
2440                 if (AOP_TYPE(left) == AOP_ACC) 
2441                     emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
2442                 else {              
2443                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2444                     if (IS_AOP_PREG(left)) {
2445                         emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
2446                         aopPut(AOP(result),"a",offset);
2447                     } else
2448                         emitcode("orl","%s,a",
2449                                  aopGet(AOP(left),offset,FALSE,TRUE));
2450                 }
2451             }
2452         }
2453     } else {
2454         // left & result in different registers
2455         if(AOP_TYPE(result) == AOP_CRY){
2456             // result = bit
2457             // if(size), result in bit
2458             // if(!size && ifx), conditional oper: if(left | right)
2459             symbol *tlbl = newiTempLabel(NULL);
2460             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
2461             if(size)
2462                 emitcode("setb","c");
2463             while(sizer--){
2464                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2465                 emitcode("orl","a,%s",
2466                          aopGet(AOP(left),offset,FALSE,FALSE));
2467                 emitcode("jnz","%05d$",tlbl->key+100);
2468                 offset++;
2469             }
2470             if(size){
2471                 CLRC;
2472                 emitcode("","%05d$:",tlbl->key+100);
2473                 outBitC(result);
2474             } else if(ifx)
2475                 jmpTrueOrFalse(ifx, tlbl);
2476         } else for(;(size--);offset++){
2477             // normal case
2478             // result = left & right
2479             if(AOP_TYPE(right) == AOP_LIT){
2480                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2481                     aopPut(AOP(result),
2482                            aopGet(AOP(left),offset,FALSE,FALSE),
2483                            offset);
2484                     continue;
2485                 }
2486             }
2487             // faster than result <- left, anl result,right
2488             // and better if result is SFR
2489             if (AOP_TYPE(left) == AOP_ACC) 
2490                 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
2491             else {
2492                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2493                 emitcode("orl","a,%s",
2494                          aopGet(AOP(left),offset,FALSE,FALSE));
2495             }
2496             aopPut(AOP(result),"a",offset);                     
2497         }
2498     }
2499
2500 release :
2501     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2502     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2503     freeAsmop(result,NULL,ic,TRUE);     
2504 }
2505
2506 /*-----------------------------------------------------------------*/
2507 /* genXor - code for xclusive or                                   */
2508 /*-----------------------------------------------------------------*/
2509 static void genXor (iCode *ic, iCode *ifx)
2510 {
2511     operand *left, *right, *result;
2512     int size, offset=0;
2513     unsigned long lit = 0L;
2514
2515     aopOp((left = IC_LEFT(ic)),ic,FALSE);
2516     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2517     aopOp((result=IC_RESULT(ic)),ic,TRUE);
2518
2519 #ifdef DEBUG_TYPE
2520     emitcode("","; Type res[%d] = l[%d]&r[%d]",
2521              AOP_TYPE(result),
2522              AOP_TYPE(left), AOP_TYPE(right));
2523     emitcode("","; Size res[%d] = l[%d]&r[%d]",
2524              AOP_SIZE(result),
2525              AOP_SIZE(left), AOP_SIZE(right));
2526 #endif
2527
2528     /* if left is a literal & right is not ||
2529        if left needs acc & right does not */
2530     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2531         (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
2532         operand *tmp = right ;
2533         right = left;
2534         left = tmp;
2535     }
2536
2537     /* if result = right then exchange them */
2538     if(sameRegs(AOP(result),AOP(right))){
2539         operand *tmp = right ;
2540         right = left;
2541         left = tmp;
2542     }
2543
2544     /* if right is bit then exchange them */
2545     if (AOP_TYPE(right) == AOP_CRY &&
2546         AOP_TYPE(left) != AOP_CRY){
2547         operand *tmp = right ;
2548         right = left;
2549         left = tmp;
2550     }
2551     if(AOP_TYPE(right) == AOP_LIT)
2552         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2553
2554     size = AOP_SIZE(result);
2555
2556     // if(bit ^ yy)
2557     // xx = bit ^ yy;
2558     if (AOP_TYPE(left) == AOP_CRY){
2559         if(AOP_TYPE(right) == AOP_LIT){
2560             // c = bit & literal;
2561             if(lit>>1){
2562                 // lit>>1  != 0 => result = 1
2563                 if(AOP_TYPE(result) == AOP_CRY){
2564                     if(size)
2565                         emitcode("setb","%s",AOP(result)->aopu.aop_dir);
2566                     else if(ifx)
2567                         continueIfTrue(ifx);
2568                     goto release;
2569                 }
2570                 emitcode("setb","c");
2571             } else{
2572                 // lit == (0 or 1)
2573                 if(lit == 0){
2574                     // lit == 0, result = left
2575                     if(size && sameRegs(AOP(result),AOP(left)))
2576                         goto release;
2577                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2578                 } else{
2579                     // lit == 1, result = not(left)
2580                     if(size && sameRegs(AOP(result),AOP(left))){
2581                         emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
2582                         goto release;
2583                     } else {
2584                         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2585                         emitcode("cpl","c");
2586                     }
2587                 }
2588             }
2589
2590         } else {
2591             // right != literal
2592             symbol *tlbl = newiTempLabel(NULL);
2593             if (AOP_TYPE(right) == AOP_CRY){
2594                 // c = bit ^ bit;
2595                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
2596             }
2597             else{
2598                 int sizer = AOP_SIZE(right);
2599                 // c = bit ^ val
2600                 // if val>>1 != 0, result = 1
2601                 emitcode("setb","c");
2602                 while(sizer){
2603                     MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
2604                     if(sizer == 1)
2605                         // test the msb of the lsb
2606                         emitcode("anl","a,#0xfe");
2607                     emitcode("jnz","%05d$",tlbl->key+100);
2608                     sizer--;
2609                 }
2610                 // val = (0,1)
2611                 emitcode("rrc","a");
2612             }
2613             emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
2614             emitcode("cpl","c");
2615             emitcode("","%05d$:",(tlbl->key+100));
2616         }
2617         // bit = c
2618         // val = c
2619         if(size)
2620             outBitC(result);
2621         // if(bit | ...)
2622         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
2623             genIfxJump(ifx, "c");           
2624         goto release ;
2625     }
2626
2627     if(sameRegs(AOP(result),AOP(left))){
2628         /* if left is same as result */
2629         for(;size--; offset++) {
2630             if(AOP_TYPE(right) == AOP_LIT){
2631                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2632                     continue;
2633                 else
2634                     if (IS_AOP_PREG(left)) {
2635                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2636                         emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
2637                         aopPut(AOP(result),"a",offset);
2638                     } else 
2639                         emitcode("xrl","%s,%s",
2640                                  aopGet(AOP(left),offset,FALSE,TRUE),
2641                                  aopGet(AOP(right),offset,FALSE,FALSE));
2642             } else {
2643                 if (AOP_TYPE(left) == AOP_ACC)
2644                     emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
2645                 else {
2646                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2647                     if (IS_AOP_PREG(left)) {
2648                         emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
2649                         aopPut(AOP(result),"a",offset);
2650                     } else
2651                         emitcode("xrl","%s,a",
2652                                  aopGet(AOP(left),offset,FALSE,TRUE));
2653                 }
2654             }
2655         }
2656     } else {
2657         // left & result in different registers
2658         if(AOP_TYPE(result) == AOP_CRY){
2659             // result = bit
2660             // if(size), result in bit
2661             // if(!size && ifx), conditional oper: if(left ^ right)
2662             symbol *tlbl = newiTempLabel(NULL);
2663             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
2664             if(size)
2665                 emitcode("setb","c");
2666             while(sizer--){
2667                 if((AOP_TYPE(right) == AOP_LIT) &&
2668                    (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
2669                     MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
2670                 } else {
2671                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2672                     emitcode("xrl","a,%s",
2673                              aopGet(AOP(left),offset,FALSE,FALSE));
2674                 }
2675                 emitcode("jnz","%05d$",tlbl->key+100);
2676                 offset++;
2677             }
2678             if(size){
2679                 CLRC;
2680                 emitcode("","%05d$:",tlbl->key+100);
2681                 outBitC(result);
2682             } else if(ifx)
2683                 jmpTrueOrFalse(ifx, tlbl);
2684         } else for(;(size--);offset++){
2685             // normal case
2686             // result = left & right
2687             if(AOP_TYPE(right) == AOP_LIT){
2688                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2689                     aopPut(AOP(result),
2690                            aopGet(AOP(left),offset,FALSE,FALSE),
2691                            offset);
2692                     continue;
2693                 }
2694             }
2695             // faster than result <- left, anl result,right
2696             // and better if result is SFR
2697             if (AOP_TYPE(left) == AOP_ACC)
2698                 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
2699             else {
2700                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2701                 emitcode("xrl","a,%s",
2702                          aopGet(AOP(left),offset,FALSE,TRUE));
2703             }
2704             aopPut(AOP(result),"a",offset);
2705         }
2706     }
2707
2708 release :
2709     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2710     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2711     freeAsmop(result,NULL,ic,TRUE);     
2712 }
2713
2714 /*-----------------------------------------------------------------*/
2715 /* genInline - write the inline code out                           */
2716 /*-----------------------------------------------------------------*/
2717 static void genInline (iCode *ic)
2718 {
2719     char buffer[MAX_INLINEASM];
2720     char *bp = buffer;
2721     char *bp1= buffer;
2722     
2723     _G.inLine += (!options.asmpeep);
2724     strcpy(buffer,IC_INLINE(ic));
2725
2726     /* emit each line as a code */
2727     while (*bp) {
2728         if (*bp == '\n') {
2729             *bp++ = '\0';
2730             emitcode(bp1,"");
2731             bp1 = bp;
2732         } else {
2733             if (*bp == ':') {
2734                 bp++;
2735                 *bp = '\0';
2736                 bp++;
2737                 emitcode(bp1,"");
2738                 bp1 = bp;
2739             } else
2740                 bp++;
2741         }
2742     }
2743     if (bp1 != bp)
2744         emitcode(bp1,"");
2745     /*     emitcode("",buffer); */
2746     _G.inLine -= (!options.asmpeep);
2747 }
2748
2749 /*-----------------------------------------------------------------*/
2750 /* genRRC - rotate right with carry                                */
2751 /*-----------------------------------------------------------------*/
2752 static void genRRC (iCode *ic)
2753 {
2754     operand *left , *result ;
2755     int size, offset = 0;
2756     char *l;    
2757
2758     /* rotate right with carry */
2759     left = IC_LEFT(ic);
2760     result=IC_RESULT(ic);
2761     aopOp (left,ic,FALSE);
2762     aopOp (result,ic,FALSE);
2763
2764     /* move it to the result */
2765     size = AOP_SIZE(result);    
2766     offset = size - 1 ;
2767     CLRC;
2768     while (size--) {
2769         l = aopGet(AOP(left),offset,FALSE,FALSE);
2770         MOVA(l);
2771         emitcode("rrc","a");
2772         if (AOP_SIZE(result) > 1)
2773             aopPut(AOP(result),"a",offset--);
2774     }
2775     /* now we need to put the carry into the
2776     highest order byte of the result */
2777     if (AOP_SIZE(result) > 1) {
2778         l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
2779         MOVA(l);
2780     }
2781     emitcode("mov","acc.7,c");
2782     aopPut(AOP(result),"a",AOP_SIZE(result)-1);
2783     freeAsmop(left,NULL,ic,TRUE);
2784     freeAsmop(result,NULL,ic,TRUE);
2785 }
2786
2787 /*-----------------------------------------------------------------*/
2788 /* genRLC - generate code for rotate left with carry               */
2789 /*-----------------------------------------------------------------*/
2790 static void genRLC (iCode *ic)
2791 {    
2792     operand *left , *result ;
2793     int size, offset = 0;
2794     char *l;    
2795
2796     /* rotate right with carry */
2797     left = IC_LEFT(ic);
2798     result=IC_RESULT(ic);
2799     aopOp (left,ic,FALSE);
2800     aopOp (result,ic,FALSE);
2801
2802     /* move it to the result */
2803     size = AOP_SIZE(result);    
2804     offset = 0 ;
2805     if (size--) {
2806         l = aopGet(AOP(left),offset,FALSE,FALSE);
2807         MOVA(l);
2808         emitcode("add","a,acc");
2809         if (AOP_SIZE(result) > 1)
2810             aopPut(AOP(result),"a",offset++);
2811         while (size--) {
2812             l = aopGet(AOP(left),offset,FALSE,FALSE);
2813             MOVA(l);
2814             emitcode("rlc","a");
2815             if (AOP_SIZE(result) > 1)
2816                 aopPut(AOP(result),"a",offset++);
2817         }
2818     }
2819     /* now we need to put the carry into the
2820     highest order byte of the result */
2821     if (AOP_SIZE(result) > 1) {
2822         l = aopGet(AOP(result),0,FALSE,FALSE);
2823         MOVA(l);
2824     }
2825     emitcode("mov","acc.0,c");
2826     aopPut(AOP(result),"a",0);
2827     freeAsmop(left,NULL,ic,TRUE);
2828     freeAsmop(result,NULL,ic,TRUE);
2829 }
2830
2831 /*-----------------------------------------------------------------*/
2832 /* genGetHbit - generates code get highest order bit               */
2833 /*-----------------------------------------------------------------*/
2834 static void genGetHbit (iCode *ic)
2835 {
2836     operand *left, *result;
2837     left = IC_LEFT(ic);
2838     result=IC_RESULT(ic);
2839     aopOp (left,ic,FALSE);
2840     aopOp (result,ic,FALSE);
2841
2842     /* get the highest order byte into a */
2843     MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
2844     if(AOP_TYPE(result) == AOP_CRY){
2845         emitcode("rlc","a");
2846         outBitC(result);
2847     }
2848     else{
2849         emitcode("rl","a");
2850         emitcode("anl","a,#0x01");
2851         outAcc(result);
2852     }
2853
2854
2855     freeAsmop(left,NULL,ic,TRUE);
2856     freeAsmop(result,NULL,ic,TRUE);
2857 }
2858
2859 /*-----------------------------------------------------------------*/
2860 /* AccRol - rotate left accumulator by known count                 */
2861 /*-----------------------------------------------------------------*/
2862 static void AccRol (int shCount)
2863 {
2864     shCount &= 0x0007;              // shCount : 0..7
2865     switch(shCount){
2866         case 0 :
2867             break;
2868         case 1 :
2869             emitcode("rl","a");
2870             break;
2871         case 2 :
2872             emitcode("rl","a");
2873             emitcode("rl","a");
2874             break;
2875         case 3 :
2876             emitcode("swap","a");
2877             emitcode("rr","a");
2878             break;
2879         case 4 :
2880             emitcode("swap","a");
2881             break;
2882         case 5 :
2883             emitcode("swap","a");
2884             emitcode("rl","a");
2885             break;
2886         case 6 :
2887             emitcode("rr","a");
2888             emitcode("rr","a");
2889             break;
2890         case 7 :
2891             emitcode("rr","a");
2892             break;
2893     }
2894 }
2895
2896 /*-----------------------------------------------------------------*/
2897 /* AccLsh - left shift accumulator by known count                  */
2898 /*-----------------------------------------------------------------*/
2899 static void AccLsh (int shCount)
2900 {
2901     if(shCount != 0){
2902         if(shCount == 1)
2903             emitcode("add","a,acc");
2904         else 
2905             if(shCount == 2) {
2906             emitcode("add","a,acc");
2907             emitcode("add","a,acc");
2908         } else {
2909             /* rotate left accumulator */
2910             AccRol(shCount);
2911             /* and kill the lower order bits */
2912             emitcode("anl","a,#0x%02x", SLMask[shCount]);
2913         }
2914     }
2915 }
2916
2917 /*-----------------------------------------------------------------*/
2918 /* AccRsh - right shift accumulator by known count                 */
2919 /*-----------------------------------------------------------------*/
2920 static void AccRsh (int shCount)
2921 {
2922     if(shCount != 0){
2923         if(shCount == 1){
2924             CLRC;
2925             emitcode("rrc","a");
2926         } else {
2927             /* rotate right accumulator */
2928             AccRol(8 - shCount);
2929             /* and kill the higher order bits */
2930             emitcode("anl","a,#0x%02x", SRMask[shCount]);
2931         }
2932     }
2933 }
2934
2935 /*-----------------------------------------------------------------*/
2936 /* AccSRsh - signed right shift accumulator by known count                 */
2937 /*-----------------------------------------------------------------*/
2938 static void AccSRsh (int shCount)
2939 {
2940     symbol *tlbl ;
2941     if(shCount != 0){
2942         if(shCount == 1){
2943             emitcode("mov","c,acc.7");
2944             emitcode("rrc","a");
2945         } else if(shCount == 2){
2946             emitcode("mov","c,acc.7");
2947             emitcode("rrc","a");
2948             emitcode("mov","c,acc.7");
2949             emitcode("rrc","a");
2950         } else {
2951             tlbl = newiTempLabel(NULL);
2952             /* rotate right accumulator */
2953             AccRol(8 - shCount);
2954             /* and kill the higher order bits */
2955             emitcode("anl","a,#0x%02x", SRMask[shCount]);
2956             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
2957             emitcode("orl","a,#0x%02x",
2958                      (unsigned char)~SRMask[shCount]);
2959             emitcode("","%05d$:",tlbl->key+100);
2960         }
2961     }
2962 }
2963
2964 /*-----------------------------------------------------------------*/
2965 /* shiftR1Left2Result - shift right one byte from left to result   */
2966 /*-----------------------------------------------------------------*/
2967 static void shiftR1Left2Result (operand *left, int offl,
2968                                 operand *result, int offr,
2969                                 int shCount, int sign)
2970 {
2971     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
2972     /* shift right accumulator */
2973     if(sign)
2974         AccSRsh(shCount);
2975     else
2976         AccRsh(shCount);
2977     aopPut(AOP(result),"a",offr);
2978 }
2979
2980 /*-----------------------------------------------------------------*/
2981 /* shiftL1Left2Result - shift left one byte from left to result    */
2982 /*-----------------------------------------------------------------*/
2983 static void shiftL1Left2Result (operand *left, int offl,
2984                                 operand *result, int offr, int shCount)
2985 {
2986     char *l;
2987     l = aopGet(AOP(left),offl,FALSE,FALSE);
2988     MOVA(l);
2989     /* shift left accumulator */
2990     AccLsh(shCount);
2991     aopPut(AOP(result),"a",offr);
2992 }
2993
2994 /*-----------------------------------------------------------------*/
2995 /* movLeft2Result - move byte from left to result                  */
2996 /*-----------------------------------------------------------------*/
2997 static void movLeft2Result (operand *left, int offl,
2998                             operand *result, int offr, int sign)
2999 {
3000     char *l;
3001     if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
3002         l = aopGet(AOP(left),offl,FALSE,FALSE);
3003
3004         if (*l == '@' && (IS_AOP_PREG(result))) {
3005             emitcode("mov","a,%s",l);
3006             aopPut(AOP(result),"a",offr);
3007         } else {
3008             if(!sign)
3009                 aopPut(AOP(result),l,offr);
3010             else{
3011                 /* MSB sign in acc.7 ! */
3012                 if(getDataSize(left) == offl+1){
3013                     emitcode("mov","a,%s",l);
3014                     aopPut(AOP(result),"a",offr);
3015                 }
3016             }
3017         }
3018     }
3019 }
3020
3021 /*-----------------------------------------------------------------*/
3022 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
3023 /*-----------------------------------------------------------------*/
3024 static void AccAXRrl1 (char *x)
3025 {
3026     emitcode("rrc","a");
3027     emitcode("xch","a,%s", x);
3028     emitcode("rrc","a");
3029     emitcode("xch","a,%s", x);
3030 }
3031
3032 /*-----------------------------------------------------------------*/
3033 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
3034 /*-----------------------------------------------------------------*/
3035 static void AccAXLrl1 (char *x)
3036 {
3037     emitcode("xch","a,%s",x);
3038     emitcode("rlc","a");
3039     emitcode("xch","a,%s",x);
3040     emitcode("rlc","a");
3041 }
3042
3043 /*-----------------------------------------------------------------*/
3044 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
3045 /*-----------------------------------------------------------------*/
3046 static void AccAXLsh1 (char *x)
3047 {
3048     emitcode("xch","a,%s",x);
3049     emitcode("add","a,acc");
3050     emitcode("xch","a,%s",x);
3051     emitcode("rlc","a");
3052 }
3053
3054 /*-----------------------------------------------------------------*/
3055 /* AccAXLsh - left shift a:x by known count (0..7)                 */
3056 /*-----------------------------------------------------------------*/
3057 static void AccAXLsh (char *x, int shCount)
3058 {
3059     switch(shCount){
3060         case 0 :
3061             break;
3062         case 1 :
3063             AccAXLsh1(x);
3064             break;
3065         case 2 :
3066             AccAXLsh1(x);
3067             AccAXLsh1(x);
3068             break;
3069         case 3 :
3070         case 4 :
3071         case 5 :                        // AAAAABBB:CCCCCDDD
3072             AccRol(shCount);            // BBBAAAAA:CCCCCDDD
3073             emitcode("anl","a,#0x%02x",
3074                      SLMask[shCount]);  // BBB00000:CCCCCDDD
3075             emitcode("xch","a,%s",x);   // CCCCCDDD:BBB00000
3076             AccRol(shCount);            // DDDCCCCC:BBB00000
3077             emitcode("xch","a,%s",x);   // BBB00000:DDDCCCCC
3078             emitcode("xrl","a,%s",x);   // (BBB^DDD)CCCCC:DDDCCCCC
3079             emitcode("xch","a,%s",x);   // DDDCCCCC:(BBB^DDD)CCCCC
3080             emitcode("anl","a,#0x%02x",
3081                      SLMask[shCount]);  // DDD00000:(BBB^DDD)CCCCC
3082             emitcode("xch","a,%s",x);   // (BBB^DDD)CCCCC:DDD00000
3083             emitcode("xrl","a,%s",x);   // BBBCCCCC:DDD00000            
3084             break;
3085         case 6 :                        // AAAAAABB:CCCCCCDD
3086             emitcode("anl","a,#0x%02x",
3087                      SRMask[shCount]);  // 000000BB:CCCCCCDD
3088             emitcode("mov","c,acc.0");  // c = B
3089             emitcode("xch","a,%s",x);   // CCCCCCDD:000000BB
3090             AccAXRrl1(x);               // BCCCCCCD:D000000B
3091             AccAXRrl1(x);               // BBCCCCCC:DD000000
3092             break;
3093         case 7 :                        // a:x <<= 7
3094             emitcode("anl","a,#0x%02x",
3095                      SRMask[shCount]);  // 0000000B:CCCCCCCD
3096             emitcode("mov","c,acc.0");  // c = B
3097             emitcode("xch","a,%s",x);   // CCCCCCCD:0000000B
3098             AccAXRrl1(x);               // BCCCCCCC:D0000000
3099             break;
3100         default :
3101             break;
3102     }
3103 }
3104
3105 /*-----------------------------------------------------------------*/
3106 /* AccAXRsh - right shift a:x known count (0..7)                   */
3107 /*-----------------------------------------------------------------*/
3108 static void AccAXRsh (char *x, int shCount)
3109 {   
3110     switch(shCount){
3111         case 0 :
3112             break;
3113         case 1 :
3114             CLRC;
3115             AccAXRrl1(x);               // 0->a:x
3116             break;
3117         case 2 :
3118             CLRC;
3119             AccAXRrl1(x);               // 0->a:x
3120             CLRC;
3121             AccAXRrl1(x);               // 0->a:x
3122             break;
3123         case 3 :
3124         case 4 :
3125         case 5 :                        // AAAAABBB:CCCCCDDD = a:x
3126             AccRol(8 - shCount);        // BBBAAAAA:DDDCCCCC
3127             emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
3128             AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
3129             emitcode("anl","a,#0x%02x",
3130                      SRMask[shCount]);  // 000CCCCC:BBBAAAAA
3131             emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
3132             emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
3133             emitcode("anl","a,#0x%02x",
3134                      SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
3135             emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
3136             emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
3137             emitcode("xch","a,%s",x);   // 000AAAAA:BBBCCCCC
3138             break;
3139         case 6 :                        // AABBBBBB:CCDDDDDD
3140             emitcode("mov","c,acc.7");
3141             AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
3142             AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
3143             emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
3144             emitcode("anl","a,#0x%02x",
3145                      SRMask[shCount]);  // 000000AA:BBBBBBCC
3146             break;
3147         case 7 :                        // ABBBBBBB:CDDDDDDD
3148             emitcode("mov","c,acc.7");  // c = A
3149             AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
3150             emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
3151             emitcode("anl","a,#0x%02x",
3152                      SRMask[shCount]);  // 0000000A:BBBBBBBC
3153             break;
3154         default :
3155             break;
3156     }
3157 }
3158
3159 /*-----------------------------------------------------------------*/
3160 /* AccAXRshS - right shift signed a:x known count (0..7)           */
3161 /*-----------------------------------------------------------------*/
3162 static void AccAXRshS (char *x, int shCount)
3163 {   
3164     symbol *tlbl ;
3165     switch(shCount){
3166         case 0 :
3167             break;
3168         case 1 :
3169             emitcode("mov","c,acc.7");
3170             AccAXRrl1(x);               // s->a:x
3171             break;
3172         case 2 :
3173             emitcode("mov","c,acc.7");
3174             AccAXRrl1(x);               // s->a:x
3175             emitcode("mov","c,acc.7");
3176             AccAXRrl1(x);               // s->a:x
3177             break;
3178         case 3 :
3179         case 4 :
3180         case 5 :                        // AAAAABBB:CCCCCDDD = a:x
3181             tlbl = newiTempLabel(NULL);
3182             AccRol(8 - shCount);        // BBBAAAAA:CCCCCDDD
3183             emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
3184             AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
3185             emitcode("anl","a,#0x%02x",
3186                      SRMask[shCount]);  // 000CCCCC:BBBAAAAA
3187             emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
3188             emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
3189             emitcode("anl","a,#0x%02x",
3190                      SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
3191             emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
3192             emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
3193             emitcode("xch","a,%s",x);   // 000SAAAA:BBBCCCCC
3194             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); 
3195             emitcode("orl","a,#0x%02x",
3196                      (unsigned char)~SRMask[shCount]);  // 111AAAAA:BBBCCCCC
3197             emitcode("","%05d$:",tlbl->key+100);
3198             break;                      // SSSSAAAA:BBBCCCCC
3199         case 6 :                        // AABBBBBB:CCDDDDDD
3200             tlbl = newiTempLabel(NULL);
3201             emitcode("mov","c,acc.7");
3202             AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
3203             AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
3204             emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
3205             emitcode("anl","a,#0x%02x",
3206                      SRMask[shCount]);  // 000000AA:BBBBBBCC
3207             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); 
3208             emitcode("orl","a,#0x%02x",
3209                      (unsigned char)~SRMask[shCount]);  // 111111AA:BBBBBBCC
3210             emitcode("","%05d$:",tlbl->key+100);
3211             break;
3212         case 7 :                        // ABBBBBBB:CDDDDDDD
3213             tlbl = newiTempLabel(NULL);
3214             emitcode("mov","c,acc.7");  // c = A
3215             AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
3216             emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
3217             emitcode("anl","a,#0x%02x",
3218                      SRMask[shCount]);  // 0000000A:BBBBBBBC
3219             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); 
3220             emitcode("orl","a,#0x%02x",
3221                      (unsigned char)~SRMask[shCount]);  // 1111111A:BBBBBBBC
3222             emitcode("","%05d$:",tlbl->key+100);
3223             break;
3224         default :
3225             break;
3226     }
3227 }
3228
3229 /*-----------------------------------------------------------------*/
3230 /* shiftL2Left2Result - shift left two bytes from left to result   */
3231 /*-----------------------------------------------------------------*/
3232 static void shiftL2Left2Result (operand *left, int offl,
3233                                 operand *result, int offr, int shCount)
3234 {
3235     if(sameRegs(AOP(result), AOP(left)) &&
3236        ((offl + MSB16) == offr)){
3237         /* don't crash result[offr] */
3238         MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
3239         emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
3240     } else {
3241         movLeft2Result(left,offl, result, offr, 0);
3242         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
3243     }
3244     /* ax << shCount (x = lsb(result))*/
3245     AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
3246     aopPut(AOP(result),"a",offr+MSB16);
3247 }
3248
3249
3250 /*-----------------------------------------------------------------*/
3251 /* shiftR2Left2Result - shift right two bytes from left to result  */
3252 /*-----------------------------------------------------------------*/
3253 static void shiftR2Left2Result (operand *left, int offl,
3254                                 operand *result, int offr,
3255                                 int shCount, int sign)
3256 {
3257     if(sameRegs(AOP(result), AOP(left)) &&
3258        ((offl + MSB16) == offr)){
3259         /* don't crash result[offr] */
3260         MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
3261         emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
3262     } else {
3263         movLeft2Result(left,offl, result, offr, 0);
3264         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
3265     }
3266     /* a:x >> shCount (x = lsb(result))*/
3267     if(sign)
3268         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
3269     else
3270         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
3271     if(getDataSize(result) > 1)
3272         aopPut(AOP(result),"a",offr+MSB16);
3273 }
3274
3275 /*-----------------------------------------------------------------*/
3276 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
3277 /*-----------------------------------------------------------------*/
3278 static void shiftLLeftOrResult (operand *left, int offl,
3279                                 operand *result, int offr, int shCount)
3280 {
3281     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
3282     /* shift left accumulator */
3283     AccLsh(shCount);
3284     /* or with result */
3285     emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
3286     /* back to result */
3287     aopPut(AOP(result),"a",offr);
3288 }
3289
3290 /*-----------------------------------------------------------------*/
3291 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
3292 /*-----------------------------------------------------------------*/
3293 static void shiftRLeftOrResult (operand *left, int offl,
3294                                 operand *result, int offr, int shCount)
3295 {
3296     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
3297     /* shift right accumulator */
3298     AccRsh(shCount);
3299     /* or with result */
3300     emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
3301     /* back to result */
3302     aopPut(AOP(result),"a",offr);
3303 }
3304
3305 /*-----------------------------------------------------------------*/
3306 /* genlshOne - left shift a one byte quantity by known count       */
3307 /*-----------------------------------------------------------------*/
3308 static void genlshOne (operand *result, operand *left, int shCount)
3309 {       
3310     shiftL1Left2Result(left, LSB, result, LSB, shCount);
3311 }
3312
3313 /*-----------------------------------------------------------------*/
3314 /* genlshTwo - left shift two bytes by known amount != 0           */
3315 /*-----------------------------------------------------------------*/
3316 static void genlshTwo (operand *result,operand *left, int shCount)
3317 {
3318     int size;
3319     
3320     size = getDataSize(result);
3321
3322     /* if shCount >= 8 */
3323     if (shCount >= 8) {
3324         shCount -= 8 ;
3325
3326         if (size > 1){
3327             if (shCount)
3328                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
3329             else 
3330                 movLeft2Result(left, LSB, result, MSB16, 0);
3331         }
3332         aopPut(AOP(result),zero,LSB);   
3333     }
3334
3335     /*  1 <= shCount <= 7 */
3336     else {  
3337         if(size == 1)
3338             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
3339         else 
3340             shiftL2Left2Result(left, LSB, result, LSB, shCount);
3341     }
3342 }
3343
3344 /*-----------------------------------------------------------------*/
3345 /* shiftLLong - shift left one long from left to result            */
3346 /* offl = LSB or MSB16                                             */
3347 /*-----------------------------------------------------------------*/
3348 static void shiftLLong (operand *left, operand *result, int offr )
3349 {
3350     char *l;
3351     int size = AOP_SIZE(result);
3352
3353     if(size >= LSB+offr){
3354         l = aopGet(AOP(left),LSB,FALSE,FALSE);
3355         MOVA(l);
3356         emitcode("add","a,acc");
3357         if (sameRegs(AOP(left),AOP(result)) && 
3358             size >= MSB16+offr && offr != LSB )
3359             emitcode("xch","a,%s",
3360                      aopGet(AOP(left),LSB+offr,FALSE,FALSE));
3361         else        
3362             aopPut(AOP(result),"a",LSB+offr);
3363     }
3364
3365     if(size >= MSB16+offr){
3366         if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
3367             l = aopGet(AOP(left),MSB16,FALSE,FALSE);
3368             MOVA(l);
3369         }
3370         emitcode("rlc","a");
3371         if (sameRegs(AOP(left),AOP(result)) && 
3372             size >= MSB24+offr && offr != LSB)
3373             emitcode("xch","a,%s",
3374                      aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
3375         else        
3376             aopPut(AOP(result),"a",MSB16+offr);
3377     }
3378
3379     if(size >= MSB24+offr){
3380         if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
3381             l = aopGet(AOP(left),MSB24,FALSE,FALSE);
3382             MOVA(l);
3383         }
3384         emitcode("rlc","a");
3385         if (sameRegs(AOP(left),AOP(result)) && 
3386             size >= MSB32+offr && offr != LSB )
3387             emitcode("xch","a,%s",
3388                      aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
3389         else        
3390             aopPut(AOP(result),"a",MSB24+offr);
3391     }
3392
3393     if(size > MSB32+offr){
3394         if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
3395             l = aopGet(AOP(left),MSB32,FALSE,FALSE);
3396             MOVA(l);    
3397         }
3398         emitcode("rlc","a");
3399         aopPut(AOP(result),"a",MSB32+offr);
3400     }
3401     if(offr != LSB)
3402         aopPut(AOP(result),zero,LSB);       
3403 }
3404
3405 /*-----------------------------------------------------------------*/
3406 /* genlshFour - shift four byte by a known amount != 0             */
3407 /*-----------------------------------------------------------------*/
3408 static void genlshFour (operand *result, operand *left, int shCount)
3409 {
3410     int size;
3411
3412     size = AOP_SIZE(result);
3413
3414     /* if shifting more that 3 bytes */
3415     if (shCount >= 24 ) {
3416         shCount -= 24;
3417         if (shCount)
3418             /* lowest order of left goes to the highest
3419             order of the destination */
3420             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
3421         else
3422             movLeft2Result(left, LSB, result, MSB32, 0);
3423         aopPut(AOP(result),zero,LSB);
3424         aopPut(AOP(result),zero,MSB16);
3425         aopPut(AOP(result),zero,MSB32);
3426         return;
3427     }
3428
3429     /* more than two bytes */
3430     else if ( shCount >= 16 ) {
3431         /* lower order two bytes goes to higher order two bytes */
3432         shCount -= 16;
3433         /* if some more remaining */
3434         if (shCount)
3435             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
3436         else {
3437             movLeft2Result(left, MSB16, result, MSB32, 0);
3438             movLeft2Result(left, LSB, result, MSB24, 0);
3439         }
3440         aopPut(AOP(result),zero,MSB16);
3441         aopPut(AOP(result),zero,LSB);
3442         return;
3443     }    
3444
3445     /* if more than 1 byte */
3446     else if ( shCount >= 8 ) {
3447         /* lower order three bytes goes to higher order  three bytes */
3448         shCount -= 8;
3449         if(size == 2){
3450             if(shCount)
3451                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
3452             else
3453                 movLeft2Result(left, LSB, result, MSB16, 0);
3454         }
3455         else{   /* size = 4 */
3456             if(shCount == 0){
3457                 movLeft2Result(left, MSB24, result, MSB32, 0);
3458                 movLeft2Result(left, MSB16, result, MSB24, 0);
3459                 movLeft2Result(left, LSB, result, MSB16, 0);
3460                 aopPut(AOP(result),zero,LSB);
3461             }
3462             else if(shCount == 1)
3463                 shiftLLong(left, result, MSB16);
3464             else{
3465                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
3466                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
3467                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
3468                 aopPut(AOP(result),zero,LSB);
3469             }
3470         }
3471     }
3472
3473     /* 1 <= shCount <= 7 */
3474     else if(shCount <= 2){
3475         shiftLLong(left, result, LSB);
3476         if(shCount == 2)
3477             shiftLLong(result, result, LSB);
3478     }
3479     /* 3 <= shCount <= 7, optimize */
3480     else{
3481         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
3482         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
3483         shiftL2Left2Result(left, LSB, result, LSB, shCount);
3484     }
3485 }
3486
3487 /*-----------------------------------------------------------------*/
3488 /* genLeftShiftLiteral - left shifting by known count              */
3489 /*-----------------------------------------------------------------*/
3490 static void genLeftShiftLiteral (operand *left,
3491                                  operand *right,
3492                                  operand *result,
3493                                  iCode *ic)
3494 {    
3495     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3496     int size;
3497
3498     freeAsmop(right,NULL,ic,TRUE);
3499
3500     aopOp(left,ic,FALSE);
3501     aopOp(result,ic,FALSE);
3502
3503     size = getSize(operandType(result));
3504
3505 #if VIEW_SIZE
3506     emitcode("; shift left ","result %d, left %d",size,
3507              AOP_SIZE(left));
3508 #endif
3509
3510     /* I suppose that the left size >= result size */
3511     if(shCount == 0){
3512         while(size--){
3513             movLeft2Result(left, size, result, size, 0);
3514         }
3515     }
3516
3517     else if(shCount >= (size * 8))
3518         while(size--)
3519             aopPut(AOP(result),zero,size);
3520     else{
3521         switch (size) {
3522             case 1:
3523                 genlshOne (result,left,shCount);
3524                 break;
3525
3526             case 2:
3527             case 3:
3528                 genlshTwo (result,left,shCount);
3529                 break;
3530
3531             case 4:
3532                 genlshFour (result,left,shCount);
3533                 break;
3534         }
3535     }
3536     freeAsmop(left,NULL,ic,TRUE);
3537     freeAsmop(result,NULL,ic,TRUE);
3538 }
3539
3540 /*-----------------------------------------------------------------*/
3541 /* genLeftShift - generates code for left shifting                 */
3542 /*-----------------------------------------------------------------*/
3543 static void genLeftShift (iCode *ic)
3544 {
3545     operand *left,*right, *result;
3546     int size, offset;
3547     char *l;
3548     symbol *tlbl , *tlbl1;
3549
3550     right = IC_RIGHT(ic);
3551     left  = IC_LEFT(ic);
3552     result = IC_RESULT(ic);
3553
3554     aopOp(right,ic,FALSE);
3555
3556     /* if the shift count is known then do it 
3557     as efficiently as possible */
3558     if (AOP_TYPE(right) == AOP_LIT) {
3559         genLeftShiftLiteral (left,right,result,ic);
3560         return ;
3561     }
3562
3563     /* shift count is unknown then we have to form 
3564     a loop get the loop count in B : Note: we take
3565     only the lower order byte since shifting
3566     more that 32 bits make no sense anyway, ( the
3567     largest size of an object can be only 32 bits ) */  
3568
3569     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3570     emitcode("inc","b");
3571     freeAsmop (right,NULL,ic,TRUE);
3572     aopOp(left,ic,FALSE);
3573     aopOp(result,ic,FALSE);
3574
3575     /* now move the left to the result if they are not the
3576     same */
3577     if (!sameRegs(AOP(left),AOP(result)) && 
3578         AOP_SIZE(result) > 1) {
3579
3580         size = AOP_SIZE(result);
3581         offset=0;
3582         while (size--) {
3583             l = aopGet(AOP(left),offset,FALSE,TRUE);
3584             if (*l == '@' && (IS_AOP_PREG(result))) {
3585
3586                 emitcode("mov","a,%s",l);
3587                 aopPut(AOP(result),"a",offset);
3588             } else
3589                 aopPut(AOP(result),l,offset);
3590             offset++;
3591         }
3592     }
3593
3594     tlbl = newiTempLabel(NULL);
3595     size = AOP_SIZE(result);
3596     offset = 0 ;   
3597     tlbl1 = newiTempLabel(NULL);
3598
3599     /* if it is only one byte then */
3600     if (size == 1) {
3601         symbol *tlbl1 = newiTempLabel(NULL);
3602
3603         l = aopGet(AOP(left),0,FALSE,FALSE);
3604         MOVA(l);
3605         emitcode("sjmp","%05d$",tlbl1->key+100); 
3606         emitcode("","%05d$:",tlbl->key+100);
3607         emitcode("add","a,acc");
3608         emitcode("","%05d$:",tlbl1->key+100);
3609         emitcode("djnz","b,%05d$",tlbl->key+100);      
3610         aopPut(AOP(result),"a",0);
3611         goto release ;
3612     }
3613     
3614     reAdjustPreg(AOP(result));    
3615     
3616     emitcode("sjmp","%05d$",tlbl1->key+100); 
3617     emitcode("","%05d$:",tlbl->key+100);    
3618     l = aopGet(AOP(result),offset,FALSE,FALSE);
3619     MOVA(l);
3620     emitcode("add","a,acc");         
3621     aopPut(AOP(result),"a",offset++);
3622     while (--size) {
3623         l = aopGet(AOP(result),offset,FALSE,FALSE);
3624         MOVA(l);
3625         emitcode("rlc","a");         
3626         aopPut(AOP(result),"a",offset++);
3627     }
3628     reAdjustPreg(AOP(result));
3629
3630     emitcode("","%05d$:",tlbl1->key+100);
3631     emitcode("djnz","b,%05d$",tlbl->key+100);
3632 release:
3633     freeAsmop(left,NULL,ic,TRUE);
3634     freeAsmop(result,NULL,ic,TRUE);
3635 }
3636
3637 /*-----------------------------------------------------------------*/
3638 /* genrshOne - right shift a one byte quantity by known count      */
3639 /*-----------------------------------------------------------------*/
3640 static void genrshOne (operand *result, operand *left,
3641                        int shCount, int sign)
3642 {
3643     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
3644 }
3645
3646 /*-----------------------------------------------------------------*/
3647 /* genrshTwo - right shift two bytes by known amount != 0          */
3648 /*-----------------------------------------------------------------*/
3649 static void genrshTwo (operand *result,operand *left,
3650                        int shCount, int sign)
3651 {
3652     /* if shCount >= 8 */
3653     if (shCount >= 8) {
3654         shCount -= 8 ;
3655         if (shCount)
3656             shiftR1Left2Result(left, MSB16, result, LSB,
3657                                shCount, sign);
3658         else 
3659             movLeft2Result(left, MSB16, result, LSB, sign);
3660         addSign(result, MSB16, sign);
3661     }
3662
3663     /*  1 <= shCount <= 7 */
3664     else
3665         shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
3666 }
3667
3668 /*-----------------------------------------------------------------*/
3669 /* shiftRLong - shift right one long from left to result           */
3670 /* offl = LSB or MSB16                                             */
3671 /*-----------------------------------------------------------------*/
3672 static void shiftRLong (operand *left, int offl,
3673                         operand *result, int sign)
3674 {
3675     if(!sign)
3676         emitcode("clr","c");
3677     MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
3678     if(sign)
3679         emitcode("mov","c,acc.7");
3680     emitcode("rrc","a");
3681     aopPut(AOP(result),"a",MSB32-offl);
3682     if(offl == MSB16)
3683         /* add sign of "a" */
3684         addSign(result, MSB32, sign);
3685
3686     MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
3687     emitcode("rrc","a");
3688     aopPut(AOP(result),"a",MSB24-offl);
3689
3690     MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
3691     emitcode("rrc","a");
3692     aopPut(AOP(result),"a",MSB16-offl);
3693
3694     if(offl == LSB){
3695         MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
3696         emitcode("rrc","a");
3697         aopPut(AOP(result),"a",LSB);
3698     }
3699 }
3700
3701 /*-----------------------------------------------------------------*/
3702 /* genrshFour - shift four byte by a known amount != 0             */
3703 /*-----------------------------------------------------------------*/
3704 static void genrshFour (operand *result, operand *left,
3705                         int shCount, int sign)
3706 {
3707     /* if shifting more that 3 bytes */
3708     if(shCount >= 24 ) {
3709         shCount -= 24;
3710         if(shCount)
3711             shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
3712         else
3713             movLeft2Result(left, MSB32, result, LSB, sign);
3714         addSign(result, MSB16, sign);
3715     }
3716     else if(shCount >= 16){
3717         shCount -= 16;
3718         if(shCount)
3719             shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
3720         else{
3721             movLeft2Result(left, MSB24, result, LSB, 0);
3722             movLeft2Result(left, MSB32, result, MSB16, sign);
3723         }
3724         addSign(result, MSB24, sign);
3725     }
3726     else if(shCount >= 8){
3727         shCount -= 8;
3728         if(shCount == 1)
3729             shiftRLong(left, MSB16, result, sign);
3730         else if(shCount == 0){
3731             movLeft2Result(left, MSB16, result, LSB, 0);
3732             movLeft2Result(left, MSB24, result, MSB16, 0);
3733             movLeft2Result(left, MSB32, result, MSB24, sign);
3734             addSign(result, MSB32, sign);
3735         }
3736         else{
3737             shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
3738             shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
3739             /* the last shift is signed */
3740             shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
3741             addSign(result, MSB32, sign);
3742         }
3743     }
3744     else{   /* 1 <= shCount <= 7 */
3745         if(shCount <= 2){
3746             shiftRLong(left, LSB, result, sign);
3747             if(shCount == 2)
3748                 shiftRLong(result, LSB, result, sign);
3749         }
3750         else{
3751             shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
3752             shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
3753             shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
3754         }
3755     }
3756 }
3757
3758 /*-----------------------------------------------------------------*/
3759 /* genRightShiftLiteral - right shifting by known count            */
3760 /*-----------------------------------------------------------------*/
3761 static void genRightShiftLiteral (operand *left,
3762                                   operand *right,
3763                                   operand *result,
3764                                   iCode *ic,
3765                                   int sign)
3766 {    
3767     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3768     int size;
3769
3770     freeAsmop(right,NULL,ic,TRUE);
3771
3772     aopOp(left,ic,FALSE);
3773     aopOp(result,ic,FALSE);
3774
3775 #if VIEW_SIZE
3776     emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
3777              AOP_SIZE(left));
3778 #endif
3779
3780     size = getDataSize(left);
3781     /* test the LEFT size !!! */
3782
3783     /* I suppose that the left size >= result size */
3784     if(shCount == 0){
3785         size = getDataSize(result);
3786         while(size--)
3787             movLeft2Result(left, size, result, size, 0);
3788     }
3789
3790     else if(shCount >= (size * 8)){
3791         if(sign)
3792             /* get sign in acc.7 */
3793             MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
3794         addSign(result, LSB, sign);
3795     } else{
3796         switch (size) {
3797             case 1:
3798                 genrshOne (result,left,shCount,sign);
3799                 break;
3800
3801             case 2:
3802                 genrshTwo (result,left,shCount,sign);
3803                 break;
3804
3805             case 4:
3806                 genrshFour (result,left,shCount,sign);
3807                 break;
3808             default :
3809                 break;
3810         }
3811
3812         freeAsmop(left,NULL,ic,TRUE);
3813         freeAsmop(result,NULL,ic,TRUE);
3814     }
3815 }
3816
3817 /*-----------------------------------------------------------------*/
3818 /* genSignedRightShift - right shift of signed number              */
3819 /*-----------------------------------------------------------------*/
3820 static void genSignedRightShift (iCode *ic)
3821 {
3822     operand *right, *left, *result;
3823     int size, offset;
3824     char *l;
3825     symbol *tlbl, *tlbl1 ;
3826
3827     /* we do it the hard way put the shift count in b
3828     and loop thru preserving the sign */
3829
3830     right = IC_RIGHT(ic);
3831     left  = IC_LEFT(ic);
3832     result = IC_RESULT(ic);
3833
3834     aopOp(right,ic,FALSE);  
3835
3836
3837     if ( AOP_TYPE(right) == AOP_LIT) {
3838         genRightShiftLiteral (left,right,result,ic,1);
3839         return ;
3840     }
3841         /* shift count is unknown then we have to form 
3842        a loop get the loop count in B : Note: we take
3843        only the lower order byte since shifting
3844        more that 32 bits make no sense anyway, ( the
3845        largest size of an object can be only 32 bits ) */  
3846
3847     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3848     emitcode("inc","b");
3849     freeAsmop (right,NULL,ic,TRUE);
3850     aopOp(left,ic,FALSE);
3851     aopOp(result,ic,FALSE);
3852
3853     /* now move the left to the result if they are not the
3854     same */
3855     if (!sameRegs(AOP(left),AOP(result)) && 
3856         AOP_SIZE(result) > 1) {
3857
3858         size = AOP_SIZE(result);
3859         offset=0;
3860         while (size--) {
3861             l = aopGet(AOP(left),offset,FALSE,TRUE);
3862             if (*l == '@' && IS_AOP_PREG(result)) {
3863
3864                 emitcode("mov","a,%s",l);
3865                 aopPut(AOP(result),"a",offset);
3866             } else
3867                 aopPut(AOP(result),l,offset);
3868             offset++;
3869         }
3870     }
3871
3872     /* mov the highest order bit to OVR */    
3873     tlbl = newiTempLabel(NULL);
3874     tlbl1= newiTempLabel(NULL);
3875
3876     size = AOP_SIZE(result);
3877     offset = size - 1;
3878     emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
3879     emitcode("rlc","a");
3880     emitcode("mov","ov,c");
3881     /* if it is only one byte then */
3882     if (size == 1) {
3883         l = aopGet(AOP(left),0,FALSE,FALSE);
3884         MOVA(l);
3885         emitcode("sjmp","%05d$",tlbl1->key+100);
3886         emitcode("","%05d$:",tlbl->key+100);
3887         emitcode("mov","c,ov");
3888         emitcode("rrc","a");
3889         emitcode("","%05d$:",tlbl1->key+100);
3890         emitcode("djnz","b,%05d$",tlbl->key+100);
3891         aopPut(AOP(result),"a",0);
3892         goto release ;
3893     }
3894
3895     reAdjustPreg(AOP(result));
3896     emitcode("sjmp","%05d$",tlbl1->key+100);
3897     emitcode("","%05d$:",tlbl->key+100);    
3898     emitcode("mov","c,ov");
3899     while (size--) {
3900         l = aopGet(AOP(result),offset,FALSE,FALSE);
3901         MOVA(l);
3902         emitcode("rrc","a");         
3903         aopPut(AOP(result),"a",offset--);
3904     }
3905     reAdjustPreg(AOP(result));
3906     emitcode("","%05d$:",tlbl1->key+100);
3907     emitcode("djnz","b,%05d$",tlbl->key+100);
3908
3909 release:
3910     freeAsmop(left,NULL,ic,TRUE);
3911     freeAsmop(result,NULL,ic,TRUE);
3912 }
3913
3914 /*-----------------------------------------------------------------*/
3915 /* genRightShift - generate code for right shifting                */
3916 /*-----------------------------------------------------------------*/
3917 static void genRightShift (iCode *ic)
3918 {
3919     operand *right, *left, *result;
3920     link *retype ;
3921     int size, offset;
3922     char *l;
3923     symbol *tlbl, *tlbl1 ;
3924
3925     /* if signed then we do it the hard way preserve the
3926     sign bit moving it inwards */
3927     retype = getSpec(operandType(IC_RESULT(ic)));
3928
3929     if (!SPEC_USIGN(retype)) {
3930         genSignedRightShift (ic);
3931         return ;
3932     }
3933
3934     /* signed & unsigned types are treated the same : i.e. the
3935     signed is NOT propagated inwards : quoting from the
3936     ANSI - standard : "for E1 >> E2, is equivalent to division
3937     by 2**E2 if unsigned or if it has a non-negative value,
3938     otherwise the result is implementation defined ", MY definition
3939     is that the sign does not get propagated */
3940
3941     right = IC_RIGHT(ic);
3942     left  = IC_LEFT(ic);
3943     result = IC_RESULT(ic);
3944
3945     aopOp(right,ic,FALSE);
3946
3947     /* if the shift count is known then do it 
3948     as efficiently as possible */
3949     if (AOP_TYPE(right) == AOP_LIT) {
3950         genRightShiftLiteral (left,right,result,ic, 0);
3951         return ;
3952     }
3953
3954     /* shift count is unknown then we have to form 
3955     a loop get the loop count in B : Note: we take
3956     only the lower order byte since shifting
3957     more that 32 bits make no sense anyway, ( the
3958     largest size of an object can be only 32 bits ) */  
3959
3960     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3961     emitcode("inc","b");
3962     freeAsmop (right,NULL,ic,TRUE);
3963     aopOp(left,ic,FALSE);
3964     aopOp(result,ic,FALSE);
3965
3966     /* now move the left to the result if they are not the
3967     same */
3968     if (!sameRegs(AOP(left),AOP(result)) && 
3969         AOP_SIZE(result) > 1) {
3970
3971         size = AOP_SIZE(result);
3972         offset=0;
3973         while (size--) {
3974             l = aopGet(AOP(left),offset,FALSE,TRUE);
3975             if (*l == '@' && IS_AOP_PREG(result)) {
3976
3977                 emitcode("mov","a,%s",l);
3978                 aopPut(AOP(result),"a",offset);
3979             } else
3980                 aopPut(AOP(result),l,offset);
3981             offset++;
3982         }
3983     }
3984
3985     tlbl = newiTempLabel(NULL);
3986     tlbl1= newiTempLabel(NULL);
3987     size = AOP_SIZE(result);
3988     offset = size - 1;
3989
3990     /* if it is only one byte then */
3991     if (size == 1) {
3992         l = aopGet(AOP(left),0,FALSE,FALSE);
3993         MOVA(l);
3994         emitcode("sjmp","%05d$",tlbl1->key+100);
3995         emitcode("","%05d$:",tlbl->key+100);
3996         CLRC;
3997         emitcode("rrc","a");
3998         emitcode("","%05d$:",tlbl1->key+100);
3999         emitcode("djnz","b,%05d$",tlbl->key+100);
4000         aopPut(AOP(result),"a",0);
4001         goto release ;
4002     }
4003
4004     reAdjustPreg(AOP(result));
4005     emitcode("sjmp","%05d$",tlbl1->key+100);
4006     emitcode("","%05d$:",tlbl->key+100);    
4007     CLRC;
4008     while (size--) {
4009         l = aopGet(AOP(result),offset,FALSE,FALSE);
4010         MOVA(l);
4011         emitcode("rrc","a");         
4012         aopPut(AOP(result),"a",offset--);
4013     }
4014     reAdjustPreg(AOP(result));
4015
4016     emitcode("","%05d$:",tlbl1->key+100);
4017     emitcode("djnz","b,%05d$",tlbl->key+100);
4018
4019 release:
4020     freeAsmop(left,NULL,ic,TRUE);
4021     freeAsmop(result,NULL,ic,TRUE);
4022 }
4023
4024 /*-----------------------------------------------------------------*/
4025 /* genUnpackBits - generates code for unpacking bits               */
4026 /*-----------------------------------------------------------------*/
4027 static void genUnpackBits (operand *result, char *rname, int ptype)
4028 {    
4029     int shCnt ;
4030     int rlen = 0 ;
4031     link *etype;
4032     int offset = 0 ;
4033
4034     etype = getSpec(operandType(result));
4035
4036     /* read the first byte  */
4037     switch (ptype) {
4038
4039     case POINTER:
4040     case IPOINTER:
4041         emitcode("mov","a,@%s",rname);
4042         break;
4043         
4044     case PPOINTER:
4045         emitcode("movx","a,@%s",rname);
4046         break;
4047         
4048     case FPOINTER:
4049         emitcode("movx","a,@dptr");
4050         break;
4051
4052     case CPOINTER:
4053         emitcode("clr","a");
4054         emitcode("movc","a","@a+dptr");
4055         break;
4056
4057     case GPOINTER:
4058         emitcode("lcall","__gptrget");
4059         break;
4060     }
4061
4062     /* if we have bitdisplacement then it fits   */
4063     /* into this byte completely or if length is */
4064     /* less than a byte                          */
4065     if ((shCnt = SPEC_BSTR(etype)) || 
4066         (SPEC_BLEN(etype) <= 8))  {
4067
4068         /* shift right acc */
4069         AccRsh(shCnt);
4070
4071         emitcode("anl","a,#0x%02x",
4072                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
4073         aopPut(AOP(result),"a",offset);
4074         return ;
4075     }
4076
4077     /* bit field did not fit in a byte  */
4078     rlen = SPEC_BLEN(etype) - 8;
4079     aopPut(AOP(result),"a",offset++);
4080
4081     while (1)  {
4082
4083         switch (ptype) {
4084         case POINTER:
4085         case IPOINTER:
4086             emitcode("inc","%s",rname);
4087             emitcode("mov","a,@%s",rname);
4088             break;
4089             
4090         case PPOINTER:
4091             emitcode("inc","%s",rname);
4092             emitcode("movx","a,@%s",rname);
4093             break;
4094
4095         case FPOINTER:
4096             emitcode("inc","dptr");
4097             emitcode("movx","a,@dptr");
4098             break;
4099             
4100         case CPOINTER:
4101             emitcode("clr","a");
4102             emitcode("inc","dptr");
4103             emitcode("movc","a","@a+dptr");
4104             break;
4105             
4106         case GPOINTER:
4107             emitcode("inc","dptr");
4108             emitcode("lcall","__gptrget");
4109             break;
4110         }
4111
4112         rlen -= 8;            
4113         /* if we are done */
4114         if ( rlen <= 0 )
4115             break ;
4116         
4117         aopPut(AOP(result),"a",offset++);
4118                               
4119     }
4120     
4121     if (rlen) {
4122         emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
4123         aopPut(AOP(result),"a",offset);        
4124     }
4125     
4126     return ;
4127 }
4128
4129
4130 /*-----------------------------------------------------------------*/
4131 /* genDataPointerGet - generates code when ptr offset is known     */
4132 /*-----------------------------------------------------------------*/
4133 static void genDataPointerGet (operand *left, 
4134                                operand *result, 
4135                                iCode *ic)
4136 {
4137     char *l;
4138     char buffer[256];
4139     int size , offset = 0;
4140     aopOp(result,ic,TRUE);
4141
4142     /* get the string representation of the name */
4143     l = aopGet(AOP(left),0,FALSE,TRUE);
4144     size = AOP_SIZE(result);
4145     while (size--) {
4146         if (offset)
4147             sprintf(buffer,"(%s + %d)",l+1,offset);
4148         else
4149             sprintf(buffer,"%s",l+1);
4150         aopPut(AOP(result),buffer,offset++);
4151     }
4152
4153     freeAsmop(left,NULL,ic,TRUE);
4154     freeAsmop(result,NULL,ic,TRUE);
4155 }
4156
4157 /*-----------------------------------------------------------------*/
4158 /* genNearPointerGet - emitcode for near pointer fetch             */
4159 /*-----------------------------------------------------------------*/
4160 static void genNearPointerGet (operand *left, 
4161                                operand *result, 
4162                                iCode *ic)
4163 {
4164     asmop *aop = NULL;
4165     regs *preg = NULL ;
4166     char *rname ;
4167     link *rtype, *retype;
4168     link *ltype = operandType(left);    
4169     char buffer[80];
4170
4171     rtype = operandType(result);
4172     retype= getSpec(rtype);
4173     
4174     aopOp(left,ic,FALSE);
4175     
4176     /* if left is rematerialisable and
4177        result is not bit variable type and
4178        the left is pointer to data space i.e
4179        lower 128 bytes of space */
4180     if (AOP_TYPE(left) == AOP_IMMD &&
4181         !IS_BITVAR(retype)         &&
4182         DCL_TYPE(ltype) == POINTER) {
4183         genDataPointerGet (left,result,ic);
4184         return ;
4185     }
4186     
4187         /* if the value is already in a pointer register
4188        then don't need anything more */
4189     if (!AOP_INPREG(AOP(left))) {
4190         /* otherwise get a free pointer register */
4191         aop = newAsmop(0);
4192         preg = getFreePtr(ic,&aop,FALSE);
4193         emitcode("mov","%s,%s",
4194                 preg->name,
4195                 aopGet(AOP(left),0,FALSE,TRUE));
4196         rname = preg->name ;
4197     } else
4198         rname = aopGet(AOP(left),0,FALSE,FALSE);
4199     
4200     freeAsmop(left,NULL,ic,TRUE);
4201     aopOp (result,ic,FALSE);
4202     
4203       /* if bitfield then unpack the bits */
4204     if (IS_BITVAR(retype)) 
4205         genUnpackBits (result,rname,POINTER);
4206     else {
4207         /* we have can just get the values */
4208         int size = AOP_SIZE(result);
4209         int offset = 0 ;        
4210         
4211         while (size--) {
4212             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
4213
4214                 emitcode("mov","a,@%s",rname);
4215                 aopPut(AOP(result),"a",offset);
4216             } else {
4217                 sprintf(buffer,"@%s",rname);
4218                 aopPut(AOP(result),buffer,offset);
4219             }
4220             offset++ ;
4221             if (size)
4222                 emitcode("inc","%s",rname);
4223         }
4224     }
4225
4226     /* now some housekeeping stuff */
4227     if (aop) {
4228         /* we had to allocate for this iCode */
4229         freeAsmop(NULL,aop,ic,TRUE);
4230     } else { 
4231         /* we did not allocate which means left
4232            already in a pointer register, then
4233            if size > 0 && this could be used again
4234            we have to point it back to where it 
4235            belongs */
4236         if (AOP_SIZE(result) > 1 &&
4237             !OP_SYMBOL(left)->remat &&
4238             ( OP_SYMBOL(left)->liveTo > ic->seq ||
4239               ic->depth )) {
4240             int size = AOP_SIZE(result) - 1;
4241             while (size--)
4242                 emitcode("dec","%s",rname);
4243         }
4244     }
4245
4246     /* done */
4247     freeAsmop(result,NULL,ic,TRUE);
4248      
4249 }
4250
4251 /*-----------------------------------------------------------------*/
4252 /* genPagedPointerGet - emitcode for paged pointer fetch           */
4253 /*-----------------------------------------------------------------*/
4254 static void genPagedPointerGet (operand *left, 
4255                                operand *result, 
4256                                iCode *ic)
4257 {
4258     asmop *aop = NULL;
4259     regs *preg = NULL ;
4260     char *rname ;
4261     link *rtype, *retype;    
4262
4263     rtype = operandType(result);
4264     retype= getSpec(rtype);
4265     
4266     aopOp(left,ic,FALSE);
4267
4268   /* if the value is already in a pointer register
4269        then don't need anything more */
4270     if (!AOP_INPREG(AOP(left))) {
4271         /* otherwise get a free pointer register */
4272         aop = newAsmop(0);
4273         preg = getFreePtr(ic,&aop,FALSE);
4274         emitcode("mov","%s,%s",
4275                 preg->name,
4276                 aopGet(AOP(left),0,FALSE,TRUE));
4277         rname = preg->name ;
4278     } else
4279         rname = aopGet(AOP(left),0,FALSE,FALSE);
4280     
4281     freeAsmop(left,NULL,ic,TRUE);
4282     aopOp (result,ic,FALSE);
4283
4284     /* if bitfield then unpack the bits */
4285     if (IS_BITVAR(retype)) 
4286         genUnpackBits (result,rname,PPOINTER);
4287     else {
4288         /* we have can just get the values */
4289         int size = AOP_SIZE(result);
4290         int offset = 0 ;        
4291         
4292         while (size--) {
4293             
4294             emitcode("movx","a,@%s",rname);
4295             aopPut(AOP(result),"a",offset);
4296             
4297             offset++ ;
4298             
4299             if (size)
4300                 emitcode("inc","%s",rname);
4301         }
4302     }
4303
4304     /* now some housekeeping stuff */
4305     if (aop) {
4306         /* we had to allocate for this iCode */
4307         freeAsmop(NULL,aop,ic,TRUE);
4308     } else { 
4309         /* we did not allocate which means left
4310            already in a pointer register, then
4311            if size > 0 && this could be used again
4312            we have to point it back to where it 
4313            belongs */
4314         if (AOP_SIZE(result) > 1 &&
4315             !OP_SYMBOL(left)->remat &&
4316             ( OP_SYMBOL(left)->liveTo > ic->seq ||
4317               ic->depth )) {
4318             int size = AOP_SIZE(result) - 1;
4319             while (size--)
4320                 emitcode("dec","%s",rname);
4321         }
4322     }
4323
4324     /* done */
4325     freeAsmop(result,NULL,ic,TRUE);
4326     
4327         
4328 }
4329
4330 /*-----------------------------------------------------------------*/
4331 /* genFarPointerGet - gget value from far space                    */
4332 /*-----------------------------------------------------------------*/
4333 static void genFarPointerGet (operand *left,
4334                               operand *result, iCode *ic)
4335 {
4336     int size, offset ;
4337     link *retype = getSpec(operandType(result));
4338
4339     aopOp(left,ic,FALSE);
4340
4341     /* if the operand is already in dptr 
4342     then we do nothing else we move the value to dptr */
4343     if (AOP_TYPE(left) != AOP_STR) {
4344         /* if this is remateriazable */
4345         if (AOP_TYPE(left) == AOP_IMMD)
4346             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
4347         else { /* we need to get it byte by byte */
4348             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
4349             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
4350             if (options.model == MODEL_FLAT24)
4351             {
4352                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
4353             }
4354         }
4355     }
4356     /* so dptr know contains the address */
4357     freeAsmop(left,NULL,ic,TRUE);
4358     aopOp(result,ic,FALSE);
4359
4360     /* if bit then unpack */
4361     if (IS_BITVAR(retype)) 
4362         genUnpackBits(result,"dptr",FPOINTER);
4363     else {
4364         size = AOP_SIZE(result);
4365         offset = 0 ;
4366
4367         while (size--) {
4368             emitcode("movx","a,@dptr");
4369             aopPut(AOP(result),"a",offset++);
4370             if (size)
4371                 emitcode("inc","dptr");
4372         }
4373     }
4374
4375     freeAsmop(result,NULL,ic,TRUE);
4376 }
4377
4378 /*-----------------------------------------------------------------*/
4379 /* emitcodePointerGet - gget value from code space                  */
4380 /*-----------------------------------------------------------------*/
4381 static void emitcodePointerGet (operand *left,
4382                                 operand *result, iCode *ic)
4383 {
4384     int size, offset ;
4385     link *retype = getSpec(operandType(result));
4386
4387     aopOp(left,ic,FALSE);
4388
4389     /* if the operand is already in dptr 
4390     then we do nothing else we move the value to dptr */
4391     if (AOP_TYPE(left) != AOP_STR) {
4392         /* if this is remateriazable */
4393         if (AOP_TYPE(left) == AOP_IMMD)
4394             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
4395         else { /* we need to get it byte by byte */
4396             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
4397             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
4398             if (options.model == MODEL_FLAT24)
4399             {
4400                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
4401             }
4402         }
4403     }
4404     /* so dptr know contains the address */
4405     freeAsmop(left,NULL,ic,TRUE);
4406     aopOp(result,ic,FALSE);
4407
4408     /* if bit then unpack */
4409     if (IS_BITVAR(retype)) 
4410         genUnpackBits(result,"dptr",CPOINTER);
4411     else {
4412         size = AOP_SIZE(result);
4413         offset = 0 ;
4414
4415         while (size--) {
4416             emitcode("clr","a");
4417             emitcode("movc","a,@a+dptr");
4418             aopPut(AOP(result),"a",offset++);
4419             if (size)
4420                 emitcode("inc","dptr");
4421         }
4422     }
4423
4424     freeAsmop(result,NULL,ic,TRUE);
4425 }
4426
4427 /*-----------------------------------------------------------------*/
4428 /* genGenPointerGet - gget value from generic pointer space        */
4429 /*-----------------------------------------------------------------*/
4430 static void genGenPointerGet (operand *left,
4431                               operand *result, iCode *ic)
4432 {
4433     int size, offset ;
4434     link *retype = getSpec(operandType(result));
4435
4436     aopOp(left,ic,FALSE);
4437
4438     /* if the operand is already in dptr 
4439     then we do nothing else we move the value to dptr */
4440     if (AOP_TYPE(left) != AOP_STR) {
4441         /* if this is remateriazable */
4442         if (AOP_TYPE(left) == AOP_IMMD) {
4443             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
4444             emitcode("mov","b,#%d",pointerCode(retype));
4445         }
4446         else { /* we need to get it byte by byte */
4447             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
4448             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
4449             if (options.model == MODEL_FLAT24)
4450             {
4451                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
4452                emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
4453             }
4454             else
4455             {
4456                 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
4457             }
4458         }
4459     }
4460     /* so dptr know contains the address */
4461     freeAsmop(left,NULL,ic,TRUE);
4462     aopOp(result,ic,FALSE); 
4463
4464     /* if bit then unpack */
4465     if (IS_BITVAR(retype)) 
4466         genUnpackBits(result,"dptr",GPOINTER);
4467     else {
4468         size = AOP_SIZE(result);
4469         offset = 0 ;
4470
4471         while (size--) {
4472             emitcode("lcall","__gptrget");
4473             aopPut(AOP(result),"a",offset++);
4474             if (size)
4475                 emitcode("inc","dptr");
4476         }
4477     }
4478
4479     freeAsmop(result,NULL,ic,TRUE);
4480 }
4481
4482 /*-----------------------------------------------------------------*/
4483 /* genPointerGet - generate code for pointer get                   */
4484 /*-----------------------------------------------------------------*/
4485 static void genPointerGet (iCode *ic)
4486 {
4487     operand *left, *result ;
4488     link *type, *etype;
4489     int p_type;
4490
4491     left = IC_LEFT(ic);
4492     result = IC_RESULT(ic) ;
4493
4494     /* depending on the type of pointer we need to
4495     move it to the correct pointer register */
4496     type = operandType(left);
4497     etype = getSpec(type);
4498     /* if left is of type of pointer then it is simple */
4499     if (IS_PTR(type) && !IS_FUNC(type->next)) 
4500         p_type = DCL_TYPE(type);
4501     else {
4502         /* we have to go by the storage class */
4503         p_type = PTR_TYPE(SPEC_OCLS(etype));
4504
4505 /*      if (SPEC_OCLS(etype)->codesp ) { */
4506 /*          p_type = CPOINTER ;  */
4507 /*      } */
4508 /*      else */
4509 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
4510 /*              p_type = FPOINTER ; */
4511 /*          else */
4512 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
4513 /*                  p_type = PPOINTER; */
4514 /*              else */
4515 /*                  if (SPEC_OCLS(etype) == idata ) */
4516 /*                      p_type = IPOINTER; */
4517 /*                  else */
4518 /*                      p_type = POINTER ; */
4519     }
4520
4521     /* now that we have the pointer type we assign
4522     the pointer values */
4523     switch (p_type) {
4524
4525     case POINTER:       
4526     case IPOINTER:
4527         genNearPointerGet (left,result,ic);
4528         break;
4529
4530     case PPOINTER:
4531         genPagedPointerGet(left,result,ic);
4532         break;
4533
4534     case FPOINTER:
4535         genFarPointerGet (left,result,ic);
4536         break;
4537
4538     case CPOINTER:
4539         emitcodePointerGet (left,result,ic);
4540         break;
4541
4542     case GPOINTER:
4543         genGenPointerGet (left,result,ic);
4544         break;
4545     }
4546
4547 }
4548
4549 /*-----------------------------------------------------------------*/
4550 /* genPackBits - generates code for packed bit storage             */
4551 /*-----------------------------------------------------------------*/
4552 static void genPackBits (link    *etype ,
4553                          operand *right ,
4554                          char *rname, int p_type)
4555 {
4556     int shCount = 0 ;
4557     int offset = 0  ;
4558     int rLen = 0 ;
4559     int blen, bstr ;   
4560     char *l ;
4561
4562     blen = SPEC_BLEN(etype);
4563     bstr = SPEC_BSTR(etype);
4564
4565     l = aopGet(AOP(right),offset++,FALSE,FALSE);
4566     MOVA(l);   
4567
4568     /* if the bit lenth is less than or    */
4569     /* it exactly fits a byte then         */
4570     if (SPEC_BLEN(etype) <= 8 )  {
4571         shCount = SPEC_BSTR(etype) ;
4572
4573         /* shift left acc */
4574         AccLsh(shCount);
4575
4576         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
4577
4578
4579             switch (p_type) {
4580                 case POINTER:
4581                     emitcode ("mov","b,a");
4582                     emitcode("mov","a,@%s",rname);
4583                     break;
4584
4585                 case FPOINTER:
4586                     emitcode ("mov","b,a");
4587                     emitcode("movx","a,@dptr");
4588                     break;
4589
4590                 case GPOINTER:
4591                     emitcode ("push","b");
4592                     emitcode ("push","acc");
4593                     emitcode ("lcall","__gptrget");
4594                     emitcode ("pop","b");
4595                     break;
4596             }
4597
4598             emitcode ("anl","a,#0x%02x",(unsigned char)
4599                       ((unsigned char)(0xFF << (blen+bstr)) | 
4600                        (unsigned char)(0xFF >> (8-bstr)) ) );
4601             emitcode ("orl","a,b");
4602             if (p_type == GPOINTER)
4603                 emitcode("pop","b");
4604         }
4605     }
4606
4607     switch (p_type) {
4608         case POINTER:
4609             emitcode("mov","@%s,a",rname);
4610             break;
4611
4612         case FPOINTER:
4613             emitcode("movx","@dptr,a");
4614             break;
4615
4616         case GPOINTER:
4617             emitcode("lcall","__gptrput");
4618             break;
4619     }
4620
4621     /* if we r done */
4622     if ( SPEC_BLEN(etype) <= 8 )
4623         return ;
4624
4625     emitcode("inc","%s",rname);
4626     rLen = SPEC_BLEN(etype) ;     
4627
4628     /* now generate for lengths greater than one byte */
4629     while (1) {
4630
4631         l = aopGet(AOP(right),offset++,FALSE,TRUE);
4632
4633         rLen -= 8 ;
4634         if (rLen <= 0 )
4635             break ;
4636
4637         switch (p_type) {
4638             case POINTER:
4639                 if (*l == '@') {
4640                     MOVA(l);
4641                     emitcode("mov","@%s,a",rname);
4642                 } else
4643                     emitcode("mov","@%s,%s",rname,l);
4644                 break;
4645
4646             case FPOINTER:
4647                 MOVA(l);
4648                 emitcode("movx","@dptr,a");
4649                 break;
4650
4651             case GPOINTER:
4652                 MOVA(l);
4653                 emitcode("lcall","__gptrput");
4654                 break;  
4655         }   
4656         emitcode ("inc","%s",rname);
4657     }
4658
4659     MOVA(l);
4660
4661     /* last last was not complete */
4662     if (rLen)   {
4663         /* save the byte & read byte */
4664         switch (p_type) {
4665             case POINTER:
4666                 emitcode ("mov","b,a");
4667                 emitcode("mov","a,@%s",rname);
4668                 break;
4669
4670             case FPOINTER:
4671                 emitcode ("mov","b,a");
4672                 emitcode("movx","a,@dptr");
4673                 break;
4674
4675             case GPOINTER:
4676                 emitcode ("push","b");
4677                 emitcode ("push","acc");
4678                 emitcode ("lcall","__gptrget");
4679                 emitcode ("pop","b");
4680                 break;
4681         }
4682
4683         emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
4684         emitcode ("orl","a,b");
4685     }
4686
4687     if (p_type == GPOINTER)
4688         emitcode("pop","b");
4689
4690     switch (p_type) {
4691
4692     case POINTER:
4693         emitcode("mov","@%s,a",rname);
4694         break;
4695         
4696     case FPOINTER:
4697         emitcode("movx","@dptr,a");
4698         break;
4699         
4700     case GPOINTER:
4701         emitcode("lcall","__gptrput");
4702         break;                  
4703     }
4704 }
4705 /*-----------------------------------------------------------------*/
4706 /* genDataPointerSet - remat pointer to data space                 */
4707 /*-----------------------------------------------------------------*/
4708 static void genDataPointerSet(operand *right,
4709                               operand *result,
4710                               iCode *ic)
4711 {
4712     int size, offset = 0 ;
4713     char *l, buffer[256];
4714
4715     aopOp(right,ic,FALSE);
4716     
4717     l = aopGet(AOP(result),0,FALSE,TRUE);
4718     size = AOP_SIZE(right);
4719     while (size--) {
4720         if (offset)
4721             sprintf(buffer,"(%s + %d)",l+1,offset);
4722         else
4723             sprintf(buffer,"%s",l+1);
4724         emitcode("mov","%s,%s",buffer,
4725                  aopGet(AOP(right),offset++,FALSE,FALSE));
4726     }
4727
4728     freeAsmop(right,NULL,ic,TRUE);
4729     freeAsmop(result,NULL,ic,TRUE);
4730 }
4731
4732 /*-----------------------------------------------------------------*/
4733 /* genNearPointerSet - emitcode for near pointer put                */
4734 /*-----------------------------------------------------------------*/
4735 static void genNearPointerSet (operand *right,
4736                                operand *result, 
4737                                iCode *ic)
4738 {
4739     asmop *aop = NULL;
4740     regs *preg = NULL ;
4741     char *rname , *l;
4742     link *retype;
4743     link *ptype = operandType(result);
4744     
4745     retype= getSpec(operandType(right));
4746
4747     aopOp(result,ic,FALSE);
4748     
4749     /* if the result is rematerializable &
4750        in data space & not a bit variable */
4751     if (AOP_TYPE(result) == AOP_IMMD &&
4752         DCL_TYPE(ptype) == POINTER   &&
4753         !IS_BITVAR(retype)) {
4754         genDataPointerSet (right,result,ic);
4755         return;
4756     }
4757
4758     /* if the value is already in a pointer register
4759     then don't need anything more */
4760     if (!AOP_INPREG(AOP(result))) {
4761         /* otherwise get a free pointer register */
4762         aop = newAsmop(0);
4763         preg = getFreePtr(ic,&aop,FALSE);
4764         emitcode("mov","%s,%s",
4765                  preg->name,
4766                  aopGet(AOP(result),0,FALSE,TRUE));
4767         rname = preg->name ;
4768     } else
4769         rname = aopGet(AOP(result),0,FALSE,FALSE);
4770
4771     freeAsmop(result,NULL,ic,TRUE);
4772     aopOp (right,ic,FALSE);
4773
4774     /* if bitfield then unpack the bits */
4775     if (IS_BITVAR(retype)) 
4776         genPackBits (retype,right,rname,POINTER);
4777     else {
4778         /* we have can just get the values */
4779         int size = AOP_SIZE(right);
4780         int offset = 0 ;    
4781
4782         while (size--) {
4783             l = aopGet(AOP(right),offset,FALSE,TRUE);
4784             if (*l == '@' ) {
4785                 MOVA(l);
4786                 emitcode("mov","@%s,a",rname);
4787             } else
4788                 emitcode("mov","@%s,%s",rname,l);
4789             if (size)
4790                 emitcode("inc","%s",rname);
4791             offset++;
4792         }
4793     }
4794
4795     /* now some housekeeping stuff */
4796     if (aop) {
4797         /* we had to allocate for this iCode */
4798         freeAsmop(NULL,aop,ic,TRUE);
4799     } else { 
4800         /* we did not allocate which means left
4801         already in a pointer register, then
4802         if size > 0 && this could be used again
4803         we have to point it back to where it 
4804         belongs */
4805         if (AOP_SIZE(right) > 1 &&
4806             !OP_SYMBOL(result)->remat &&
4807             ( OP_SYMBOL(result)->liveTo > ic->seq ||
4808               ic->depth )) {
4809             int size = AOP_SIZE(right) - 1;
4810             while (size--)
4811                 emitcode("dec","%s",rname);
4812         }
4813     }
4814
4815     /* done */
4816     freeAsmop(right,NULL,ic,TRUE);
4817
4818
4819 }
4820
4821 /*-----------------------------------------------------------------*/
4822 /* genPagedPointerSet - emitcode for Paged pointer put             */
4823 /*-----------------------------------------------------------------*/
4824 static void genPagedPointerSet (operand *right,
4825                                operand *result, 
4826                                iCode *ic)
4827 {
4828     asmop *aop = NULL;
4829     regs *preg = NULL ;
4830     char *rname , *l;
4831     link *retype;
4832        
4833     retype= getSpec(operandType(right));
4834     
4835     aopOp(result,ic,FALSE);
4836     
4837     /* if the value is already in a pointer register
4838        then don't need anything more */
4839     if (!AOP_INPREG(AOP(result))) {
4840         /* otherwise get a free pointer register */
4841         aop = newAsmop(0);
4842         preg = getFreePtr(ic,&aop,FALSE);
4843         emitcode("mov","%s,%s",
4844                 preg->name,
4845                 aopGet(AOP(result),0,FALSE,TRUE));
4846         rname = preg->name ;
4847     } else
4848         rname = aopGet(AOP(result),0,FALSE,FALSE);
4849     
4850     freeAsmop(result,NULL,ic,TRUE);
4851     aopOp (right,ic,FALSE);
4852
4853     /* if bitfield then unpack the bits */
4854     if (IS_BITVAR(retype)) 
4855         genPackBits (retype,right,rname,PPOINTER);
4856     else {
4857         /* we have can just get the values */
4858         int size = AOP_SIZE(right);
4859         int offset = 0 ;        
4860         
4861         while (size--) {
4862             l = aopGet(AOP(right),offset,FALSE,TRUE);
4863             
4864             MOVA(l);
4865             emitcode("movx","@%s,a",rname);
4866
4867             if (size)
4868                 emitcode("inc","%s",rname);
4869
4870             offset++;
4871         }
4872     }
4873     
4874     /* now some housekeeping stuff */
4875     if (aop) {
4876         /* we had to allocate for this iCode */
4877         freeAsmop(NULL,aop,ic,TRUE);
4878     } else { 
4879         /* we did not allocate which means left
4880            already in a pointer register, then
4881            if size > 0 && this could be used again
4882            we have to point it back to where it 
4883            belongs */
4884         if (AOP_SIZE(right) > 1 &&
4885             !OP_SYMBOL(result)->remat &&
4886             ( OP_SYMBOL(result)->liveTo > ic->seq ||
4887               ic->depth )) {
4888             int size = AOP_SIZE(right) - 1;
4889             while (size--)
4890                 emitcode("dec","%s",rname);
4891         }
4892     }
4893
4894     /* done */
4895     freeAsmop(right,NULL,ic,TRUE);
4896     
4897         
4898 }
4899
4900 /*-----------------------------------------------------------------*/
4901 /* genFarPointerSet - set value from far space                     */
4902 /*-----------------------------------------------------------------*/
4903 static void genFarPointerSet (operand *right,
4904                               operand *result, iCode *ic)
4905 {
4906     int size, offset ;
4907     link *retype = getSpec(operandType(right));
4908
4909     aopOp(result,ic,FALSE);
4910
4911     /* if the operand is already in dptr 
4912     then we do nothing else we move the value to dptr */
4913     if (AOP_TYPE(result) != AOP_STR) {
4914         /* if this is remateriazable */
4915         if (AOP_TYPE(result) == AOP_IMMD)
4916             emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
4917         else { /* we need to get it byte by byte */
4918             emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
4919             emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
4920             if (options.model == MODEL_FLAT24)
4921             {
4922                emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
4923             }
4924         }
4925     }
4926     /* so dptr know contains the address */
4927     freeAsmop(result,NULL,ic,TRUE);
4928     aopOp(right,ic,FALSE);
4929
4930     /* if bit then unpack */
4931     if (IS_BITVAR(retype)) 
4932         genPackBits(retype,right,"dptr",FPOINTER);
4933     else {
4934         size = AOP_SIZE(right);
4935         offset = 0 ;
4936
4937         while (size--) {
4938             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
4939             MOVA(l);
4940             emitcode("movx","@dptr,a");
4941             if (size)
4942                 emitcode("inc","dptr");
4943         }
4944     }
4945
4946     freeAsmop(right,NULL,ic,TRUE);
4947 }
4948
4949 /*-----------------------------------------------------------------*/
4950 /* genGenPointerSet - set value from generic pointer space         */
4951 /*-----------------------------------------------------------------*/
4952 static void genGenPointerSet (operand *right,
4953                               operand *result, iCode *ic)
4954 {
4955     int size, offset ;
4956     link *retype = getSpec(operandType(right));
4957
4958     aopOp(result,ic,FALSE);
4959
4960     /* if the operand is already in dptr 
4961     then we do nothing else we move the value to dptr */
4962     if (AOP_TYPE(result) != AOP_STR) {
4963         /* if this is remateriazable */
4964         if (AOP_TYPE(result) == AOP_IMMD) {
4965             emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
4966             emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
4967         }
4968         else { /* we need to get it byte by byte */
4969             emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
4970             emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
4971             if (options.model == MODEL_FLAT24)
4972             {
4973                emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
4974                emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
4975             }
4976             else
4977             {
4978                 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
4979             }
4980         }
4981     }
4982     /* so dptr know contains the address */
4983     freeAsmop(result,NULL,ic,TRUE);
4984     aopOp(right,ic,FALSE);
4985
4986     /* if bit then unpack */
4987     if (IS_BITVAR(retype)) 
4988         genPackBits(retype,right,"dptr",GPOINTER);
4989     else {
4990         size = AOP_SIZE(right);
4991         offset = 0 ;
4992
4993         while (size--) {
4994             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
4995             MOVA(l);
4996             emitcode("lcall","__gptrput");
4997             if (size)
4998                 emitcode("inc","dptr");
4999         }
5000     }
5001
5002     freeAsmop(right,NULL,ic,TRUE);
5003 }
5004
5005 /*-----------------------------------------------------------------*/
5006 /* genPointerSet - stores the value into a pointer location        */
5007 /*-----------------------------------------------------------------*/
5008 static void genPointerSet (iCode *ic)
5009 {    
5010     operand *right, *result ;
5011     link *type, *etype;
5012     int p_type;
5013
5014     right = IC_RIGHT(ic);
5015     result = IC_RESULT(ic) ;
5016
5017     /* depending on the type of pointer we need to
5018     move it to the correct pointer register */
5019     type = operandType(result);
5020     etype = getSpec(type);
5021     /* if left is of type of pointer then it is simple */
5022     if (IS_PTR(type) && !IS_FUNC(type->next)) {
5023         p_type = DCL_TYPE(type);
5024     }
5025     else {
5026         /* we have to go by the storage class */
5027         p_type = PTR_TYPE(SPEC_OCLS(etype));
5028
5029 /*      if (SPEC_OCLS(etype)->codesp ) { */
5030 /*          p_type = CPOINTER ;  */
5031 /*      } */
5032 /*      else */
5033 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
5034 /*              p_type = FPOINTER ; */
5035 /*          else */
5036 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
5037 /*                  p_type = PPOINTER ; */
5038 /*              else */
5039 /*                  if (SPEC_OCLS(etype) == idata ) */
5040 /*                      p_type = IPOINTER ; */
5041 /*                  else */
5042 /*                      p_type = POINTER ; */
5043     }
5044
5045     /* now that we have the pointer type we assign
5046     the pointer values */
5047     switch (p_type) {
5048
5049     case POINTER:
5050     case IPOINTER:
5051         genNearPointerSet (right,result,ic);
5052         break;
5053
5054     case PPOINTER:
5055         genPagedPointerSet (right,result,ic);
5056         break;
5057
5058     case FPOINTER:
5059         genFarPointerSet (right,result,ic);
5060         break;
5061
5062     case GPOINTER:
5063         genGenPointerSet (right,result,ic);
5064         break;
5065     }
5066
5067 }
5068
5069 /*-----------------------------------------------------------------*/
5070 /* genIfx - generate code for Ifx statement                        */
5071 /*-----------------------------------------------------------------*/
5072 static void genIfx (iCode *ic, iCode *popIc)
5073 {
5074     operand *cond = IC_COND(ic);
5075     int isbit =0;
5076
5077     aopOp(cond,ic,FALSE);
5078
5079     /* get the value into acc */
5080     if (AOP_TYPE(cond) != AOP_CRY)
5081         toBoolean(cond);
5082     else
5083         isbit = 1;
5084     /* the result is now in the accumulator */
5085     freeAsmop(cond,NULL,ic,TRUE);
5086
5087     /* if there was something to be popped then do it */
5088     if (popIc)
5089         genIpop(popIc);
5090
5091     /* if the condition is  a bit variable */
5092     if (isbit && IS_ITEMP(cond) && 
5093         SPIL_LOC(cond))
5094         genIfxJump(ic,SPIL_LOC(cond)->rname);
5095     else
5096         if (isbit && !IS_ITEMP(cond))
5097             genIfxJump(ic,OP_SYMBOL(cond)->rname);
5098         else
5099             genIfxJump(ic,"a");
5100
5101     ic->generated = 1;
5102 }
5103
5104 /*-----------------------------------------------------------------*/
5105 /* genAddrOf - generates code for address of                       */
5106 /*-----------------------------------------------------------------*/
5107 static void genAddrOf (iCode *ic)
5108 {
5109     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
5110     int size, offset ;
5111
5112     aopOp(IC_RESULT(ic),ic,FALSE);
5113
5114     /* if the operand is on the stack then we 
5115     need to get the stack offset of this
5116     variable */
5117     if (sym->onStack) {
5118         /* if it has an offset then we need to compute
5119         it */
5120         if (sym->stack) {
5121             emitcode("mov","a,_bp");
5122             emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
5123             aopPut(AOP(IC_RESULT(ic)),"a",0);       
5124         } else {
5125             /* we can just move _bp */
5126             aopPut(AOP(IC_RESULT(ic)),"_bp",0);
5127         }
5128         /* fill the result with zero */
5129         size = AOP_SIZE(IC_RESULT(ic)) - 1;
5130         
5131         
5132         if (options.stack10bit && size < (FPTRSIZE - 1))
5133         {
5134             fprintf(stderr, 
5135                     "*** warning: pointer to stack var truncated.\n");
5136         }
5137         
5138         offset = 1;
5139         while (size--)
5140         {
5141             /* Yuck! */
5142             if (options.stack10bit && offset == 2)
5143             {
5144                 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
5145             }
5146             else
5147             {
5148                 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
5149             }
5150         }
5151
5152         goto release;
5153     }
5154
5155     /* object not on stack then we need the name */
5156     size = AOP_SIZE(IC_RESULT(ic));
5157     offset = 0;
5158
5159     while (size--) {
5160         char s[SDCC_NAME_MAX];
5161         if (offset) 
5162             sprintf(s,"#(%s >> %d)",
5163                     sym->rname,
5164                     offset*8);
5165         else
5166             sprintf(s,"#%s",sym->rname);
5167         aopPut(AOP(IC_RESULT(ic)),s,offset++);
5168     }
5169
5170 release:
5171     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
5172
5173 }
5174
5175 /*-----------------------------------------------------------------*/
5176 /* genFarFarAssign - assignment when both are in far space         */
5177 /*-----------------------------------------------------------------*/
5178 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
5179 {
5180     int size = AOP_SIZE(right);
5181     int offset = 0;
5182     char *l ;
5183     /* first push the right side on to the stack */
5184     while (size--) {
5185         l = aopGet(AOP(right),offset++,FALSE,FALSE);
5186         MOVA(l);
5187         emitcode ("push","acc");
5188     }
5189     
5190     freeAsmop(right,NULL,ic,FALSE);
5191     /* now assign DPTR to result */
5192     aopOp(result,ic,FALSE);
5193     size = AOP_SIZE(result);
5194     while (size--) {
5195         emitcode ("pop","acc");
5196         aopPut(AOP(result),"a",--offset);
5197     }
5198     freeAsmop(result,NULL,ic,FALSE);
5199         
5200 }
5201
5202 /*-----------------------------------------------------------------*/
5203 /* genAssign - generate code for assignment                        */
5204 /*-----------------------------------------------------------------*/
5205 static void genAssign (iCode *ic)
5206 {
5207     operand *result, *right;
5208     int size, offset ;
5209         unsigned long lit = 0L;
5210
5211     result = IC_RESULT(ic);
5212     right  = IC_RIGHT(ic) ;
5213
5214     /* if they are the same */
5215     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
5216         return ;
5217
5218     aopOp(right,ic,FALSE);
5219     
5220     /* special case both in far space */
5221     if ((AOP_TYPE(right) == AOP_DPTR ||
5222          AOP_TYPE(right) == AOP_DPTR2) &&
5223         IS_TRUE_SYMOP(result)       &&
5224         isOperandInFarSpace(result)) {
5225         
5226         genFarFarAssign (result,right,ic);
5227         return ;
5228     }
5229
5230     aopOp(result,ic,TRUE);
5231
5232     /* if they are the same registers */
5233     if (sameRegs(AOP(right),AOP(result)))
5234         goto release;
5235
5236     /* if the result is a bit */
5237     if (AOP_TYPE(result) == AOP_CRY) {
5238
5239         /* if the right size is a literal then
5240         we know what the value is */
5241         if (AOP_TYPE(right) == AOP_LIT) {
5242             if (((int) operandLitValue(right))) 
5243                 aopPut(AOP(result),one,0);
5244             else
5245                 aopPut(AOP(result),zero,0);
5246             goto release;
5247         }
5248
5249         /* the right is also a bit variable */
5250         if (AOP_TYPE(right) == AOP_CRY) {
5251             emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5252             aopPut(AOP(result),"c",0);
5253             goto release ;
5254         }
5255
5256         /* we need to or */
5257         toBoolean(right);
5258         aopPut(AOP(result),"a",0);
5259         goto release ;
5260     }
5261
5262     /* bit variables done */
5263     /* general case */
5264     size = AOP_SIZE(result);
5265     offset = 0 ;
5266     if(AOP_TYPE(right) == AOP_LIT)
5267         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5268     if((size > 1) &&
5269        (AOP_TYPE(result) != AOP_REG) &&
5270        (AOP_TYPE(right) == AOP_LIT) &&
5271        !IS_FLOAT(operandType(right)) &&
5272        (lit < 256L)){
5273         emitcode("clr","a");
5274         while (size--) {
5275             if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
5276                 aopPut(AOP(result),"a",size);
5277             else
5278                 aopPut(AOP(result),
5279                        aopGet(AOP(right),size,FALSE,FALSE),
5280                        size);
5281         }
5282     } else {
5283         while (size--) {
5284             aopPut(AOP(result),
5285                    aopGet(AOP(right),offset,FALSE,FALSE),
5286                    offset);
5287             offset++;
5288         }
5289     }
5290     
5291 release:
5292     freeAsmop (right,NULL,ic,FALSE);
5293     freeAsmop (result,NULL,ic,TRUE);
5294 }   
5295
5296 /*-----------------------------------------------------------------*/
5297 /* genJumpTab - genrates code for jump table                       */
5298 /*-----------------------------------------------------------------*/
5299 static void genJumpTab (iCode *ic)
5300 {
5301     symbol *jtab;
5302     char *l;
5303
5304     aopOp(IC_JTCOND(ic),ic,FALSE);
5305     /* get the condition into accumulator */
5306     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
5307     MOVA(l);
5308     /* multiply by three */
5309     emitcode("add","a,acc");
5310     emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
5311     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
5312
5313     jtab = newiTempLabel(NULL);
5314     emitcode("mov","dptr,#%05d$",jtab->key+100);
5315     emitcode("jmp","@a+dptr");
5316     emitcode("","%05d$:",jtab->key+100);
5317     /* now generate the jump labels */
5318     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
5319          jtab = setNextItem(IC_JTLABELS(ic)))
5320         emitcode("ljmp","%05d$",jtab->key+100);
5321
5322 }
5323
5324 /*-----------------------------------------------------------------*/
5325 /* genCast - gen code for casting                                  */
5326 /*-----------------------------------------------------------------*/
5327 static void genCast (iCode *ic)
5328 {
5329     operand *result = IC_RESULT(ic);
5330     link *ctype = operandType(IC_LEFT(ic));
5331     link *rtype = operandType(IC_RIGHT(ic));
5332     operand *right = IC_RIGHT(ic);
5333     int size, offset ;
5334
5335     /* if they are equivalent then do nothing */
5336     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
5337         return ;
5338
5339     aopOp(right,ic,FALSE) ;
5340     aopOp(result,ic,FALSE);
5341
5342     /* if the result is a bit */
5343     if (AOP_TYPE(result) == AOP_CRY) {
5344         /* if the right size is a literal then
5345         we know what the value is */
5346         if (AOP_TYPE(right) == AOP_LIT) {
5347             if (((int) operandLitValue(right))) 
5348                 aopPut(AOP(result),one,0);
5349             else
5350                 aopPut(AOP(result),zero,0);
5351
5352             goto release;
5353         }
5354
5355         /* the right is also a bit variable */
5356         if (AOP_TYPE(right) == AOP_CRY) {
5357             emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5358             aopPut(AOP(result),"c",0);
5359             goto release ;
5360         }
5361
5362         /* we need to or */
5363         toBoolean(right);
5364         aopPut(AOP(result),"a",0);
5365         goto release ;
5366     }
5367
5368     /* if they are the same size : or less */
5369     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
5370
5371         /* if they are in the same place */
5372         if (sameRegs(AOP(right),AOP(result)))
5373             goto release;
5374
5375         /* if they in different places then copy */
5376         size = AOP_SIZE(result);
5377         offset = 0 ;
5378         while (size--) {
5379             aopPut(AOP(result),
5380                    aopGet(AOP(right),offset,FALSE,FALSE),
5381                    offset);
5382             offset++;
5383         }
5384         goto release;
5385     }
5386
5387
5388     /* if the result is of type pointer */
5389     if (IS_PTR(ctype)) {
5390
5391         int p_type;
5392         link *type = operandType(right);
5393         link *etype = getSpec(type);
5394
5395         /* pointer to generic pointer */
5396         if (IS_GENPTR(ctype)) {
5397             char *l = zero;
5398             
5399             if (IS_PTR(type)) 
5400                 p_type = DCL_TYPE(type);
5401             else {
5402                 /* we have to go by the storage class */
5403                 p_type = PTR_TYPE(SPEC_OCLS(etype));
5404             }
5405                 
5406             /* the first two bytes are known */
5407             size = GPTRSIZE - 1; 
5408             offset = 0 ;
5409             while (size--) {
5410                 aopPut(AOP(result),
5411                        aopGet(AOP(right),offset,FALSE,FALSE),
5412                        offset);
5413                 offset++;
5414             }
5415             /* the last byte depending on type */
5416             switch (p_type) {
5417             case IPOINTER:
5418             case POINTER:
5419                 l = zero;
5420                 break;
5421             case FPOINTER:
5422                 l = one;
5423                 break;
5424             case CPOINTER:
5425                 l = "#0x02";
5426                 break;                          
5427             case PPOINTER:
5428                 l = "#0x03";
5429                 break;
5430                 
5431             default:
5432                 /* this should never happen */
5433                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
5434                        "got unknown pointer type");
5435                 exit(1);
5436             }
5437             aopPut(AOP(result),l, GPTRSIZE - 1);            
5438             goto release ;
5439         }
5440         
5441         /* just copy the pointers */
5442         size = AOP_SIZE(result);
5443         offset = 0 ;
5444         while (size--) {
5445             aopPut(AOP(result),
5446                    aopGet(AOP(right),offset,FALSE,FALSE),
5447                    offset);
5448             offset++;
5449         }
5450         goto release ;
5451     }
5452     
5453     /* so we now know that the size of destination is greater
5454     than the size of the source */
5455     /* we move to result for the size of source */
5456     size = AOP_SIZE(right);
5457     offset = 0 ;
5458     while (size--) {
5459         aopPut(AOP(result),
5460                aopGet(AOP(right),offset,FALSE,FALSE),
5461                offset);
5462         offset++;
5463     }
5464
5465     /* now depending on the sign of the source && destination */
5466     size = AOP_SIZE(result) - AOP_SIZE(right);
5467     /* if unsigned or not an integral type */
5468     if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
5469         while (size--)
5470             aopPut(AOP(result),zero,offset++);
5471     } else {
5472         /* we need to extend the sign :{ */
5473         char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
5474                          FALSE,FALSE);
5475         MOVA(l);
5476         emitcode("rlc","a");
5477         emitcode("subb","a,acc");
5478         while (size--)
5479             aopPut(AOP(result),"a",offset++);   
5480     }
5481
5482     /* we are done hurray !!!! */
5483
5484 release:
5485     freeAsmop(right,NULL,ic,TRUE);
5486     freeAsmop(result,NULL,ic,TRUE);
5487
5488 }
5489
5490 /*-----------------------------------------------------------------*/
5491 /* genDjnz - generate decrement & jump if not zero instrucion      */
5492 /*-----------------------------------------------------------------*/
5493 static int genDjnz (iCode *ic, iCode *ifx)
5494 {
5495     symbol *lbl, *lbl1;
5496     if (!ifx)
5497         return 0;
5498     
5499     /* if the if condition has a false label
5500        then we cannot save */
5501     if (IC_FALSE(ifx))
5502         return 0;
5503
5504     /* if the minus is not of the form 
5505        a = a - 1 */
5506     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
5507         !IS_OP_LITERAL(IC_RIGHT(ic)))
5508         return 0;
5509
5510     if (operandLitValue(IC_RIGHT(ic)) != 1)
5511         return 0;
5512
5513     /* if the size of this greater than one then no
5514        saving */
5515     if (getSize(operandType(IC_RESULT(ic))) > 1)
5516         return 0;
5517
5518     /* otherwise we can save BIG */
5519     lbl = newiTempLabel(NULL);
5520     lbl1= newiTempLabel(NULL);
5521
5522     aopOp(IC_RESULT(ic),ic,FALSE);
5523     
5524     if (IS_AOP_PREG(IC_RESULT(ic))) {
5525         emitcode("dec","%s",
5526                  aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
5527         emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
5528         emitcode("jnz","%05d$",lbl->key+100);
5529     } else {    
5530         emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
5531                   lbl->key+100);
5532     }
5533     emitcode ("sjmp","%05d$",lbl1->key+100);
5534     emitcode ("","%05d$:",lbl->key+100);
5535     emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
5536     emitcode ("","%05d$:",lbl1->key+100);
5537     
5538     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
5539     ifx->generated = 1;
5540     return 1;
5541 }
5542
5543 /*-----------------------------------------------------------------*/
5544 /* genReceive - generate code for a receive iCode                  */
5545 /*-----------------------------------------------------------------*/
5546 static void genReceive (iCode *ic)
5547 {    
5548     if (isOperandInFarSpace(IC_RESULT(ic)) && 
5549         ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
5550           IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
5551
5552         int size = getSize(operandType(IC_RESULT(ic)));
5553         int offset =  fReturnSize - size;
5554         while (size--) {
5555             emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
5556                                     fReturn[fReturnSize - offset - 1] : "acc"));
5557             offset++;
5558         }
5559         aopOp(IC_RESULT(ic),ic,FALSE);  
5560         size = AOP_SIZE(IC_RESULT(ic));
5561         offset = 0;
5562         while (size--) {
5563             emitcode ("pop","acc");
5564             aopPut (AOP(IC_RESULT(ic)),"a",offset++);
5565         }
5566         
5567     } else {
5568         _G.accInUse++;
5569         aopOp(IC_RESULT(ic),ic,FALSE);  
5570         _G.accInUse--;
5571         assignResultValue(IC_RESULT(ic));       
5572     }
5573
5574     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
5575 }
5576
5577 /*-----------------------------------------------------------------*/
5578 /* gen51Code - generate code for 8051 based controllers            */
5579 /*-----------------------------------------------------------------*/
5580 void gen51Code (iCode *lic)
5581 {
5582     iCode *ic;
5583     int cln = 0;
5584
5585     lineHead = lineCurr = NULL;
5586
5587     /* print the allocation information */
5588     if (allocInfo)
5589         printAllocInfo( currFunc, codeOutFile);
5590     /* if debug information required */
5591 /*     if (options.debug && currFunc) { */
5592     if (currFunc) {
5593         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
5594         _G.debugLine = 1;
5595         if (IS_STATIC(currFunc->etype))
5596             emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name); 
5597         else
5598             emitcode("","G$%s$0$0 ==.",currFunc->name);
5599         _G.debugLine = 0;
5600     }
5601     /* stack pointer name */
5602     if (options.useXstack)
5603         spname = "_spx";
5604     else
5605         spname = "sp";
5606     
5607  
5608     for (ic = lic ; ic ; ic = ic->next ) {
5609         
5610         if ( cln != ic->lineno ) {
5611             if ( options.debug ) {
5612                 _G.debugLine = 1;
5613                 emitcode("","C$%s$%d$%d$%d ==.",
5614                          ic->filename,ic->lineno,
5615                          ic->level,ic->block);
5616                 _G.debugLine = 0;
5617             }
5618             emitcode(";","%s %d",ic->filename,ic->lineno);
5619             cln = ic->lineno ;
5620         }
5621         /* if the result is marked as
5622            spilt and rematerializable or code for
5623            this has already been generated then
5624            do nothing */
5625         if (resultRemat(ic) || ic->generated ) 
5626             continue ;
5627         
5628         /* depending on the operation */
5629         switch (ic->op) {
5630         case '!' :
5631             genNot(ic);
5632             break;
5633             
5634         case '~' :
5635             genCpl(ic);
5636             break;
5637             
5638         case UNARYMINUS:
5639             genUminus (ic);
5640             break;
5641             
5642         case IPUSH:
5643             genIpush (ic);
5644             break;
5645             
5646         case IPOP:
5647             /* IPOP happens only when trying to restore a 
5648                spilt live range, if there is an ifx statement
5649                following this pop then the if statement might
5650                be using some of the registers being popped which
5651                would destory the contents of the register so
5652                we need to check for this condition and handle it */
5653             if (ic->next            && 
5654                 ic->next->op == IFX &&
5655                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
5656                 genIfx (ic->next,ic);
5657             else
5658                 genIpop (ic);
5659             break; 
5660             
5661         case CALL:
5662             genCall (ic);
5663             break;
5664             
5665         case PCALL:
5666             genPcall (ic);
5667             break;
5668             
5669         case FUNCTION:
5670             genFunction (ic);
5671             break;
5672             
5673         case ENDFUNCTION:
5674             genEndFunction (ic);
5675             break;
5676             
5677         case RETURN:
5678             genRet (ic);
5679             break;
5680             
5681         case LABEL:
5682             genLabel (ic);
5683             break;
5684             
5685         case GOTO:
5686             genGoto (ic);
5687             break;
5688             
5689         case '+' :
5690             genPlus (ic) ;
5691             break;
5692             
5693         case '-' :
5694             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
5695                 genMinus (ic);
5696             break;
5697             
5698         case '*' :
5699             genMult (ic);
5700             break;
5701             
5702         case '/' :
5703             genDiv (ic) ;
5704             break;
5705             
5706         case '%' :
5707             genMod (ic);
5708             break;
5709             
5710         case '>' :
5711             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
5712             break;
5713             
5714         case '<' :
5715             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
5716             break;
5717             
5718         case LE_OP:
5719             genCmpLe (ic,ifxForOp(IC_RESULT(ic),ic));
5720             break
5721
5722         case GE_OP:
5723             genCmpGe (ic,ifxForOp(IC_RESULT(ic),ic));
5724             break;
5725
5726         case NE_OP:
5727             genCmpNe (ic,ifxForOp(IC_RESULT(ic),ic));       
5728             break;      
5729             
5730         case EQ_OP:
5731             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
5732             break;          
5733             
5734         case AND_OP:
5735             genAndOp (ic);
5736             break;
5737             
5738         case OR_OP:
5739             genOrOp (ic);
5740             break;
5741             
5742         case '^' :
5743             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
5744             break;
5745             
5746         case '|' :
5747                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
5748             break;
5749             
5750         case BITWISEAND:
5751             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
5752             break;
5753             
5754         case INLINEASM:
5755             genInline (ic);
5756             break;
5757             
5758         case RRC:
5759             genRRC (ic);
5760             break;
5761             
5762         case RLC:
5763             genRLC (ic);
5764             break;
5765             
5766         case GETHBIT:
5767             genGetHbit (ic);
5768             break;
5769             
5770         case LEFT_OP:
5771             genLeftShift (ic);
5772             break;
5773             
5774         case RIGHT_OP:
5775             genRightShift (ic);
5776             break;
5777             
5778         case GET_VALUE_AT_ADDRESS:
5779             genPointerGet(ic);
5780             break;
5781             
5782         case '=' :
5783             if (POINTER_SET(ic))
5784                 genPointerSet(ic);
5785             else
5786                 genAssign(ic);
5787             break;
5788             
5789         case IFX:
5790             genIfx (ic,NULL);
5791             break;
5792             
5793         case ADDRESS_OF:
5794             genAddrOf (ic);
5795             break;
5796             
5797         case JUMPTABLE:
5798             genJumpTab (ic);
5799             break;
5800             
5801         case CAST:
5802             genCast (ic);
5803             break;
5804             
5805         case RECEIVE:
5806             genReceive(ic);
5807             break;
5808             
5809         case SEND:
5810             addSet(&_G.sendSet,ic);
5811             break;
5812
5813         default :
5814             ic = ic;
5815             /*      piCode(ic,stdout); */
5816             
5817         }
5818     }
5819     
5820
5821     /* now we are ready to call the 
5822        peep hole optimizer */
5823     if (!options.nopeep)
5824         peepHole (&lineHead);
5825
5826     /* now do the actual printing */
5827     printLine (lineHead,codeOutFile);    
5828     return;
5829 }