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