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