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