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