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