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