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