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