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