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