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