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