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