]> git.gag.com Git - fw/sdcc/blob - src/avr/gen.c
191a13d9ae0ed35dbca880a3600251ce7a67309a
[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
3748   etype = getSpec (operandType (result));
3749
3750   /* read the first byte  */
3751   switch (ptype)
3752     {
3753
3754     case POINTER:
3755     case IPOINTER:
3756     case PPOINTER:
3757     case FPOINTER:
3758       emitcode ("ld", "r0,%s+", rname);
3759       break;
3760
3761     case CPOINTER:
3762       emitcode ("ldm", "r0,%s+", rname);
3763       break;
3764
3765     case GPOINTER:
3766       emitcode ("call", "__gptrget_pi");
3767       break;
3768     }
3769
3770   /* if we have bitdisplacement then it fits   */
3771   /* into this byte completely or if length is */
3772   /* less than a byte                          */
3773   if ((shCnt = SPEC_BSTR (etype)) || (SPEC_BLEN (etype) <= 8))
3774     {
3775
3776       /* shift right r0 */
3777       R0Rsh (shCnt);
3778       emitcode ("andi", "r0,0x%02x",
3779                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
3780
3781       aopPut (AOP (result), "r0", offset);
3782       return;
3783     }
3784
3785   /* bit field did not fit in a byte  */
3786   rlen = SPEC_BLEN (etype) - 8;
3787   aopPut (AOP (result), "a", offset++);
3788
3789   while (1)
3790     {
3791
3792       switch (ptype)
3793         {
3794         case POINTER:
3795         case IPOINTER:
3796         case PPOINTER:
3797         case FPOINTER:
3798           emitcode ("ld", "r0,%s+", rname);
3799           break;
3800
3801         case CPOINTER:
3802           emitcode ("ldm", "r0,%s+", rname);
3803           break;
3804
3805         case GPOINTER:
3806           emitcode ("lcall", "__gptrget_pi");
3807           break;
3808         }
3809
3810       rlen -= 8;
3811       /* if we are done */
3812       if (rlen <= 0)
3813         break;
3814
3815       aopPut (AOP (result), "r0", offset++);
3816
3817     }
3818
3819   if (rlen)
3820     {
3821       emitcode ("andi", "r0,#0x%02x", ((unsigned char) -1) >> (-rlen));
3822       aopPut (AOP (result), "r0", offset);
3823     }
3824
3825   return;
3826 }
3827
3828
3829 /*-----------------------------------------------------------------*/
3830 /* genDataPointerGet - generates code when ptr offset is known     */
3831 /*-----------------------------------------------------------------*/
3832 static void
3833 genDataPointerGet (operand * left,
3834                    operand * result,
3835                    iCode * ic)
3836 {
3837   char *l;
3838   char buffer[256];
3839   int size, offset = 0;
3840   aopOp (result, ic, TRUE);
3841
3842   /* get the string representation of the name */
3843   l = aopGet (AOP (left), 0);
3844   size = AOP_SIZE (result);
3845   while (size--)
3846     {
3847       if (offset)
3848         sprintf (buffer, "(%s + %d)", l + 1, offset);
3849       else
3850         sprintf (buffer, "%s", l + 1);
3851       emitcode ("lds", "%s,%s", aopGet (AOP (result), offset++), buffer);
3852     }
3853
3854   freeAsmop (left, NULL, ic, TRUE);
3855   freeAsmop (result, NULL, ic, TRUE);
3856 }
3857
3858 /*-----------------------------------------------------------------*/
3859 /* genNearPointerGet - emitcode for near pointer fetch             */
3860 /*-----------------------------------------------------------------*/
3861 static void
3862 genNearPointerGet (operand * left,
3863                    operand * result,
3864                    iCode * ic)
3865 {
3866   asmop *aop = NULL;
3867   regs *preg = NULL;
3868   char *rname;
3869   sym_link *rtype, *retype;
3870   sym_link *ltype = operandType (left);
3871   char buffer[80];
3872
3873   rtype = operandType (result);
3874   retype = getSpec (rtype);
3875
3876   aopOp (left, ic, FALSE);
3877
3878   /* if left is rematerialisable and
3879      result is not bit variable type and
3880      the left is pointer to data space i.e
3881      lower 128 bytes of space */
3882   if (AOP_TYPE (left) == AOP_IMMD &&
3883       !IS_BITVAR (retype) &&
3884       DCL_TYPE (ltype) == POINTER)
3885     {
3886       genDataPointerGet (left, result, ic);
3887       return;
3888     }
3889
3890   /* if the value is already in a pointer register
3891      then don't need anything more */
3892   if (!AOP_INPREG (AOP (left)))
3893     {
3894       /* otherwise get a free pointer register */
3895       aop = newAsmop (0);
3896       preg = getFreePtr (ic, &aop, FALSE, 0);
3897       emitcode ("mov", "%s,%s",
3898                 preg->name,
3899                 aopGet (AOP (left), 0));
3900       rname = preg->name;
3901     }
3902   else
3903     rname = aopGet (AOP (left), 0);
3904
3905   freeAsmop (left, NULL, ic, TRUE);
3906   aopOp (result, ic, FALSE);
3907
3908   /* if bitfield then unpack the bits */
3909   if (IS_BITVAR (retype))
3910     genUnpackBits (result, rname, POINTER);
3911   else
3912     {
3913       /* we have can just get the values */
3914       int size = AOP_SIZE (result);
3915       int offset = 0;
3916
3917       while (size--)
3918         {
3919           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
3920             {
3921
3922               emitcode ("mov", "a,@%s", rname);
3923               aopPut (AOP (result), "a", offset);
3924             }
3925           else
3926             {
3927               sprintf (buffer, "@%s", rname);
3928               aopPut (AOP (result), buffer, offset);
3929             }
3930           offset++;
3931           if (size)
3932             emitcode ("inc", "%s", rname);
3933         }
3934     }
3935
3936   /* now some housekeeping stuff */
3937   if (aop)
3938     {
3939       /* we had to allocate for this iCode */
3940       freeAsmop (NULL, aop, ic, TRUE);
3941     }
3942   else
3943     {
3944       /* we did not allocate which means left
3945          already in a pointer register, then
3946          if size > 0 && this could be used again
3947          we have to point it back to where it
3948          belongs */
3949       if (AOP_SIZE (result) > 1 &&
3950           !OP_SYMBOL (left)->remat &&
3951           (OP_SYMBOL (left)->liveTo > ic->seq ||
3952            ic->depth))
3953         {
3954           int size = AOP_SIZE (result) - 1;
3955           while (size--)
3956             emitcode ("dec", "%s", rname);
3957         }
3958     }
3959
3960   /* done */
3961   freeAsmop (result, NULL, ic, TRUE);
3962
3963 }
3964
3965 /*-----------------------------------------------------------------*/
3966 /* genPagedPointerGet - emitcode for paged pointer fetch           */
3967 /*-----------------------------------------------------------------*/
3968 static void
3969 genPagedPointerGet (operand * left,
3970                     operand * result,
3971                     iCode * ic)
3972 {
3973   asmop *aop = NULL;
3974   regs *preg = NULL;
3975   char *rname;
3976   sym_link *rtype, *retype;
3977
3978   rtype = operandType (result);
3979   retype = getSpec (rtype);
3980
3981   aopOp (left, ic, FALSE);
3982
3983   /* if the value is already in a pointer register
3984      then don't need anything more */
3985   if (!AOP_INPREG (AOP (left)))
3986     {
3987       /* otherwise get a free pointer register */
3988       aop = newAsmop (0);
3989       preg = getFreePtr (ic, &aop, FALSE, 0);
3990       emitcode ("mov", "%s,%s",
3991                 preg->name,
3992                 aopGet (AOP (left), 0));
3993       rname = preg->name;
3994     }
3995   else
3996     rname = aopGet (AOP (left), 0);
3997
3998   freeAsmop (left, NULL, ic, TRUE);
3999   aopOp (result, ic, FALSE);
4000
4001   /* if bitfield then unpack the bits */
4002   if (IS_BITVAR (retype))
4003     genUnpackBits (result, rname, PPOINTER);
4004   else
4005     {
4006       /* we have can just get the values */
4007       int size = AOP_SIZE (result);
4008       int offset = 0;
4009
4010       while (size--)
4011         {
4012
4013           emitcode ("movx", "a,@%s", rname);
4014           aopPut (AOP (result), "a", offset);
4015
4016           offset++;
4017
4018           if (size)
4019             emitcode ("inc", "%s", rname);
4020         }
4021     }
4022
4023   /* now some housekeeping stuff */
4024   if (aop)
4025     {
4026       /* we had to allocate for this iCode */
4027       freeAsmop (NULL, aop, ic, TRUE);
4028     }
4029   else
4030     {
4031       /* we did not allocate which means left
4032          already in a pointer register, then
4033          if size > 0 && this could be used again
4034          we have to point it back to where it
4035          belongs */
4036       if (AOP_SIZE (result) > 1 &&
4037           !OP_SYMBOL (left)->remat &&
4038           (OP_SYMBOL (left)->liveTo > ic->seq ||
4039            ic->depth))
4040         {
4041           int size = AOP_SIZE (result) - 1;
4042           while (size--)
4043             emitcode ("dec", "%s", rname);
4044         }
4045     }
4046
4047   /* done */
4048   freeAsmop (result, NULL, ic, TRUE);
4049
4050
4051 }
4052
4053 /*-----------------------------------------------------------------*/
4054 /* genFarPointerGet - gget value from far space                    */
4055 /*-----------------------------------------------------------------*/
4056 static void
4057 genFarPointerGet (operand * left,
4058                   operand * result, iCode * ic)
4059 {
4060   int size, offset;
4061   sym_link *retype = getSpec (operandType (result));
4062
4063   aopOp (left, ic, FALSE);
4064
4065   /* if the operand is already in dptr
4066      then we do nothing else we move the value to dptr */
4067   if (AOP_TYPE (left) != AOP_STR)
4068     {
4069       /* if this is remateriazable */
4070       if (AOP_TYPE (left) == AOP_IMMD)
4071         emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0));
4072       else
4073         {                       /* we need to get it byte by byte */
4074           emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0));
4075           emitcode ("mov", "dph,%s", aopGet (AOP (left), 1));
4076           if (options.model == MODEL_FLAT24)
4077             {
4078               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2));
4079             }
4080         }
4081     }
4082   /* so dptr know contains the address */
4083   freeAsmop (left, NULL, ic, TRUE);
4084   aopOp (result, ic, FALSE);
4085
4086   /* if bit then unpack */
4087   if (IS_BITVAR (retype))
4088     genUnpackBits (result, "dptr", FPOINTER);
4089   else
4090     {
4091       size = AOP_SIZE (result);
4092       offset = 0;
4093
4094       while (size--)
4095         {
4096           emitcode ("movx", "a,@dptr");
4097           aopPut (AOP (result), "a", offset++);
4098           if (size)
4099             emitcode ("inc", "dptr");
4100         }
4101     }
4102
4103   freeAsmop (result, NULL, ic, TRUE);
4104 }
4105
4106 /*-----------------------------------------------------------------*/
4107 /* emitcodePointerGet - gget value from code space                  */
4108 /*-----------------------------------------------------------------*/
4109 static void
4110 emitcodePointerGet (operand * left,
4111                     operand * result, iCode * ic)
4112 {
4113   int size, offset;
4114   sym_link *retype = getSpec (operandType (result));
4115
4116   aopOp (left, ic, FALSE);
4117
4118   /* if the operand is already in dptr
4119      then we do nothing else we move the value to dptr */
4120   if (AOP_TYPE (left) != AOP_STR)
4121     {
4122       /* if this is remateriazable */
4123       if (AOP_TYPE (left) == AOP_IMMD)
4124         emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0));
4125       else
4126         {                       /* we need to get it byte by byte */
4127           emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0));
4128           emitcode ("mov", "dph,%s", aopGet (AOP (left), 1));
4129           if (options.model == MODEL_FLAT24)
4130             {
4131               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2));
4132             }
4133         }
4134     }
4135   /* so dptr know contains the address */
4136   freeAsmop (left, NULL, ic, TRUE);
4137   aopOp (result, ic, FALSE);
4138
4139   /* if bit then unpack */
4140   if (IS_BITVAR (retype))
4141     genUnpackBits (result, "dptr", CPOINTER);
4142   else
4143     {
4144       size = AOP_SIZE (result);
4145       offset = 0;
4146
4147       while (size--)
4148         {
4149           emitcode ("clr", "a");
4150           emitcode ("movc", "a,@a+dptr");
4151           aopPut (AOP (result), "a", offset++);
4152           if (size)
4153             emitcode ("inc", "dptr");
4154         }
4155     }
4156
4157   freeAsmop (result, NULL, ic, TRUE);
4158 }
4159
4160 /*-----------------------------------------------------------------*/
4161 /* genGenPointerGet - gget value from generic pointer space        */
4162 /*-----------------------------------------------------------------*/
4163 static void
4164 genGenPointerGet (operand * left,
4165                   operand * result, iCode * ic)
4166 {
4167   int size, offset;
4168   sym_link *retype = getSpec (operandType (result));
4169
4170   aopOp (left, ic, FALSE);
4171
4172   /* if the operand is already in dptr
4173      then we do nothing else we move the value to dptr */
4174   if (AOP_TYPE (left) != AOP_STR)
4175     {
4176       /* if this is remateriazable */
4177       if (AOP_TYPE (left) == AOP_IMMD)
4178         {
4179           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0));
4180           emitcode ("mov", "b,#%d", pointerCode (retype));
4181         }
4182       else
4183         {                       /* we need to get it byte by byte */
4184           emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0));
4185           emitcode ("mov", "dph,%s", aopGet (AOP (left), 1));
4186           if (options.model == MODEL_FLAT24)
4187             {
4188               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2));
4189               emitcode ("mov", "b,%s", aopGet (AOP (left), 3));
4190             }
4191           else
4192             {
4193               emitcode ("mov", "b,%s", aopGet (AOP (left), 2));
4194             }
4195         }
4196     }
4197   /* so dptr know contains the address */
4198   freeAsmop (left, NULL, ic, TRUE);
4199   aopOp (result, ic, FALSE);
4200
4201   /* if bit then unpack */
4202   if (IS_BITVAR (retype))
4203     genUnpackBits (result, "dptr", GPOINTER);
4204   else
4205     {
4206       size = AOP_SIZE (result);
4207       offset = 0;
4208
4209       while (size--)
4210         {
4211           emitcode ("lcall", "__gptrget");
4212           aopPut (AOP (result), "a", offset++);
4213           if (size)
4214             emitcode ("inc", "dptr");
4215         }
4216     }
4217
4218   freeAsmop (result, NULL, ic, TRUE);
4219 }
4220
4221 /*-----------------------------------------------------------------*/
4222 /* genPointerGet - generate code for pointer get                   */
4223 /*-----------------------------------------------------------------*/
4224 static void
4225 genPointerGet (iCode * ic)
4226 {
4227   operand *left, *result;
4228   sym_link *type, *etype;
4229   int p_type;
4230
4231   left = IC_LEFT (ic);
4232   result = IC_RESULT (ic);
4233
4234   /* depending on the type of pointer we need to
4235      move it to the correct pointer register */
4236   type = operandType (left);
4237   etype = getSpec (type);
4238   /* if left is of type of pointer then it is simple */
4239   if (IS_PTR (type) && !IS_FUNC (type->next))
4240     p_type = DCL_TYPE (type);
4241   else
4242     {
4243       /* we have to go by the storage class */
4244       p_type = PTR_TYPE (SPEC_OCLS (etype));
4245
4246       /*  if (SPEC_OCLS(etype)->codesp ) { */
4247       /*      p_type = CPOINTER ;  */
4248       /*  } */
4249       /*  else */
4250       /*      if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
4251       /*    p_type = FPOINTER ; */
4252       /*      else */
4253       /*    if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
4254       /*        p_type = PPOINTER; */
4255       /*    else */
4256       /*        if (SPEC_OCLS(etype) == idata ) */
4257       /*      p_type = IPOINTER; */
4258       /*        else */
4259       /*      p_type = POINTER ; */
4260     }
4261
4262   /* now that we have the pointer type we assign
4263      the pointer values */
4264   switch (p_type)
4265     {
4266
4267     case POINTER:
4268     case IPOINTER:
4269       genNearPointerGet (left, result, ic);
4270       break;
4271
4272     case PPOINTER:
4273       genPagedPointerGet (left, result, ic);
4274       break;
4275
4276     case FPOINTER:
4277       genFarPointerGet (left, result, ic);
4278       break;
4279
4280     case CPOINTER:
4281       emitcodePointerGet (left, result, ic);
4282       break;
4283
4284     case GPOINTER:
4285       genGenPointerGet (left, result, ic);
4286       break;
4287     }
4288
4289 }
4290
4291 /*-----------------------------------------------------------------*/
4292 /* genPackBits - generates code for packed bit storage             */
4293 /*-----------------------------------------------------------------*/
4294 static void
4295 genPackBits (sym_link * etype,
4296              operand * right,
4297              char *rname, int p_type)
4298 {
4299   int shCount = 0;
4300   int offset = 0;
4301   int rLen = 0;
4302   int blen, bstr;
4303   char *l;
4304
4305   blen = SPEC_BLEN (etype);
4306   bstr = SPEC_BSTR (etype);
4307
4308   l = aopGet (AOP (right), offset++);
4309   MOVA (l);
4310
4311   /* if the bit lenth is less than or    */
4312   /* it exactly fits a byte then         */
4313   if (SPEC_BLEN (etype) <= 8)
4314     {
4315       shCount = SPEC_BSTR (etype);
4316
4317       /* shift left acc */
4318       //    AccLsh(shCount);
4319
4320       if (SPEC_BLEN (etype) < 8)
4321         {                       /* if smaller than a byte */
4322
4323
4324           switch (p_type)
4325             {
4326             case POINTER:
4327               emitcode ("mov", "b,a");
4328               emitcode ("mov", "a,@%s", rname);
4329               break;
4330
4331             case FPOINTER:
4332               emitcode ("mov", "b,a");
4333               emitcode ("movx", "a,@dptr");
4334               break;
4335
4336             case GPOINTER:
4337               emitcode ("push", "b");
4338               emitcode ("push", "acc");
4339               emitcode ("lcall", "__gptrget");
4340               emitcode ("pop", "b");
4341               break;
4342             }
4343
4344           emitcode ("anl", "a,#0x%02x", (unsigned char)
4345                     ((unsigned char) (0xFF << (blen + bstr)) |
4346                      (unsigned char) (0xFF >> (8 - bstr))));
4347           emitcode ("orl", "a,b");
4348           if (p_type == GPOINTER)
4349             emitcode ("pop", "b");
4350         }
4351     }
4352
4353   switch (p_type)
4354     {
4355     case POINTER:
4356       emitcode ("mov", "@%s,a", rname);
4357       break;
4358
4359     case FPOINTER:
4360       emitcode ("movx", "@dptr,a");
4361       break;
4362
4363     case GPOINTER:
4364       emitcode ("lcall", "__gptrput");
4365       break;
4366     }
4367
4368   /* if we r done */
4369   if (SPEC_BLEN (etype) <= 8)
4370     return;
4371
4372   emitcode ("inc", "%s", rname);
4373   rLen = SPEC_BLEN (etype);
4374
4375   /* now generate for lengths greater than one byte */
4376   while (1)
4377     {
4378
4379       l = aopGet (AOP (right), offset++);
4380
4381       rLen -= 8;
4382       if (rLen <= 0)
4383         break;
4384
4385       switch (p_type)
4386         {
4387         case POINTER:
4388           if (*l == '@')
4389             {
4390               MOVA (l);
4391               emitcode ("mov", "@%s,a", rname);
4392             }
4393           else
4394             emitcode ("mov", "@%s,%s", rname, l);
4395           break;
4396
4397         case FPOINTER:
4398           MOVA (l);
4399           emitcode ("movx", "@dptr,a");
4400           break;
4401
4402         case GPOINTER:
4403           MOVA (l);
4404           emitcode ("lcall", "__gptrput");
4405           break;
4406         }
4407       emitcode ("inc", "%s", rname);
4408     }
4409
4410   MOVA (l);
4411
4412   /* last last was not complete */
4413   if (rLen)
4414     {
4415       /* save the byte & read byte */
4416       switch (p_type)
4417         {
4418         case POINTER:
4419           emitcode ("mov", "b,a");
4420           emitcode ("mov", "a,@%s", rname);
4421           break;
4422
4423         case FPOINTER:
4424           emitcode ("mov", "b,a");
4425           emitcode ("movx", "a,@dptr");
4426           break;
4427
4428         case GPOINTER:
4429           emitcode ("push", "b");
4430           emitcode ("push", "acc");
4431           emitcode ("lcall", "__gptrget");
4432           emitcode ("pop", "b");
4433           break;
4434         }
4435
4436       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << -rLen));
4437       emitcode ("orl", "a,b");
4438     }
4439
4440   if (p_type == GPOINTER)
4441     emitcode ("pop", "b");
4442
4443   switch (p_type)
4444     {
4445
4446     case POINTER:
4447       emitcode ("mov", "@%s,a", rname);
4448       break;
4449
4450     case FPOINTER:
4451       emitcode ("movx", "@dptr,a");
4452       break;
4453
4454     case GPOINTER:
4455       emitcode ("lcall", "__gptrput");
4456       break;
4457     }
4458 }
4459 /*-----------------------------------------------------------------*/
4460 /* genDataPointerSet - remat pointer to data space                 */
4461 /*-----------------------------------------------------------------*/
4462 static void
4463 genDataPointerSet (operand * right,
4464                    operand * result,
4465                    iCode * ic)
4466 {
4467   int size, offset = 0;
4468   char *l, buffer[256];
4469
4470   aopOp (right, ic, FALSE);
4471
4472   l = aopGet (AOP (result), 0);
4473   size = AOP_SIZE (right);
4474   while (size--)
4475     {
4476       if (offset)
4477         sprintf (buffer, "(%s + %d)", l + 1, offset);
4478       else
4479         sprintf (buffer, "%s", l + 1);
4480       emitcode ("mov", "%s,%s", buffer,
4481                 aopGet (AOP (right), offset++));
4482     }
4483
4484   freeAsmop (right, NULL, ic, TRUE);
4485   freeAsmop (result, NULL, ic, TRUE);
4486 }
4487
4488 /*-----------------------------------------------------------------*/
4489 /* genNearPointerSet - emitcode for near pointer put                */
4490 /*-----------------------------------------------------------------*/
4491 static void
4492 genNearPointerSet (operand * right,
4493                    operand * result,
4494                    iCode * ic)
4495 {
4496   asmop *aop = NULL;
4497   regs *preg = NULL;
4498   char *rname, *l;
4499   sym_link *retype;
4500   sym_link *ptype = operandType (result);
4501
4502   retype = getSpec (operandType (right));
4503
4504   aopOp (result, ic, FALSE);
4505
4506   /* if the result is rematerializable &
4507      in data space & not a bit variable */
4508   if (AOP_TYPE (result) == AOP_IMMD &&
4509       DCL_TYPE (ptype) == POINTER &&
4510       !IS_BITVAR (retype))
4511     {
4512       genDataPointerSet (right, result, ic);
4513       return;
4514     }
4515
4516   /* if the value is already in a pointer register
4517      then don't need anything more */
4518   if (!AOP_INPREG (AOP (result)))
4519     {
4520       /* otherwise get a free pointer register */
4521       aop = newAsmop (0);
4522       preg = getFreePtr (ic, &aop, FALSE, 0);
4523       emitcode ("mov", "%s,%s",
4524                 preg->name,
4525                 aopGet (AOP (result), 0));
4526       rname = preg->name;
4527     }
4528   else
4529     rname = aopGet (AOP (result), 0);
4530
4531   freeAsmop (result, NULL, ic, TRUE);
4532   aopOp (right, ic, FALSE);
4533
4534   /* if bitfield then unpack the bits */
4535   if (IS_BITVAR (retype))
4536     genPackBits (retype, right, rname, POINTER);
4537   else
4538     {
4539       /* we have can just get the values */
4540       int size = AOP_SIZE (right);
4541       int offset = 0;
4542
4543       while (size--)
4544         {
4545           l = aopGet (AOP (right), offset);
4546           if (*l == '@')
4547             {
4548               MOVA (l);
4549               emitcode ("mov", "@%s,a", rname);
4550             }
4551           else
4552             emitcode ("mov", "@%s,%s", rname, l);
4553           if (size)
4554             emitcode ("inc", "%s", rname);
4555           offset++;
4556         }
4557     }
4558
4559   /* now some housekeeping stuff */
4560   if (aop)
4561     {
4562       /* we had to allocate for this iCode */
4563       freeAsmop (NULL, aop, ic, TRUE);
4564     }
4565   else
4566     {
4567       /* we did not allocate which means left
4568          already in a pointer register, then
4569          if size > 0 && this could be used again
4570          we have to point it back to where it
4571          belongs */
4572       if (AOP_SIZE (right) > 1 &&
4573           !OP_SYMBOL (result)->remat &&
4574           (OP_SYMBOL (result)->liveTo > ic->seq ||
4575            ic->depth))
4576         {
4577           int size = AOP_SIZE (right) - 1;
4578           while (size--)
4579             emitcode ("dec", "%s", rname);
4580         }
4581     }
4582
4583   /* done */
4584   freeAsmop (right, NULL, ic, TRUE);
4585
4586
4587 }
4588
4589 /*-----------------------------------------------------------------*/
4590 /* genPagedPointerSet - emitcode for Paged pointer put             */
4591 /*-----------------------------------------------------------------*/
4592 static void
4593 genPagedPointerSet (operand * right,
4594                     operand * result,
4595                     iCode * ic)
4596 {
4597   asmop *aop = NULL;
4598   regs *preg = NULL;
4599   char *rname, *l;
4600   sym_link *retype;
4601
4602   retype = getSpec (operandType (right));
4603
4604   aopOp (result, ic, FALSE);
4605
4606   /* if the value is already in a pointer register
4607      then don't need anything more */
4608   if (!AOP_INPREG (AOP (result)))
4609     {
4610       /* otherwise get a free pointer register */
4611       aop = newAsmop (0);
4612       preg = getFreePtr (ic, &aop, FALSE, 0);
4613       emitcode ("mov", "%s,%s",
4614                 preg->name,
4615                 aopGet (AOP (result), 0));
4616       rname = preg->name;
4617     }
4618   else
4619     rname = aopGet (AOP (result), 0);
4620
4621   freeAsmop (result, NULL, ic, TRUE);
4622   aopOp (right, ic, FALSE);
4623
4624   /* if bitfield then unpack the bits */
4625   if (IS_BITVAR (retype))
4626     genPackBits (retype, right, rname, PPOINTER);
4627   else
4628     {
4629       /* we have can just get the values */
4630       int size = AOP_SIZE (right);
4631       int offset = 0;
4632
4633       while (size--)
4634         {
4635           l = aopGet (AOP (right), offset);
4636
4637           MOVA (l);
4638           emitcode ("movx", "@%s,a", rname);
4639
4640           if (size)
4641             emitcode ("inc", "%s", rname);
4642
4643           offset++;
4644         }
4645     }
4646
4647   /* now some housekeeping stuff */
4648   if (aop)
4649     {
4650       /* we had to allocate for this iCode */
4651       freeAsmop (NULL, aop, ic, TRUE);
4652     }
4653   else
4654     {
4655       /* we did not allocate which means left
4656          already in a pointer register, then
4657          if size > 0 && this could be used again
4658          we have to point it back to where it
4659          belongs */
4660       if (AOP_SIZE (right) > 1 &&
4661           !OP_SYMBOL (result)->remat &&
4662           (OP_SYMBOL (result)->liveTo > ic->seq ||
4663            ic->depth))
4664         {
4665           int size = AOP_SIZE (right) - 1;
4666           while (size--)
4667             emitcode ("dec", "%s", rname);
4668         }
4669     }
4670
4671   /* done */
4672   freeAsmop (right, NULL, ic, TRUE);
4673
4674
4675 }
4676
4677 /*-----------------------------------------------------------------*/
4678 /* genFarPointerSet - set value from far space                     */
4679 /*-----------------------------------------------------------------*/
4680 static void
4681 genFarPointerSet (operand * right,
4682                   operand * result, iCode * ic)
4683 {
4684   int size, offset;
4685   sym_link *retype = getSpec (operandType (right));
4686
4687   aopOp (result, ic, FALSE);
4688
4689   /* if the operand is already in dptr
4690      then we do nothing else we move the value to dptr */
4691   if (AOP_TYPE (result) != AOP_STR)
4692     {
4693       /* if this is remateriazable */
4694       if (AOP_TYPE (result) == AOP_IMMD)
4695         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0));
4696       else
4697         {                       /* we need to get it byte by byte */
4698           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0));
4699           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1));
4700           if (options.model == MODEL_FLAT24)
4701             {
4702               emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2));
4703             }
4704         }
4705     }
4706   /* so dptr know contains the address */
4707   freeAsmop (result, NULL, ic, TRUE);
4708   aopOp (right, ic, FALSE);
4709
4710   /* if bit then unpack */
4711   if (IS_BITVAR (retype))
4712     genPackBits (retype, right, "dptr", FPOINTER);
4713   else
4714     {
4715       size = AOP_SIZE (right);
4716       offset = 0;
4717
4718       while (size--)
4719         {
4720           char *l = aopGet (AOP (right), offset++);
4721           MOVA (l);
4722           emitcode ("movx", "@dptr,a");
4723           if (size)
4724             emitcode ("inc", "dptr");
4725         }
4726     }
4727
4728   freeAsmop (right, NULL, ic, TRUE);
4729 }
4730
4731 /*-----------------------------------------------------------------*/
4732 /* genGenPointerSet - set value from generic pointer space         */
4733 /*-----------------------------------------------------------------*/
4734 static void
4735 genGenPointerSet (operand * right,
4736                   operand * result, iCode * ic)
4737 {
4738   int size, offset;
4739   sym_link *retype = getSpec (operandType (right));
4740
4741   aopOp (result, ic, FALSE);
4742
4743   /* if the operand is already in dptr
4744      then we do nothing else we move the value to dptr */
4745   if (AOP_TYPE (result) != AOP_STR)
4746     {
4747       /* if this is remateriazable */
4748       if (AOP_TYPE (result) == AOP_IMMD)
4749         {
4750           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0));
4751           emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0));
4752         }
4753       else
4754         {                       /* we need to get it byte by byte */
4755           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0));
4756           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1));
4757           if (options.model == MODEL_FLAT24)
4758             {
4759               emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2));
4760               emitcode ("mov", "b,%s", aopGet (AOP (result), 3));
4761             }
4762           else
4763             {
4764               emitcode ("mov", "b,%s", aopGet (AOP (result), 2));
4765             }
4766         }
4767     }
4768   /* so dptr know contains the address */
4769   freeAsmop (result, NULL, ic, TRUE);
4770   aopOp (right, ic, FALSE);
4771
4772   /* if bit then unpack */
4773   if (IS_BITVAR (retype))
4774     genPackBits (retype, right, "dptr", GPOINTER);
4775   else
4776     {
4777       size = AOP_SIZE (right);
4778       offset = 0;
4779
4780       while (size--)
4781         {
4782           char *l = aopGet (AOP (right), offset++);
4783           MOVA (l);
4784           emitcode ("lcall", "__gptrput");
4785           if (size)
4786             emitcode ("inc", "dptr");
4787         }
4788     }
4789
4790   freeAsmop (right, NULL, ic, TRUE);
4791 }
4792
4793 /*-----------------------------------------------------------------*/
4794 /* genPointerSet - stores the value into a pointer location        */
4795 /*-----------------------------------------------------------------*/
4796 static void
4797 genPointerSet (iCode * ic)
4798 {
4799   operand *right, *result;
4800   sym_link *type, *etype;
4801   int p_type;
4802
4803   right = IC_RIGHT (ic);
4804   result = IC_RESULT (ic);
4805
4806   /* depending on the type of pointer we need to
4807      move it to the correct pointer register */
4808   type = operandType (result);
4809   etype = getSpec (type);
4810   /* if left is of type of pointer then it is simple */
4811   if (IS_PTR (type) && !IS_FUNC (type->next))
4812     {
4813       p_type = DCL_TYPE (type);
4814     }
4815   else
4816     {
4817       /* we have to go by the storage class */
4818       p_type = PTR_TYPE (SPEC_OCLS (etype));
4819
4820       /*  if (SPEC_OCLS(etype)->codesp ) { */
4821       /*      p_type = CPOINTER ;  */
4822       /*  } */
4823       /*  else */
4824       /*      if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
4825       /*    p_type = FPOINTER ; */
4826       /*      else */
4827       /*    if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
4828       /*        p_type = PPOINTER ; */
4829       /*    else */
4830       /*        if (SPEC_OCLS(etype) == idata ) */
4831       /*      p_type = IPOINTER ; */
4832       /*        else */
4833       /*      p_type = POINTER ; */
4834     }
4835
4836   /* now that we have the pointer type we assign
4837      the pointer values */
4838   switch (p_type)
4839     {
4840
4841     case POINTER:
4842     case IPOINTER:
4843       genNearPointerSet (right, result, ic);
4844       break;
4845
4846     case PPOINTER:
4847       genPagedPointerSet (right, result, ic);
4848       break;
4849
4850     case FPOINTER:
4851       genFarPointerSet (right, result, ic);
4852       break;
4853
4854     case GPOINTER:
4855       genGenPointerSet (right, result, ic);
4856       break;
4857     }
4858
4859 }
4860
4861 /*-----------------------------------------------------------------*/
4862 /* genIfx - generate code for Ifx statement                        */
4863 /*-----------------------------------------------------------------*/
4864 static void
4865 genIfx (iCode * ic, iCode * popIc)
4866 {
4867   operand *cond = IC_COND (ic);
4868   int isbit = 0;
4869
4870   aopOp (cond, ic, FALSE);
4871
4872   /* get the value into acc */
4873   if (AOP_TYPE (cond) != AOP_CRY)
4874     toBoolean (cond, "", 0);
4875   else
4876     isbit = 1;
4877   /* the result is now in the accumulator */
4878   freeAsmop (cond, NULL, ic, TRUE);
4879
4880   /* if there was something to be popped then do it */
4881   if (popIc)
4882     genIpop (popIc);
4883
4884   /* if the condition is  a bit variable */
4885   /*     if (isbit && IS_ITEMP(cond) && SPIL_LOC(cond)) { */
4886   /*  //  genIfxJump(ic,SPIL_LOC(cond)->rname); */
4887   /*     } */
4888   /*     else */
4889   /*  if (isbit && !IS_ITEMP(cond)) */
4890   /*    //      genIfxJump(ic,OP_SYMBOL(cond)->rname); */
4891   /*  else */
4892   /*    // genIfxJump(ic,"a"); */
4893
4894   ic->generated = 1;
4895 }
4896
4897 /*-----------------------------------------------------------------*/
4898 /* genAddrOf - generates code for address of                       */
4899 /*-----------------------------------------------------------------*/
4900 static void
4901 genAddrOf (iCode * ic)
4902 {
4903   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
4904   int size, offset;
4905
4906   aopOp (IC_RESULT (ic), ic, FALSE);
4907
4908   /* if the operand is on the stack then we
4909      need to get the stack offset of this
4910      variable */
4911   if (sym->onStack)
4912     {
4913       /* if it has an offset then we need to compute
4914          it */
4915       if (sym->stack)
4916         {
4917           emitcode ("mov", "a,_bp");
4918           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
4919           aopPut (AOP (IC_RESULT (ic)), "a", 0);
4920         }
4921       else
4922         {
4923           /* we can just move _bp */
4924           aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
4925         }
4926       /* fill the result with zero */
4927       size = AOP_SIZE (IC_RESULT (ic)) - 1;
4928
4929
4930       if (options.stack10bit && size < (FPTRSIZE - 1))
4931         {
4932           fprintf (stderr,
4933                    "*** warning: pointer to stack var truncated.\n");
4934         }
4935
4936       offset = 1;
4937       while (size--)
4938         {
4939           /* Yuck! */
4940           if (options.stack10bit && offset == 2)
4941             {
4942               aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
4943             }
4944           else
4945             {
4946               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
4947             }
4948         }
4949
4950       goto release;
4951     }
4952
4953   /* object not on stack then we need the name */
4954   size = AOP_SIZE (IC_RESULT (ic));
4955   offset = 0;
4956
4957   while (size--)
4958     {
4959       char s[SDCC_NAME_MAX];
4960       if (offset)
4961         sprintf (s, "#(%s >> %d)",
4962                  sym->rname,
4963                  offset * 8);
4964       else
4965         sprintf (s, "#%s", sym->rname);
4966       aopPut (AOP (IC_RESULT (ic)), s, offset++);
4967     }
4968
4969 release:
4970   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4971
4972 }
4973
4974 /*-----------------------------------------------------------------*/
4975 /* genFarFarAssign - assignment when both are in far space         */
4976 /*-----------------------------------------------------------------*/
4977 static void
4978 genFarFarAssign (operand * result, operand * right, iCode * ic)
4979 {
4980   int size = AOP_SIZE (right);
4981   int offset = 0;
4982   char *l;
4983   /* first push the right side on to the stack */
4984   while (size--)
4985     {
4986       l = aopGet (AOP (right), offset++);
4987       MOVA (l);
4988       emitcode ("push", "acc");
4989     }
4990
4991   freeAsmop (right, NULL, ic, FALSE);
4992   /* now assign DPTR to result */
4993   aopOp (result, ic, FALSE);
4994   size = AOP_SIZE (result);
4995   while (size--)
4996     {
4997       emitcode ("pop", "acc");
4998       aopPut (AOP (result), "a", --offset);
4999     }
5000   freeAsmop (result, NULL, ic, FALSE);
5001
5002 }
5003
5004 /*-----------------------------------------------------------------*/
5005 /* genAssign - generate code for assignment                        */
5006 /*-----------------------------------------------------------------*/
5007 static void
5008 genAssign (iCode * ic)
5009 {
5010   operand *result, *right;
5011   int size, offset;
5012   unsigned long lit = 0L;
5013
5014   result = IC_RESULT (ic);
5015   right = IC_RIGHT (ic);
5016
5017   /* if they are the same */
5018   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
5019     return;
5020
5021   aopOp (right, ic, FALSE);
5022
5023   /* special case both in far space */
5024   if (AOP_TYPE (right) == AOP_DPTR &&
5025       IS_TRUE_SYMOP (result) &&
5026       isOperandInFarSpace (result))
5027     {
5028
5029       genFarFarAssign (result, right, ic);
5030       return;
5031     }
5032
5033   aopOp (result, ic, TRUE);
5034
5035   /* if they are the same registers */
5036   if (sameRegs (AOP (right), AOP (result)))
5037     goto release;
5038
5039   /* if the result is a bit */
5040   if (AOP_TYPE (result) == AOP_CRY)
5041     {
5042
5043       /* if the right size is a literal then
5044          we know what the value is */
5045       if (AOP_TYPE (right) == AOP_LIT)
5046         {
5047           if (((int) operandLitValue (right)))
5048             aopPut (AOP (result), one, 0);
5049           else
5050             aopPut (AOP (result), zero, 0);
5051           goto release;
5052         }
5053
5054       /* the right is also a bit variable */
5055       if (AOP_TYPE (right) == AOP_CRY)
5056         {
5057           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5058           aopPut (AOP (result), "c", 0);
5059           goto release;
5060         }
5061
5062       /* we need to or */
5063       toBoolean (right, "", 0);
5064       aopPut (AOP (result), "a", 0);
5065       goto release;
5066     }
5067
5068   /* bit variables done */
5069   /* general case */
5070   size = AOP_SIZE (result);
5071   offset = 0;
5072   if (AOP_TYPE (right) == AOP_LIT)
5073     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5074   if ((size > 1) &&
5075       (AOP_TYPE (result) != AOP_REG) &&
5076       (AOP_TYPE (right) == AOP_LIT) &&
5077       !IS_FLOAT (operandType (right)) &&
5078       (lit < 256L))
5079     {
5080       emitcode ("clr", "a");
5081       while (size--)
5082         {
5083           if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
5084             aopPut (AOP (result), "a", size);
5085           else
5086             aopPut (AOP (result),
5087                     aopGet (AOP (right), size),
5088                     size);
5089         }
5090     }
5091   else
5092     {
5093       while (size--)
5094         {
5095           aopPut (AOP (result),
5096                   aopGet (AOP (right), offset),
5097                   offset);
5098           offset++;
5099         }
5100     }
5101
5102 release:
5103   freeAsmop (right, NULL, ic, FALSE);
5104   freeAsmop (result, NULL, ic, TRUE);
5105 }
5106
5107 /*-----------------------------------------------------------------*/
5108 /* genJumpTab - genrates code for jump table                       */
5109 /*-----------------------------------------------------------------*/
5110 static void
5111 genJumpTab (iCode * ic)
5112 {
5113   symbol *jtab;
5114   char *l;
5115
5116   aopOp (IC_JTCOND (ic), ic, FALSE);
5117   /* get the condition into accumulator */
5118   l = aopGet (AOP (IC_JTCOND (ic)), 0);
5119   MOVA (l);
5120   /* multiply by three */
5121   emitcode ("add", "a,acc");
5122   emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0));
5123   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
5124
5125   jtab = newiTempLabel (NULL);
5126   emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
5127   emitcode ("jmp", "@a+dptr");
5128   emitcode ("", "%05d$:", jtab->key + 100);
5129   /* now generate the jump labels */
5130   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
5131        jtab = setNextItem (IC_JTLABELS (ic)))
5132     emitcode ("ljmp", "%05d$", jtab->key + 100);
5133
5134 }
5135
5136 /*-----------------------------------------------------------------*/
5137 /* genCast - gen code for casting                                  */
5138 /*-----------------------------------------------------------------*/
5139 static void
5140 genCast (iCode * ic)
5141 {
5142   operand *result = IC_RESULT (ic);
5143   sym_link *ctype = operandType (IC_LEFT (ic));
5144   sym_link *rtype = operandType (IC_RIGHT (ic));
5145   operand *right = IC_RIGHT (ic);
5146   int size, offset;
5147
5148   /* if they are equivalent then do nothing */
5149   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
5150     return;
5151
5152   aopOp (right, ic, FALSE);
5153   aopOp (result, ic, FALSE);
5154
5155   /* if the result is a bit */
5156   if (AOP_TYPE (result) == AOP_CRY)
5157     {
5158       /* if the right size is a literal then
5159          we know what the value is */
5160       if (AOP_TYPE (right) == AOP_LIT)
5161         {
5162           if (((int) operandLitValue (right)))
5163             aopPut (AOP (result), one, 0);
5164           else
5165             aopPut (AOP (result), zero, 0);
5166
5167           goto release;
5168         }
5169
5170       /* the right is also a bit variable */
5171       if (AOP_TYPE (right) == AOP_CRY)
5172         {
5173           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5174           aopPut (AOP (result), "c", 0);
5175           goto release;
5176         }
5177
5178       /* we need to or */
5179       toBoolean (right, "", 0);
5180       aopPut (AOP (result), "a", 0);
5181       goto release;
5182     }
5183
5184   /* if they are the same size : or less */
5185   if (AOP_SIZE (result) <= AOP_SIZE (right))
5186     {
5187
5188       /* if they are in the same place */
5189       if (sameRegs (AOP (right), AOP (result)))
5190         goto release;
5191
5192       /* if they in different places then copy */
5193       size = AOP_SIZE (result);
5194       offset = 0;
5195       while (size--)
5196         {
5197           aopPut (AOP (result),
5198                   aopGet (AOP (right), offset),
5199                   offset);
5200           offset++;
5201         }
5202       goto release;
5203     }
5204
5205
5206   /* if the result is of type pointer */
5207   if (IS_PTR (ctype))
5208     {
5209
5210       int p_type;
5211       sym_link *type = operandType (right);
5212       sym_link *etype = getSpec (type);
5213
5214       /* pointer to generic pointer */
5215       if (IS_GENPTR (ctype))
5216         {
5217           char *l = zero;
5218
5219           if (IS_PTR (type))
5220             p_type = DCL_TYPE (type);
5221           else
5222             {
5223               /* we have to go by the storage class */
5224               p_type = PTR_TYPE (SPEC_OCLS (etype));
5225             }
5226
5227           /* the first two bytes are known */
5228           size = GPTRSIZE - 1;
5229           offset = 0;
5230           while (size--)
5231             {
5232               aopPut (AOP (result),
5233                       aopGet (AOP (right), offset),
5234                       offset);
5235               offset++;
5236             }
5237           /* the last byte depending on type */
5238           switch (p_type)
5239             {
5240             case IPOINTER:
5241             case POINTER:
5242               l = zero;
5243               break;
5244             case FPOINTER:
5245               l = one;
5246               break;
5247             case CPOINTER:
5248               l = "#0x02";
5249               break;
5250             case PPOINTER:
5251               l = "#0x03";
5252               break;
5253
5254             default:
5255               /* this should never happen */
5256               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5257                       "got unknown pointer type");
5258               exit (1);
5259             }
5260           aopPut (AOP (result), l, GPTRSIZE - 1);
5261           goto release;
5262         }
5263
5264       /* just copy the pointers */
5265       size = AOP_SIZE (result);
5266       offset = 0;
5267       while (size--)
5268         {
5269           aopPut (AOP (result),
5270                   aopGet (AOP (right), offset),
5271                   offset);
5272           offset++;
5273         }
5274       goto release;
5275     }
5276
5277   /* so we now know that the size of destination is greater
5278      than the size of the source */
5279   /* we move to result for the size of source */
5280   size = AOP_SIZE (right);
5281   offset = 0;
5282   while (size--)
5283     {
5284       aopPut (AOP (result),
5285               aopGet (AOP (right), offset),
5286               offset);
5287       offset++;
5288     }
5289
5290   /* now depending on the sign of the source && destination */
5291   size = AOP_SIZE (result) - AOP_SIZE (right);
5292   /* if unsigned or not an integral type */
5293   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype))
5294     {
5295       while (size--)
5296         aopPut (AOP (result), zero, offset++);
5297     }
5298   else
5299     {
5300       /* we need to extend the sign :{ */
5301       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1);
5302       MOVA (l);
5303       emitcode ("rlc", "a");
5304       emitcode ("subb", "a,acc");
5305       while (size--)
5306         aopPut (AOP (result), "a", offset++);
5307     }
5308
5309   /* we are done hurray !!!! */
5310
5311 release:
5312   freeAsmop (right, NULL, ic, TRUE);
5313   freeAsmop (result, NULL, ic, TRUE);
5314
5315 }
5316
5317 /*-----------------------------------------------------------------*/
5318 /* genDjnz - generate decrement & jump if not zero instrucion      */
5319 /*-----------------------------------------------------------------*/
5320 static int
5321 genDjnz (iCode * ic, iCode * ifx)
5322 {
5323   symbol *lbl, *lbl1;
5324   if (!ifx)
5325     return 0;
5326
5327   /* if the if condition has a false label
5328      then we cannot save */
5329   if (IC_FALSE (ifx))
5330     return 0;
5331
5332   /* if the minus is not of the form
5333      a = a - 1 */
5334   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
5335       !IS_OP_LITERAL (IC_RIGHT (ic)))
5336     return 0;
5337
5338   if (operandLitValue (IC_RIGHT (ic)) != 1)
5339     return 0;
5340
5341   /* if the size of this greater than one then no
5342      saving */
5343   if (getSize (operandType (IC_RESULT (ic))) > 1)
5344     return 0;
5345
5346   /* otherwise we can save BIG */
5347   lbl = newiTempLabel (NULL);
5348   lbl1 = newiTempLabel (NULL);
5349
5350   aopOp (IC_RESULT (ic), ic, FALSE);
5351
5352   if (IS_AOP_PREG (IC_RESULT (ic)))
5353     {
5354       emitcode ("dec", "%s",
5355                 aopGet (AOP (IC_RESULT (ic)), 0));
5356       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0));
5357       emitcode ("jnz", "%05d$", lbl->key + 100);
5358     }
5359   else
5360     {
5361       emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0),
5362                 lbl->key + 100);
5363     }
5364   emitcode ("sjmp", "%05d$", lbl1->key + 100);
5365   emitcode ("", "%05d$:", lbl->key + 100);
5366   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5367   emitcode ("", "%05d$:", lbl1->key + 100);
5368
5369   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5370   ifx->generated = 1;
5371   return 1;
5372 }
5373
5374 static char *recvregs[8] =
5375 {
5376   "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23"
5377 };
5378 static recvCnt = 0;
5379
5380 /*-----------------------------------------------------------------*/
5381 /* genReceive - generate code for a receive iCode                  */
5382 /*-----------------------------------------------------------------*/
5383 static void
5384 genReceive (iCode * ic)
5385 {
5386   int size, offset = 0;
5387   aopOp (IC_RESULT (ic), ic, FALSE);
5388   size = AOP_SIZE (IC_RESULT (ic));
5389   while (size--)
5390     {
5391       aopPut (AOP (IC_RESULT (ic)), recvregs[recvCnt++], offset);
5392       offset++;
5393     }
5394   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5395 }
5396
5397 /*-----------------------------------------------------------------*/
5398 /* gen51Code - generate code for 8051 based controllers            */
5399 /*-----------------------------------------------------------------*/
5400 void
5401 genAVRCode (iCode * lic)
5402 {
5403   iCode *ic;
5404   int cln = 0;
5405
5406   lineHead = lineCurr = NULL;
5407   recvCnt = 0;
5408   /* print the allocation information */
5409   if (allocInfo)
5410     printAllocInfo (currFunc, codeOutFile);
5411   /* if debug information required */
5412   /*     if (options.debug && currFunc) { */
5413   if (currFunc)
5414     {
5415       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
5416       _G.debugLine = 1;
5417       emitcode("",".type %s,@function",currFunc->name);
5418       _G.debugLine = 0;
5419     }
5420   /* stack pointer name */
5421   spname = "sp";
5422
5423
5424   for (ic = lic; ic; ic = ic->next)
5425     {
5426
5427       if (cln != ic->lineno)
5428         {
5429           if (options.debug)
5430             {
5431               _G.debugLine = 1;
5432               emitcode ("", "C$%s$%d$%d$%d ==.",
5433                         FileBaseName (ic->filename), ic->lineno,
5434                         ic->level, ic->block);
5435               _G.debugLine = 0;
5436             }
5437           emitcode (";", "%s %d", ic->filename, ic->lineno);
5438           cln = ic->lineno;
5439         }
5440       /* if the result is marked as
5441          spilt and rematerializable or code for
5442          this has already been generated then
5443          do nothing */
5444       if (resultRemat (ic) || ic->generated)
5445         continue;
5446
5447       /* depending on the operation */
5448       switch (ic->op)
5449         {
5450         case '!':
5451           genNot (ic);
5452           break;
5453
5454         case '~':
5455           genCpl (ic);
5456           break;
5457
5458         case UNARYMINUS:
5459           genUminus (ic);
5460           break;
5461
5462         case IPUSH:
5463           genIpush (ic);
5464           break;
5465
5466         case IPOP:
5467           /* IPOP happens only when trying to restore a
5468              spilt live range, if there is an ifx statement
5469              following this pop then the if statement might
5470              be using some of the registers being popped which
5471              would destory the contents of the register so
5472              we need to check for this condition and handle it */
5473           if (ic->next &&
5474               ic->next->op == IFX &&
5475               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
5476             genIfx (ic->next, ic);
5477           else
5478             genIpop (ic);
5479           break;
5480
5481         case CALL:
5482           genCall (ic);
5483           break;
5484
5485         case PCALL:
5486           genPcall (ic);
5487           break;
5488
5489         case FUNCTION:
5490           genFunction (ic);
5491           break;
5492
5493         case ENDFUNCTION:
5494           genEndFunction (ic);
5495           break;
5496
5497         case RETURN:
5498           genRet (ic);
5499           break;
5500
5501         case LABEL:
5502           genLabel (ic);
5503           break;
5504
5505         case GOTO:
5506           genGoto (ic);
5507           break;
5508
5509         case '+':
5510           genPlus (ic);
5511           break;
5512
5513         case '-':
5514           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
5515             genMinus (ic);
5516           break;
5517
5518         case '*':
5519           genMult (ic);
5520           break;
5521
5522         case '/':
5523           genDiv (ic);
5524           break;
5525
5526         case '%':
5527           genMod (ic);
5528           break;
5529
5530         case '>':
5531           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
5532           break;
5533
5534         case '<':
5535           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
5536           break;
5537
5538         case LE_OP:
5539           genCmpLe (ic, ifxForOp (IC_RESULT (ic), ic));
5540           break;
5541
5542         case GE_OP:
5543           genCmpGe (ic, ifxForOp (IC_RESULT (ic), ic));
5544           break;
5545
5546         case NE_OP:
5547           genCmpNe (ic, ifxForOp (IC_RESULT (ic), ic));
5548           break;
5549
5550         case EQ_OP:
5551           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
5552           break;
5553
5554         case AND_OP:
5555           genAndOp (ic);
5556           break;
5557
5558         case OR_OP:
5559           genOrOp (ic);
5560           break;
5561
5562         case '^':
5563           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
5564           break;
5565
5566         case '|':
5567           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
5568           break;
5569
5570         case BITWISEAND:
5571           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
5572           break;
5573
5574         case INLINEASM:
5575           genInline (ic);
5576           break;
5577
5578         case RRC:
5579           genRRC (ic);
5580           break;
5581
5582         case RLC:
5583           genRLC (ic);
5584           break;
5585
5586         case GETHBIT:
5587           genGetHbit (ic);
5588           break;
5589
5590         case LEFT_OP:
5591           genLeftShift (ic);
5592           break;
5593
5594         case RIGHT_OP:
5595           genRightShift (ic);
5596           break;
5597
5598         case GET_VALUE_AT_ADDRESS:
5599           genPointerGet (ic);
5600           break;
5601
5602         case '=':
5603           if (POINTER_SET (ic))
5604             genPointerSet (ic);
5605           else
5606             genAssign (ic);
5607           break;
5608
5609         case IFX:
5610           genIfx (ic, NULL);
5611           break;
5612
5613         case ADDRESS_OF:
5614           genAddrOf (ic);
5615           break;
5616
5617         case JUMPTABLE:
5618           genJumpTab (ic);
5619           break;
5620
5621         case CAST:
5622           genCast (ic);
5623           break;
5624
5625         case RECEIVE:
5626           genReceive (ic);
5627           break;
5628
5629         case SEND:
5630           addSet (&_G.sendSet, ic);
5631           break;
5632
5633         default:
5634           ic = ic;
5635           /*      piCode(ic,stdout); */
5636
5637         }
5638     }
5639
5640
5641   /* now we are ready to call the
5642      peep hole optimizer */
5643   if (!options.nopeep)
5644     peepHole (&lineHead);
5645
5646   /* now do the actual printing */
5647   printLine (lineHead, codeOutFile);
5648   return;
5649 }