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