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