some more avr intermediate stuff
[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     /* should have transformed by the parser */
1993     assert(1);
1994 }
1995
1996 enum {
1997     AVR_EQ = 0,
1998     AVR_NE,
1999     AVR_LT,
2000     AVR_GE
2001 };
2002
2003 /*-----------------------------------------------------------------*/
2004 /* revavrcnd - reverse a conditional for avr                       */
2005 /*-----------------------------------------------------------------*/
2006 static int revavrcnd(int type)
2007 {
2008     static struct {
2009         int type, rtype;
2010     } rar[] = { { AVR_EQ, AVR_NE}, {AVR_LT, AVR_GE}};
2011     int i;
2012
2013     for (i = 0 ; i < (sizeof(rar)/sizeof(rar[0]));i++) {
2014         if (rar[i].type == type) return rar[i].rtype;
2015         if (rar[i].rtype== type) return rar[i].type;
2016     }
2017     assert(1); /* cannot happen */
2018 }
2019
2020 static char *br_name[4] = {"breq","brne","brlt","brge"};
2021 static char *br_uname[4]= {"breq","brne","brlo","brcc"};
2022
2023 /*-----------------------------------------------------------------*/
2024 /* genBranch - generate the branch instruction                     */
2025 /*-----------------------------------------------------------------*/
2026 static void genBranch (iCode *ifx, int br_type, int sign)
2027 {
2028     int tj = (IC_TRUE(ifx) ? 1 : 0) ;
2029
2030     if (tj) { /* if true jump */
2031         char *nm = (sign ? br_name[br_type] : br_uname[br_type]);
2032         emitcode(nm,"L%05d",IC_TRUE(ifx)->key);
2033     } else { /* if false jump */
2034         int rtype = revavrcnd(br_type);
2035         char *nm = (sign ? br_name[rtype] : br_uname[rtype]);
2036         emitcode(nm,"L%05d",IC_FALSE(ifx)->key);
2037     }
2038     ifx->generated = 1;
2039 }
2040
2041 /*-----------------------------------------------------------------*/
2042 /* genCmpLt - less than comparisons                                */
2043 /*-----------------------------------------------------------------*/
2044 static void genCmpLt (iCode *ic, iCode *ifx)
2045 {
2046     operand *left, *right, *result;
2047     link *letype , *retype;
2048     symbol *lbl;
2049     int sign, size, offset =0;
2050
2051     left = IC_LEFT(ic);
2052     right= IC_RIGHT(ic);
2053     result = IC_RESULT(ic);
2054
2055     letype = getSpec(operandType(left));
2056     retype =getSpec(operandType(right));
2057     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2058
2059     /* assign the amsops */
2060     aopOp (left,ic,FALSE);
2061     aopOp (right,ic,FALSE);
2062     aopOp (result,ic,TRUE);
2063     size = AOP_SIZE(AOP(left));
2064
2065     if (ifx) {
2066         if (size == 1) {
2067             if (AOP_TYPE(AOP(right)) == AOP_LIT) {
2068                 emitcode("cpi","%s,lo8(%d)",aopGet(AOP(left),0),
2069                          (int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
2070                 genBranch(ifx,AVR_LT);
2071             } else { /* right != literal */
2072                 emitcode("cp","%s,%s",aopGet(AOP(left),0),aopGet(AOP(right),0));
2073                 genBranch(ifx,AVR_LT);
2074         } else { /* size != 1 */
2075             while (size--) {
2076                 if (offset = 0) 
2077                     emitcode("cp","%s,%s",aopGet(AOP(left),0),aopGet(AOP(right),0));
2078                 else
2079                     emitcode("cpc","%s,%s",aopGet(AOP(left),offset),aopGet(AOP(right),offset));
2080                 offset++;
2081             }
2082             genBranch(ifx,AVR_LT);
2083         }
2084     } else { /* no ifx */
2085         emitCode("clr","r0");
2086         while (size--) {
2087             if (offset = 0) 
2088                 emitcode("cp","%s,%s",aopGet(AOP(left),0),aopGet(AOP(right),0));
2089             else
2090                 emitcode("cpc","%s,%s",aopGet(AOP(left),offset),aopGet(AOP(right),offset));
2091             offset++;
2092         }
2093         lbl = newiTempLabel(NULL);
2094         if (sign) emitcode(br_uname[AVR_GE],"L%05d",lbl->key);
2095         else emitcode(br_name[AVR_GE],"L%05d",lbl->key);
2096         emitcode("inc","r0");
2097         emitcode("","L%05d:",lbl->key);
2098         aopPut(AOP(result),"r0",0);
2099         size = AOP_SIZE(AOP(result)) - 1;
2100         offset = 1;
2101         while (size--) aopPut(AOP(result),zero,offset++);
2102     }
2103
2104     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2105     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2106     freeAsmop(result,NULL,ic,TRUE); 
2107 }
2108
2109 /*-----------------------------------------------------------------*/
2110 /* genCmpEq - generates code for equal to                          */
2111 /*-----------------------------------------------------------------*/
2112 static void genCmpEq (iCode *ic, iCode *ifx)
2113 {
2114     operand *left, *right, *result;
2115
2116     aopOp((left=IC_LEFT(ic)),ic,FALSE);
2117     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2118     aopOp((result=IC_RESULT(ic)),ic,TRUE);
2119
2120     /* if literal, literal on the right or 
2121     if the right is in a pointer register and left 
2122     is not */
2123     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
2124         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
2125         operand *t = IC_RIGHT(ic);
2126         IC_RIGHT(ic) = IC_LEFT(ic);
2127         IC_LEFT(ic) = t;
2128     }
2129
2130
2131 release:
2132     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2133     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2134     freeAsmop(result,NULL,ic,TRUE);
2135 }
2136
2137 /*-----------------------------------------------------------------*/
2138 /* ifxForOp - returns the icode containing the ifx for operand     */
2139 /*-----------------------------------------------------------------*/
2140 static iCode *ifxForOp ( operand *op, iCode *ic )
2141 {
2142     /* if true symbol then needs to be assigned */
2143     if (IS_TRUE_SYMOP(op))
2144         return NULL ;
2145
2146     /* if this has register type condition and
2147     the next instruction is ifx with the same operand
2148     and live to of the operand is upto the ifx only then */
2149     if (ic->next &&
2150         ic->next->op == IFX &&
2151         IC_COND(ic->next)->key == op->key &&
2152         OP_SYMBOL(op)->liveTo <= ic->next->seq )
2153         return ic->next;
2154
2155     return NULL;
2156 }
2157 /*-----------------------------------------------------------------*/
2158 /* genAndOp - for && operation                                     */
2159 /*-----------------------------------------------------------------*/
2160 static void genAndOp (iCode *ic)
2161 {
2162     operand *left,*right, *result;
2163     symbol *tlbl;
2164
2165     /* note here that && operations that are in an
2166     if statement are taken away by backPatchLabels
2167     only those used in arthmetic operations remain */
2168     aopOp((left=IC_LEFT(ic)),ic,FALSE);
2169     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2170     aopOp((result=IC_RESULT(ic)),ic,FALSE);
2171
2172     /* if both are bit variables */
2173     if (AOP_TYPE(left) == AOP_CRY &&
2174         AOP_TYPE(right) == AOP_CRY ) {
2175         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2176         emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
2177         outBitC(result);
2178     } else {
2179         tlbl = newiTempLabel(NULL);
2180         toBoolean(left);    
2181         emitcode("jz","%05d$",tlbl->key+100);
2182         toBoolean(right);
2183         emitcode("","%05d$:",tlbl->key+100);
2184         outBitAcc(result);
2185     }
2186
2187     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2188     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2189     freeAsmop(result,NULL,ic,TRUE);
2190 }
2191
2192
2193 /*-----------------------------------------------------------------*/
2194 /* genOrOp - for || operation                                      */
2195 /*-----------------------------------------------------------------*/
2196 static void genOrOp (iCode *ic)
2197 {
2198     operand *left,*right, *result;
2199     symbol *tlbl;
2200
2201     /* note here that || operations that are in an
2202     if statement are taken away by backPatchLabels
2203     only those used in arthmetic operations remain */
2204     aopOp((left=IC_LEFT(ic)),ic,FALSE);
2205     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2206     aopOp((result=IC_RESULT(ic)),ic,FALSE);
2207
2208     /* if both are bit variables */
2209     if (AOP_TYPE(left) == AOP_CRY &&
2210         AOP_TYPE(right) == AOP_CRY ) {
2211         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2212         emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
2213         outBitC(result);
2214     } else {
2215         tlbl = newiTempLabel(NULL);
2216         toBoolean(left);
2217         emitcode("jnz","%05d$",tlbl->key+100);
2218         toBoolean(right);
2219         emitcode("","%05d$:",tlbl->key+100);
2220         outBitAcc(result);
2221     }
2222
2223     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2224     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2225     freeAsmop(result,NULL,ic,TRUE);            
2226 }
2227
2228 /*-----------------------------------------------------------------*/
2229 /* isLiteralBit - test if lit == 2^n                               */
2230 /*-----------------------------------------------------------------*/
2231 static int isLiteralBit(unsigned long lit)
2232 {
2233     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
2234     0x100L,0x200L,0x400L,0x800L,
2235     0x1000L,0x2000L,0x4000L,0x8000L,
2236     0x10000L,0x20000L,0x40000L,0x80000L,
2237     0x100000L,0x200000L,0x400000L,0x800000L,
2238     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
2239     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
2240     int idx;
2241     
2242     for(idx = 0; idx < 32; idx++)
2243         if(lit == pw[idx])
2244             return idx+1;
2245     return 0;
2246 }
2247
2248 /*-----------------------------------------------------------------*/
2249 /* continueIfTrue -                                                */
2250 /*-----------------------------------------------------------------*/
2251 static void continueIfTrue (iCode *ic)
2252 {
2253     if(IC_TRUE(ic))
2254         emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
2255     ic->generated = 1;
2256 }
2257
2258 /*-----------------------------------------------------------------*/
2259 /* jmpIfTrue -                                                     */
2260 /*-----------------------------------------------------------------*/
2261 static void jumpIfTrue (iCode *ic)
2262 {
2263     if(!IC_TRUE(ic))
2264         emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
2265     ic->generated = 1;
2266 }
2267
2268 /*-----------------------------------------------------------------*/
2269 /* jmpTrueOrFalse -                                                */
2270 /*-----------------------------------------------------------------*/
2271 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
2272 {
2273     // ugly but optimized by peephole
2274     if(IC_TRUE(ic)){
2275         symbol *nlbl = newiTempLabel(NULL);
2276         emitcode("sjmp","%05d$",nlbl->key+100);                 
2277         emitcode("","%05d$:",tlbl->key+100);
2278         emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
2279         emitcode("","%05d$:",nlbl->key+100);
2280     }
2281     else{
2282         emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
2283         emitcode("","%05d$:",tlbl->key+100);
2284     }
2285     ic->generated = 1;
2286 }
2287
2288 /*-----------------------------------------------------------------*/
2289 /* genAnd  - code for and                                          */
2290 /*-----------------------------------------------------------------*/
2291 static void genAnd (iCode *ic, iCode *ifx)
2292 {
2293     operand *left, *right, *result;
2294     int size, offset=0;  
2295     unsigned long lit = 0L;
2296     int bytelit = 0;
2297     char buffer[10];
2298
2299     aopOp((left = IC_LEFT(ic)),ic,FALSE);
2300     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2301     aopOp((result=IC_RESULT(ic)),ic,TRUE);
2302
2303 #ifdef DEBUG_TYPE
2304     emitcode("","; Type res[%d] = l[%d]&r[%d]",
2305              AOP_TYPE(result),
2306              AOP_TYPE(left), AOP_TYPE(right));
2307     emitcode("","; Size res[%d] = l[%d]&r[%d]",
2308              AOP_SIZE(result),
2309              AOP_SIZE(left), AOP_SIZE(right));
2310 #endif
2311
2312     /* if left is a literal & right is not then exchange them */
2313     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2314         AOP_NEEDSACC(left)) {
2315         operand *tmp = right ;
2316         right = left;
2317         left = tmp;
2318     }
2319
2320     /* if result = right then exchange them */
2321     if(sameRegs(AOP(result),AOP(right))){
2322         operand *tmp = right ;
2323         right = left;
2324         left = tmp;
2325     }
2326
2327     /* if right is bit then exchange them */
2328     if (AOP_TYPE(right) == AOP_CRY &&
2329         AOP_TYPE(left) != AOP_CRY){
2330         operand *tmp = right ;
2331         right = left;
2332         left = tmp;
2333     }
2334     if(AOP_TYPE(right) == AOP_LIT)
2335         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2336
2337     size = AOP_SIZE(result);
2338
2339     // if(bit & yy)
2340     // result = bit & yy;
2341     if (AOP_TYPE(left) == AOP_CRY){
2342         // c = bit & literal;
2343         if(AOP_TYPE(right) == AOP_LIT){
2344             if(lit & 1) {
2345                 if(size && sameRegs(AOP(result),AOP(left)))
2346                     // no change
2347                     goto release;
2348                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2349             } else {
2350                 // bit(result) = 0;
2351                 if(size && (AOP_TYPE(result) == AOP_CRY)){
2352                     emitcode("clr","%s",AOP(result)->aopu.aop_dir);
2353                     goto release;
2354                 }
2355                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
2356                     jumpIfTrue(ifx);
2357                     goto release;
2358                 }
2359                 emitcode("clr","c");
2360             }
2361         } else {
2362             if (AOP_TYPE(right) == AOP_CRY){
2363                 // c = bit & bit;
2364                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
2365                 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
2366             } else {
2367                 // c = bit & val;
2368                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
2369                 // c = lsb
2370                 emitcode("rrc","a");
2371                 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
2372             }
2373         }
2374         // bit = c
2375         // val = c
2376         if(size)
2377             outBitC(result);
2378         // if(bit & ...)
2379         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
2380             genIfxJump(ifx, "c");           
2381         goto release ;
2382     }
2383
2384     // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
2385     // bit = val & 0xZZ     - size = 1, ifx = FALSE -
2386     if((AOP_TYPE(right) == AOP_LIT) &&
2387        (AOP_TYPE(result) == AOP_CRY) &&
2388        (AOP_TYPE(left) != AOP_CRY)){
2389         int posbit = isLiteralBit(lit);
2390         /* left &  2^n */
2391         if(posbit){
2392             posbit--;
2393             MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
2394             // bit = left & 2^n
2395             if(size)
2396                 emitcode("mov","c,acc.%d",posbit&0x07);
2397             // if(left &  2^n)
2398             else{
2399                 if(ifx){
2400                     sprintf(buffer,"acc.%d",posbit&0x07);
2401                     genIfxJump(ifx, buffer);
2402                 }
2403                 goto release;
2404             }
2405         } else {
2406             symbol *tlbl = newiTempLabel(NULL);
2407             int sizel = AOP_SIZE(left);
2408             if(size)
2409                 emitcode("setb","c");
2410             while(sizel--){
2411                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
2412                     MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
2413                     // byte ==  2^n ?
2414                     if((posbit = isLiteralBit(bytelit)) != 0)
2415                         emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
2416                     else{
2417                         if(bytelit != 0x0FFL)
2418                             emitcode("anl","a,%s",
2419                                      aopGet(AOP(right),offset,FALSE,TRUE));
2420                         emitcode("jnz","%05d$",tlbl->key+100);
2421                     }
2422                 }
2423                 offset++;
2424             }
2425             // bit = left & literal
2426             if(size){
2427                 emitcode("clr","c");
2428                 emitcode("","%05d$:",tlbl->key+100);
2429             }
2430             // if(left & literal)
2431             else{
2432                 if(ifx)
2433                     jmpTrueOrFalse(ifx, tlbl);
2434                 goto release ;
2435             }
2436         }
2437         outBitC(result);
2438         goto release ;
2439     }
2440
2441     /* if left is same as result */
2442     if(sameRegs(AOP(result),AOP(left))){
2443         for(;size--; offset++) {
2444             if(AOP_TYPE(right) == AOP_LIT){
2445                 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
2446                     continue;
2447                 else 
2448                     if (bytelit == 0)
2449                         aopPut(AOP(result),zero,offset);
2450                     else 
2451                         if (IS_AOP_PREG(result)) {
2452                             MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2453                             emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
2454                             aopPut(AOP(result),"a",offset);
2455                         } else
2456                             emitcode("anl","%s,%s",
2457                                      aopGet(AOP(left),offset,FALSE,TRUE),
2458                                      aopGet(AOP(right),offset,FALSE,FALSE));
2459             } else {
2460                 if (AOP_TYPE(left) == AOP_ACC)
2461                     emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
2462                 else {
2463                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2464                     if (IS_AOP_PREG(result)) {
2465                         emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
2466                         aopPut(AOP(result),"a",offset);
2467
2468                     } else
2469                         emitcode("anl","%s,a",
2470                                  aopGet(AOP(left),offset,FALSE,TRUE));
2471                 }
2472             }
2473         }
2474     } else {
2475         // left & result in different registers
2476         if(AOP_TYPE(result) == AOP_CRY){
2477             // result = bit
2478             // if(size), result in bit
2479             // if(!size && ifx), conditional oper: if(left & right)
2480             symbol *tlbl = newiTempLabel(NULL);
2481             int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
2482             if(size)
2483                 emitcode("setb","c");
2484             while(sizer--){
2485                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2486                 emitcode("anl","a,%s",
2487                          aopGet(AOP(left),offset,FALSE,FALSE));
2488                 emitcode("jnz","%05d$",tlbl->key+100);
2489                 offset++;
2490             }
2491             if(size){
2492                 CLRC;
2493                 emitcode("","%05d$:",tlbl->key+100);
2494                 outBitC(result);
2495             } else if(ifx)
2496                 jmpTrueOrFalse(ifx, tlbl);
2497         } else {
2498             for(;(size--);offset++) {
2499                 // normal case
2500                 // result = left & right
2501                 if(AOP_TYPE(right) == AOP_LIT){
2502                     if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
2503                         aopPut(AOP(result),
2504                                aopGet(AOP(left),offset,FALSE,FALSE),
2505                                offset);
2506                         continue;
2507                     } else if(bytelit == 0){
2508                         aopPut(AOP(result),zero,offset);
2509                         continue;
2510                     }
2511                 }
2512                 // faster than result <- left, anl result,right
2513                 // and better if result is SFR
2514                 if (AOP_TYPE(left) == AOP_ACC) 
2515                     emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
2516                 else {
2517                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2518                     emitcode("anl","a,%s",
2519                              aopGet(AOP(left),offset,FALSE,FALSE));
2520                 }
2521                 aopPut(AOP(result),"a",offset);
2522             }
2523         }
2524     }
2525
2526 release :
2527     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2528     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2529     freeAsmop(result,NULL,ic,TRUE);     
2530 }
2531
2532 /*-----------------------------------------------------------------*/
2533 /* genOr  - code for or                                            */
2534 /*-----------------------------------------------------------------*/
2535 static void genOr (iCode *ic, iCode *ifx)
2536 {
2537     operand *left, *right, *result;
2538     int size, offset=0;
2539     unsigned long lit = 0L;
2540
2541     aopOp((left = IC_LEFT(ic)),ic,FALSE);
2542     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2543     aopOp((result=IC_RESULT(ic)),ic,TRUE);
2544
2545 #ifdef DEBUG_TYPE
2546     emitcode("","; Type res[%d] = l[%d]&r[%d]",
2547              AOP_TYPE(result),
2548              AOP_TYPE(left), AOP_TYPE(right));
2549     emitcode("","; Size res[%d] = l[%d]&r[%d]",
2550              AOP_SIZE(result),
2551              AOP_SIZE(left), AOP_SIZE(right));
2552 #endif
2553
2554     /* if left is a literal & right is not then exchange them */
2555     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2556         AOP_NEEDSACC(left)) {
2557         operand *tmp = right ;
2558         right = left;
2559         left = tmp;
2560     }
2561
2562     /* if result = right then exchange them */
2563     if(sameRegs(AOP(result),AOP(right))){
2564         operand *tmp = right ;
2565         right = left;
2566         left = tmp;
2567     }
2568
2569     /* if right is bit then exchange them */
2570     if (AOP_TYPE(right) == AOP_CRY &&
2571         AOP_TYPE(left) != AOP_CRY){
2572         operand *tmp = right ;
2573         right = left;
2574         left = tmp;
2575     }
2576     if(AOP_TYPE(right) == AOP_LIT)
2577         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2578
2579     size = AOP_SIZE(result);
2580
2581     // if(bit | yy)
2582     // xx = bit | yy;
2583     if (AOP_TYPE(left) == AOP_CRY){
2584         if(AOP_TYPE(right) == AOP_LIT){
2585             // c = bit & literal;
2586             if(lit){
2587                 // lit != 0 => result = 1
2588                 if(AOP_TYPE(result) == AOP_CRY){
2589                     if(size)
2590                         emitcode("setb","%s",AOP(result)->aopu.aop_dir);
2591                     else if(ifx)
2592                         continueIfTrue(ifx);
2593                     goto release;
2594                 }
2595                 emitcode("setb","c");
2596             } else {
2597                 // lit == 0 => result = left
2598                 if(size && sameRegs(AOP(result),AOP(left)))
2599                     goto release;
2600                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2601             }
2602         } else {
2603             if (AOP_TYPE(right) == AOP_CRY){
2604                 // c = bit | bit;
2605                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
2606                 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
2607             }
2608             else{
2609                 // c = bit | val;
2610                 symbol *tlbl = newiTempLabel(NULL);
2611                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
2612                     emitcode("setb","c");
2613                 emitcode("jb","%s,%05d$",
2614                          AOP(left)->aopu.aop_dir,tlbl->key+100);
2615                 toBoolean(right);
2616                 emitcode("jnz","%05d$",tlbl->key+100);
2617                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
2618                     jmpTrueOrFalse(ifx, tlbl);
2619                     goto release;
2620                 } else {
2621                     CLRC;
2622                     emitcode("","%05d$:",tlbl->key+100);
2623                 }
2624             }
2625         }
2626         // bit = c
2627         // val = c
2628         if(size)
2629             outBitC(result);
2630         // if(bit | ...)
2631         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
2632             genIfxJump(ifx, "c");           
2633         goto release ;
2634     }
2635
2636     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
2637     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
2638     if((AOP_TYPE(right) == AOP_LIT) &&
2639        (AOP_TYPE(result) == AOP_CRY) &&
2640        (AOP_TYPE(left) != AOP_CRY)){
2641         if(lit){
2642             // result = 1
2643             if(size)
2644                 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
2645             else 
2646                 continueIfTrue(ifx);
2647             goto release;
2648         } else {
2649             // lit = 0, result = boolean(left)
2650             if(size)
2651                 emitcode("setb","c");
2652             toBoolean(right);
2653             if(size){
2654                 symbol *tlbl = newiTempLabel(NULL);
2655                 emitcode("jnz","%05d$",tlbl->key+100);
2656                 CLRC;
2657                 emitcode("","%05d$:",tlbl->key+100);
2658             } else {
2659                 genIfxJump (ifx,"a");
2660                 goto release;
2661             }
2662         }
2663         outBitC(result);
2664         goto release ;
2665     }
2666
2667     /* if left is same as result */
2668     if(sameRegs(AOP(result),AOP(left))){
2669         for(;size--; offset++) {
2670             if(AOP_TYPE(right) == AOP_LIT){
2671                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2672                     continue;
2673                 else 
2674                     if (IS_AOP_PREG(left)) {
2675                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2676                         emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
2677                         aopPut(AOP(result),"a",offset);
2678                     } else
2679                         emitcode("orl","%s,%s",
2680                                  aopGet(AOP(left),offset,FALSE,TRUE),
2681                                  aopGet(AOP(right),offset,FALSE,FALSE));
2682             } else {
2683                 if (AOP_TYPE(left) == AOP_ACC) 
2684                     emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
2685                 else {              
2686                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2687                     if (IS_AOP_PREG(left)) {
2688                         emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
2689                         aopPut(AOP(result),"a",offset);
2690                     } else
2691                         emitcode("orl","%s,a",
2692                                  aopGet(AOP(left),offset,FALSE,TRUE));
2693                 }
2694             }
2695         }
2696     } else {
2697         // left & result in different registers
2698         if(AOP_TYPE(result) == AOP_CRY){
2699             // result = bit
2700             // if(size), result in bit
2701             // if(!size && ifx), conditional oper: if(left | right)
2702             symbol *tlbl = newiTempLabel(NULL);
2703             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
2704             if(size)
2705                 emitcode("setb","c");
2706             while(sizer--){
2707                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2708                 emitcode("orl","a,%s",
2709                          aopGet(AOP(left),offset,FALSE,FALSE));
2710                 emitcode("jnz","%05d$",tlbl->key+100);
2711                 offset++;
2712             }
2713             if(size){
2714                 CLRC;
2715                 emitcode("","%05d$:",tlbl->key+100);
2716                 outBitC(result);
2717             } else if(ifx)
2718                 jmpTrueOrFalse(ifx, tlbl);
2719         } else for(;(size--);offset++){
2720             // normal case
2721             // result = left & right
2722             if(AOP_TYPE(right) == AOP_LIT){
2723                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2724                     aopPut(AOP(result),
2725                            aopGet(AOP(left),offset,FALSE,FALSE),
2726                            offset);
2727                     continue;
2728                 }
2729             }
2730             // faster than result <- left, anl result,right
2731             // and better if result is SFR
2732             if (AOP_TYPE(left) == AOP_ACC) 
2733                 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
2734             else {
2735                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2736                 emitcode("orl","a,%s",
2737                          aopGet(AOP(left),offset,FALSE,FALSE));
2738             }
2739             aopPut(AOP(result),"a",offset);                     
2740         }
2741     }
2742
2743 release :
2744     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2745     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2746     freeAsmop(result,NULL,ic,TRUE);     
2747 }
2748
2749 /*-----------------------------------------------------------------*/
2750 /* genXor - code for xclusive or                                   */
2751 /*-----------------------------------------------------------------*/
2752 static void genXor (iCode *ic, iCode *ifx)
2753 {
2754     operand *left, *right, *result;
2755     int size, offset=0;
2756     unsigned long lit = 0L;
2757
2758     aopOp((left = IC_LEFT(ic)),ic,FALSE);
2759     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2760     aopOp((result=IC_RESULT(ic)),ic,TRUE);
2761
2762 #ifdef DEBUG_TYPE
2763     emitcode("","; Type res[%d] = l[%d]&r[%d]",
2764              AOP_TYPE(result),
2765              AOP_TYPE(left), AOP_TYPE(right));
2766     emitcode("","; Size res[%d] = l[%d]&r[%d]",
2767              AOP_SIZE(result),
2768              AOP_SIZE(left), AOP_SIZE(right));
2769 #endif
2770
2771     /* if left is a literal & right is not ||
2772        if left needs acc & right does not */
2773     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2774         (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
2775         operand *tmp = right ;
2776         right = left;
2777         left = tmp;
2778     }
2779
2780     /* if result = right then exchange them */
2781     if(sameRegs(AOP(result),AOP(right))){
2782         operand *tmp = right ;
2783         right = left;
2784         left = tmp;
2785     }
2786
2787     /* if right is bit then exchange them */
2788     if (AOP_TYPE(right) == AOP_CRY &&
2789         AOP_TYPE(left) != AOP_CRY){
2790         operand *tmp = right ;
2791         right = left;
2792         left = tmp;
2793     }
2794     if(AOP_TYPE(right) == AOP_LIT)
2795         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2796
2797     size = AOP_SIZE(result);
2798
2799     // if(bit ^ yy)
2800     // xx = bit ^ yy;
2801     if (AOP_TYPE(left) == AOP_CRY){
2802         if(AOP_TYPE(right) == AOP_LIT){
2803             // c = bit & literal;
2804             if(lit>>1){
2805                 // lit>>1  != 0 => result = 1
2806                 if(AOP_TYPE(result) == AOP_CRY){
2807                     if(size)
2808                         emitcode("setb","%s",AOP(result)->aopu.aop_dir);
2809                     else if(ifx)
2810                         continueIfTrue(ifx);
2811                     goto release;
2812                 }
2813                 emitcode("setb","c");
2814             } else{
2815                 // lit == (0 or 1)
2816                 if(lit == 0){
2817                     // lit == 0, result = left
2818                     if(size && sameRegs(AOP(result),AOP(left)))
2819                         goto release;
2820                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2821                 } else{
2822                     // lit == 1, result = not(left)
2823                     if(size && sameRegs(AOP(result),AOP(left))){
2824                         emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
2825                         goto release;
2826                     } else {
2827                         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2828                         emitcode("cpl","c");
2829                     }
2830                 }
2831             }
2832
2833         } else {
2834             // right != literal
2835             symbol *tlbl = newiTempLabel(NULL);
2836             if (AOP_TYPE(right) == AOP_CRY){
2837                 // c = bit ^ bit;
2838                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
2839             }
2840             else{
2841                 int sizer = AOP_SIZE(right);
2842                 // c = bit ^ val
2843                 // if val>>1 != 0, result = 1
2844                 emitcode("setb","c");
2845                 while(sizer){
2846                     MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
2847                     if(sizer == 1)
2848                         // test the msb of the lsb
2849                         emitcode("anl","a,#0xfe");
2850                     emitcode("jnz","%05d$",tlbl->key+100);
2851                     sizer--;
2852                 }
2853                 // val = (0,1)
2854                 emitcode("rrc","a");
2855             }
2856             emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
2857             emitcode("cpl","c");
2858             emitcode("","%05d$:",(tlbl->key+100));
2859         }
2860         // bit = c
2861         // val = c
2862         if(size)
2863             outBitC(result);
2864         // if(bit | ...)
2865         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
2866             genIfxJump(ifx, "c");           
2867         goto release ;
2868     }
2869
2870     if(sameRegs(AOP(result),AOP(left))){
2871         /* if left is same as result */
2872         for(;size--; offset++) {
2873             if(AOP_TYPE(right) == AOP_LIT){
2874                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2875                     continue;
2876                 else
2877                     if (IS_AOP_PREG(left)) {
2878                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2879                         emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
2880                         aopPut(AOP(result),"a",offset);
2881                     } else 
2882                         emitcode("xrl","%s,%s",
2883                                  aopGet(AOP(left),offset,FALSE,TRUE),
2884                                  aopGet(AOP(right),offset,FALSE,FALSE));
2885             } else {
2886                 if (AOP_TYPE(left) == AOP_ACC)
2887                     emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
2888                 else {
2889                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2890                     if (IS_AOP_PREG(left)) {
2891                         emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
2892                         aopPut(AOP(result),"a",offset);
2893                     } else
2894                         emitcode("xrl","%s,a",
2895                                  aopGet(AOP(left),offset,FALSE,TRUE));
2896                 }
2897             }
2898         }
2899     } else {
2900         // left & result in different registers
2901         if(AOP_TYPE(result) == AOP_CRY){
2902             // result = bit
2903             // if(size), result in bit
2904             // if(!size && ifx), conditional oper: if(left ^ right)
2905             symbol *tlbl = newiTempLabel(NULL);
2906             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
2907             if(size)
2908                 emitcode("setb","c");
2909             while(sizer--){
2910                 if((AOP_TYPE(right) == AOP_LIT) &&
2911                    (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
2912                     MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
2913                 } else {
2914                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2915                     emitcode("xrl","a,%s",
2916                              aopGet(AOP(left),offset,FALSE,FALSE));
2917                 }
2918                 emitcode("jnz","%05d$",tlbl->key+100);
2919                 offset++;
2920             }
2921             if(size){
2922                 CLRC;
2923                 emitcode("","%05d$:",tlbl->key+100);
2924                 outBitC(result);
2925             } else if(ifx)
2926                 jmpTrueOrFalse(ifx, tlbl);
2927         } else for(;(size--);offset++){
2928             // normal case
2929             // result = left & right
2930             if(AOP_TYPE(right) == AOP_LIT){
2931                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2932                     aopPut(AOP(result),
2933                            aopGet(AOP(left),offset,FALSE,FALSE),
2934                            offset);
2935                     continue;
2936                 }
2937             }
2938             // faster than result <- left, anl result,right
2939             // and better if result is SFR
2940             if (AOP_TYPE(left) == AOP_ACC)
2941                 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
2942             else {
2943                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2944                 emitcode("xrl","a,%s",
2945                          aopGet(AOP(left),offset,FALSE,TRUE));
2946             }
2947             aopPut(AOP(result),"a",offset);
2948         }
2949     }
2950
2951 release :
2952     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2953     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2954     freeAsmop(result,NULL,ic,TRUE);     
2955 }
2956
2957 /*-----------------------------------------------------------------*/
2958 /* genInline - write the inline code out                           */
2959 /*-----------------------------------------------------------------*/
2960 static void genInline (iCode *ic)
2961 {
2962     char buffer[MAX_INLINEASM];
2963     char *bp = buffer;
2964     char *bp1= buffer;
2965     
2966     _G.inLine += (!options.asmpeep);
2967     strcpy(buffer,IC_INLINE(ic));
2968
2969     /* emit each line as a code */
2970     while (*bp) {
2971         if (*bp == '\n') {
2972             *bp++ = '\0';
2973             emitcode(bp1,"");
2974             bp1 = bp;
2975         } else {
2976             if (*bp == ':') {
2977                 bp++;
2978                 *bp = '\0';
2979                 bp++;
2980                 emitcode(bp1,"");
2981                 bp1 = bp;
2982             } else
2983                 bp++;
2984         }
2985     }
2986     if (bp1 != bp)
2987         emitcode(bp1,"");
2988     /*     emitcode("",buffer); */
2989     _G.inLine -= (!options.asmpeep);
2990 }
2991
2992 /*-----------------------------------------------------------------*/
2993 /* genRRC - rotate right with carry                                */
2994 /*-----------------------------------------------------------------*/
2995 static void genRRC (iCode *ic)
2996 {
2997     operand *left , *result ;
2998     int size, offset = 0;
2999     char *l;    
3000
3001     /* rotate right with carry */
3002     left = IC_LEFT(ic);
3003     result=IC_RESULT(ic);
3004     aopOp (left,ic,FALSE);
3005     aopOp (result,ic,FALSE);
3006
3007     /* move it to the result */
3008     size = AOP_SIZE(result);    
3009     offset = size - 1 ;
3010     CLRC;
3011     while (size--) {
3012         l = aopGet(AOP(left),offset,FALSE,FALSE);
3013         MOVA(l);
3014         emitcode("rrc","a");
3015         if (AOP_SIZE(result) > 1)
3016             aopPut(AOP(result),"a",offset--);
3017     }
3018     /* now we need to put the carry into the
3019     highest order byte of the result */
3020     if (AOP_SIZE(result) > 1) {
3021         l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
3022         MOVA(l);
3023     }
3024     emitcode("mov","acc.7,c");
3025     aopPut(AOP(result),"a",AOP_SIZE(result)-1);
3026     freeAsmop(left,NULL,ic,TRUE);
3027     freeAsmop(result,NULL,ic,TRUE);
3028 }
3029
3030 /*-----------------------------------------------------------------*/
3031 /* genRLC - generate code for rotate left with carry               */
3032 /*-----------------------------------------------------------------*/
3033 static void genRLC (iCode *ic)
3034 {    
3035     operand *left , *result ;
3036     int size, offset = 0;
3037     char *l;    
3038
3039     /* rotate right with carry */
3040     left = IC_LEFT(ic);
3041     result=IC_RESULT(ic);
3042     aopOp (left,ic,FALSE);
3043     aopOp (result,ic,FALSE);
3044
3045     /* move it to the result */
3046     size = AOP_SIZE(result);    
3047     offset = 0 ;
3048     if (size--) {
3049         l = aopGet(AOP(left),offset,FALSE,FALSE);
3050         MOVA(l);
3051         emitcode("add","a,acc");
3052         if (AOP_SIZE(result) > 1)
3053             aopPut(AOP(result),"a",offset++);
3054         while (size--) {
3055             l = aopGet(AOP(left),offset,FALSE,FALSE);
3056             MOVA(l);
3057             emitcode("rlc","a");
3058             if (AOP_SIZE(result) > 1)
3059                 aopPut(AOP(result),"a",offset++);
3060         }
3061     }
3062     /* now we need to put the carry into the
3063     highest order byte of the result */
3064     if (AOP_SIZE(result) > 1) {
3065         l = aopGet(AOP(result),0,FALSE,FALSE);
3066         MOVA(l);
3067     }
3068     emitcode("mov","acc.0,c");
3069     aopPut(AOP(result),"a",0);
3070     freeAsmop(left,NULL,ic,TRUE);
3071     freeAsmop(result,NULL,ic,TRUE);
3072 }
3073
3074 /*-----------------------------------------------------------------*/
3075 /* genGetHbit - generates code get highest order bit               */
3076 /*-----------------------------------------------------------------*/
3077 static void genGetHbit (iCode *ic)
3078 {
3079     operand *left, *result;
3080     left = IC_LEFT(ic);
3081     result=IC_RESULT(ic);
3082     aopOp (left,ic,FALSE);
3083     aopOp (result,ic,FALSE);
3084
3085     /* get the highest order byte into a */
3086     MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
3087     if(AOP_TYPE(result) == AOP_CRY){
3088         emitcode("rlc","a");
3089         outBitC(result);
3090     }
3091     else{
3092         emitcode("rl","a");
3093         emitcode("anl","a,#0x01");
3094         outAcc(result);
3095     }
3096
3097
3098     freeAsmop(left,NULL,ic,TRUE);
3099     freeAsmop(result,NULL,ic,TRUE);
3100 }
3101
3102 /*-----------------------------------------------------------------*/
3103 /* AccRol - rotate left accumulator by known count                 */
3104 /*-----------------------------------------------------------------*/
3105 static void AccRol (int shCount)
3106 {
3107     shCount &= 0x0007;              // shCount : 0..7
3108     switch(shCount){
3109         case 0 :
3110             break;
3111         case 1 :
3112             emitcode("rl","a");
3113             break;
3114         case 2 :
3115             emitcode("rl","a");
3116             emitcode("rl","a");
3117             break;
3118         case 3 :
3119             emitcode("swap","a");
3120             emitcode("rr","a");
3121             break;
3122         case 4 :
3123             emitcode("swap","a");
3124             break;
3125         case 5 :
3126             emitcode("swap","a");
3127             emitcode("rl","a");
3128             break;
3129         case 6 :
3130             emitcode("rr","a");
3131             emitcode("rr","a");
3132             break;
3133         case 7 :
3134             emitcode("rr","a");
3135             break;
3136     }
3137 }
3138
3139 /*-----------------------------------------------------------------*/
3140 /* AccLsh - left shift accumulator by known count                  */
3141 /*-----------------------------------------------------------------*/
3142 static void AccLsh (int shCount)
3143 {
3144     if(shCount != 0){
3145         if(shCount == 1)
3146             emitcode("add","a,acc");
3147         else 
3148             if(shCount == 2) {
3149             emitcode("add","a,acc");
3150             emitcode("add","a,acc");
3151         } else {
3152             /* rotate left accumulator */
3153             AccRol(shCount);
3154             /* and kill the lower order bits */
3155             emitcode("anl","a,#0x%02x", SLMask[shCount]);
3156         }
3157     }
3158 }
3159
3160 /*-----------------------------------------------------------------*/
3161 /* AccRsh - right shift accumulator by known count                 */
3162 /*-----------------------------------------------------------------*/
3163 static void AccRsh (int shCount)
3164 {
3165     if(shCount != 0){
3166         if(shCount == 1){
3167             CLRC;
3168             emitcode("rrc","a");
3169         } else {
3170             /* rotate right accumulator */
3171             AccRol(8 - shCount);
3172             /* and kill the higher order bits */
3173             emitcode("anl","a,#0x%02x", SRMask[shCount]);
3174         }
3175     }
3176 }
3177
3178 /*-----------------------------------------------------------------*/
3179 /* AccSRsh - signed right shift accumulator by known count                 */
3180 /*-----------------------------------------------------------------*/
3181 static void AccSRsh (int shCount)
3182 {
3183     symbol *tlbl ;
3184     if(shCount != 0){
3185         if(shCount == 1){
3186             emitcode("mov","c,acc.7");
3187             emitcode("rrc","a");
3188         } else if(shCount == 2){
3189             emitcode("mov","c,acc.7");
3190             emitcode("rrc","a");
3191             emitcode("mov","c,acc.7");
3192             emitcode("rrc","a");
3193         } else {
3194             tlbl = newiTempLabel(NULL);
3195             /* rotate right accumulator */
3196             AccRol(8 - shCount);
3197             /* and kill the higher order bits */
3198             emitcode("anl","a,#0x%02x", SRMask[shCount]);
3199             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
3200             emitcode("orl","a,#0x%02x",
3201                      (unsigned char)~SRMask[shCount]);
3202             emitcode("","%05d$:",tlbl->key+100);
3203         }
3204     }
3205 }
3206
3207 /*-----------------------------------------------------------------*/
3208 /* shiftR1Left2Result - shift right one byte from left to result   */
3209 /*-----------------------------------------------------------------*/
3210 static void shiftR1Left2Result (operand *left, int offl,
3211                                 operand *result, int offr,
3212                                 int shCount, int sign)
3213 {
3214     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
3215     /* shift right accumulator */
3216     if(sign)
3217         AccSRsh(shCount);
3218     else
3219         AccRsh(shCount);
3220     aopPut(AOP(result),"a",offr);
3221 }
3222
3223 /*-----------------------------------------------------------------*/
3224 /* shiftL1Left2Result - shift left one byte from left to result    */
3225 /*-----------------------------------------------------------------*/
3226 static void shiftL1Left2Result (operand *left, int offl,
3227                                 operand *result, int offr, int shCount)
3228 {
3229     char *l;
3230     l = aopGet(AOP(left),offl,FALSE,FALSE);
3231     MOVA(l);
3232     /* shift left accumulator */
3233     AccLsh(shCount);
3234     aopPut(AOP(result),"a",offr);
3235 }
3236
3237 /*-----------------------------------------------------------------*/
3238 /* movLeft2Result - move byte from left to result                  */
3239 /*-----------------------------------------------------------------*/
3240 static void movLeft2Result (operand *left, int offl,
3241                             operand *result, int offr, int sign)
3242 {
3243     char *l;
3244     if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
3245         l = aopGet(AOP(left),offl,FALSE,FALSE);
3246
3247         if (*l == '@' && (IS_AOP_PREG(result))) {
3248             emitcode("mov","a,%s",l);
3249             aopPut(AOP(result),"a",offr);
3250         } else {
3251             if(!sign)
3252                 aopPut(AOP(result),l,offr);
3253             else{
3254                 /* MSB sign in acc.7 ! */
3255                 if(getDataSize(left) == offl+1){
3256                     emitcode("mov","a,%s",l);
3257                     aopPut(AOP(result),"a",offr);
3258                 }
3259             }
3260         }
3261     }
3262 }
3263
3264 /*-----------------------------------------------------------------*/
3265 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
3266 /*-----------------------------------------------------------------*/
3267 static void AccAXRrl1 (char *x)
3268 {
3269     emitcode("rrc","a");
3270     emitcode("xch","a,%s", x);
3271     emitcode("rrc","a");
3272     emitcode("xch","a,%s", x);
3273 }
3274
3275 /*-----------------------------------------------------------------*/
3276 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
3277 /*-----------------------------------------------------------------*/
3278 static void AccAXLrl1 (char *x)
3279 {
3280     emitcode("xch","a,%s",x);
3281     emitcode("rlc","a");
3282     emitcode("xch","a,%s",x);
3283     emitcode("rlc","a");
3284 }
3285
3286 /*-----------------------------------------------------------------*/
3287 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
3288 /*-----------------------------------------------------------------*/
3289 static void AccAXLsh1 (char *x)
3290 {
3291     emitcode("xch","a,%s",x);
3292     emitcode("add","a,acc");
3293     emitcode("xch","a,%s",x);
3294     emitcode("rlc","a");
3295 }
3296
3297 /*-----------------------------------------------------------------*/
3298 /* AccAXLsh - left shift a:x by known count (0..7)                 */
3299 /*-----------------------------------------------------------------*/
3300 static void AccAXLsh (char *x, int shCount)
3301 {
3302     switch(shCount){
3303         case 0 :
3304             break;
3305         case 1 :
3306             AccAXLsh1(x);
3307             break;
3308         case 2 :
3309             AccAXLsh1(x);
3310             AccAXLsh1(x);
3311             break;
3312         case 3 :
3313         case 4 :
3314         case 5 :                        // AAAAABBB:CCCCCDDD
3315             AccRol(shCount);            // BBBAAAAA:CCCCCDDD
3316             emitcode("anl","a,#0x%02x",
3317                      SLMask[shCount]);  // BBB00000:CCCCCDDD
3318             emitcode("xch","a,%s",x);   // CCCCCDDD:BBB00000
3319             AccRol(shCount);            // DDDCCCCC:BBB00000
3320             emitcode("xch","a,%s",x);   // BBB00000:DDDCCCCC
3321             emitcode("xrl","a,%s",x);   // (BBB^DDD)CCCCC:DDDCCCCC
3322             emitcode("xch","a,%s",x);   // DDDCCCCC:(BBB^DDD)CCCCC
3323             emitcode("anl","a,#0x%02x",
3324                      SLMask[shCount]);  // DDD00000:(BBB^DDD)CCCCC
3325             emitcode("xch","a,%s",x);   // (BBB^DDD)CCCCC:DDD00000
3326             emitcode("xrl","a,%s",x);   // BBBCCCCC:DDD00000            
3327             break;
3328         case 6 :                        // AAAAAABB:CCCCCCDD
3329             emitcode("anl","a,#0x%02x",
3330                      SRMask[shCount]);  // 000000BB:CCCCCCDD
3331             emitcode("mov","c,acc.0");  // c = B
3332             emitcode("xch","a,%s",x);   // CCCCCCDD:000000BB
3333             AccAXRrl1(x);               // BCCCCCCD:D000000B
3334             AccAXRrl1(x);               // BBCCCCCC:DD000000
3335             break;
3336         case 7 :                        // a:x <<= 7
3337             emitcode("anl","a,#0x%02x",
3338                      SRMask[shCount]);  // 0000000B:CCCCCCCD
3339             emitcode("mov","c,acc.0");  // c = B
3340             emitcode("xch","a,%s",x);   // CCCCCCCD:0000000B
3341             AccAXRrl1(x);               // BCCCCCCC:D0000000
3342             break;
3343         default :
3344             break;
3345     }
3346 }
3347
3348 /*-----------------------------------------------------------------*/
3349 /* AccAXRsh - right shift a:x known count (0..7)                   */
3350 /*-----------------------------------------------------------------*/
3351 static void AccAXRsh (char *x, int shCount)
3352 {   
3353     switch(shCount){
3354         case 0 :
3355             break;
3356         case 1 :
3357             CLRC;
3358             AccAXRrl1(x);               // 0->a:x
3359             break;
3360         case 2 :
3361             CLRC;
3362             AccAXRrl1(x);               // 0->a:x
3363             CLRC;
3364             AccAXRrl1(x);               // 0->a:x
3365             break;
3366         case 3 :
3367         case 4 :
3368         case 5 :                        // AAAAABBB:CCCCCDDD = a:x
3369             AccRol(8 - shCount);        // BBBAAAAA:DDDCCCCC
3370             emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
3371             AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
3372             emitcode("anl","a,#0x%02x",
3373                      SRMask[shCount]);  // 000CCCCC:BBBAAAAA
3374             emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
3375             emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
3376             emitcode("anl","a,#0x%02x",
3377                      SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
3378             emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
3379             emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
3380             emitcode("xch","a,%s",x);   // 000AAAAA:BBBCCCCC
3381             break;
3382         case 6 :                        // AABBBBBB:CCDDDDDD
3383             emitcode("mov","c,acc.7");
3384             AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
3385             AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
3386             emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
3387             emitcode("anl","a,#0x%02x",
3388                      SRMask[shCount]);  // 000000AA:BBBBBBCC
3389             break;
3390         case 7 :                        // ABBBBBBB:CDDDDDDD
3391             emitcode("mov","c,acc.7");  // c = A
3392             AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
3393             emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
3394             emitcode("anl","a,#0x%02x",
3395                      SRMask[shCount]);  // 0000000A:BBBBBBBC
3396             break;
3397         default :
3398             break;
3399     }
3400 }
3401
3402 /*-----------------------------------------------------------------*/
3403 /* AccAXRshS - right shift signed a:x known count (0..7)           */
3404 /*-----------------------------------------------------------------*/
3405 static void AccAXRshS (char *x, int shCount)
3406 {   
3407     symbol *tlbl ;
3408     switch(shCount){
3409         case 0 :
3410             break;
3411         case 1 :
3412             emitcode("mov","c,acc.7");
3413             AccAXRrl1(x);               // s->a:x
3414             break;
3415         case 2 :
3416             emitcode("mov","c,acc.7");
3417             AccAXRrl1(x);               // s->a:x
3418             emitcode("mov","c,acc.7");
3419             AccAXRrl1(x);               // s->a:x
3420             break;
3421         case 3 :
3422         case 4 :
3423         case 5 :                        // AAAAABBB:CCCCCDDD = a:x
3424             tlbl = newiTempLabel(NULL);
3425             AccRol(8 - shCount);        // BBBAAAAA:CCCCCDDD
3426             emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
3427             AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
3428             emitcode("anl","a,#0x%02x",
3429                      SRMask[shCount]);  // 000CCCCC:BBBAAAAA
3430             emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
3431             emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
3432             emitcode("anl","a,#0x%02x",
3433                      SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
3434             emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
3435             emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
3436             emitcode("xch","a,%s",x);   // 000SAAAA:BBBCCCCC
3437             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); 
3438             emitcode("orl","a,#0x%02x",
3439                      (unsigned char)~SRMask[shCount]);  // 111AAAAA:BBBCCCCC
3440             emitcode("","%05d$:",tlbl->key+100);
3441             break;                      // SSSSAAAA:BBBCCCCC
3442         case 6 :                        // AABBBBBB:CCDDDDDD
3443             tlbl = newiTempLabel(NULL);
3444             emitcode("mov","c,acc.7");
3445             AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
3446             AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
3447             emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
3448             emitcode("anl","a,#0x%02x",
3449                      SRMask[shCount]);  // 000000AA:BBBBBBCC
3450             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); 
3451             emitcode("orl","a,#0x%02x",
3452                      (unsigned char)~SRMask[shCount]);  // 111111AA:BBBBBBCC
3453             emitcode("","%05d$:",tlbl->key+100);
3454             break;
3455         case 7 :                        // ABBBBBBB:CDDDDDDD
3456             tlbl = newiTempLabel(NULL);
3457             emitcode("mov","c,acc.7");  // c = A
3458             AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
3459             emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
3460             emitcode("anl","a,#0x%02x",
3461                      SRMask[shCount]);  // 0000000A:BBBBBBBC
3462             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); 
3463             emitcode("orl","a,#0x%02x",
3464                      (unsigned char)~SRMask[shCount]);  // 1111111A:BBBBBBBC
3465             emitcode("","%05d$:",tlbl->key+100);
3466             break;
3467         default :
3468             break;
3469     }
3470 }
3471
3472 /*-----------------------------------------------------------------*/
3473 /* shiftL2Left2Result - shift left two bytes from left to result   */
3474 /*-----------------------------------------------------------------*/
3475 static void shiftL2Left2Result (operand *left, int offl,
3476                                 operand *result, int offr, int shCount)
3477 {
3478     if(sameRegs(AOP(result), AOP(left)) &&
3479        ((offl + MSB16) == offr)){
3480         /* don't crash result[offr] */
3481         MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
3482         emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
3483     } else {
3484         movLeft2Result(left,offl, result, offr, 0);
3485         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
3486     }
3487     /* ax << shCount (x = lsb(result))*/
3488     AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
3489     aopPut(AOP(result),"a",offr+MSB16);
3490 }
3491
3492
3493 /*-----------------------------------------------------------------*/
3494 /* shiftR2Left2Result - shift right two bytes from left to result  */
3495 /*-----------------------------------------------------------------*/
3496 static void shiftR2Left2Result (operand *left, int offl,
3497                                 operand *result, int offr,
3498                                 int shCount, int sign)
3499 {
3500     if(sameRegs(AOP(result), AOP(left)) &&
3501        ((offl + MSB16) == offr)){
3502         /* don't crash result[offr] */
3503         MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
3504         emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
3505     } else {
3506         movLeft2Result(left,offl, result, offr, 0);
3507         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
3508     }
3509     /* a:x >> shCount (x = lsb(result))*/
3510     if(sign)
3511         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
3512     else
3513         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
3514     if(getDataSize(result) > 1)
3515         aopPut(AOP(result),"a",offr+MSB16);
3516 }
3517
3518 /*-----------------------------------------------------------------*/
3519 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
3520 /*-----------------------------------------------------------------*/
3521 static void shiftLLeftOrResult (operand *left, int offl,
3522                                 operand *result, int offr, int shCount)
3523 {
3524     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
3525     /* shift left accumulator */
3526     AccLsh(shCount);
3527     /* or with result */
3528     emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
3529     /* back to result */
3530     aopPut(AOP(result),"a",offr);
3531 }
3532
3533 /*-----------------------------------------------------------------*/
3534 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
3535 /*-----------------------------------------------------------------*/
3536 static void shiftRLeftOrResult (operand *left, int offl,
3537                                 operand *result, int offr, int shCount)
3538 {
3539     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
3540     /* shift right accumulator */
3541     AccRsh(shCount);
3542     /* or with result */
3543     emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
3544     /* back to result */
3545     aopPut(AOP(result),"a",offr);
3546 }
3547
3548 /*-----------------------------------------------------------------*/
3549 /* genlshOne - left shift a one byte quantity by known count       */
3550 /*-----------------------------------------------------------------*/
3551 static void genlshOne (operand *result, operand *left, int shCount)
3552 {       
3553     shiftL1Left2Result(left, LSB, result, LSB, shCount);
3554 }
3555
3556 /*-----------------------------------------------------------------*/
3557 /* genlshTwo - left shift two bytes by known amount != 0           */
3558 /*-----------------------------------------------------------------*/
3559 static void genlshTwo (operand *result,operand *left, int shCount)
3560 {
3561     int size;
3562     
3563     size = getDataSize(result);
3564
3565     /* if shCount >= 8 */
3566     if (shCount >= 8) {
3567         shCount -= 8 ;
3568
3569         if (size > 1){
3570             if (shCount)
3571                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
3572             else 
3573                 movLeft2Result(left, LSB, result, MSB16, 0);
3574         }
3575         aopPut(AOP(result),zero,LSB);   
3576     }
3577
3578     /*  1 <= shCount <= 7 */
3579     else {  
3580         if(size == 1)
3581             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
3582         else 
3583             shiftL2Left2Result(left, LSB, result, LSB, shCount);
3584     }
3585 }
3586
3587 /*-----------------------------------------------------------------*/
3588 /* shiftLLong - shift left one long from left to result            */
3589 /* offl = LSB or MSB16                                             */
3590 /*-----------------------------------------------------------------*/
3591 static void shiftLLong (operand *left, operand *result, int offr )
3592 {
3593     char *l;
3594     int size = AOP_SIZE(result);
3595
3596     if(size >= LSB+offr){
3597         l = aopGet(AOP(left),LSB,FALSE,FALSE);
3598         MOVA(l);
3599         emitcode("add","a,acc");
3600         if (sameRegs(AOP(left),AOP(result)) && 
3601             size >= MSB16+offr && offr != LSB )
3602             emitcode("xch","a,%s",
3603                      aopGet(AOP(left),LSB+offr,FALSE,FALSE));
3604         else        
3605             aopPut(AOP(result),"a",LSB+offr);
3606     }
3607
3608     if(size >= MSB16+offr){
3609         if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
3610             l = aopGet(AOP(left),MSB16,FALSE,FALSE);
3611             MOVA(l);
3612         }
3613         emitcode("rlc","a");
3614         if (sameRegs(AOP(left),AOP(result)) && 
3615             size >= MSB24+offr && offr != LSB)
3616             emitcode("xch","a,%s",
3617                      aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
3618         else        
3619             aopPut(AOP(result),"a",MSB16+offr);
3620     }
3621
3622     if(size >= MSB24+offr){
3623         if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
3624             l = aopGet(AOP(left),MSB24,FALSE,FALSE);
3625             MOVA(l);
3626         }
3627         emitcode("rlc","a");
3628         if (sameRegs(AOP(left),AOP(result)) && 
3629             size >= MSB32+offr && offr != LSB )
3630             emitcode("xch","a,%s",
3631                      aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
3632         else        
3633             aopPut(AOP(result),"a",MSB24+offr);
3634     }
3635
3636     if(size > MSB32+offr){
3637         if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
3638             l = aopGet(AOP(left),MSB32,FALSE,FALSE);
3639             MOVA(l);    
3640         }
3641         emitcode("rlc","a");
3642         aopPut(AOP(result),"a",MSB32+offr);
3643     }
3644     if(offr != LSB)
3645         aopPut(AOP(result),zero,LSB);       
3646 }
3647
3648 /*-----------------------------------------------------------------*/
3649 /* genlshFour - shift four byte by a known amount != 0             */
3650 /*-----------------------------------------------------------------*/
3651 static void genlshFour (operand *result, operand *left, int shCount)
3652 {
3653     int size;
3654
3655     size = AOP_SIZE(result);
3656
3657     /* if shifting more that 3 bytes */
3658     if (shCount >= 24 ) {
3659         shCount -= 24;
3660         if (shCount)
3661             /* lowest order of left goes to the highest
3662             order of the destination */
3663             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
3664         else
3665             movLeft2Result(left, LSB, result, MSB32, 0);
3666         aopPut(AOP(result),zero,LSB);
3667         aopPut(AOP(result),zero,MSB16);
3668         aopPut(AOP(result),zero,MSB32);
3669         return;
3670     }
3671
3672     /* more than two bytes */
3673     else if ( shCount >= 16 ) {
3674         /* lower order two bytes goes to higher order two bytes */
3675         shCount -= 16;
3676         /* if some more remaining */
3677         if (shCount)
3678             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
3679         else {
3680             movLeft2Result(left, MSB16, result, MSB32, 0);
3681             movLeft2Result(left, LSB, result, MSB24, 0);
3682         }
3683         aopPut(AOP(result),zero,MSB16);
3684         aopPut(AOP(result),zero,LSB);
3685         return;
3686     }    
3687
3688     /* if more than 1 byte */
3689     else if ( shCount >= 8 ) {
3690         /* lower order three bytes goes to higher order  three bytes */
3691         shCount -= 8;
3692         if(size == 2){
3693             if(shCount)
3694                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
3695             else
3696                 movLeft2Result(left, LSB, result, MSB16, 0);
3697         }
3698         else{   /* size = 4 */
3699             if(shCount == 0){
3700                 movLeft2Result(left, MSB24, result, MSB32, 0);
3701                 movLeft2Result(left, MSB16, result, MSB24, 0);
3702                 movLeft2Result(left, LSB, result, MSB16, 0);
3703                 aopPut(AOP(result),zero,LSB);
3704             }
3705             else if(shCount == 1)
3706                 shiftLLong(left, result, MSB16);
3707             else{
3708                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
3709                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
3710                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
3711                 aopPut(AOP(result),zero,LSB);
3712             }
3713         }
3714     }
3715
3716     /* 1 <= shCount <= 7 */
3717     else if(shCount <= 2){
3718         shiftLLong(left, result, LSB);
3719         if(shCount == 2)
3720             shiftLLong(result, result, LSB);
3721     }
3722     /* 3 <= shCount <= 7, optimize */
3723     else{
3724         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
3725         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
3726         shiftL2Left2Result(left, LSB, result, LSB, shCount);
3727     }
3728 }
3729
3730 /*-----------------------------------------------------------------*/
3731 /* genLeftShiftLiteral - left shifting by known count              */
3732 /*-----------------------------------------------------------------*/
3733 static void genLeftShiftLiteral (operand *left,
3734                                  operand *right,
3735                                  operand *result,
3736                                  iCode *ic)
3737 {    
3738     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3739     int size;
3740
3741     freeAsmop(right,NULL,ic,TRUE);
3742
3743     aopOp(left,ic,FALSE);
3744     aopOp(result,ic,FALSE);
3745
3746     size = getSize(operandType(result));
3747
3748 #if VIEW_SIZE
3749     emitcode("; shift left ","result %d, left %d",size,
3750              AOP_SIZE(left));
3751 #endif
3752
3753     /* I suppose that the left size >= result size */
3754     if(shCount == 0){
3755         while(size--){
3756             movLeft2Result(left, size, result, size, 0);
3757         }
3758     }
3759
3760     else if(shCount >= (size * 8))
3761         while(size--)
3762             aopPut(AOP(result),zero,size);
3763     else{
3764         switch (size) {
3765             case 1:
3766                 genlshOne (result,left,shCount);
3767                 break;
3768
3769             case 2:
3770             case 3:
3771                 genlshTwo (result,left,shCount);
3772                 break;
3773
3774             case 4:
3775                 genlshFour (result,left,shCount);
3776                 break;
3777         }
3778     }
3779     freeAsmop(left,NULL,ic,TRUE);
3780     freeAsmop(result,NULL,ic,TRUE);
3781 }
3782
3783 /*-----------------------------------------------------------------*/
3784 /* genLeftShift - generates code for left shifting                 */
3785 /*-----------------------------------------------------------------*/
3786 static void genLeftShift (iCode *ic)
3787 {
3788     operand *left,*right, *result;
3789     int size, offset;
3790     char *l;
3791     symbol *tlbl , *tlbl1;
3792
3793     right = IC_RIGHT(ic);
3794     left  = IC_LEFT(ic);
3795     result = IC_RESULT(ic);
3796
3797     aopOp(right,ic,FALSE);
3798
3799     /* if the shift count is known then do it 
3800     as efficiently as possible */
3801     if (AOP_TYPE(right) == AOP_LIT) {
3802         genLeftShiftLiteral (left,right,result,ic);
3803         return ;
3804     }
3805
3806     /* shift count is unknown then we have to form 
3807     a loop get the loop count in B : Note: we take
3808     only the lower order byte since shifting
3809     more that 32 bits make no sense anyway, ( the
3810     largest size of an object can be only 32 bits ) */  
3811
3812     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3813     emitcode("inc","b");
3814     freeAsmop (right,NULL,ic,TRUE);
3815     aopOp(left,ic,FALSE);
3816     aopOp(result,ic,FALSE);
3817
3818     /* now move the left to the result if they are not the
3819     same */
3820     if (!sameRegs(AOP(left),AOP(result)) && 
3821         AOP_SIZE(result) > 1) {
3822
3823         size = AOP_SIZE(result);
3824         offset=0;
3825         while (size--) {
3826             l = aopGet(AOP(left),offset,FALSE,TRUE);
3827             if (*l == '@' && (IS_AOP_PREG(result))) {
3828
3829                 emitcode("mov","a,%s",l);
3830                 aopPut(AOP(result),"a",offset);
3831             } else
3832                 aopPut(AOP(result),l,offset);
3833             offset++;
3834         }
3835     }
3836
3837     tlbl = newiTempLabel(NULL);
3838     size = AOP_SIZE(result);
3839     offset = 0 ;   
3840     tlbl1 = newiTempLabel(NULL);
3841
3842     /* if it is only one byte then */
3843     if (size == 1) {
3844         symbol *tlbl1 = newiTempLabel(NULL);
3845
3846         l = aopGet(AOP(left),0,FALSE,FALSE);
3847         MOVA(l);
3848         emitcode("sjmp","%05d$",tlbl1->key+100); 
3849         emitcode("","%05d$:",tlbl->key+100);
3850         emitcode("add","a,acc");
3851         emitcode("","%05d$:",tlbl1->key+100);
3852         emitcode("djnz","b,%05d$",tlbl->key+100);      
3853         aopPut(AOP(result),"a",0);
3854         goto release ;
3855     }
3856     
3857     reAdjustPreg(AOP(result));    
3858     
3859     emitcode("sjmp","%05d$",tlbl1->key+100); 
3860     emitcode("","%05d$:",tlbl->key+100);    
3861     l = aopGet(AOP(result),offset,FALSE,FALSE);
3862     MOVA(l);
3863     emitcode("add","a,acc");         
3864     aopPut(AOP(result),"a",offset++);
3865     while (--size) {
3866         l = aopGet(AOP(result),offset,FALSE,FALSE);
3867         MOVA(l);
3868         emitcode("rlc","a");         
3869         aopPut(AOP(result),"a",offset++);
3870     }
3871     reAdjustPreg(AOP(result));
3872
3873     emitcode("","%05d$:",tlbl1->key+100);
3874     emitcode("djnz","b,%05d$",tlbl->key+100);
3875 release:
3876     freeAsmop(left,NULL,ic,TRUE);
3877     freeAsmop(result,NULL,ic,TRUE);
3878 }
3879
3880 /*-----------------------------------------------------------------*/
3881 /* genrshOne - right shift a one byte quantity by known count      */
3882 /*-----------------------------------------------------------------*/
3883 static void genrshOne (operand *result, operand *left,
3884                        int shCount, int sign)
3885 {
3886     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
3887 }
3888
3889 /*-----------------------------------------------------------------*/
3890 /* genrshTwo - right shift two bytes by known amount != 0          */
3891 /*-----------------------------------------------------------------*/
3892 static void genrshTwo (operand *result,operand *left,
3893                        int shCount, int sign)
3894 {
3895     /* if shCount >= 8 */
3896     if (shCount >= 8) {
3897         shCount -= 8 ;
3898         if (shCount)
3899             shiftR1Left2Result(left, MSB16, result, LSB,
3900                                shCount, sign);
3901         else 
3902             movLeft2Result(left, MSB16, result, LSB, sign);
3903         addSign(result, MSB16, sign);
3904     }
3905
3906     /*  1 <= shCount <= 7 */
3907     else
3908         shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
3909 }
3910
3911 /*-----------------------------------------------------------------*/
3912 /* shiftRLong - shift right one long from left to result           */
3913 /* offl = LSB or MSB16                                             */
3914 /*-----------------------------------------------------------------*/
3915 static void shiftRLong (operand *left, int offl,
3916                         operand *result, int sign)
3917 {
3918     if(!sign)
3919         emitcode("clr","c");
3920     MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
3921     if(sign)
3922         emitcode("mov","c,acc.7");
3923     emitcode("rrc","a");
3924     aopPut(AOP(result),"a",MSB32-offl);
3925     if(offl == MSB16)
3926         /* add sign of "a" */
3927         addSign(result, MSB32, sign);
3928
3929     MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
3930     emitcode("rrc","a");
3931     aopPut(AOP(result),"a",MSB24-offl);
3932
3933     MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
3934     emitcode("rrc","a");
3935     aopPut(AOP(result),"a",MSB16-offl);
3936
3937     if(offl == LSB){
3938         MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
3939         emitcode("rrc","a");
3940         aopPut(AOP(result),"a",LSB);
3941     }
3942 }
3943
3944 /*-----------------------------------------------------------------*/
3945 /* genrshFour - shift four byte by a known amount != 0             */
3946 /*-----------------------------------------------------------------*/
3947 static void genrshFour (operand *result, operand *left,
3948                         int shCount, int sign)
3949 {
3950     /* if shifting more that 3 bytes */
3951     if(shCount >= 24 ) {
3952         shCount -= 24;
3953         if(shCount)
3954             shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
3955         else
3956             movLeft2Result(left, MSB32, result, LSB, sign);
3957         addSign(result, MSB16, sign);
3958     }
3959     else if(shCount >= 16){
3960         shCount -= 16;
3961         if(shCount)
3962             shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
3963         else{
3964             movLeft2Result(left, MSB24, result, LSB, 0);
3965             movLeft2Result(left, MSB32, result, MSB16, sign);
3966         }
3967         addSign(result, MSB24, sign);
3968     }
3969     else if(shCount >= 8){
3970         shCount -= 8;
3971         if(shCount == 1)
3972             shiftRLong(left, MSB16, result, sign);
3973         else if(shCount == 0){
3974             movLeft2Result(left, MSB16, result, LSB, 0);
3975             movLeft2Result(left, MSB24, result, MSB16, 0);
3976             movLeft2Result(left, MSB32, result, MSB24, sign);
3977             addSign(result, MSB32, sign);
3978         }
3979         else{
3980             shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
3981             shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
3982             /* the last shift is signed */
3983             shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
3984             addSign(result, MSB32, sign);
3985         }
3986     }
3987     else{   /* 1 <= shCount <= 7 */
3988         if(shCount <= 2){
3989             shiftRLong(left, LSB, result, sign);
3990             if(shCount == 2)
3991                 shiftRLong(result, LSB, result, sign);
3992         }
3993         else{
3994             shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
3995             shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
3996             shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
3997         }
3998     }
3999 }
4000
4001 /*-----------------------------------------------------------------*/
4002 /* genRightShiftLiteral - right shifting by known count            */
4003 /*-----------------------------------------------------------------*/
4004 static void genRightShiftLiteral (operand *left,
4005                                   operand *right,
4006                                   operand *result,
4007                                   iCode *ic,
4008                                   int sign)
4009 {    
4010     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
4011     int size;
4012
4013     freeAsmop(right,NULL,ic,TRUE);
4014
4015     aopOp(left,ic,FALSE);
4016     aopOp(result,ic,FALSE);
4017
4018 #if VIEW_SIZE
4019     emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
4020              AOP_SIZE(left));
4021 #endif
4022
4023     size = getDataSize(left);
4024     /* test the LEFT size !!! */
4025
4026     /* I suppose that the left size >= result size */
4027     if(shCount == 0){
4028         size = getDataSize(result);
4029         while(size--)
4030             movLeft2Result(left, size, result, size, 0);
4031     }
4032
4033     else if(shCount >= (size * 8)){
4034         if(sign)
4035             /* get sign in acc.7 */
4036             MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
4037         addSign(result, LSB, sign);
4038     } else{
4039         switch (size) {
4040             case 1:
4041                 genrshOne (result,left,shCount,sign);
4042                 break;
4043
4044             case 2:
4045                 genrshTwo (result,left,shCount,sign);
4046                 break;
4047
4048             case 4:
4049                 genrshFour (result,left,shCount,sign);
4050                 break;
4051             default :
4052                 break;
4053         }
4054
4055         freeAsmop(left,NULL,ic,TRUE);
4056         freeAsmop(result,NULL,ic,TRUE);
4057     }
4058 }
4059
4060 /*-----------------------------------------------------------------*/
4061 /* genSignedRightShift - right shift of signed number              */
4062 /*-----------------------------------------------------------------*/
4063 static void genSignedRightShift (iCode *ic)
4064 {
4065     operand *right, *left, *result;
4066     int size, offset;
4067     char *l;
4068     symbol *tlbl, *tlbl1 ;
4069
4070     /* we do it the hard way put the shift count in b
4071     and loop thru preserving the sign */
4072
4073     right = IC_RIGHT(ic);
4074     left  = IC_LEFT(ic);
4075     result = IC_RESULT(ic);
4076
4077     aopOp(right,ic,FALSE);  
4078
4079
4080     if ( AOP_TYPE(right) == AOP_LIT) {
4081         genRightShiftLiteral (left,right,result,ic,1);
4082         return ;
4083     }
4084         /* shift count is unknown then we have to form 
4085        a loop get the loop count in B : Note: we take
4086        only the lower order byte since shifting
4087        more that 32 bits make no sense anyway, ( the
4088        largest size of an object can be only 32 bits ) */  
4089
4090     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
4091     emitcode("inc","b");
4092     freeAsmop (right,NULL,ic,TRUE);
4093     aopOp(left,ic,FALSE);
4094     aopOp(result,ic,FALSE);
4095
4096     /* now move the left to the result if they are not the
4097     same */
4098     if (!sameRegs(AOP(left),AOP(result)) && 
4099         AOP_SIZE(result) > 1) {
4100
4101         size = AOP_SIZE(result);
4102         offset=0;
4103         while (size--) {
4104             l = aopGet(AOP(left),offset,FALSE,TRUE);
4105             if (*l == '@' && IS_AOP_PREG(result)) {
4106
4107                 emitcode("mov","a,%s",l);
4108                 aopPut(AOP(result),"a",offset);
4109             } else
4110                 aopPut(AOP(result),l,offset);
4111             offset++;
4112         }
4113     }
4114
4115     /* mov the highest order bit to OVR */    
4116     tlbl = newiTempLabel(NULL);
4117     tlbl1= newiTempLabel(NULL);
4118
4119     size = AOP_SIZE(result);
4120     offset = size - 1;
4121     emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
4122     emitcode("rlc","a");
4123     emitcode("mov","ov,c");
4124     /* if it is only one byte then */
4125     if (size == 1) {
4126         l = aopGet(AOP(left),0,FALSE,FALSE);
4127         MOVA(l);
4128         emitcode("sjmp","%05d$",tlbl1->key+100);
4129         emitcode("","%05d$:",tlbl->key+100);
4130         emitcode("mov","c,ov");
4131         emitcode("rrc","a");
4132         emitcode("","%05d$:",tlbl1->key+100);
4133         emitcode("djnz","b,%05d$",tlbl->key+100);
4134         aopPut(AOP(result),"a",0);
4135         goto release ;
4136     }
4137
4138     reAdjustPreg(AOP(result));
4139     emitcode("sjmp","%05d$",tlbl1->key+100);
4140     emitcode("","%05d$:",tlbl->key+100);    
4141     emitcode("mov","c,ov");
4142     while (size--) {
4143         l = aopGet(AOP(result),offset,FALSE,FALSE);
4144         MOVA(l);
4145         emitcode("rrc","a");         
4146         aopPut(AOP(result),"a",offset--);
4147     }
4148     reAdjustPreg(AOP(result));
4149     emitcode("","%05d$:",tlbl1->key+100);
4150     emitcode("djnz","b,%05d$",tlbl->key+100);
4151
4152 release:
4153     freeAsmop(left,NULL,ic,TRUE);
4154     freeAsmop(result,NULL,ic,TRUE);
4155 }
4156
4157 /*-----------------------------------------------------------------*/
4158 /* genRightShift - generate code for right shifting                */
4159 /*-----------------------------------------------------------------*/
4160 static void genRightShift (iCode *ic)
4161 {
4162     operand *right, *left, *result;
4163     link *retype ;
4164     int size, offset;
4165     char *l;
4166     symbol *tlbl, *tlbl1 ;
4167
4168     /* if signed then we do it the hard way preserve the
4169     sign bit moving it inwards */
4170     retype = getSpec(operandType(IC_RESULT(ic)));
4171
4172     if (!SPEC_USIGN(retype)) {
4173         genSignedRightShift (ic);
4174         return ;
4175     }
4176
4177     /* signed & unsigned types are treated the same : i.e. the
4178     signed is NOT propagated inwards : quoting from the
4179     ANSI - standard : "for E1 >> E2, is equivalent to division
4180     by 2**E2 if unsigned or if it has a non-negative value,
4181     otherwise the result is implementation defined ", MY definition
4182     is that the sign does not get propagated */
4183
4184     right = IC_RIGHT(ic);
4185     left  = IC_LEFT(ic);
4186     result = IC_RESULT(ic);
4187
4188     aopOp(right,ic,FALSE);
4189
4190     /* if the shift count is known then do it 
4191     as efficiently as possible */
4192     if (AOP_TYPE(right) == AOP_LIT) {
4193         genRightShiftLiteral (left,right,result,ic, 0);
4194         return ;
4195     }
4196
4197     /* shift count is unknown then we have to form 
4198     a loop get the loop count in B : Note: we take
4199     only the lower order byte since shifting
4200     more that 32 bits make no sense anyway, ( the
4201     largest size of an object can be only 32 bits ) */  
4202
4203     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
4204     emitcode("inc","b");
4205     freeAsmop (right,NULL,ic,TRUE);
4206     aopOp(left,ic,FALSE);
4207     aopOp(result,ic,FALSE);
4208
4209     /* now move the left to the result if they are not the
4210     same */
4211     if (!sameRegs(AOP(left),AOP(result)) && 
4212         AOP_SIZE(result) > 1) {
4213
4214         size = AOP_SIZE(result);
4215         offset=0;
4216         while (size--) {
4217             l = aopGet(AOP(left),offset,FALSE,TRUE);
4218             if (*l == '@' && IS_AOP_PREG(result)) {
4219
4220                 emitcode("mov","a,%s",l);
4221                 aopPut(AOP(result),"a",offset);
4222             } else
4223                 aopPut(AOP(result),l,offset);
4224             offset++;
4225         }
4226     }
4227
4228     tlbl = newiTempLabel(NULL);
4229     tlbl1= newiTempLabel(NULL);
4230     size = AOP_SIZE(result);
4231     offset = size - 1;
4232
4233     /* if it is only one byte then */
4234     if (size == 1) {
4235         l = aopGet(AOP(left),0,FALSE,FALSE);
4236         MOVA(l);
4237         emitcode("sjmp","%05d$",tlbl1->key+100);
4238         emitcode("","%05d$:",tlbl->key+100);
4239         CLRC;
4240         emitcode("rrc","a");
4241         emitcode("","%05d$:",tlbl1->key+100);
4242         emitcode("djnz","b,%05d$",tlbl->key+100);
4243         aopPut(AOP(result),"a",0);
4244         goto release ;
4245     }
4246
4247     reAdjustPreg(AOP(result));
4248     emitcode("sjmp","%05d$",tlbl1->key+100);
4249     emitcode("","%05d$:",tlbl->key+100);    
4250     CLRC;
4251     while (size--) {
4252         l = aopGet(AOP(result),offset,FALSE,FALSE);
4253         MOVA(l);
4254         emitcode("rrc","a");         
4255         aopPut(AOP(result),"a",offset--);
4256     }
4257     reAdjustPreg(AOP(result));
4258
4259     emitcode("","%05d$:",tlbl1->key+100);
4260     emitcode("djnz","b,%05d$",tlbl->key+100);
4261
4262 release:
4263     freeAsmop(left,NULL,ic,TRUE);
4264     freeAsmop(result,NULL,ic,TRUE);
4265 }
4266
4267 /*-----------------------------------------------------------------*/
4268 /* genUnpackBits - generates code for unpacking bits               */
4269 /*-----------------------------------------------------------------*/
4270 static void genUnpackBits (operand *result, char *rname, int ptype)
4271 {    
4272     int shCnt ;
4273     int rlen = 0 ;
4274     link *etype;
4275     int offset = 0 ;
4276
4277     etype = getSpec(operandType(result));
4278
4279     /* read the first byte  */
4280     switch (ptype) {
4281
4282     case POINTER:
4283     case IPOINTER:
4284         emitcode("mov","a,@%s",rname);
4285         break;
4286         
4287     case PPOINTER:
4288         emitcode("movx","a,@%s",rname);
4289         break;
4290         
4291     case FPOINTER:
4292         emitcode("movx","a,@dptr");
4293         break;
4294
4295     case CPOINTER:
4296         emitcode("clr","a");
4297         emitcode("movc","a","@a+dptr");
4298         break;
4299
4300     case GPOINTER:
4301         emitcode("lcall","__gptrget");
4302         break;
4303     }
4304
4305     /* if we have bitdisplacement then it fits   */
4306     /* into this byte completely or if length is */
4307     /* less than a byte                          */
4308     if ((shCnt = SPEC_BSTR(etype)) || 
4309         (SPEC_BLEN(etype) <= 8))  {
4310
4311         /* shift right acc */
4312         AccRsh(shCnt);
4313
4314         emitcode("anl","a,#0x%02x",
4315                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
4316         aopPut(AOP(result),"a",offset);
4317         return ;
4318     }
4319
4320     /* bit field did not fit in a byte  */
4321     rlen = SPEC_BLEN(etype) - 8;
4322     aopPut(AOP(result),"a",offset++);
4323
4324     while (1)  {
4325
4326         switch (ptype) {
4327         case POINTER:
4328         case IPOINTER:
4329             emitcode("inc","%s",rname);
4330             emitcode("mov","a,@%s",rname);
4331             break;
4332             
4333         case PPOINTER:
4334             emitcode("inc","%s",rname);
4335             emitcode("movx","a,@%s",rname);
4336             break;
4337
4338         case FPOINTER:
4339             emitcode("inc","dptr");
4340             emitcode("movx","a,@dptr");
4341             break;
4342             
4343         case CPOINTER:
4344             emitcode("clr","a");
4345             emitcode("inc","dptr");
4346             emitcode("movc","a","@a+dptr");
4347             break;
4348             
4349         case GPOINTER:
4350             emitcode("inc","dptr");
4351             emitcode("lcall","__gptrget");
4352             break;
4353         }
4354
4355         rlen -= 8;            
4356         /* if we are done */
4357         if ( rlen <= 0 )
4358             break ;
4359         
4360         aopPut(AOP(result),"a",offset++);
4361                               
4362     }
4363     
4364     if (rlen) {
4365         emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
4366         aopPut(AOP(result),"a",offset);        
4367     }
4368     
4369     return ;
4370 }
4371
4372
4373 /*-----------------------------------------------------------------*/
4374 /* genDataPointerGet - generates code when ptr offset is known     */
4375 /*-----------------------------------------------------------------*/
4376 static void genDataPointerGet (operand *left, 
4377                                operand *result, 
4378                                iCode *ic)
4379 {
4380     char *l;
4381     char buffer[256];
4382     int size , offset = 0;
4383     aopOp(result,ic,TRUE);
4384
4385     /* get the string representation of the name */
4386     l = aopGet(AOP(left),0,FALSE,TRUE);
4387     size = AOP_SIZE(result);
4388     while (size--) {
4389         if (offset)
4390             sprintf(buffer,"(%s + %d)",l+1,offset);
4391         else
4392             sprintf(buffer,"%s",l+1);
4393         aopPut(AOP(result),buffer,offset++);
4394     }
4395
4396     freeAsmop(left,NULL,ic,TRUE);
4397     freeAsmop(result,NULL,ic,TRUE);
4398 }
4399
4400 /*-----------------------------------------------------------------*/
4401 /* genNearPointerGet - emitcode for near pointer fetch             */
4402 /*-----------------------------------------------------------------*/
4403 static void genNearPointerGet (operand *left, 
4404                                operand *result, 
4405                                iCode *ic)
4406 {
4407     asmop *aop = NULL;
4408     regs *preg = NULL ;
4409     char *rname ;
4410     link *rtype, *retype;
4411     link *ltype = operandType(left);    
4412     char buffer[80];
4413
4414     rtype = operandType(result);
4415     retype= getSpec(rtype);
4416     
4417     aopOp(left,ic,FALSE);
4418     
4419     /* if left is rematerialisable and
4420        result is not bit variable type and
4421        the left is pointer to data space i.e
4422        lower 128 bytes of space */
4423     if (AOP_TYPE(left) == AOP_IMMD &&
4424         !IS_BITVAR(retype)         &&
4425         DCL_TYPE(ltype) == POINTER) {
4426         genDataPointerGet (left,result,ic);
4427         return ;
4428     }
4429     
4430         /* if the value is already in a pointer register
4431        then don't need anything more */
4432     if (!AOP_INPREG(AOP(left))) {
4433         /* otherwise get a free pointer register */
4434         aop = newAsmop(0);
4435         preg = getFreePtr(ic,&aop,FALSE);
4436         emitcode("mov","%s,%s",
4437                 preg->name,
4438                 aopGet(AOP(left),0,FALSE,TRUE));
4439         rname = preg->name ;
4440     } else
4441         rname = aopGet(AOP(left),0,FALSE,FALSE);
4442     
4443     freeAsmop(left,NULL,ic,TRUE);
4444     aopOp (result,ic,FALSE);
4445     
4446       /* if bitfield then unpack the bits */
4447     if (IS_BITVAR(retype)) 
4448         genUnpackBits (result,rname,POINTER);
4449     else {
4450         /* we have can just get the values */
4451         int size = AOP_SIZE(result);
4452         int offset = 0 ;        
4453         
4454         while (size--) {
4455             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
4456
4457                 emitcode("mov","a,@%s",rname);
4458                 aopPut(AOP(result),"a",offset);
4459             } else {
4460                 sprintf(buffer,"@%s",rname);
4461                 aopPut(AOP(result),buffer,offset);
4462             }
4463             offset++ ;
4464             if (size)
4465                 emitcode("inc","%s",rname);
4466         }
4467     }
4468
4469     /* now some housekeeping stuff */
4470     if (aop) {
4471         /* we had to allocate for this iCode */
4472         freeAsmop(NULL,aop,ic,TRUE);
4473     } else { 
4474         /* we did not allocate which means left
4475            already in a pointer register, then
4476            if size > 0 && this could be used again
4477            we have to point it back to where it 
4478            belongs */
4479         if (AOP_SIZE(result) > 1 &&
4480             !OP_SYMBOL(left)->remat &&
4481             ( OP_SYMBOL(left)->liveTo > ic->seq ||
4482               ic->depth )) {
4483             int size = AOP_SIZE(result) - 1;
4484             while (size--)
4485                 emitcode("dec","%s",rname);
4486         }
4487     }
4488
4489     /* done */
4490     freeAsmop(result,NULL,ic,TRUE);
4491      
4492 }
4493
4494 /*-----------------------------------------------------------------*/
4495 /* genPagedPointerGet - emitcode for paged pointer fetch           */
4496 /*-----------------------------------------------------------------*/
4497 static void genPagedPointerGet (operand *left, 
4498                                operand *result, 
4499                                iCode *ic)
4500 {
4501     asmop *aop = NULL;
4502     regs *preg = NULL ;
4503     char *rname ;
4504     link *rtype, *retype;    
4505
4506     rtype = operandType(result);
4507     retype= getSpec(rtype);
4508     
4509     aopOp(left,ic,FALSE);
4510
4511   /* if the value is already in a pointer register
4512        then don't need anything more */
4513     if (!AOP_INPREG(AOP(left))) {
4514         /* otherwise get a free pointer register */
4515         aop = newAsmop(0);
4516         preg = getFreePtr(ic,&aop,FALSE);
4517         emitcode("mov","%s,%s",
4518                 preg->name,
4519                 aopGet(AOP(left),0,FALSE,TRUE));
4520         rname = preg->name ;
4521     } else
4522         rname = aopGet(AOP(left),0,FALSE,FALSE);
4523     
4524     freeAsmop(left,NULL,ic,TRUE);
4525     aopOp (result,ic,FALSE);
4526
4527     /* if bitfield then unpack the bits */
4528     if (IS_BITVAR(retype)) 
4529         genUnpackBits (result,rname,PPOINTER);
4530     else {
4531         /* we have can just get the values */
4532         int size = AOP_SIZE(result);
4533         int offset = 0 ;        
4534         
4535         while (size--) {
4536             
4537             emitcode("movx","a,@%s",rname);
4538             aopPut(AOP(result),"a",offset);
4539             
4540             offset++ ;
4541             
4542             if (size)
4543                 emitcode("inc","%s",rname);
4544         }
4545     }
4546
4547     /* now some housekeeping stuff */
4548     if (aop) {
4549         /* we had to allocate for this iCode */
4550         freeAsmop(NULL,aop,ic,TRUE);
4551     } else { 
4552         /* we did not allocate which means left
4553            already in a pointer register, then
4554            if size > 0 && this could be used again
4555            we have to point it back to where it 
4556            belongs */
4557         if (AOP_SIZE(result) > 1 &&
4558             !OP_SYMBOL(left)->remat &&
4559             ( OP_SYMBOL(left)->liveTo > ic->seq ||
4560               ic->depth )) {
4561             int size = AOP_SIZE(result) - 1;
4562             while (size--)
4563                 emitcode("dec","%s",rname);
4564         }
4565     }
4566
4567     /* done */
4568     freeAsmop(result,NULL,ic,TRUE);
4569     
4570         
4571 }
4572
4573 /*-----------------------------------------------------------------*/
4574 /* genFarPointerGet - gget value from far space                    */
4575 /*-----------------------------------------------------------------*/
4576 static void genFarPointerGet (operand *left,
4577                               operand *result, iCode *ic)
4578 {
4579     int size, offset ;
4580     link *retype = getSpec(operandType(result));
4581
4582     aopOp(left,ic,FALSE);
4583
4584     /* if the operand is already in dptr 
4585     then we do nothing else we move the value to dptr */
4586     if (AOP_TYPE(left) != AOP_STR) {
4587         /* if this is remateriazable */
4588         if (AOP_TYPE(left) == AOP_IMMD)
4589             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
4590         else { /* we need to get it byte by byte */
4591             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
4592             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
4593             if (options.model == MODEL_FLAT24)
4594             {
4595                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
4596             }
4597         }
4598     }
4599     /* so dptr know contains the address */
4600     freeAsmop(left,NULL,ic,TRUE);
4601     aopOp(result,ic,FALSE);
4602
4603     /* if bit then unpack */
4604     if (IS_BITVAR(retype)) 
4605         genUnpackBits(result,"dptr",FPOINTER);
4606     else {
4607         size = AOP_SIZE(result);
4608         offset = 0 ;
4609
4610         while (size--) {
4611             emitcode("movx","a,@dptr");
4612             aopPut(AOP(result),"a",offset++);
4613             if (size)
4614                 emitcode("inc","dptr");
4615         }
4616     }
4617
4618     freeAsmop(result,NULL,ic,TRUE);
4619 }
4620
4621 /*-----------------------------------------------------------------*/
4622 /* emitcodePointerGet - gget value from code space                  */
4623 /*-----------------------------------------------------------------*/
4624 static void emitcodePointerGet (operand *left,
4625                                 operand *result, iCode *ic)
4626 {
4627     int size, offset ;
4628     link *retype = getSpec(operandType(result));
4629
4630     aopOp(left,ic,FALSE);
4631
4632     /* if the operand is already in dptr 
4633     then we do nothing else we move the value to dptr */
4634     if (AOP_TYPE(left) != AOP_STR) {
4635         /* if this is remateriazable */
4636         if (AOP_TYPE(left) == AOP_IMMD)
4637             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
4638         else { /* we need to get it byte by byte */
4639             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
4640             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
4641             if (options.model == MODEL_FLAT24)
4642             {
4643                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
4644             }
4645         }
4646     }
4647     /* so dptr know contains the address */
4648     freeAsmop(left,NULL,ic,TRUE);
4649     aopOp(result,ic,FALSE);
4650
4651     /* if bit then unpack */
4652     if (IS_BITVAR(retype)) 
4653         genUnpackBits(result,"dptr",CPOINTER);
4654     else {
4655         size = AOP_SIZE(result);
4656         offset = 0 ;
4657
4658         while (size--) {
4659             emitcode("clr","a");
4660             emitcode("movc","a,@a+dptr");
4661             aopPut(AOP(result),"a",offset++);
4662             if (size)
4663                 emitcode("inc","dptr");
4664         }
4665     }
4666
4667     freeAsmop(result,NULL,ic,TRUE);
4668 }
4669
4670 /*-----------------------------------------------------------------*/
4671 /* genGenPointerGet - gget value from generic pointer space        */
4672 /*-----------------------------------------------------------------*/
4673 static void genGenPointerGet (operand *left,
4674                               operand *result, iCode *ic)
4675 {
4676     int size, offset ;
4677     link *retype = getSpec(operandType(result));
4678
4679     aopOp(left,ic,FALSE);
4680
4681     /* if the operand is already in dptr 
4682     then we do nothing else we move the value to dptr */
4683     if (AOP_TYPE(left) != AOP_STR) {
4684         /* if this is remateriazable */
4685         if (AOP_TYPE(left) == AOP_IMMD) {
4686             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
4687             emitcode("mov","b,#%d",pointerCode(retype));
4688         }
4689         else { /* we need to get it byte by byte */
4690             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
4691             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
4692             if (options.model == MODEL_FLAT24)
4693             {
4694                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
4695                emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
4696             }
4697             else
4698             {
4699                 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
4700             }
4701         }
4702     }
4703     /* so dptr know contains the address */
4704     freeAsmop(left,NULL,ic,TRUE);
4705     aopOp(result,ic,FALSE); 
4706
4707     /* if bit then unpack */
4708     if (IS_BITVAR(retype)) 
4709         genUnpackBits(result,"dptr",GPOINTER);
4710     else {
4711         size = AOP_SIZE(result);
4712         offset = 0 ;
4713
4714         while (size--) {
4715             emitcode("lcall","__gptrget");
4716             aopPut(AOP(result),"a",offset++);
4717             if (size)
4718                 emitcode("inc","dptr");
4719         }
4720     }
4721
4722     freeAsmop(result,NULL,ic,TRUE);
4723 }
4724
4725 /*-----------------------------------------------------------------*/
4726 /* genPointerGet - generate code for pointer get                   */
4727 /*-----------------------------------------------------------------*/
4728 static void genPointerGet (iCode *ic)
4729 {
4730     operand *left, *result ;
4731     link *type, *etype;
4732     int p_type;
4733
4734     left = IC_LEFT(ic);
4735     result = IC_RESULT(ic) ;
4736
4737     /* depending on the type of pointer we need to
4738     move it to the correct pointer register */
4739     type = operandType(left);
4740     etype = getSpec(type);
4741     /* if left is of type of pointer then it is simple */
4742     if (IS_PTR(type) && !IS_FUNC(type->next)) 
4743         p_type = DCL_TYPE(type);
4744     else {
4745         /* we have to go by the storage class */
4746         p_type = PTR_TYPE(SPEC_OCLS(etype));
4747
4748 /*      if (SPEC_OCLS(etype)->codesp ) { */
4749 /*          p_type = CPOINTER ;  */
4750 /*      } */
4751 /*      else */
4752 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
4753 /*              p_type = FPOINTER ; */
4754 /*          else */
4755 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
4756 /*                  p_type = PPOINTER; */
4757 /*              else */
4758 /*                  if (SPEC_OCLS(etype) == idata ) */
4759 /*                      p_type = IPOINTER; */
4760 /*                  else */
4761 /*                      p_type = POINTER ; */
4762     }
4763
4764     /* now that we have the pointer type we assign
4765     the pointer values */
4766     switch (p_type) {
4767
4768     case POINTER:       
4769     case IPOINTER:
4770         genNearPointerGet (left,result,ic);
4771         break;
4772
4773     case PPOINTER:
4774         genPagedPointerGet(left,result,ic);
4775         break;
4776
4777     case FPOINTER:
4778         genFarPointerGet (left,result,ic);
4779         break;
4780
4781     case CPOINTER:
4782         emitcodePointerGet (left,result,ic);
4783         break;
4784
4785     case GPOINTER:
4786         genGenPointerGet (left,result,ic);
4787         break;
4788     }
4789
4790 }
4791
4792 /*-----------------------------------------------------------------*/
4793 /* genPackBits - generates code for packed bit storage             */
4794 /*-----------------------------------------------------------------*/
4795 static void genPackBits (link    *etype ,
4796                          operand *right ,
4797                          char *rname, int p_type)
4798 {
4799     int shCount = 0 ;
4800     int offset = 0  ;
4801     int rLen = 0 ;
4802     int blen, bstr ;   
4803     char *l ;
4804
4805     blen = SPEC_BLEN(etype);
4806     bstr = SPEC_BSTR(etype);
4807
4808     l = aopGet(AOP(right),offset++,FALSE,FALSE);
4809     MOVA(l);   
4810
4811     /* if the bit lenth is less than or    */
4812     /* it exactly fits a byte then         */
4813     if (SPEC_BLEN(etype) <= 8 )  {
4814         shCount = SPEC_BSTR(etype) ;
4815
4816         /* shift left acc */
4817         AccLsh(shCount);
4818
4819         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
4820
4821
4822             switch (p_type) {
4823                 case POINTER:
4824                     emitcode ("mov","b,a");
4825                     emitcode("mov","a,@%s",rname);
4826                     break;
4827
4828                 case FPOINTER:
4829                     emitcode ("mov","b,a");
4830                     emitcode("movx","a,@dptr");
4831                     break;
4832
4833                 case GPOINTER:
4834                     emitcode ("push","b");
4835                     emitcode ("push","acc");
4836                     emitcode ("lcall","__gptrget");
4837                     emitcode ("pop","b");
4838                     break;
4839             }
4840
4841             emitcode ("anl","a,#0x%02x",(unsigned char)
4842                       ((unsigned char)(0xFF << (blen+bstr)) | 
4843                        (unsigned char)(0xFF >> (8-bstr)) ) );
4844             emitcode ("orl","a,b");
4845             if (p_type == GPOINTER)
4846                 emitcode("pop","b");
4847         }
4848     }
4849
4850     switch (p_type) {
4851         case POINTER:
4852             emitcode("mov","@%s,a",rname);
4853             break;
4854
4855         case FPOINTER:
4856             emitcode("movx","@dptr,a");
4857             break;
4858
4859         case GPOINTER:
4860             emitcode("lcall","__gptrput");
4861             break;
4862     }
4863
4864     /* if we r done */
4865     if ( SPEC_BLEN(etype) <= 8 )
4866         return ;
4867
4868     emitcode("inc","%s",rname);
4869     rLen = SPEC_BLEN(etype) ;     
4870
4871     /* now generate for lengths greater than one byte */
4872     while (1) {
4873
4874         l = aopGet(AOP(right),offset++,FALSE,TRUE);
4875
4876         rLen -= 8 ;
4877         if (rLen <= 0 )
4878             break ;
4879
4880         switch (p_type) {
4881             case POINTER:
4882                 if (*l == '@') {
4883                     MOVA(l);
4884                     emitcode("mov","@%s,a",rname);
4885                 } else
4886                     emitcode("mov","@%s,%s",rname,l);
4887                 break;
4888
4889             case FPOINTER:
4890                 MOVA(l);
4891                 emitcode("movx","@dptr,a");
4892                 break;
4893
4894             case GPOINTER:
4895                 MOVA(l);
4896                 emitcode("lcall","__gptrput");
4897                 break;  
4898         }   
4899         emitcode ("inc","%s",rname);
4900     }
4901
4902     MOVA(l);
4903
4904     /* last last was not complete */
4905     if (rLen)   {
4906         /* save the byte & read byte */
4907         switch (p_type) {
4908             case POINTER:
4909                 emitcode ("mov","b,a");
4910                 emitcode("mov","a,@%s",rname);
4911                 break;
4912
4913             case FPOINTER:
4914                 emitcode ("mov","b,a");
4915                 emitcode("movx","a,@dptr");
4916                 break;
4917
4918             case GPOINTER:
4919                 emitcode ("push","b");
4920                 emitcode ("push","acc");
4921                 emitcode ("lcall","__gptrget");
4922                 emitcode ("pop","b");
4923                 break;
4924         }
4925
4926         emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
4927         emitcode ("orl","a,b");
4928     }
4929
4930     if (p_type == GPOINTER)
4931         emitcode("pop","b");
4932
4933     switch (p_type) {
4934
4935     case POINTER:
4936         emitcode("mov","@%s,a",rname);
4937         break;
4938         
4939     case FPOINTER:
4940         emitcode("movx","@dptr,a");
4941         break;
4942         
4943     case GPOINTER:
4944         emitcode("lcall","__gptrput");
4945         break;                  
4946     }
4947 }
4948 /*-----------------------------------------------------------------*/
4949 /* genDataPointerSet - remat pointer to data space                 */
4950 /*-----------------------------------------------------------------*/
4951 static void genDataPointerSet(operand *right,
4952                               operand *result,
4953                               iCode *ic)
4954 {
4955     int size, offset = 0 ;
4956     char *l, buffer[256];
4957
4958     aopOp(right,ic,FALSE);
4959     
4960     l = aopGet(AOP(result),0,FALSE,TRUE);
4961     size = AOP_SIZE(right);
4962     while (size--) {
4963         if (offset)
4964             sprintf(buffer,"(%s + %d)",l+1,offset);
4965         else
4966             sprintf(buffer,"%s",l+1);
4967         emitcode("mov","%s,%s",buffer,
4968                  aopGet(AOP(right),offset++,FALSE,FALSE));
4969     }
4970
4971     freeAsmop(right,NULL,ic,TRUE);
4972     freeAsmop(result,NULL,ic,TRUE);
4973 }
4974
4975 /*-----------------------------------------------------------------*/
4976 /* genNearPointerSet - emitcode for near pointer put                */
4977 /*-----------------------------------------------------------------*/
4978 static void genNearPointerSet (operand *right,
4979                                operand *result, 
4980                                iCode *ic)
4981 {
4982     asmop *aop = NULL;
4983     regs *preg = NULL ;
4984     char *rname , *l;
4985     link *retype;
4986     link *ptype = operandType(result);
4987     
4988     retype= getSpec(operandType(right));
4989
4990     aopOp(result,ic,FALSE);
4991     
4992     /* if the result is rematerializable &
4993        in data space & not a bit variable */
4994     if (AOP_TYPE(result) == AOP_IMMD &&
4995         DCL_TYPE(ptype) == POINTER   &&
4996         !IS_BITVAR(retype)) {
4997         genDataPointerSet (right,result,ic);
4998         return;
4999     }
5000
5001     /* if the value is already in a pointer register
5002     then don't need anything more */
5003     if (!AOP_INPREG(AOP(result))) {
5004         /* otherwise get a free pointer register */
5005         aop = newAsmop(0);
5006         preg = getFreePtr(ic,&aop,FALSE);
5007         emitcode("mov","%s,%s",
5008                  preg->name,
5009                  aopGet(AOP(result),0,FALSE,TRUE));
5010         rname = preg->name ;
5011     } else
5012         rname = aopGet(AOP(result),0,FALSE,FALSE);
5013
5014     freeAsmop(result,NULL,ic,TRUE);
5015     aopOp (right,ic,FALSE);
5016
5017     /* if bitfield then unpack the bits */
5018     if (IS_BITVAR(retype)) 
5019         genPackBits (retype,right,rname,POINTER);
5020     else {
5021         /* we have can just get the values */
5022         int size = AOP_SIZE(right);
5023         int offset = 0 ;    
5024
5025         while (size--) {
5026             l = aopGet(AOP(right),offset,FALSE,TRUE);
5027             if (*l == '@' ) {
5028                 MOVA(l);
5029                 emitcode("mov","@%s,a",rname);
5030             } else
5031                 emitcode("mov","@%s,%s",rname,l);
5032             if (size)
5033                 emitcode("inc","%s",rname);
5034             offset++;
5035         }
5036     }
5037
5038     /* now some housekeeping stuff */
5039     if (aop) {
5040         /* we had to allocate for this iCode */
5041         freeAsmop(NULL,aop,ic,TRUE);
5042     } else { 
5043         /* we did not allocate which means left
5044         already in a pointer register, then
5045         if size > 0 && this could be used again
5046         we have to point it back to where it 
5047         belongs */
5048         if (AOP_SIZE(right) > 1 &&
5049             !OP_SYMBOL(result)->remat &&
5050             ( OP_SYMBOL(result)->liveTo > ic->seq ||
5051               ic->depth )) {
5052             int size = AOP_SIZE(right) - 1;
5053             while (size--)
5054                 emitcode("dec","%s",rname);
5055         }
5056     }
5057
5058     /* done */
5059     freeAsmop(right,NULL,ic,TRUE);
5060
5061
5062 }
5063
5064 /*-----------------------------------------------------------------*/
5065 /* genPagedPointerSet - emitcode for Paged pointer put             */
5066 /*-----------------------------------------------------------------*/
5067 static void genPagedPointerSet (operand *right,
5068                                operand *result, 
5069                                iCode *ic)
5070 {
5071     asmop *aop = NULL;
5072     regs *preg = NULL ;
5073     char *rname , *l;
5074     link *retype;
5075        
5076     retype= getSpec(operandType(right));
5077     
5078     aopOp(result,ic,FALSE);
5079     
5080     /* if the value is already in a pointer register
5081        then don't need anything more */
5082     if (!AOP_INPREG(AOP(result))) {
5083         /* otherwise get a free pointer register */
5084         aop = newAsmop(0);
5085         preg = getFreePtr(ic,&aop,FALSE);
5086         emitcode("mov","%s,%s",
5087                 preg->name,
5088                 aopGet(AOP(result),0,FALSE,TRUE));
5089         rname = preg->name ;
5090     } else
5091         rname = aopGet(AOP(result),0,FALSE,FALSE);
5092     
5093     freeAsmop(result,NULL,ic,TRUE);
5094     aopOp (right,ic,FALSE);
5095
5096     /* if bitfield then unpack the bits */
5097     if (IS_BITVAR(retype)) 
5098         genPackBits (retype,right,rname,PPOINTER);
5099     else {
5100         /* we have can just get the values */
5101         int size = AOP_SIZE(right);
5102         int offset = 0 ;        
5103         
5104         while (size--) {
5105             l = aopGet(AOP(right),offset,FALSE,TRUE);
5106             
5107             MOVA(l);
5108             emitcode("movx","@%s,a",rname);
5109
5110             if (size)
5111                 emitcode("inc","%s",rname);
5112
5113             offset++;
5114         }
5115     }
5116     
5117     /* now some housekeeping stuff */
5118     if (aop) {
5119         /* we had to allocate for this iCode */
5120         freeAsmop(NULL,aop,ic,TRUE);
5121     } else { 
5122         /* we did not allocate which means left
5123            already in a pointer register, then
5124            if size > 0 && this could be used again
5125            we have to point it back to where it 
5126            belongs */
5127         if (AOP_SIZE(right) > 1 &&
5128             !OP_SYMBOL(result)->remat &&
5129             ( OP_SYMBOL(result)->liveTo > ic->seq ||
5130               ic->depth )) {
5131             int size = AOP_SIZE(right) - 1;
5132             while (size--)
5133                 emitcode("dec","%s",rname);
5134         }
5135     }
5136
5137     /* done */
5138     freeAsmop(right,NULL,ic,TRUE);
5139     
5140         
5141 }
5142
5143 /*-----------------------------------------------------------------*/
5144 /* genFarPointerSet - set value from far space                     */
5145 /*-----------------------------------------------------------------*/
5146 static void genFarPointerSet (operand *right,
5147                               operand *result, iCode *ic)
5148 {
5149     int size, offset ;
5150     link *retype = getSpec(operandType(right));
5151
5152     aopOp(result,ic,FALSE);
5153
5154     /* if the operand is already in dptr 
5155     then we do nothing else we move the value to dptr */
5156     if (AOP_TYPE(result) != AOP_STR) {
5157         /* if this is remateriazable */
5158         if (AOP_TYPE(result) == AOP_IMMD)
5159             emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
5160         else { /* we need to get it byte by byte */
5161             emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
5162             emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
5163             if (options.model == MODEL_FLAT24)
5164             {
5165                emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
5166             }
5167         }
5168     }
5169     /* so dptr know contains the address */
5170     freeAsmop(result,NULL,ic,TRUE);
5171     aopOp(right,ic,FALSE);
5172
5173     /* if bit then unpack */
5174     if (IS_BITVAR(retype)) 
5175         genPackBits(retype,right,"dptr",FPOINTER);
5176     else {
5177         size = AOP_SIZE(right);
5178         offset = 0 ;
5179
5180         while (size--) {
5181             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
5182             MOVA(l);
5183             emitcode("movx","@dptr,a");
5184             if (size)
5185                 emitcode("inc","dptr");
5186         }
5187     }
5188
5189     freeAsmop(right,NULL,ic,TRUE);
5190 }
5191
5192 /*-----------------------------------------------------------------*/
5193 /* genGenPointerSet - set value from generic pointer space         */
5194 /*-----------------------------------------------------------------*/
5195 static void genGenPointerSet (operand *right,
5196                               operand *result, iCode *ic)
5197 {
5198     int size, offset ;
5199     link *retype = getSpec(operandType(right));
5200
5201     aopOp(result,ic,FALSE);
5202
5203     /* if the operand is already in dptr 
5204     then we do nothing else we move the value to dptr */
5205     if (AOP_TYPE(result) != AOP_STR) {
5206         /* if this is remateriazable */
5207         if (AOP_TYPE(result) == AOP_IMMD) {
5208             emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
5209             emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
5210         }
5211         else { /* we need to get it byte by byte */
5212             emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
5213             emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
5214             if (options.model == MODEL_FLAT24)
5215             {
5216                emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
5217                emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
5218             }
5219             else
5220             {
5221                 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
5222             }
5223         }
5224     }
5225     /* so dptr know contains the address */
5226     freeAsmop(result,NULL,ic,TRUE);
5227     aopOp(right,ic,FALSE);
5228
5229     /* if bit then unpack */
5230     if (IS_BITVAR(retype)) 
5231         genPackBits(retype,right,"dptr",GPOINTER);
5232     else {
5233         size = AOP_SIZE(right);
5234         offset = 0 ;
5235
5236         while (size--) {
5237             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
5238             MOVA(l);
5239             emitcode("lcall","__gptrput");
5240             if (size)
5241                 emitcode("inc","dptr");
5242         }
5243     }
5244
5245     freeAsmop(right,NULL,ic,TRUE);
5246 }
5247
5248 /*-----------------------------------------------------------------*/
5249 /* genPointerSet - stores the value into a pointer location        */
5250 /*-----------------------------------------------------------------*/
5251 static void genPointerSet (iCode *ic)
5252 {    
5253     operand *right, *result ;
5254     link *type, *etype;
5255     int p_type;
5256
5257     right = IC_RIGHT(ic);
5258     result = IC_RESULT(ic) ;
5259
5260     /* depending on the type of pointer we need to
5261     move it to the correct pointer register */
5262     type = operandType(result);
5263     etype = getSpec(type);
5264     /* if left is of type of pointer then it is simple */
5265     if (IS_PTR(type) && !IS_FUNC(type->next)) {
5266         p_type = DCL_TYPE(type);
5267     }
5268     else {
5269         /* we have to go by the storage class */
5270         p_type = PTR_TYPE(SPEC_OCLS(etype));
5271
5272 /*      if (SPEC_OCLS(etype)->codesp ) { */
5273 /*          p_type = CPOINTER ;  */
5274 /*      } */
5275 /*      else */
5276 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
5277 /*              p_type = FPOINTER ; */
5278 /*          else */
5279 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
5280 /*                  p_type = PPOINTER ; */
5281 /*              else */
5282 /*                  if (SPEC_OCLS(etype) == idata ) */
5283 /*                      p_type = IPOINTER ; */
5284 /*                  else */
5285 /*                      p_type = POINTER ; */
5286     }
5287
5288     /* now that we have the pointer type we assign
5289     the pointer values */
5290     switch (p_type) {
5291
5292     case POINTER:
5293     case IPOINTER:
5294         genNearPointerSet (right,result,ic);
5295         break;
5296
5297     case PPOINTER:
5298         genPagedPointerSet (right,result,ic);
5299         break;
5300
5301     case FPOINTER:
5302         genFarPointerSet (right,result,ic);
5303         break;
5304
5305     case GPOINTER:
5306         genGenPointerSet (right,result,ic);
5307         break;
5308     }
5309
5310 }
5311
5312 /*-----------------------------------------------------------------*/
5313 /* genIfx - generate code for Ifx statement                        */
5314 /*-----------------------------------------------------------------*/
5315 static void genIfx (iCode *ic, iCode *popIc)
5316 {
5317     operand *cond = IC_COND(ic);
5318     int isbit =0;
5319
5320     aopOp(cond,ic,FALSE);
5321
5322     /* get the value into acc */
5323     if (AOP_TYPE(cond) != AOP_CRY)
5324         toBoolean(cond);
5325     else
5326         isbit = 1;
5327     /* the result is now in the accumulator */
5328     freeAsmop(cond,NULL,ic,TRUE);
5329
5330     /* if there was something to be popped then do it */
5331     if (popIc)
5332         genIpop(popIc);
5333
5334     /* if the condition is  a bit variable */
5335     if (isbit && IS_ITEMP(cond) && 
5336         SPIL_LOC(cond))
5337         genIfxJump(ic,SPIL_LOC(cond)->rname);
5338     else
5339         if (isbit && !IS_ITEMP(cond))
5340             genIfxJump(ic,OP_SYMBOL(cond)->rname);
5341         else
5342             genIfxJump(ic,"a");
5343
5344     ic->generated = 1;
5345 }
5346
5347 /*-----------------------------------------------------------------*/
5348 /* genAddrOf - generates code for address of                       */
5349 /*-----------------------------------------------------------------*/
5350 static void genAddrOf (iCode *ic)
5351 {
5352     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
5353     int size, offset ;
5354
5355     aopOp(IC_RESULT(ic),ic,FALSE);
5356
5357     /* if the operand is on the stack then we 
5358     need to get the stack offset of this
5359     variable */
5360     if (sym->onStack) {
5361         /* if it has an offset then we need to compute
5362         it */
5363         if (sym->stack) {
5364             emitcode("mov","a,_bp");
5365             emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
5366             aopPut(AOP(IC_RESULT(ic)),"a",0);       
5367         } else {
5368             /* we can just move _bp */
5369             aopPut(AOP(IC_RESULT(ic)),"_bp",0);
5370         }
5371         /* fill the result with zero */
5372         size = AOP_SIZE(IC_RESULT(ic)) - 1;
5373         
5374         
5375         if (options.stack10bit && size < (FPTRSIZE - 1))
5376         {
5377             fprintf(stderr, 
5378                     "*** warning: pointer to stack var truncated.\n");
5379         }
5380         
5381         offset = 1;
5382         while (size--)
5383         {
5384             /* Yuck! */
5385             if (options.stack10bit && offset == 2)
5386             {
5387                 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
5388             }
5389             else
5390             {
5391                 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
5392             }
5393         }
5394
5395         goto release;
5396     }
5397
5398     /* object not on stack then we need the name */
5399     size = AOP_SIZE(IC_RESULT(ic));
5400     offset = 0;
5401
5402     while (size--) {
5403         char s[SDCC_NAME_MAX];
5404         if (offset) 
5405             sprintf(s,"#(%s >> %d)",
5406                     sym->rname,
5407                     offset*8);
5408         else
5409             sprintf(s,"#%s",sym->rname);
5410         aopPut(AOP(IC_RESULT(ic)),s,offset++);
5411     }
5412
5413 release:
5414     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
5415
5416 }
5417
5418 /*-----------------------------------------------------------------*/
5419 /* genFarFarAssign - assignment when both are in far space         */
5420 /*-----------------------------------------------------------------*/
5421 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
5422 {
5423     int size = AOP_SIZE(right);
5424     int offset = 0;
5425     char *l ;
5426     /* first push the right side on to the stack */
5427     while (size--) {
5428         l = aopGet(AOP(right),offset++,FALSE,FALSE);
5429         MOVA(l);
5430         emitcode ("push","acc");
5431     }
5432     
5433     freeAsmop(right,NULL,ic,FALSE);
5434     /* now assign DPTR to result */
5435     aopOp(result,ic,FALSE);
5436     size = AOP_SIZE(result);
5437     while (size--) {
5438         emitcode ("pop","acc");
5439         aopPut(AOP(result),"a",--offset);
5440     }
5441     freeAsmop(result,NULL,ic,FALSE);
5442         
5443 }
5444
5445 /*-----------------------------------------------------------------*/
5446 /* genAssign - generate code for assignment                        */
5447 /*-----------------------------------------------------------------*/
5448 static void genAssign (iCode *ic)
5449 {
5450     operand *result, *right;
5451     int size, offset ;
5452         unsigned long lit = 0L;
5453
5454     result = IC_RESULT(ic);
5455     right  = IC_RIGHT(ic) ;
5456
5457     /* if they are the same */
5458     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
5459         return ;
5460
5461     aopOp(right,ic,FALSE);
5462     
5463     /* special case both in far space */
5464     if ((AOP_TYPE(right) == AOP_DPTR ||
5465          AOP_TYPE(right) == AOP_DPTR2) &&
5466         IS_TRUE_SYMOP(result)       &&
5467         isOperandInFarSpace(result)) {
5468         
5469         genFarFarAssign (result,right,ic);
5470         return ;
5471     }
5472
5473     aopOp(result,ic,TRUE);
5474
5475     /* if they are the same registers */
5476     if (sameRegs(AOP(right),AOP(result)))
5477         goto release;
5478
5479     /* if the result is a bit */
5480     if (AOP_TYPE(result) == AOP_CRY) {
5481
5482         /* if the right size is a literal then
5483         we know what the value is */
5484         if (AOP_TYPE(right) == AOP_LIT) {
5485             if (((int) operandLitValue(right))) 
5486                 aopPut(AOP(result),one,0);
5487             else
5488                 aopPut(AOP(result),zero,0);
5489             goto release;
5490         }
5491
5492         /* the right is also a bit variable */
5493         if (AOP_TYPE(right) == AOP_CRY) {
5494             emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5495             aopPut(AOP(result),"c",0);
5496             goto release ;
5497         }
5498
5499         /* we need to or */
5500         toBoolean(right);
5501         aopPut(AOP(result),"a",0);
5502         goto release ;
5503     }
5504
5505     /* bit variables done */
5506     /* general case */
5507     size = AOP_SIZE(result);
5508     offset = 0 ;
5509     if(AOP_TYPE(right) == AOP_LIT)
5510         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5511     if((size > 1) &&
5512        (AOP_TYPE(result) != AOP_REG) &&
5513        (AOP_TYPE(right) == AOP_LIT) &&
5514        !IS_FLOAT(operandType(right)) &&
5515        (lit < 256L)){
5516         emitcode("clr","a");
5517         while (size--) {
5518             if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
5519                 aopPut(AOP(result),"a",size);
5520             else
5521                 aopPut(AOP(result),
5522                        aopGet(AOP(right),size,FALSE,FALSE),
5523                        size);
5524         }
5525     } else {
5526         while (size--) {
5527             aopPut(AOP(result),
5528                    aopGet(AOP(right),offset,FALSE,FALSE),
5529                    offset);
5530             offset++;
5531         }
5532     }
5533     
5534 release:
5535     freeAsmop (right,NULL,ic,FALSE);
5536     freeAsmop (result,NULL,ic,TRUE);
5537 }   
5538
5539 /*-----------------------------------------------------------------*/
5540 /* genJumpTab - genrates code for jump table                       */
5541 /*-----------------------------------------------------------------*/
5542 static void genJumpTab (iCode *ic)
5543 {
5544     symbol *jtab;
5545     char *l;
5546
5547     aopOp(IC_JTCOND(ic),ic,FALSE);
5548     /* get the condition into accumulator */
5549     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
5550     MOVA(l);
5551     /* multiply by three */
5552     emitcode("add","a,acc");
5553     emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
5554     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
5555
5556     jtab = newiTempLabel(NULL);
5557     emitcode("mov","dptr,#%05d$",jtab->key+100);
5558     emitcode("jmp","@a+dptr");
5559     emitcode("","%05d$:",jtab->key+100);
5560     /* now generate the jump labels */
5561     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
5562          jtab = setNextItem(IC_JTLABELS(ic)))
5563         emitcode("ljmp","%05d$",jtab->key+100);
5564
5565 }
5566
5567 /*-----------------------------------------------------------------*/
5568 /* genCast - gen code for casting                                  */
5569 /*-----------------------------------------------------------------*/
5570 static void genCast (iCode *ic)
5571 {
5572     operand *result = IC_RESULT(ic);
5573     link *ctype = operandType(IC_LEFT(ic));
5574     link *rtype = operandType(IC_RIGHT(ic));
5575     operand *right = IC_RIGHT(ic);
5576     int size, offset ;
5577
5578     /* if they are equivalent then do nothing */
5579     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
5580         return ;
5581
5582     aopOp(right,ic,FALSE) ;
5583     aopOp(result,ic,FALSE);
5584
5585     /* if the result is a bit */
5586     if (AOP_TYPE(result) == AOP_CRY) {
5587         /* if the right size is a literal then
5588         we know what the value is */
5589         if (AOP_TYPE(right) == AOP_LIT) {
5590             if (((int) operandLitValue(right))) 
5591                 aopPut(AOP(result),one,0);
5592             else
5593                 aopPut(AOP(result),zero,0);
5594
5595             goto release;
5596         }
5597
5598         /* the right is also a bit variable */
5599         if (AOP_TYPE(right) == AOP_CRY) {
5600             emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5601             aopPut(AOP(result),"c",0);
5602             goto release ;
5603         }
5604
5605         /* we need to or */
5606         toBoolean(right);
5607         aopPut(AOP(result),"a",0);
5608         goto release ;
5609     }
5610
5611     /* if they are the same size : or less */
5612     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
5613
5614         /* if they are in the same place */
5615         if (sameRegs(AOP(right),AOP(result)))
5616             goto release;
5617
5618         /* if they in different places then copy */
5619         size = AOP_SIZE(result);
5620         offset = 0 ;
5621         while (size--) {
5622             aopPut(AOP(result),
5623                    aopGet(AOP(right),offset,FALSE,FALSE),
5624                    offset);
5625             offset++;
5626         }
5627         goto release;
5628     }
5629
5630
5631     /* if the result is of type pointer */
5632     if (IS_PTR(ctype)) {
5633
5634         int p_type;
5635         link *type = operandType(right);
5636         link *etype = getSpec(type);
5637
5638         /* pointer to generic pointer */
5639         if (IS_GENPTR(ctype)) {
5640             char *l = zero;
5641             
5642             if (IS_PTR(type)) 
5643                 p_type = DCL_TYPE(type);
5644             else {
5645                 /* we have to go by the storage class */
5646                 p_type = PTR_TYPE(SPEC_OCLS(etype));
5647             }
5648                 
5649             /* the first two bytes are known */
5650             size = GPTRSIZE - 1; 
5651             offset = 0 ;
5652             while (size--) {
5653                 aopPut(AOP(result),
5654                        aopGet(AOP(right),offset,FALSE,FALSE),
5655                        offset);
5656                 offset++;
5657             }
5658             /* the last byte depending on type */
5659             switch (p_type) {
5660             case IPOINTER:
5661             case POINTER:
5662                 l = zero;
5663                 break;
5664             case FPOINTER:
5665                 l = one;
5666                 break;
5667             case CPOINTER:
5668                 l = "#0x02";
5669                 break;                          
5670             case PPOINTER:
5671                 l = "#0x03";
5672                 break;
5673                 
5674             default:
5675                 /* this should never happen */
5676                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
5677                        "got unknown pointer type");
5678                 exit(1);
5679             }
5680             aopPut(AOP(result),l, GPTRSIZE - 1);            
5681             goto release ;
5682         }
5683         
5684         /* just copy the pointers */
5685         size = AOP_SIZE(result);
5686         offset = 0 ;
5687         while (size--) {
5688             aopPut(AOP(result),
5689                    aopGet(AOP(right),offset,FALSE,FALSE),
5690                    offset);
5691             offset++;
5692         }
5693         goto release ;
5694     }
5695     
5696     /* so we now know that the size of destination is greater
5697     than the size of the source */
5698     /* we move to result for the size of source */
5699     size = AOP_SIZE(right);
5700     offset = 0 ;
5701     while (size--) {
5702         aopPut(AOP(result),
5703                aopGet(AOP(right),offset,FALSE,FALSE),
5704                offset);
5705         offset++;
5706     }
5707
5708     /* now depending on the sign of the source && destination */
5709     size = AOP_SIZE(result) - AOP_SIZE(right);
5710     /* if unsigned or not an integral type */
5711     if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
5712         while (size--)
5713             aopPut(AOP(result),zero,offset++);
5714     } else {
5715         /* we need to extend the sign :{ */
5716         char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
5717                          FALSE,FALSE);
5718         MOVA(l);
5719         emitcode("rlc","a");
5720         emitcode("subb","a,acc");
5721         while (size--)
5722             aopPut(AOP(result),"a",offset++);   
5723     }
5724
5725     /* we are done hurray !!!! */
5726
5727 release:
5728     freeAsmop(right,NULL,ic,TRUE);
5729     freeAsmop(result,NULL,ic,TRUE);
5730
5731 }
5732
5733 /*-----------------------------------------------------------------*/
5734 /* genDjnz - generate decrement & jump if not zero instrucion      */
5735 /*-----------------------------------------------------------------*/
5736 static int genDjnz (iCode *ic, iCode *ifx)
5737 {
5738     symbol *lbl, *lbl1;
5739     if (!ifx)
5740         return 0;
5741     
5742     /* if the if condition has a false label
5743        then we cannot save */
5744     if (IC_FALSE(ifx))
5745         return 0;
5746
5747     /* if the minus is not of the form 
5748        a = a - 1 */
5749     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
5750         !IS_OP_LITERAL(IC_RIGHT(ic)))
5751         return 0;
5752
5753     if (operandLitValue(IC_RIGHT(ic)) != 1)
5754         return 0;
5755
5756     /* if the size of this greater than one then no
5757        saving */
5758     if (getSize(operandType(IC_RESULT(ic))) > 1)
5759         return 0;
5760
5761     /* otherwise we can save BIG */
5762     lbl = newiTempLabel(NULL);
5763     lbl1= newiTempLabel(NULL);
5764
5765     aopOp(IC_RESULT(ic),ic,FALSE);
5766     
5767     if (IS_AOP_PREG(IC_RESULT(ic))) {
5768         emitcode("dec","%s",
5769                  aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
5770         emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
5771         emitcode("jnz","%05d$",lbl->key+100);
5772     } else {    
5773         emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
5774                   lbl->key+100);
5775     }
5776     emitcode ("sjmp","%05d$",lbl1->key+100);
5777     emitcode ("","%05d$:",lbl->key+100);
5778     emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
5779     emitcode ("","%05d$:",lbl1->key+100);
5780     
5781     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
5782     ifx->generated = 1;
5783     return 1;
5784 }
5785
5786 /*-----------------------------------------------------------------*/
5787 /* genReceive - generate code for a receive iCode                  */
5788 /*-----------------------------------------------------------------*/
5789 static void genReceive (iCode *ic)
5790 {    
5791     if (isOperandInFarSpace(IC_RESULT(ic)) && 
5792         ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
5793           IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
5794
5795         int size = getSize(operandType(IC_RESULT(ic)));
5796         int offset =  fReturnSize - size;
5797         while (size--) {
5798             emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
5799                                     fReturn[fReturnSize - offset - 1] : "acc"));
5800             offset++;
5801         }
5802         aopOp(IC_RESULT(ic),ic,FALSE);  
5803         size = AOP_SIZE(IC_RESULT(ic));
5804         offset = 0;
5805         while (size--) {
5806             emitcode ("pop","acc");
5807             aopPut (AOP(IC_RESULT(ic)),"a",offset++);
5808         }
5809         
5810     } else {
5811         _G.accInUse++;
5812         aopOp(IC_RESULT(ic),ic,FALSE);  
5813         _G.accInUse--;
5814         assignResultValue(IC_RESULT(ic));       
5815     }
5816
5817     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
5818 }
5819
5820 /*-----------------------------------------------------------------*/
5821 /* gen51Code - generate code for 8051 based controllers            */
5822 /*-----------------------------------------------------------------*/
5823 void gen51Code (iCode *lic)
5824 {
5825     iCode *ic;
5826     int cln = 0;
5827
5828     lineHead = lineCurr = NULL;
5829
5830     /* print the allocation information */
5831     if (allocInfo)
5832         printAllocInfo( currFunc, codeOutFile);
5833     /* if debug information required */
5834 /*     if (options.debug && currFunc) { */
5835     if (currFunc) {
5836         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
5837         _G.debugLine = 1;
5838         if (IS_STATIC(currFunc->etype))
5839             emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name); 
5840         else
5841             emitcode("","G$%s$0$0 ==.",currFunc->name);
5842         _G.debugLine = 0;
5843     }
5844     /* stack pointer name */
5845     if (options.useXstack)
5846         spname = "_spx";
5847     else
5848         spname = "sp";
5849     
5850  
5851     for (ic = lic ; ic ; ic = ic->next ) {
5852         
5853         if ( cln != ic->lineno ) {
5854             if ( options.debug ) {
5855                 _G.debugLine = 1;
5856                 emitcode("","C$%s$%d$%d$%d ==.",
5857                          ic->filename,ic->lineno,
5858                          ic->level,ic->block);
5859                 _G.debugLine = 0;
5860             }
5861             emitcode(";","%s %d",ic->filename,ic->lineno);
5862             cln = ic->lineno ;
5863         }
5864         /* if the result is marked as
5865            spilt and rematerializable or code for
5866            this has already been generated then
5867            do nothing */
5868         if (resultRemat(ic) || ic->generated ) 
5869             continue ;
5870         
5871         /* depending on the operation */
5872         switch (ic->op) {
5873         case '!' :
5874             genNot(ic);
5875             break;
5876             
5877         case '~' :
5878             genCpl(ic);
5879             break;
5880             
5881         case UNARYMINUS:
5882             genUminus (ic);
5883             break;
5884             
5885         case IPUSH:
5886             genIpush (ic);
5887             break;
5888             
5889         case IPOP:
5890             /* IPOP happens only when trying to restore a 
5891                spilt live range, if there is an ifx statement
5892                following this pop then the if statement might
5893                be using some of the registers being popped which
5894                would destory the contents of the register so
5895                we need to check for this condition and handle it */
5896             if (ic->next            && 
5897                 ic->next->op == IFX &&
5898                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
5899                 genIfx (ic->next,ic);
5900             else
5901                 genIpop (ic);
5902             break; 
5903             
5904         case CALL:
5905             genCall (ic);
5906             break;
5907             
5908         case PCALL:
5909             genPcall (ic);
5910             break;
5911             
5912         case FUNCTION:
5913             genFunction (ic);
5914             break;
5915             
5916         case ENDFUNCTION:
5917             genEndFunction (ic);
5918             break;
5919             
5920         case RETURN:
5921             genRet (ic);
5922             break;
5923             
5924         case LABEL:
5925             genLabel (ic);
5926             break;
5927             
5928         case GOTO:
5929             genGoto (ic);
5930             break;
5931             
5932         case '+' :
5933             genPlus (ic) ;
5934             break;
5935             
5936         case '-' :
5937             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
5938                 genMinus (ic);
5939             break;
5940             
5941         case '*' :
5942             genMult (ic);
5943             break;
5944             
5945         case '/' :
5946             genDiv (ic) ;
5947             break;
5948             
5949         case '%' :
5950             genMod (ic);
5951             break;
5952             
5953         case '>' :
5954             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
5955             break;
5956             
5957         case '<' :
5958             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
5959             break;
5960             
5961         case LE_OP:
5962             genCmpLe (ic,ifxForOp(IC_RESULT(ic),ic));
5963             break
5964
5965         case GE_OP:
5966             genCmpGe (ic,ifxForOp(IC_RESULT(ic),ic));
5967             break;
5968
5969         case NE_OP:
5970             genCmpNe (ic,ifxForOp(IC_RESULT(ic),ic));       
5971             break;      
5972             
5973         case EQ_OP:
5974             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
5975             break;          
5976             
5977         case AND_OP:
5978             genAndOp (ic);
5979             break;
5980             
5981         case OR_OP:
5982             genOrOp (ic);
5983             break;
5984             
5985         case '^' :
5986             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
5987             break;
5988             
5989         case '|' :
5990                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
5991             break;
5992             
5993         case BITWISEAND:
5994             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
5995             break;
5996             
5997         case INLINEASM:
5998             genInline (ic);
5999             break;
6000             
6001         case RRC:
6002             genRRC (ic);
6003             break;
6004             
6005         case RLC:
6006             genRLC (ic);
6007             break;
6008             
6009         case GETHBIT:
6010             genGetHbit (ic);
6011             break;
6012             
6013         case LEFT_OP:
6014             genLeftShift (ic);
6015             break;
6016             
6017         case RIGHT_OP:
6018             genRightShift (ic);
6019             break;
6020             
6021         case GET_VALUE_AT_ADDRESS:
6022             genPointerGet(ic);
6023             break;
6024             
6025         case '=' :
6026             if (POINTER_SET(ic))
6027                 genPointerSet(ic);
6028             else
6029                 genAssign(ic);
6030             break;
6031             
6032         case IFX:
6033             genIfx (ic,NULL);
6034             break;
6035             
6036         case ADDRESS_OF:
6037             genAddrOf (ic);
6038             break;
6039             
6040         case JUMPTABLE:
6041             genJumpTab (ic);
6042             break;
6043             
6044         case CAST:
6045             genCast (ic);
6046             break;
6047             
6048         case RECEIVE:
6049             genReceive(ic);
6050             break;
6051             
6052         case SEND:
6053             addSet(&_G.sendSet,ic);
6054             break;
6055
6056         default :
6057             ic = ic;
6058             /*      piCode(ic,stdout); */
6059             
6060         }
6061     }
6062     
6063
6064     /* now we are ready to call the 
6065        peep hole optimizer */
6066     if (!options.nopeep)
6067         peepHole (&lineHead);
6068
6069     /* now do the actual printing */
6070     printLine (lineHead,codeOutFile);    
6071     return;
6072 }