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