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