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