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