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