* src/mcs51/gen.c, src/avr/gen.c, src/pic/gen.c, src/z80/gen.c,
[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   bool inComment = FALSE;
2953
2954   _G.inLine += (!options.asmpeep);
2955
2956   buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
2957
2958   /* emit each line as a code */
2959   while (*bp)
2960     {
2961       switch (*bp)
2962         {
2963         case ';':
2964           inComment = TRUE;
2965           ++bp;
2966           break;
2967
2968         case '\n':
2969           inComment = FALSE;
2970           *bp++ = '\0';
2971           emitcode (bp1, "");
2972           bp1 = bp;
2973           break;
2974
2975         default:
2976           /* Add \n for labels, not dirs such as c:\mydir */
2977           if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
2978             {
2979               ++bp;
2980               *bp = '\0';
2981               ++bp;
2982               emitcode (bp1, "");
2983               bp1 = bp;
2984             }
2985           else
2986             ++bp;
2987           break;
2988         }
2989     }
2990     if (bp1 != bp)
2991       emitcode (bp1, "");
2992
2993     Safe_free (buffer);
2994
2995     _G.inLine -= (!options.asmpeep);
2996 }
2997
2998 /*-----------------------------------------------------------------*/
2999 /* genRotC - rotate right/left with carry , lr = 1 rotate right    */
3000 /*-----------------------------------------------------------------*/
3001 static void
3002 genRotC (iCode * ic, int lr)
3003 {
3004         operand *left, *result;
3005         int size, offset = 0;
3006
3007         /* rotate right with carry */
3008         left = IC_LEFT (ic);
3009         result = IC_RESULT (ic);
3010         aopOp (left, ic, FALSE);
3011         aopOp (result, ic, FALSE);
3012
3013         /* move it to the result */
3014         size = AOP_SIZE (result);
3015         if (!sameRegs (AOP (left), AOP (result))) {
3016                 offset = 0;
3017                 while (size--) {
3018                         aopPut (AOP (result),
3019                                 aopGet (AOP (left), offset), offset);
3020                         offset++;
3021                 }
3022                 size = AOP_SIZE (result);
3023         }
3024         if (lr)
3025                 offset = size - 1;
3026         else
3027                 offset = 0;
3028
3029         CLRC;
3030         emitcode ("sbrc", "%s,%d", aopGet (AOP (result), offset),
3031                   (lr ? 0 : 7));
3032         emitcode ("sec", "");
3033
3034         while (size--) {
3035                 emitcode ((lr ? "ror" : "rol"), "%s",
3036                           aopGet (AOP (result), offset));
3037                 if (lr)
3038                         offset--;
3039                 else
3040                         offset++;
3041         }
3042         freeAsmop (left, NULL, ic, TRUE);
3043         freeAsmop (result, NULL, ic, TRUE);
3044 }
3045
3046 /*-----------------------------------------------------------------*/
3047 /* genRRC - rotate right with carry                                */
3048 /*-----------------------------------------------------------------*/
3049 static void
3050 genRRC (iCode * ic)
3051 {
3052         genRotC (ic, 1);
3053 }
3054
3055 /*-----------------------------------------------------------------*/
3056 /* genRLC - generate code for rotate left with carry               */
3057 /*-----------------------------------------------------------------*/
3058 static void
3059 genRLC (iCode * ic)
3060 {
3061         genRotC (ic, 0);
3062 }
3063
3064 /*-----------------------------------------------------------------*/
3065 /* genGetHbit - generates code get highest order bit               */
3066 /*-----------------------------------------------------------------*/
3067 static void
3068 genGetHbit (iCode * ic)
3069 {
3070         operand *left, *result;
3071         int size, offset;
3072
3073         left = IC_LEFT (ic);
3074         result = IC_RESULT (ic);
3075         aopOp (left, ic, FALSE);
3076         aopOp (result, ic, FALSE);
3077
3078         size = AOP_SIZE (result);
3079         if (!sameRegs (AOP (left), AOP (result))) {
3080                 emitcode ("clr", "%s", aopGet (AOP (result), size - 1));
3081                 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3082                 emitcode ("subi", "%s,<(-1)",
3083                           aopGet (AOP (result), size - 1));
3084         }
3085         else {
3086                 emitcode ("clr", "r0");
3087                 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3088                 emitcode ("subi", "r0,<(-1)");
3089                 aopPut (AOP (result), "r0", 0);
3090         }
3091         offset = 1;
3092         size--;
3093         while (size--) {
3094                 emitcode ("clr", aopGet (AOP (result), offset++));
3095         }
3096         freeAsmop (left, NULL, ic, TRUE);
3097         freeAsmop (result, NULL, ic, TRUE);
3098 }
3099
3100 /*-----------------------------------------------------------------*/
3101 /* genShiftLeftLit - shift left by a known amount                  */
3102 /*-----------------------------------------------------------------*/
3103 static void
3104 genShiftLeftLit (iCode * ic)
3105 {
3106         operand *left, *right, *result;
3107         int size, shCount, offset = 0;
3108         int lByteZ = 0;
3109
3110         right = IC_RIGHT (ic);
3111         left = IC_LEFT (ic);
3112         result = IC_RESULT (ic);
3113
3114         aopOp (left, ic, FALSE);
3115         aopOp (result, ic, FALSE);
3116         size = AOP_SIZE (result);
3117         shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3118
3119         if (shCount > (size * 8 - 1)) {
3120                 while (size--)
3121                         aopPut (AOP (result), zero, offset++);
3122                 goto release;
3123         }
3124         switch (size) {
3125         case 1:
3126                 if (!sameRegs (AOP (left), AOP (result)))
3127                         aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3128                 if (shCount >= 4) {
3129                         if (AOP_ISHIGHREG(AOP(result),0)) {
3130                                 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3131                                 emitcode ("andi", "%s,0xf0");
3132                         } else {
3133                                 emitcode ("ldi","r24,0xf0");
3134                                 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3135                                 emitcode ("and", "%s,r24");
3136                         }
3137                         shCount -= 4;
3138                 }
3139                 if (shCount == 1) {
3140                         emitcode ("add", "%s,%s", aopGet (AOP (result), 0),
3141                                   aopGet (AOP (result), 0));
3142                         shCount--;
3143                 }
3144                 while (shCount--)
3145                         emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3146                 break;
3147         case 2:
3148                 if (shCount >= 12) {
3149                         aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3150                         aopPut (AOP (result), zero, 0);                 
3151                         emitcode ("swap", "%s", aopGet (AOP (result), 1));
3152                         if (AOP_ISHIGHREG(AOP(result),1)) {
3153                                 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3154                         } else {
3155                                 emitcode ("ldi","r24,0xf0");
3156                                 emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
3157                         }
3158                         shCount -= 12;
3159                         lByteZ = 1;
3160                 }
3161                 if (shCount >= 8) {
3162                         aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3163                         aopPut (AOP (result), zero, 0);
3164                         shCount -= 8;
3165                         lByteZ = 1;
3166                 }
3167                 if (shCount >= 4) {
3168                         shCount -= 4;
3169                         if (!sameRegs (AOP (left), AOP (result))) {
3170                                 aopPut (AOP (result), aopGet (AOP (left), 0),
3171                                         0);
3172                                 aopPut (AOP (result), aopGet (AOP (left), 1),
3173                                         1);
3174                         }
3175                         emitcode ("mov", "r24,%s", aopGet (AOP (result), 0));
3176                         emitcode ("andi", "r24,0x0f");
3177                         if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
3178                                 emitcode("ldi","r25,0xf0");
3179                         }
3180                         emitcode ("swap", "%s", aopGet (AOP (result), 0));
3181                         if (AOP_ISHIGHREG(AOP(result),0)) {
3182                                 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 0));
3183                         } else {
3184                                 emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
3185                         }
3186                         emitcode ("swap", "%s", aopGet (AOP (result), 1));
3187                         if (AOP_ISHIGHREG(AOP(result),1)) {
3188                                 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3189                         } else {
3190                                 emitcode ("and", "%s,r25", aopGet (AOP (result), 1));
3191                         }
3192                         emitcode ("or", "%s,r24", aopGet (AOP (result), 1));
3193                         while (shCount--) {
3194                                 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3195                                 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3196                         }
3197                 }
3198                 if (!lByteZ && !sameRegs (AOP (result), AOP (left))
3199                     && shCount) {
3200                         offset = 0;
3201                         while (size--) {
3202                                 aopPut (AOP (result),
3203                                         aopGet (AOP (left), offset), offset);
3204                                 offset++;
3205                         }
3206                 }
3207                 while (shCount--) {
3208                         if (lByteZ) {
3209                                 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3210                         }
3211                         else {
3212                                 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3213                                 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3214                         }
3215                 }
3216                 break;
3217         case 3:
3218                 assert ("shifting generic pointer ?\n");
3219                 break;
3220         case 4:
3221                 /* 32 bits we do only byte boundaries */
3222                 if (shCount >= 24) {
3223                         aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3224                         aopPut (AOP (result), zero, 2);
3225                         aopPut (AOP (result), zero, 1);
3226                         aopPut (AOP (result), zero, 0);
3227                         lByteZ = 3;
3228                         shCount -= 24;
3229                 }
3230                 if (shCount >= 16) {
3231                         aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3232                         aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3233                         aopPut (AOP (result), zero, 1);
3234                         aopPut (AOP (result), zero, 0);
3235                         lByteZ = 2;
3236                         shCount -= 16;
3237                 }
3238                 if (shCount >= 8) {
3239                         aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3240                         aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3241                         aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3242                         aopPut (AOP (result), zero, 0);
3243                         shCount -= 8;
3244                         lByteZ = 1;
3245                 }
3246                 if (!lByteZ && !sameRegs (AOP (left), AOP (right))) {
3247                         offset = 0;
3248                         while (size--) {
3249                                 aopPut (AOP (result),
3250                                         aopGet (AOP (left), offset), offset);
3251                                 offset++;
3252                         }
3253                         offset = 0;
3254                         size = AOP_SIZE (result);
3255                 }
3256                 if (shCount) {
3257                         switch (lByteZ) {
3258                         case 0:
3259                                 while (shCount--) {
3260                                         emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3261                                         emitcode ("rol", "%s", aopGet (AOP (result), 1));
3262                                         emitcode ("rol", "%s", aopGet (AOP (result), 2));
3263                                         emitcode ("rol", "%s", aopGet (AOP (result), 3));
3264                                 }
3265                                 break;
3266                         case 1:
3267                                 while (shCount--) {
3268                                         emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3269                                         emitcode ("rol", "%s", aopGet (AOP (result), 2));
3270                                         emitcode ("rol", "%s", aopGet (AOP (result), 3));
3271                                 }
3272                                 break;
3273                         case 2:
3274                                 while (shCount--) {
3275                                         emitcode ("lsl", "%s", aopGet (AOP (result), 2));
3276                                         emitcode ("rol", "%s", aopGet (AOP (result), 3));
3277                                 }
3278                                 break;
3279                         case 3:
3280                                 while (shCount--) {
3281                                         emitcode ("lsl", "%s", aopGet (AOP (result), 3));
3282                                 }
3283                                 break;
3284                         }
3285                 }
3286         }
3287
3288       release:
3289         freeAsmop (left, NULL, ic, TRUE);
3290         freeAsmop (right, NULL, ic, TRUE);
3291         freeAsmop (result, NULL, ic, TRUE);
3292 }
3293
3294 /*-----------------------------------------------------------------*/
3295 /* genLeftShift - generates code for left shifting                 */
3296 /*-----------------------------------------------------------------*/
3297 static void
3298 genLeftShift (iCode * ic)
3299 {
3300         operand *left, *right, *result;
3301         int size, offset;
3302         symbol *tlbl;
3303
3304         right = IC_RIGHT (ic);
3305         left = IC_LEFT (ic);
3306         result = IC_RESULT (ic);
3307
3308         aopOp (right, ic, FALSE);
3309
3310         if (AOP_TYPE (right) == AOP_LIT) {
3311                 genShiftLeftLit (ic);
3312                 return;
3313         }
3314
3315         /* unknown count */
3316         aopOp (left, ic, FALSE);
3317         aopOp (result, ic, FALSE);
3318         size = AOP_SIZE (result);
3319         offset = 0;
3320         if (AOP_SIZE (right) > 1) {
3321                 if (isRegPair (AOP (right))) {
3322                         emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3323                 }
3324                 else {
3325                         emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3326                         emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3327                 }
3328         }
3329         else {
3330                 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3331         }
3332         if (!sameRegs (AOP (left), AOP (result))) {
3333                 while (size--) {
3334                         aopPut (AOP (result), aopGet (AOP (left), offset),
3335                                 offset);
3336                         offset++;
3337                 }
3338                 size = AOP_SIZE (result);
3339         }
3340         tlbl = newiTempLabel (NULL);
3341         emitcode ("", "L%05d:", tlbl->key);
3342         offset = 0;
3343         while (size--) {
3344                 if (offset)
3345                         emitcode ("rol", "%s", aopGet (AOP (result), offset));
3346                 else
3347                         emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3348                 offset++;
3349         }
3350         if (AOP_SIZE (right) > 1)
3351                 emitcode ("sbiw", "r24,1");
3352         else
3353                 emitcode ("dec", "r24");
3354         emitcode ("brne", "L%05d", tlbl->key);
3355
3356         freeAsmop (left, NULL, ic, TRUE);
3357         freeAsmop (right, NULL, ic, TRUE);
3358         freeAsmop (result, NULL, ic, TRUE);
3359 }
3360
3361 /*-----------------------------------------------------------------*/
3362 /* genShiftRightLit - generate for right shift with known count    */
3363 /*-----------------------------------------------------------------*/
3364 static void
3365 genShiftRightLit (iCode * ic)
3366 {
3367         operand *left = IC_LEFT (ic)
3368         , *right = IC_RIGHT (ic)
3369         , *result = IC_RESULT (ic);
3370         int size, shCount, offset = 0;
3371         int hByteZ = 0;
3372         sym_link *letype = getSpec (operandType (left));
3373         int sign = !SPEC_USIGN (letype);
3374
3375         right = IC_RIGHT (ic);
3376         left = IC_LEFT (ic);
3377         result = IC_RESULT (ic);
3378
3379         aopOp (left, ic, FALSE);
3380         aopOp (result, ic, FALSE);
3381         size = AOP_SIZE (result);
3382         shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3383
3384         /* if signed then give up and use a loop to shift */
3385         if (sign) {
3386                 symbol *tlbl;
3387                 if (!sameRegs (AOP (left), AOP (result))) {
3388                         while (size--) {
3389                                 aopPut (AOP (result),
3390                                         aopGet (AOP (left), offset), offset);
3391                                 offset++;
3392                         }
3393                         size = AOP_SIZE (result);
3394                         offset = 0;
3395                 }
3396                 /* be as economical as possible */
3397                 if (shCount <= 4) {
3398                         while (shCount--) {
3399                                 size = AOP_SIZE (result);
3400                                 offset = size - 1;
3401                                 while (size--) {
3402                                         /* highest order byte */
3403                                         if (offset == (AOP_SIZE(result)-1)) 
3404                                                 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3405                                         else
3406                                                 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3407                                         offset--;                                               
3408                                 }
3409                         }
3410                 }
3411                 else {
3412                         emitcode ("ldi", "r24,<(%d)", shCount);
3413                         tlbl = newiTempLabel (NULL);
3414                         emitcode ("", "L%05d:", tlbl->key);
3415                         offset = size - 1;
3416                         while (size--) {
3417                                 if (offset == (AOP_SIZE(result) - 1))
3418                                         emitcode ("asr", "%s", aopGet (AOP (result), offset));
3419                                 else
3420                                         emitcode ("ror", "%s", aopGet (AOP (result), offset));
3421                                 offset--;
3422                         }
3423                         emitcode ("dec", "r24");
3424                         emitcode ("brne", "L%05d", tlbl->key);
3425                 }
3426                 goto release;
3427         }
3428         if (shCount > (size * 8 - 1)) {
3429                 while (size--)
3430                         aopPut (AOP (result), zero, offset++);
3431                 goto release;
3432         }
3433         /* for unsigned we can much more efficient */
3434         switch (size) {
3435         case 1:
3436                 if (!sameRegs (AOP (left), AOP (result)))
3437                         aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3438                 if (shCount >= 4) {
3439                         emitcode ("swap", "%s", aopGet (AOP (result), 0));
3440                         if (AOP_ISHIGHREG(AOP(result),0)) {
3441                                 emitcode ("andi", "%s,0x0f",aopGet(AOP(result),0));
3442                         } else {
3443                                 emitcode ("ldi","r24,0x0f");
3444                                 emitcode ("and", "%s,r24",aopGet(AOP(result),0));
3445                         }
3446                         shCount -= 4;
3447                 }
3448                 while (shCount--)
3449                         emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3450                 break;
3451         case 2:
3452                 if (shCount >= 12) {
3453                         aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3454                         aopPut (AOP (result), zero, 1);
3455                         emitcode ("swap", "%s", aopGet (AOP (result), 0));
3456                         if (AOP_ISHIGHREG(AOP(result),0)) {
3457                                 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3458                         } else {
3459                                 emitcode ("ldi","r24,0x0f");
3460                                 emitcode ("and", "%s,r24",aopGet(AOP(result),0));
3461                         }
3462                         shCount -= 12;
3463                         hByteZ = 1;
3464                 }
3465                 if (shCount >= 8) {
3466                         aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3467                         aopPut (AOP (result), zero, 1);
3468                         shCount -= 8;
3469                         hByteZ = 1;
3470                 }
3471                 if (shCount >= 4) {
3472                         shCount -= 4;
3473                         if (!sameRegs (AOP (left), AOP (result))) {
3474                                 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3475                                 aopPut (AOP (result), aopGet (AOP (left), 1), 1);
3476                         }
3477                         if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
3478                                 emitcode("ldi","r25,0x0f");
3479                         }
3480                         emitcode ("mov", "r24,%s", aopGet (AOP (result), 1));
3481                         emitcode ("andi", "r24,0xf0");
3482                         emitcode ("swap", "%s", aopGet (AOP (result), 0));
3483                         if (AOP_ISHIGHREG(AOP(result),0)) {
3484                                 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3485                         } else {
3486                                 emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
3487                         }
3488                         emitcode ("or", "%s,r24", aopGet (AOP (result), 0));
3489                         emitcode ("swap", "%s", aopGet (AOP (result), 1));
3490                         if (AOP_ISHIGHREG(AOP(result),1)) {
3491                                 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 1));
3492                         } else {
3493                                 emitcode ("and", "%s,r24", aopGet (AOP (result), 1));                           
3494                         }
3495                         while (shCount--) {
3496                                 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3497                                 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3498                         }
3499
3500                 }
3501                 if (!hByteZ && !sameRegs (AOP (result), AOP (left))
3502                     && shCount) {
3503                         offset = 0;
3504                         while (size--) {
3505                                 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3506                                 offset++;
3507                         }
3508                 }
3509                 while (shCount--) {
3510                         if (hByteZ) {
3511                                 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3512                         }
3513                         else {
3514                                 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3515                                 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3516                         }
3517                 }
3518                 break;
3519
3520         case 3:
3521                 assert ("shifting generic pointer ?\n");
3522                 break;
3523         case 4:
3524                 /* 32 bits we do only byte boundaries */
3525                 if (shCount >= 24) {
3526                         aopPut (AOP (result), aopGet (AOP (left), 3), 0);
3527                         aopPut (AOP (result), zero, 1);
3528                         aopPut (AOP (result), zero, 2);
3529                         aopPut (AOP (result), zero, 3);
3530                         hByteZ = 3;
3531                         shCount -= 24;
3532                 }
3533                 if (shCount >= 16) {
3534                         aopPut (AOP (result), aopGet (AOP (left), 3), 1);
3535                         aopPut (AOP (result), aopGet (AOP (left), 2), 0);
3536                         aopPut (AOP (result), zero, 2);
3537                         aopPut (AOP (result), zero, 3);
3538                         hByteZ = 2;
3539                         shCount -= 16;
3540                 }
3541                 if (shCount >= 8) {
3542                         aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3543                         aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3544                         aopPut (AOP (result), aopGet (AOP (left), 3), 2);
3545                         aopPut (AOP (result), zero, 3);
3546                         shCount -= 8;
3547                         hByteZ = 1;
3548                 }
3549                 if (!hByteZ && !sameRegs (AOP (left), AOP (right))) {
3550                         offset = 0;
3551                         while (size--) {
3552                                 aopPut (AOP (result),
3553                                         aopGet (AOP (left), offset), offset);
3554                                 offset++;
3555                         }
3556                         offset = 0;
3557                         size = AOP_SIZE (result);
3558                 }
3559                 if (shCount) {
3560                         switch (hByteZ) {
3561                         case 0:
3562                                 while (shCount--) {
3563                                         emitcode ("lsr", "%s", aopGet (AOP (result), 3));
3564                                         emitcode ("ror", "%s", aopGet (AOP (result), 2));
3565                                         emitcode ("ror", "%s", aopGet (AOP (result), 1));
3566                                         emitcode ("ror", "%s", aopGet (AOP (result), 0));
3567                                 }
3568                                 break;
3569                         case 1:
3570                                 while (shCount--) {
3571                                         emitcode ("lsr", "%s", aopGet (AOP (result), 2));
3572                                         emitcode ("ror", "%s", aopGet (AOP (result), 1));
3573                                         emitcode ("ror", "%s", aopGet (AOP (result), 0));
3574                                 }
3575                                 break;
3576                         case 2:
3577                                 while (shCount--) {
3578                                         emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3579                                         emitcode ("ror", "%s", aopGet (AOP (result), 0));
3580                                 }
3581                                 break;
3582                         case 3:
3583                                 while (shCount--) {
3584                                         emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3585                                 }
3586                                 break;
3587                         }
3588                 }
3589         }
3590       release:
3591         freeAsmop (left, NULL, ic, TRUE);
3592         freeAsmop (right, NULL, ic, TRUE);
3593         freeAsmop (result, NULL, ic, TRUE);
3594 }
3595
3596 /*-----------------------------------------------------------------*/
3597 /* genRightShift - generate code for right shifting                */
3598 /*-----------------------------------------------------------------*/
3599 static void
3600 genRightShift (iCode * ic)
3601 {
3602         operand *right, *left, *result;
3603         sym_link *letype;
3604         int size, offset;
3605         int sign = 0, first = 1;
3606         symbol *tlbl;
3607
3608         aopOp (right = IC_RIGHT (ic), ic, FALSE);
3609
3610         if (AOP_TYPE (right) == AOP_LIT) {
3611                 genShiftRightLit (ic);
3612                 return;
3613         }
3614         /* unknown count */
3615         if (AOP_SIZE (right) > 1) {
3616                 if (isRegPair (AOP (right))) {
3617                         emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3618                 }
3619                 else {
3620                         emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3621                         emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3622                 }
3623         }
3624         else {
3625                 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3626         }
3627         aopOp (left = IC_LEFT (ic), ic, FALSE);
3628         aopOp (result = IC_RESULT (ic), ic, FALSE);
3629         size = AOP_SIZE (result);
3630         tlbl = newiTempLabel (NULL);
3631         emitcode ("", "L%05d:", tlbl->key);
3632         offset = size - 1;
3633         letype = getSpec (operandType (left));
3634         sign = !SPEC_USIGN (letype);
3635         if (!sameRegs (AOP (left), AOP (result))) {
3636                 while (size--) {
3637                         aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3638                         offset++;
3639                 }
3640                 size = AOP_SIZE (result);
3641         }
3642         size = AOP_SIZE (result);
3643         while (size--) {
3644                 if (first) {
3645                         if (sign)
3646                                 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3647                         else
3648                                 emitcode ("lsr", "%s", aopGet (AOP (result), offset));
3649                         first = 0;
3650                 }
3651                 else
3652                         emitcode ("ror", "%s", aopGet (AOP (result), offset));
3653                 offset--;
3654         }
3655         if (AOP_SIZE (right) > 1)
3656                 emitcode ("sbiw", "r24,1");
3657         else
3658                 emitcode ("dec", "r24");
3659         emitcode ("brne", "L%05d", tlbl->key);
3660
3661         freeAsmop (left, NULL, ic, TRUE);
3662         freeAsmop (result, NULL, ic, TRUE);
3663 }
3664
3665 /*-----------------------------------------------------------------*/
3666 /* RRsh - shift right rn by known count                            */
3667 /*-----------------------------------------------------------------*/
3668 static void
3669 RRsh (int shCount,int reg)
3670 {
3671         shCount &= 0x0007;      // shCount : 0..7
3672
3673         switch (shCount) {
3674         case 0:
3675                 break;
3676         case 1:
3677                 emitcode ("lsr", "r%d",reg);
3678                 break;
3679         case 2:
3680                 emitcode ("lsr", "r%d",reg);
3681                 emitcode ("lsr", "r%d",reg);
3682                 break;
3683         case 3:
3684                 emitcode ("swap", "r%d",reg);
3685                 emitcode ("lsl", "r%d",reg);
3686                 break;
3687         case 4:
3688                 emitcode ("swap", "r%d",reg);
3689                 break;
3690         case 5:
3691                 emitcode ("swap", "r%d",reg);
3692                 emitcode ("lsr", "r%d",reg);
3693                 break;
3694         case 6:
3695                 emitcode ("swap","r%d",reg);
3696                 emitcode ("lsr", "r%d",reg);
3697                 emitcode ("lsr", "r%d",reg);
3698                 break;
3699         case 7:
3700                 emitcode ("swap","r%d",reg);
3701                 emitcode ("lsr", "r%d",reg);
3702                 emitcode ("lsr", "r%d",reg);
3703                 emitcode ("lsr", "r%d",reg);
3704                 break;
3705         }
3706 }
3707
3708 /*-----------------------------------------------------------------*/
3709 /* RLsh - shift left rn by known count                             */
3710 /*-----------------------------------------------------------------*/
3711 static void
3712 RLsh (int shCount, int reg)
3713 {
3714         shCount &= 0x0007;      // shCount : 0..7
3715
3716         switch (shCount) {
3717         case 0:
3718                 break;
3719         case 1:
3720                 emitcode ("lsl", "r%d",reg);
3721                 break;
3722         case 2:
3723                 emitcode ("lsl", "r%d",reg);
3724                 emitcode ("lsl", "r%d",reg);
3725                 break;
3726         case 3:
3727                 emitcode ("swap","r%d",reg);
3728                 emitcode ("lsr", "r%d",reg);
3729                 break;
3730         case 4:
3731                 emitcode ("swap", "r%d",reg);
3732                 break;
3733         case 5:
3734                 emitcode ("swap","r%d",reg);
3735                 emitcode ("lsl", "r%d",reg);
3736                 break;
3737         case 6:
3738                 emitcode ("swap","r%d",reg);
3739                 emitcode ("lsl", "r%d",reg);
3740                 emitcode ("lsl", "r%d",reg);
3741                 break;
3742         case 7:
3743                 emitcode ("swap","r%d",reg);
3744                 emitcode ("lsl", "r%d",reg);
3745                 emitcode ("lsl", "r%d",reg);
3746                 emitcode ("lsl", "r%d",reg);
3747                 break;
3748         }
3749 }
3750
3751 /*-----------------------------------------------------------------*/
3752 /* genUnpackBits - generates code for unpacking bits               */
3753 /*-----------------------------------------------------------------*/
3754 static void
3755 genUnpackBits (operand * result, char *rname, int ptype)
3756 {
3757         int shCnt;
3758         int rlen = 0;
3759         sym_link *etype;
3760         int offset = 0;
3761         int rsize;
3762
3763         etype = getSpec (operandType (result));
3764         rsize = getSize (operandType (result));
3765         /* read the first byte  */
3766         switch (ptype) {
3767
3768         case POINTER:
3769         case IPOINTER:
3770         case PPOINTER:
3771         case FPOINTER:
3772                 emitcode ("ld", "r24,%s+", rname);
3773                 break;
3774
3775         case CPOINTER:
3776                 emitcode ("lpm", "r24,%s+", rname);
3777                 break;
3778
3779         case GPOINTER:
3780                 emitcode ("call","__gptrget_pi");
3781                 emitcode ("mov","r24,r0");
3782                 break;
3783         }
3784
3785         rlen = SPEC_BLEN (etype);
3786
3787         /* if we have bitdisplacement then it fits   */
3788         /* into this byte completely or if length is */
3789         /* less than a byte                          */
3790         if ((shCnt = SPEC_BSTR (etype)) || (SPEC_BLEN (etype) <= 8)) {
3791
3792                 /* shift right acc */
3793                 RRsh (shCnt,24);
3794
3795                 emitcode ("andi", "r24,lo(0x%x)",
3796                           ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
3797                 aopPut (AOP (result), "r24", offset++);
3798                 goto finish;
3799         }
3800
3801         /* bit field did not fit in a byte  */
3802         aopPut (AOP (result), "r24", offset++);
3803
3804         while (1) {
3805
3806                 switch (ptype) {
3807
3808                 case POINTER:
3809                 case IPOINTER:
3810                 case PPOINTER:
3811                 case FPOINTER:
3812                         emitcode ("ld", "r24,%s+");
3813                         break;
3814
3815                 case CPOINTER:
3816                         emitcode ("lpm", "r24,%s+");
3817                         break;
3818
3819                 case GPOINTER:
3820                         emitcode ("call", "__gptrget_pi");
3821                         break;
3822                 }
3823
3824                 rlen -= 8;
3825                 /* if we are done */
3826                 if (rlen < 8)
3827                         break;
3828
3829                 aopPut (AOP (result), "r24", offset++);
3830
3831         }
3832
3833         if (rlen) {
3834                 aopPut (AOP (result), "r24", offset++);
3835         }
3836
3837       finish:
3838         if (offset < rsize) {
3839                 rsize -= offset;
3840                 while (rsize--)
3841                         aopPut (AOP (result), zero, offset++);
3842         }
3843         return;
3844 }
3845
3846 /*-----------------------------------------------------------------*/
3847 /* genDataPointerGet - generates code when ptr offset is known     */
3848 /*-----------------------------------------------------------------*/
3849 static void
3850 genDataPointerGet (operand * left, operand * result, iCode * ic)
3851 {
3852         char *l;
3853         char buffer[256];
3854         int size, offset = 0;
3855         aopOp (result, ic, TRUE);
3856
3857         /* get the string representation of the name */
3858         l = aopGet (AOP (left), 0);
3859         size = AOP_SIZE (result);
3860         while (size--) {
3861                 if (offset)
3862                         sprintf (buffer, "(%s + %d)", l, offset);
3863                 else
3864                         sprintf (buffer, "%s", l);
3865                 emitcode ("lds", "%s,%s", aopGet (AOP (result), offset++),
3866                           buffer);
3867         }
3868
3869         freeAsmop (left, NULL, ic, TRUE);
3870         freeAsmop (result, NULL, ic, TRUE);
3871 }
3872
3873 /*-----------------------------------------------------------------*/
3874 /* genNearPointerGet - emitcode for near pointer fetch             */
3875 /*-----------------------------------------------------------------*/
3876 static void
3877 genMemPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
3878 {
3879         asmop *aop = NULL;
3880         regs *preg = NULL;
3881         int gotFreePtr = 0;
3882         char *rname, *frname = NULL;
3883         sym_link *rtype, *retype;
3884         sym_link *ltype = operandType (left);
3885
3886         rtype = operandType (result);
3887         retype = getSpec (rtype);
3888
3889         aopOp (left, ic, FALSE);
3890
3891         /* if left is rematerialisable and
3892            result is not bit variable type and
3893            the left is pointer to data space i.e
3894            lower 128 bytes of space */
3895         if (AOP_TYPE (left) == AOP_IMMD &&
3896             !IS_BITVAR (retype) && DCL_TYPE (ltype) == POINTER) {
3897                 genDataPointerGet (left, result, ic);
3898                 return;
3899         }
3900
3901         /* if the value is already in a pointer register
3902            then don't need anything more */
3903         if (!AOP_INPREG (AOP (left))) {
3904                 /* otherwise get a free pointer register */
3905                 aop = newAsmop (0);
3906                 preg = getFreePtr (ic, &aop, FALSE, 0);
3907                 if (isRegPair (AOP (left) )) {
3908                         emitcode ("movw", "%s,%s",
3909                                   aop->aopu.aop_ptr->name,
3910                                   aopGet(AOP(left),0));
3911                 } else {
3912                         emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name, 
3913                                   aopGet (AOP (left), 0));
3914                         emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
3915                                   aopGet (AOP (left), 1));
3916                 }
3917                 gotFreePtr = 1;
3918         }
3919         else {
3920                 aop = AOP(left);
3921                 frname = aopGet(aop,0);
3922         }
3923         if (AOP_ISX(aop)) {
3924                 rname = "X";
3925         } else if (AOP_ISZ(aop)) {
3926                 rname = "Z";
3927         } else {
3928                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
3929                         "pointer not in correct register");
3930                 exit (0);
3931         }
3932
3933         aopOp (result, ic, FALSE);
3934
3935         /* if bitfield then unpack the bits */
3936         if (IS_BITVAR (retype))
3937                 genUnpackBits (result, rname, POINTER);
3938         else {
3939                 /* we have can just get the values */
3940                 int size = AOP_SIZE (result);
3941                 int offset = 0;
3942
3943                 while (size--) {
3944                         if (size || pi) {
3945                                 emitcode ("ld","%s,%s+",aopGet(AOP(result),offset), rname);
3946                         } else {
3947                                 emitcode ("ld","%s,%s",aopGet(AOP(result),offset), rname);
3948                         }
3949                 }
3950         }
3951
3952         /* now some housekeeping stuff */
3953         if (gotFreePtr) {
3954                 /* we had to allocate for this iCode */
3955                 if (pi) {
3956                         if (isRegPair (AOP (left) )) {
3957                                 emitcode ("movw", "%s,%s",
3958                                           aopGet (AOP(left),0),
3959                                           aop->aopu.aop_ptr->name);
3960                         } else {
3961                                 emitcode ("mov", "%s,%s", 
3962                                           aopGet (AOP (left), 0),
3963                                           aop->aopu.aop_ptr->name);
3964                                 emitcode ("mov", "%s,%s", 
3965                                           aopGet (AOP (left), 1),
3966                                           aop->aop_ptr2->name);
3967                         }
3968                 }
3969                 freeAsmop (NULL, aop, ic, TRUE);
3970         } else {
3971
3972                 /* we did not allocate which means left
3973                    already in a pointer register, then
3974                    if size > 0 && this could be used again
3975                    we have to point it back to where it
3976                    belongs */
3977                 if ((AOP_SIZE (result) > 1 &&
3978                      !OP_SYMBOL (left)->remat &&
3979                      (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) && !pi) {
3980                         int size = AOP_SIZE (result) - 1;
3981                         emitcode ("sbiw", "%s,%d",frname,size);
3982                 }
3983         }
3984
3985         /* done */
3986         if (pi) pi->generated = 1;
3987         freeAsmop (left, NULL, ic, TRUE);
3988         freeAsmop (result, NULL, ic, TRUE);
3989
3990 }
3991
3992 /*-----------------------------------------------------------------*/
3993 /* genCodePointerGet - gget value from code space                  */
3994 /*-----------------------------------------------------------------*/
3995 static void
3996 genCodePointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
3997 {
3998         int size, offset;
3999         sym_link *retype = getSpec (operandType (result));      
4000         asmop *aop = NULL;
4001         int gotFreePtr = 0;
4002
4003         aopOp (left, ic, FALSE);
4004
4005         /* if the operand is already in Z register
4006            then we do nothing else we move the value to Z register */
4007         if (AOP_ISZ(AOP(left))) {
4008                 aop = AOP (left);
4009         } else {
4010                 aop = newAsmop(0);
4011                 getFreePtr(ic,&aop,FALSE,TRUE);
4012                 if (isRegPair(AOP (left))) {
4013                         emitcode ("movw","r30,%s",aopGet (AOP (left), 0));
4014                 } else {                        
4015                         emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
4016                         emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
4017                 }
4018                 gotFreePtr = 1;
4019         } 
4020
4021         aopOp (result, ic, FALSE);
4022
4023         /* if bit then unpack */
4024         if (IS_BITVAR (retype))
4025                 genUnpackBits (result, "Z", CPOINTER);
4026         else {
4027                 size = AOP_SIZE (result);
4028                 offset = 0;
4029
4030                 while (size--) {
4031                         if (size || pi) {
4032                                 emitcode ("lpm","%s,Z+",aopGet(AOP(result),offset++));
4033                         } else {
4034                                 emitcode ("lpm","%s,Z",aopGet(AOP(result),offset++));
4035                         }
4036                 }
4037         }
4038
4039         /* now some housekeeping stuff */
4040         if (gotFreePtr) {
4041                 /* we had to allocate for this iCode */
4042                 if (pi) {
4043                         if (isRegPair(AOP (left))) {
4044                                 emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
4045                         } else {                        
4046                                 emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
4047                                 emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
4048                         }
4049                 }
4050                 freeAsmop (NULL, aop, ic, TRUE);
4051         } else {
4052
4053                 /* we did not allocate which means left
4054                    already in a pointer register, then
4055                    if size > 0 && this could be used again
4056                    we have to point it back to where it
4057                    belongs */
4058                 if ((AOP_SIZE (result) > 1 &&
4059                      !OP_SYMBOL (left)->remat &&
4060                      (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) &&
4061                     !pi) {
4062                         int size = AOP_SIZE (result) - 1;
4063                         emitcode ("sbiw", "r30,%d",size);
4064                 }
4065         }
4066
4067         /* done */
4068         if (pi) pi->generated=1;
4069         freeAsmop (left, NULL, ic, TRUE);
4070         freeAsmop (result, NULL, ic, TRUE);
4071
4072 }
4073
4074 /*-----------------------------------------------------------------*/
4075 /* genGenPointerGet - gget value from generic pointer space        */
4076 /*-----------------------------------------------------------------*/
4077 static void
4078 genGenPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
4079 {
4080         int size, offset;
4081         int gotFreePtr = 0;
4082         sym_link *retype = getSpec (operandType (result));
4083         asmop *aop = NULL;
4084
4085         aopOp (left, ic, FALSE);
4086
4087         /* if the operand is already in dptr
4088            then we do nothing else we move the value to dptr */
4089         if (AOP_ISZ(AOP(left))) {
4090                 aop = AOP(left);
4091         } else {
4092                 aop = newAsmop(0);
4093                 getFreePtr(ic,&aop,FALSE,TRUE);
4094                 if (isRegPair(AOP(left))) {
4095                         emitcode ("movw", "r30,%s", aopGet (AOP (left), 0));
4096                 } else {
4097                         emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
4098                         emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
4099                 }
4100                 emitcode ("mov", "r24,%s", aopGet (AOP (left), 2));
4101                 gotFreePtr=1;
4102         }
4103
4104         /* so Z register now contains the address */
4105
4106         aopOp (result, ic, FALSE);
4107
4108         /* if bit then unpack */
4109         if (IS_BITVAR (retype))
4110                 genUnpackBits (result, "Z", GPOINTER);
4111         else {
4112                 size = AOP_SIZE (result);
4113                 offset = 0;
4114
4115                 while (size--) {
4116                         if (size || pi) 
4117                                 emitcode ("call", "__gptrget_pi");
4118                         else
4119                                 emitcode ("call", "__gptrget");
4120                         aopPut (AOP (result), "r0", offset++);
4121                 }
4122         }
4123
4124
4125         /* now some housekeeping stuff */
4126         if (gotFreePtr) {
4127                 /* we had to allocate for this iCode */
4128                 if (pi) {
4129                         if (isRegPair(AOP (left))) {
4130                                 emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
4131                         } else {                        
4132                                 emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
4133                                 emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
4134                         }
4135                 }
4136                 freeAsmop (NULL, aop, ic, TRUE);
4137         } else {
4138
4139                 /* we did not allocate which means left
4140                    already in a pointer register, then
4141                    if size > 0 && this could be used again
4142                    we have to point it back to where it
4143                    belongs */
4144                 if ((AOP_SIZE (result) > 1 &&
4145                      !OP_SYMBOL (left)->remat &&
4146                      (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) &&
4147                     !pi) {
4148                         int size = AOP_SIZE (result) - 1;
4149                         emitcode ("sbiw", "r30,%d",size);
4150                 }
4151         }
4152         if (pi) pi->generated=1;
4153         freeAsmop (left, NULL, ic, TRUE);
4154         freeAsmop (result, NULL, ic, TRUE);
4155 }
4156
4157 /*-----------------------------------------------------------------*/
4158 /* genPointerGet - generate code for pointer get                   */
4159 /*-----------------------------------------------------------------*/
4160 static void
4161 genPointerGet (iCode * ic, iCode *pi)
4162 {
4163         operand *left, *result;
4164         sym_link *type, *etype;
4165         int p_type;
4166
4167         left = IC_LEFT (ic);
4168         result = IC_RESULT (ic);
4169
4170         /* depending on the type of pointer we need to
4171            move it to the correct pointer register */
4172         type = operandType (left);
4173         etype = getSpec (type);
4174         /* if left is of type of pointer then it is simple */
4175         if (IS_PTR (type) && !IS_FUNC (type->next))
4176                 p_type = DCL_TYPE (type);
4177         else {
4178                 /* we have to go by the storage class */
4179                 p_type = PTR_TYPE (SPEC_OCLS (etype));
4180
4181
4182         }
4183
4184         /* now that we have the pointer type we assign
4185            the pointer values */
4186         switch (p_type) {
4187
4188         case POINTER:
4189         case IPOINTER:
4190         case PPOINTER:
4191         case FPOINTER:
4192                 genMemPointerGet (left, result, ic, pi);
4193                 break;
4194
4195         case CPOINTER:
4196                 genCodePointerGet (left, result, ic, pi);
4197                 break;
4198
4199         case GPOINTER:
4200                 genGenPointerGet (left, result, ic, pi);
4201                 break;
4202         }
4203
4204 }
4205
4206 /*-----------------------------------------------------------------*/
4207 /* genPackBits - generates code for packed bit storage             */
4208 /*-----------------------------------------------------------------*/
4209 static void
4210 genPackBits (sym_link * etype,
4211              operand * right,
4212              char *rname, int p_type)
4213 {
4214         int shCount = 0;
4215         int offset = 0;
4216         int rLen = 0;
4217         int blen, bstr;
4218         char *l;
4219
4220         blen = SPEC_BLEN (etype);
4221         bstr = SPEC_BSTR (etype);
4222
4223         l = aopGet (AOP (right), offset++);
4224         MOVR24 (l);
4225
4226         /* if the bit lenth is less than or    */
4227         /* it exactly fits a byte then         */
4228         if (SPEC_BLEN (etype) <= 8) {
4229                 shCount = SPEC_BSTR (etype);
4230
4231                 /* shift left acc */
4232                 RLsh (shCount,24);
4233
4234                 if (SPEC_BLEN (etype) < 8) {                    /* if smaller than a byte */
4235
4236                         switch (p_type) {
4237                         case POINTER:
4238                         case IPOINTER:
4239                         case PPOINTER:
4240                         case FPOINTER:
4241                                 emitcode ("ld", "r1,%s",rname);
4242                                 break;
4243
4244                         case GPOINTER:
4245                                 emitcode ("push", "r1");
4246                                 emitcode ("push", "r24");
4247                                 emitcode ("call", "__gptrget");
4248                                 emitcode ("pop", "r1");
4249                                 emitcode ("mov","r24,r0");
4250                                 break;
4251                         }
4252
4253                         emitcode ("andi", "r24,#0x%02x", (unsigned char)
4254                                   ((unsigned char) (0xFF << (blen + bstr)) |
4255                                    (unsigned char) (0xFF >> (8 - bstr))));
4256                         emitcode ("or", "r24,r1");
4257                         if (p_type == GPOINTER)
4258                                 emitcode ("pop", "r1");
4259                 }
4260         }
4261
4262         switch (p_type) {
4263         case POINTER:
4264         case IPOINTER:
4265         case PPOINTER:
4266         case FPOINTER:
4267                 emitcode("st","%s+,r24");
4268                 break;
4269
4270         case GPOINTER:
4271                 emitcode("mov","r0,r24");
4272                 emitcode ("call", "__gptrput_pi");
4273                 break;
4274         }
4275
4276         /* if we r done */
4277         if (SPEC_BLEN (etype) <= 8)
4278                 return;
4279
4280         rLen = SPEC_BLEN (etype);
4281
4282         /* now generate for lengths greater than one byte */
4283         while (1) {
4284
4285                 l = aopGet (AOP (right), offset++);
4286
4287                 rLen -= 8;
4288                 if (rLen < 8)
4289                         break;
4290
4291                 switch (p_type) {
4292                 case POINTER:
4293                 case IPOINTER:
4294                 case PPOINTER:
4295                 case FPOINTER:
4296                         emitcode ("st", "%s+,%s",rname,l);
4297                         break;
4298
4299                 case GPOINTER:
4300                         MOVR0 (l);
4301                         emitcode ("lcall", "__gptrput_pi");
4302                         break;
4303                 }
4304         }
4305
4306         MOVR24 (l);
4307
4308         /* last last was not complete */
4309         if (rLen) {
4310                 /* save the byte & read byte */
4311                 switch (p_type) {
4312                 case POINTER:
4313                 case IPOINTER:
4314                 case PPOINTER:
4315                 case FPOINTER:
4316                         emitcode ("st","%s+,r24",rname);
4317                         break;
4318                 case GPOINTER:
4319                         emitcode ("push", "r1");
4320                         emitcode ("push", "r24");
4321                         emitcode ("lcall", "__gptrget");
4322                         emitcode ("mov","r24,r0");
4323                         emitcode ("pop", "r1");
4324                         break;
4325                 }
4326
4327                 emitcode ("andi", "r24,0x%02x", (((unsigned char) -1 << rLen) & 0xff));
4328                 emitcode ("or", "r24,r1");
4329         }
4330
4331         if (p_type == GPOINTER)
4332                 emitcode ("pop", "r1");
4333
4334         switch (p_type) {
4335
4336         case POINTER:
4337         case IPOINTER:
4338         case PPOINTER:
4339         case FPOINTER:
4340                 emitcode ("st", "%s,r24", rname);
4341                 break;
4342
4343         case GPOINTER:
4344                 emitcode ("mov","r0,r24");
4345                 emitcode ("call", "__gptrput");
4346                 break;
4347         }
4348 }
4349
4350 /*-----------------------------------------------------------------*/
4351 /* genDataPointerSet - remat pointer to data space                 */
4352 /*-----------------------------------------------------------------*/
4353 static void
4354 genDataPointerSet (operand * right, operand * result, iCode * ic)
4355 {
4356         int size, offset = 0;
4357         char *l, buffer[256];
4358
4359         aopOp (right, ic, FALSE);
4360
4361         l = aopGet (AOP (result), 0);
4362         size = AOP_SIZE (right);
4363         while (size--) {
4364                 if (offset)
4365                         sprintf (buffer, "(%s + %d)", l, offset);
4366                 else
4367                         sprintf (buffer, "%s", l);
4368                 emitcode ("sts", "%s,%s", buffer,
4369                           aopGet (AOP (right), offset++));
4370         }
4371
4372         freeAsmop (right, NULL, ic, TRUE);
4373         freeAsmop (result, NULL, ic, TRUE);
4374 }
4375
4376 /*-----------------------------------------------------------------*/
4377 /* genNearPointerSet - emitcode for near pointer put               */
4378 /*-----------------------------------------------------------------*/
4379 static void
4380 genMemPointerSet (operand * right, operand * result, iCode * ic, iCode *pi)
4381 {
4382         asmop *aop = NULL;
4383         char *frname = NULL, *rname, *l;
4384         int gotFreePtr = 0;
4385         sym_link *retype;
4386         sym_link *ptype = operandType (result);
4387         
4388         retype = getSpec (operandType (right));
4389         
4390         aopOp (result, ic, FALSE);
4391         
4392         /* if the result is rematerializable &
4393            in data space & not a bit variable */
4394         if (AOP_TYPE (result) == AOP_IMMD &&
4395             DCL_TYPE (ptype) == POINTER && !IS_BITVAR (retype)) {
4396                 genDataPointerSet (right, result, ic);
4397                 return;
4398         }
4399         if (!AOP_INPREG(AOP(result))) {
4400                 /* otherwise get a free pointer register */
4401                 aop = newAsmop (0);
4402                 getFreePtr (ic, &aop, FALSE, 0);
4403                 if (isRegPair (AOP (result) )) {
4404                         emitcode ("movw", "%s,%s",aop->aopu.aop_ptr->name,
4405                                   aopGet(AOP (result), 0));
4406                 } else {
4407                         emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name, 
4408                                   aopGet (AOP (result), 0));
4409                         emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
4410                                   aopGet (AOP (result), 1));
4411                 }
4412                 gotFreePtr = 1;         
4413         } else {
4414                 aop = AOP(result);
4415                 frname = aopGet(aop,0);
4416         }
4417         
4418         aopOp (right, ic, FALSE);
4419         if (AOP_ISX(aop)) {
4420                 rname = "X";
4421         } else if (AOP_ISZ(aop)) {
4422                 rname = "Z";
4423         } else {
4424                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4425                         "pointer not in correct register");
4426                 exit (0);
4427         }
4428         /* if bitfield then unpack the bits */
4429         if (IS_BITVAR (retype))
4430                 genPackBits (retype, right, rname, POINTER);
4431         else {
4432                 /* we have can just get the values */
4433                 int size = AOP_SIZE (right);
4434                 int offset = 0;
4435
4436                 while (size--) {
4437                         l = aopGet (AOP (right), offset);
4438                         if (size || pi)
4439                                 emitcode ("st", "%s+,%s", rname,l);
4440                         else
4441                                 emitcode ("st", "%s,%s", rname,l);                              
4442                         offset++;
4443                 }
4444         }
4445         
4446         /* now some housekeeping stuff */
4447         if (gotFreePtr) {
4448                 /* we had to allocate for this iCode */
4449                 if (pi) {
4450                         if (isRegPair (AOP (result) )) {
4451                                 emitcode ("movw", "%s,%s",
4452                                           aopGet(AOP(result),0),
4453                                           aop->aopu.aop_ptr->name);
4454                         } else {
4455                                 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name, 
4456                                           aopGet (AOP (result), 0));
4457                                 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
4458                                           aopGet (AOP (result), 1));
4459                         }
4460                 }
4461                 freeAsmop (NULL, aop, ic, TRUE);
4462         } else {
4463
4464                 /* we did not allocate which means left
4465                    already in a pointer register, then
4466                    if size > 0 && this could be used again
4467                    we have to point it back to where it
4468                    belongs */
4469                 if ((AOP_SIZE (right) > 1 &&
4470                      !OP_SYMBOL (result)->remat &&
4471                      (OP_SYMBOL (right)->liveTo > ic->seq || ic->depth)) && !pi) {
4472                         int size = AOP_SIZE (right) - 1;
4473                         emitcode ("sbiw", "%s,%d",frname,size);
4474                 }
4475         }
4476
4477         /* done */
4478         if (pi) pi->generated = 1;
4479         freeAsmop (result, NULL, ic, TRUE);
4480         freeAsmop (right, NULL, ic, TRUE);
4481 }
4482
4483 /*-----------------------------------------------------------------*/
4484 /* genGenPointerSet - set value from generic pointer space         */
4485 /*-----------------------------------------------------------------*/
4486 static void
4487 genGenPointerSet (operand * right, operand * result, iCode * ic, iCode *pi)
4488 {
4489         int size, offset;
4490         int gotFreePtr = 0;
4491         sym_link *retype = getSpec (operandType (right));
4492         asmop *aop = NULL;       
4493         
4494         aopOp (result, ic, FALSE);
4495         
4496         /* if the operand is already in dptr
4497            then we do nothing else we move the value to dptr */
4498         if (AOP_ISZ(AOP(result))) {
4499                 aop = AOP(right);
4500         } else {
4501                 aop = newAsmop(0);
4502                 getFreePtr(ic,&aop,FALSE,TRUE);
4503                 if (isRegPair(AOP(result))) {
4504                         emitcode ("movw", "r30,%s", aopGet (AOP (result), 0));
4505                 } else {
4506                         emitcode ("mov", "r30,%s", aopGet (AOP (result), 0));
4507                         emitcode ("mov", "r31,%s", aopGet (AOP (result), 1));
4508                 }
4509                 emitcode ("mov", "r24,%s",  aopGet (AOP (result), 2));
4510                 gotFreePtr=1;
4511         }
4512         
4513         /* so Z register now contains the address */
4514         aopOp (right, ic, FALSE);
4515         
4516         /* if bit then unpack */
4517         if (IS_BITVAR (retype))
4518                 genUnpackBits (result, "Z", GPOINTER);
4519         else {
4520                 size = AOP_SIZE (right);
4521                 offset = 0;
4522                 
4523                 while (size--) {
4524                         char *l = aopGet(AOP (right), offset++);
4525                         MOVR0(l);
4526                         
4527                         if (size || pi) 
4528                                 emitcode ("call", "__gptrput_pi");
4529                         else
4530                                 emitcode ("call", "__gptrput");
4531                 }
4532         }
4533
4534         /* now some housekeeping stuff */
4535         if (gotFreePtr) {
4536                 /* we had to allocate for this iCode */
4537                 if (pi) {
4538                         if (isRegPair(AOP(result))) {
4539                                 emitcode ("movw", "%s,r30", aopGet (AOP (result), 0));
4540                         } else {
4541                                 emitcode ("mov", "%s,r30", aopGet (AOP (result), 0));
4542                                 emitcode ("mov", "%s,r31", aopGet (AOP (result), 1));
4543                         }
4544                 }
4545                 freeAsmop (NULL, aop, ic, TRUE);
4546         } else {
4547
4548                 /* we did not allocate which means left
4549                    already in a pointer register, then
4550                    if size > 0 && this could be used again
4551                    we have to point it back to where it
4552                    belongs */
4553                 if ((AOP_SIZE (right) > 1 &&
4554                      !OP_SYMBOL (result)->remat &&
4555                      (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) && !pi) {
4556                         int size = AOP_SIZE (right) - 1;
4557                         emitcode ("sbiw", "r30,%d",size);
4558                 }
4559         }
4560         if (pi) pi->generated = 1;
4561         freeAsmop (right, NULL, ic, TRUE);
4562         freeAsmop (result, NULL, ic, TRUE);
4563 }
4564
4565 /*-----------------------------------------------------------------*/
4566 /* genPointerSet - stores the value into a pointer location        */
4567 /*-----------------------------------------------------------------*/
4568 static void
4569 genPointerSet (iCode * ic, iCode *pi)
4570 {
4571         operand *right, *result;
4572         sym_link *type, *etype;
4573         int p_type;
4574
4575         right = IC_RIGHT (ic);
4576         result = IC_RESULT (ic);
4577
4578         /* depending on the type of pointer we need to
4579            move it to the correct pointer register */
4580         type = operandType (result);
4581         etype = getSpec (type);
4582         /* if left is of type of pointer then it is simple */
4583         if (IS_PTR (type) && !IS_FUNC (type->next)) {
4584                 p_type = DCL_TYPE (type);
4585         }
4586         else {
4587                 /* we have to go by the storage class */
4588                 p_type = PTR_TYPE (SPEC_OCLS (etype));
4589
4590         }
4591
4592         /* now that we have the pointer type we assign
4593            the pointer values */
4594         switch (p_type) {
4595
4596         case POINTER:
4597         case IPOINTER:
4598         case PPOINTER:
4599         case FPOINTER:
4600                 genMemPointerSet (right, result, ic, pi);
4601                 break;
4602
4603         case GPOINTER:
4604                 genGenPointerSet (right, result, ic, pi);
4605                 break;
4606
4607         default:
4608           werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
4609                   "genPointerSet: illegal pointer type");
4610         }
4611
4612 }
4613
4614 /*-----------------------------------------------------------------*/
4615 /* genIfx - generate code for Ifx statement                        */
4616 /*-----------------------------------------------------------------*/
4617 static void
4618 genIfx (iCode * ic, iCode * popIc)
4619 {
4620         operand *cond = IC_COND (ic);
4621         char *cname ;
4622         symbol *lbl;
4623         int tob = 0;
4624
4625         aopOp (cond, ic, FALSE);
4626
4627         /* get the value into acc */    
4628         if (AOP_SIZE(cond) == 1 && AOP_ISHIGHREG(AOP(cond),0)) {
4629                 cname = aopGet(AOP(cond),0);
4630         } else {
4631                 toBoolean (cond, "r24", 0);
4632                 tob = 1;
4633                 cname = "r24";
4634         }
4635         /* the result is now in the accumulator */
4636         freeAsmop (cond, NULL, ic, TRUE);
4637
4638         /* if there was something to be popped then do it */
4639         if (popIc) {
4640                 genIpop (popIc);
4641                 emitcode("cpi","%s,0",cname);
4642         } else if (!tob) emitcode("cpi","%s,0",cname);
4643
4644         lbl = newiTempLabel(NULL);
4645         if (IC_TRUE(ic)) {
4646                 emitcode ("breq","L%05d",lbl->key);
4647                 emitcode ("jmp","L%05d",IC_TRUE(ic)->key);
4648                 emitcode ("","L%05d:",lbl->key);
4649         } else {
4650                 emitcode ("brne","L%05d",lbl->key);
4651                 emitcode ("jmp","L%05d",IC_FALSE(ic)->key);
4652                 emitcode ("","L%05d:",lbl->key);
4653         }
4654         ic->generated = 1;
4655 }
4656
4657 /*-----------------------------------------------------------------*/
4658 /* genAddrOf - generates code for address of                       */
4659 /*-----------------------------------------------------------------*/
4660 static void
4661 genAddrOf (iCode * ic)
4662 {
4663         symbol *sym = OP_SYMBOL (IC_LEFT (ic));
4664         int size, offset;
4665
4666         aopOp (IC_RESULT (ic), ic, FALSE);
4667         assert(AOP_SIZE(IC_RESULT(ic)) >= 2);
4668         /* if the operand is on the stack then we
4669            need to get the stack offset of this
4670            variable */
4671         if (sym->onStack) {
4672                 /* if it has an offset then we need to compute it */
4673                 if (sym->stack) {
4674                         if (allHigh(AOP(IC_RESULT(ic)))) {
4675                                 if (isRegPair (AOP(IC_RESULT(ic)))) {
4676                                         emitcode ("movw","%s,r28",aopGet(AOP(IC_RESULT(ic)),0));                                        
4677                                 } else {
4678                                         emitcode ("mov","%s,r28",aopGet(AOP(IC_RESULT(ic)),0));
4679                                         emitcode ("mov","%s,r29",aopGet(AOP(IC_RESULT(ic)),1));                                 
4680                                 }
4681                                 if (sym->stack < 0) {
4682                                         emitcode("subi","%s,<(%d)",aopGet(AOP(IC_RESULT(ic)),0),-sym->stack);
4683                                         emitcode("sbci","%s,>(%d)",aopGet(AOP(IC_RESULT(ic)),1),-sym->stack);
4684                                 } else {
4685                                         emitcode("subi","%s,<(-%d)",aopGet(AOP(IC_RESULT(ic)),0),sym->stack);
4686                                         emitcode("sbci","%s,>(-%d)",aopGet(AOP(IC_RESULT(ic)),1),sym->stack);
4687                                 }
4688                         } else {
4689                                 emitcode("movw","r24,r28");
4690                                 if (sym->stack > -63 && sym->stack < 63) {
4691                                         if (sym->stack < 0)
4692                                                 emitcode("sbiw","r24,%d",-sym->stack);
4693                                         else
4694                                                 emitcode("sbiw","r24,%d",sym->stack);
4695                                 } else {                                        
4696                                         if (sym->stack < 0) {
4697                                                 emitcode("subi","r24,<(%d)",-sym->stack);
4698                                                 emitcode("sbci","r25,>(%d)",-sym->stack);
4699                                         } else {
4700                                                 emitcode("subi","r24,<(-%d)",sym->stack);
4701                                                 emitcode("sbci","r25,>(-%d)",sym->stack);
4702                                         }
4703                                 }
4704                                 
4705                                 aopPut(AOP(IC_RESULT(ic)),"r24",0);
4706                                 aopPut(AOP(IC_RESULT(ic)),"r25",1);
4707                         }
4708                 }
4709                 else {
4710                         aopPut(AOP(IC_RESULT(ic)),"r28",0);
4711                         aopPut(AOP(IC_RESULT(ic)),"r29",1);
4712                 }
4713                 /* fill the result with zero */
4714                 size = AOP_SIZE (IC_RESULT (ic)) - 2;
4715                 offset = 2;
4716                 while (size--) {
4717                         aopPut (AOP (IC_RESULT (ic)), zero, offset++);
4718                 }
4719
4720                 goto release;
4721         }
4722
4723         /* object not on stack then we need the name */
4724         size = AOP_SIZE (IC_RESULT (ic));
4725         offset = 0;
4726         assert(size<=2);
4727         while (size--) {
4728                 char s[SDCC_NAME_MAX];
4729                 if (offset)
4730                         sprintf (s, ">(%s)", sym->rname);
4731                 else
4732                         sprintf (s, "<(%s)", sym->rname);
4733                 aopPut (AOP (IC_RESULT (ic)), s, offset++);
4734         }
4735
4736       release:
4737         freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4738
4739 }
4740
4741 /*-----------------------------------------------------------------*/
4742 /* genFarFarAssign - assignment when both are in far space         */
4743 /*-----------------------------------------------------------------*/
4744 static void
4745 genFarFarAssign (operand * result, operand * right, iCode * ic)
4746 {
4747         int size = AOP_SIZE (right);
4748         int offset = 0;
4749         char *l;
4750         /* first push the right side on to the stack */
4751         while (size--) {
4752                 l = aopGet (AOP (right), offset++);
4753                 MOVA (l);
4754                 emitcode ("push", "acc");
4755         }
4756
4757         freeAsmop (right, NULL, ic, FALSE);
4758         /* now assign DPTR to result */
4759         aopOp (result, ic, FALSE);
4760         size = AOP_SIZE (result);
4761         while (size--) {
4762                 emitcode ("pop", "acc");
4763                 aopPut (AOP (result), "a", --offset);
4764         }
4765         freeAsmop (result, NULL, ic, FALSE);
4766
4767 }
4768
4769 /*-----------------------------------------------------------------*/
4770 /* genAssign - generate code for assignment                        */
4771 /*-----------------------------------------------------------------*/
4772 static void
4773 genAssign (iCode * ic)
4774 {
4775         operand *result, *right;
4776         int size, offset;
4777         unsigned long lit = 0L;
4778
4779         result = IC_RESULT (ic);
4780         right = IC_RIGHT (ic);
4781
4782         /* if they are the same */
4783         if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4784                 return;
4785
4786         aopOp (right, ic, FALSE);
4787
4788         /* special case both in far space */
4789         if (AOP_TYPE (right) == AOP_DPTR &&
4790             IS_TRUE_SYMOP (result) && isOperandInFarSpace (result)) {
4791
4792                 genFarFarAssign (result, right, ic);
4793                 return;
4794         }
4795
4796         aopOp (result, ic, TRUE);
4797
4798         /* if they are the same registers */
4799         if (sameRegs (AOP (right), AOP (result)))
4800                 goto release;
4801
4802         /* if the result is a bit */
4803         if (AOP_TYPE (result) == AOP_CRY) {
4804
4805                 /* if the right size is a literal then
4806                    we know what the value is */
4807                 if (AOP_TYPE (right) == AOP_LIT) {
4808                         if (((int) operandLitValue (right)))
4809                                 aopPut (AOP (result), one, 0);
4810                         else
4811                                 aopPut (AOP (result), zero, 0);
4812                         goto release;
4813                 }
4814
4815                 /* the right is also a bit variable */
4816                 if (AOP_TYPE (right) == AOP_CRY) {
4817                         emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4818                         aopPut (AOP (result), "c", 0);
4819                         goto release;
4820                 }
4821
4822                 /* we need to or */
4823                 toBoolean (right, "", 0);
4824                 aopPut (AOP (result), "a", 0);
4825                 goto release;
4826         }
4827
4828         /* bit variables done */
4829         /* general case */
4830         size = AOP_SIZE (result);
4831         offset = 0;
4832         if (AOP_TYPE (right) == AOP_LIT)
4833                 lit =
4834                         (unsigned long) floatFromVal (AOP (right)->aopu.
4835                                                       aop_lit);
4836         if ((size > 1) && (AOP_TYPE (result) != AOP_REG)
4837             && (AOP_TYPE (right) == AOP_LIT)
4838             && !IS_FLOAT (operandType (right)) && (lit < 256L)) {
4839                 emitcode ("clr", "a");
4840                 while (size--) {
4841                         if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) ==
4842                             0) aopPut (AOP (result), "a", size);
4843                         else
4844                                 aopPut (AOP (result),
4845                                         aopGet (AOP (right), size), size);
4846                 }
4847         }
4848         else {
4849                 while (size--) {
4850                         aopPut (AOP (result),
4851                                 aopGet (AOP (right), offset), offset);
4852                         offset++;
4853                 }
4854         }
4855
4856       release:
4857         freeAsmop (right, NULL, ic, FALSE);
4858         freeAsmop (result, NULL, ic, TRUE);
4859 }
4860
4861 /*-----------------------------------------------------------------*/
4862 /* genJumpTab - genrates code for jump table                       */
4863 /*-----------------------------------------------------------------*/
4864 static void
4865 genJumpTab (iCode * ic)
4866 {
4867         symbol *jtab;
4868         char *l;
4869
4870         aopOp (IC_JTCOND (ic), ic, FALSE);
4871         /* get the condition into accumulator */
4872         l = aopGet (AOP (IC_JTCOND (ic)), 0);
4873         MOVA (l);
4874         /* multiply by three */
4875         emitcode ("add", "a,acc");
4876         emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0));
4877         freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
4878
4879         jtab = newiTempLabel (NULL);
4880         emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
4881         emitcode ("jmp", "@a+dptr");
4882         emitcode ("", "%05d$:", jtab->key + 100);
4883         /* now generate the jump labels */
4884         for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
4885              jtab = setNextItem (IC_JTLABELS (ic)))
4886                 emitcode ("ljmp", "%05d$", jtab->key + 100);
4887
4888 }
4889
4890 /*-----------------------------------------------------------------*/
4891 /* genCast - gen code for casting                                  */
4892 /*-----------------------------------------------------------------*/
4893 static void
4894 genCast (iCode * ic)
4895 {
4896         operand *result = IC_RESULT (ic);
4897         sym_link *ctype = operandType (IC_LEFT (ic));
4898         sym_link *rtype = operandType (IC_RIGHT (ic));
4899         operand *right = IC_RIGHT (ic);
4900         int size, offset;
4901
4902         /* if they are equivalent then do nothing */
4903         if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4904                 return;
4905
4906         aopOp (right, ic, FALSE);
4907         aopOp (result, ic, FALSE);
4908
4909         /* if the result is a bit */
4910         if (AOP_TYPE (result) == AOP_CRY) {
4911                 /* if the right size is a literal then
4912                    we know what the value is */
4913                 if (AOP_TYPE (right) == AOP_LIT) {
4914                         if (((int) operandLitValue (right)))
4915                                 aopPut (AOP (result), one, 0);
4916                         else
4917                                 aopPut (AOP (result), zero, 0);
4918
4919                         goto release;
4920                 }
4921
4922                 /* the right is also a bit variable */
4923                 if (AOP_TYPE (right) == AOP_CRY) {
4924                         emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4925                         aopPut (AOP (result), "c", 0);
4926                         goto release;
4927                 }
4928
4929                 /* we need to or */
4930                 toBoolean (right, "", 0);
4931                 aopPut (AOP (result), "a", 0);
4932                 goto release;
4933         }
4934
4935         /* if they are the same size : or less */
4936         if (AOP_SIZE (result) <= AOP_SIZE (right)) {
4937
4938                 /* if they are in the same place */
4939                 if (sameRegs (AOP (right), AOP (result)))
4940                         goto release;
4941
4942                 /* if they in different places then copy */
4943                 size = AOP_SIZE (result);
4944                 offset = 0;
4945                 while (size--) {
4946                         aopPut (AOP (result),
4947                                 aopGet (AOP (right), offset), offset);
4948                         offset++;
4949                 }
4950                 goto release;
4951         }
4952
4953
4954         /* if the result is of type pointer */
4955         if (IS_PTR (ctype)) {
4956
4957                 int p_type;
4958                 sym_link *type = operandType (right);
4959                 sym_link *etype = getSpec (type);
4960
4961                 /* pointer to generic pointer */
4962                 if (IS_GENPTR (ctype)) {
4963                         if (IS_PTR (type))
4964                                 p_type = DCL_TYPE (type);
4965                         else {
4966                                 /* we have to go by the storage class */
4967                                 p_type = PTR_TYPE (SPEC_OCLS (etype));
4968                         }
4969
4970                         /* the first two bytes are known */
4971                         size = GPTRSIZE - 1;
4972                         offset = 0;
4973                         while (size--) {
4974                                 aopPut (AOP (result),
4975                                         aopGet (AOP (right), offset), offset);
4976                                 offset++;
4977                         }
4978                     
4979                     /* the last byte depending on type */
4980                     {
4981                         int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
4982                         char gpValStr[10];
4983                         
4984                         if (gpVal == -1)
4985                         {
4986                             // pointerTypeToGPByte will have bitched.
4987                             exit(1);
4988                         }
4989                         
4990                         sprintf(gpValStr, "#0x%x", gpVal);
4991                         aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
4992                     }               
4993                     goto release;
4994                 }
4995
4996                 /* just copy the pointers */
4997                 size = AOP_SIZE (result);
4998                 offset = 0;
4999                 while (size--) {
5000                         aopPut (AOP (result),
5001                                 aopGet (AOP (right), offset), offset);
5002                         offset++;
5003                 }
5004                 goto release;
5005         }
5006
5007         /* so we now know that the size of destination is greater
5008            than the size of the source */
5009         /* we move to result for the size of source */
5010         size = AOP_SIZE (right);
5011         offset = 0;
5012         while (size--) {
5013                 aopPut (AOP (result), aopGet (AOP (right), offset), offset);
5014                 offset++;
5015         }
5016
5017         /* now depending on the sign of the source && destination */
5018         size = AOP_SIZE (result) - AOP_SIZE (right);
5019         /* if unsigned or not an integral type */
5020         if (SPEC_USIGN (rtype) || !IS_SPEC (rtype)) {
5021                 while (size--)
5022                         aopPut (AOP (result), zero, offset++);
5023         }
5024         else {
5025                 /* we need to extend the sign :{ */
5026                 // PENDING: Does nothing on avr
5027 #if 0
5028                 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1);
5029                 MOVA (l);
5030 #endif
5031                 emitcode ("rlc", "a");
5032                 emitcode ("subb", "a,acc");
5033                 while (size--)
5034                         aopPut (AOP (result), "a", offset++);
5035         }
5036
5037         /* we are done hurray !!!! */
5038
5039       release:
5040         freeAsmop (right, NULL, ic, TRUE);
5041         freeAsmop (result, NULL, ic, TRUE);
5042
5043 }
5044
5045 /*-----------------------------------------------------------------*/
5046 /* genDjnz - generate decrement & jump if not zero instrucion      */
5047 /*-----------------------------------------------------------------*/
5048 static int
5049 genDjnz (iCode * ic, iCode * ifx)
5050 {
5051         symbol *lbl, *lbl1;
5052         if (!ifx)
5053                 return 0;
5054
5055         /* if the if condition has a false label
5056            then we cannot save */
5057         if (IC_FALSE (ifx))
5058                 return 0;
5059
5060         /* if the minus is not of the form
5061            a = a - 1 */
5062         if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
5063             !IS_OP_LITERAL (IC_RIGHT (ic)))
5064                 return 0;
5065
5066         if (operandLitValue (IC_RIGHT (ic)) != 1)
5067                 return 0;
5068
5069         /* if the size of this greater than one then no
5070            saving */
5071         if (getSize (operandType (IC_RESULT (ic))) > 1)
5072                 return 0;
5073
5074         /* otherwise we can save BIG */
5075         lbl = newiTempLabel (NULL);
5076         lbl1 = newiTempLabel (NULL);
5077
5078         aopOp (IC_RESULT (ic), ic, FALSE);
5079
5080         if (IS_AOP_PREG (IC_RESULT (ic))) {
5081                 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0));
5082                 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0));
5083                 emitcode ("jnz", "%05d$", lbl->key + 100);
5084         }
5085         else {
5086                 emitcode ("djnz", "%s,%05d$",
5087                           aopGet (AOP (IC_RESULT (ic)), 0), lbl->key + 100);
5088         }
5089         emitcode ("sjmp", "%05d$", lbl1->key + 100);
5090         emitcode ("", "%05d$:", lbl->key + 100);
5091         emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5092         emitcode ("", "%05d$:", lbl1->key + 100);
5093
5094         freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5095         ifx->generated = 1;
5096         return 1;
5097 }
5098
5099 static char *recvregs[8] = {
5100         "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23"
5101 };
5102
5103 static int recvCnt = 0;
5104
5105 /*-----------------------------------------------------------------*/
5106 /* genReceive - generate code for a receive iCode                  */
5107 /*-----------------------------------------------------------------*/
5108 static void
5109 genReceive (iCode * ic)
5110 {
5111         int size, offset = 0;
5112         aopOp (IC_RESULT (ic), ic, FALSE);
5113         size = AOP_SIZE (IC_RESULT (ic));
5114         while (size--) {
5115                 aopPut (AOP (IC_RESULT (ic)), recvregs[recvCnt++], offset);
5116                 offset++;
5117         }
5118         freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5119 }
5120
5121 /*-----------------------------------------------------------------*/
5122 /* genDummyRead - generate code for dummy read of volatiles        */
5123 /*-----------------------------------------------------------------*/
5124 static void
5125 genDummyRead (iCode * ic)
5126 {
5127   emitcode (";     genDummyRead","");
5128   emitcode (";     not implemented","");
5129
5130   ic = ic;
5131 }
5132
5133 /*-----------------------------------------------------------------*/
5134 /* gen51Code - generate code for 8051 based controllers            */
5135 /*-----------------------------------------------------------------*/
5136 void
5137 genAVRCode (iCode * lic)
5138 {
5139         iCode *ic;
5140         int cln = 0;
5141
5142         lineHead = lineCurr = NULL;
5143         recvCnt = 0;
5144         /* print the allocation information */
5145         if (allocInfo)
5146                 printAllocInfo (currFunc, codeOutBuf);
5147         /* if debug information required */
5148         if (options.debug && currFunc) {
5149                 debugFile->writeFunction (currFunc, lic);
5150         }
5151         /* stack pointer name */
5152         spname = "sp";
5153
5154
5155         for (ic = lic; ic; ic = ic->next) {
5156
5157                 if (cln != ic->lineno) {
5158                         if (options.debug) {
5159                                 debugFile->writeCLine (ic);
5160                         }
5161                         emitcode (";", "%s %d", ic->filename, ic->lineno);
5162                         cln = ic->lineno;
5163                 }
5164                 /* if the result is marked as
5165                    spilt and rematerializable or code for
5166                    this has already been generated then
5167                    do nothing */
5168                 if (resultRemat (ic) || ic->generated)
5169                         continue;
5170
5171                 /* depending on the operation */
5172                 switch (ic->op) {
5173                 case '!':
5174                         genNot (ic);
5175                         break;
5176
5177                 case '~':
5178                         genCpl (ic);
5179                         break;
5180
5181                 case UNARYMINUS:
5182                         genUminus (ic);
5183                         break;
5184
5185                 case IPUSH:
5186                         genIpush (ic);
5187                         break;
5188
5189                 case IPOP:
5190                         /* IPOP happens only when trying to restore a
5191                            spilt live range, if there is an ifx statement
5192                            following this pop then the if statement might
5193                            be using some of the registers being popped which
5194                            would destory the contents of the register so
5195                            we need to check for this condition and handle it */
5196                         if (ic->next &&
5197                             ic->next->op == IFX &&
5198                             regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
5199                                 genIfx (ic->next, ic);
5200                         else
5201                                 genIpop (ic);
5202                         break;
5203
5204                 case CALL:
5205                         genCall (ic);
5206                         break;
5207
5208                 case PCALL:
5209                         genPcall (ic);
5210                         break;
5211
5212                 case FUNCTION:
5213                         genFunction (ic);
5214                         break;
5215
5216                 case ENDFUNCTION:
5217                         genEndFunction (ic);
5218                         break;
5219
5220                 case RETURN:
5221                         genRet (ic);
5222                         break;
5223
5224                 case LABEL:
5225                         genLabel (ic);
5226                         break;
5227
5228                 case GOTO:
5229                         genGoto (ic);
5230                         break;
5231
5232                 case '+':
5233                         genPlus (ic);
5234                         break;
5235
5236                 case '-':
5237                         if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
5238                                 genMinus (ic);
5239                         break;
5240
5241                 case '*':
5242                         genMult (ic);
5243                         break;
5244
5245                 case '/':
5246                         genDiv (ic);
5247                         break;
5248
5249                 case '%':
5250                         genMod (ic);
5251                         break;
5252
5253                 case '>':
5254                         genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
5255                         break;
5256
5257                 case '<':
5258                         genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
5259                         break;
5260
5261                 case LE_OP:
5262                         genCmpLe (ic, ifxForOp (IC_RESULT (ic), ic));
5263                         break;
5264
5265                 case GE_OP:
5266                         genCmpGe (ic, ifxForOp (IC_RESULT (ic), ic));
5267                         break;
5268
5269                 case NE_OP:
5270                         genCmpNe (ic, ifxForOp (IC_RESULT (ic), ic));
5271                         break;
5272
5273                 case EQ_OP:
5274                         genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
5275                         break;
5276
5277                 case AND_OP:
5278                         genAndOp (ic);
5279                         break;
5280
5281                 case OR_OP:
5282                         genOrOp (ic);
5283                         break;
5284
5285                 case '^':
5286                         genXor (ic, ifxForOp (IC_RESULT (ic), ic));
5287                         break;
5288
5289                 case '|':
5290                         genOr (ic, ifxForOp (IC_RESULT (ic), ic));
5291                         break;
5292
5293                 case BITWISEAND:
5294                         genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
5295                         break;
5296
5297                 case INLINEASM:
5298                         genInline (ic);
5299                         break;
5300
5301                 case RRC:
5302                         genRRC (ic);
5303                         break;
5304
5305                 case RLC:
5306                         genRLC (ic);
5307                         break;
5308
5309                 case GETHBIT:
5310                         genGetHbit (ic);
5311                         break;
5312
5313                 case LEFT_OP:
5314                         genLeftShift (ic);
5315                         break;
5316
5317                 case RIGHT_OP:
5318                         genRightShift (ic);
5319                         break;
5320
5321                 case GET_VALUE_AT_ADDRESS:
5322                         genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
5323                         break;
5324
5325                 case '=':
5326                         if (POINTER_SET (ic))
5327                                 genPointerSet (ic, hasInc(IC_RESULT(ic),ic));
5328                         else
5329                                 genAssign (ic);
5330                         break;
5331
5332                 case IFX:
5333                         genIfx (ic, NULL);
5334                         break;
5335
5336                 case ADDRESS_OF:
5337                         genAddrOf (ic);
5338                         break;
5339
5340                 case JUMPTABLE:
5341                         genJumpTab (ic);
5342                         break;
5343
5344                 case CAST:
5345                         genCast (ic);
5346                         break;
5347
5348                 case RECEIVE:
5349                         genReceive (ic);
5350                         break;
5351
5352                 case SEND:
5353                         addSet (&_G.sendSet, ic);
5354                         break;
5355
5356                 case DUMMY_READ_VOLATILE:
5357                         genDummyRead (ic);
5358                         break;
5359
5360                 default:
5361                         ic = ic;
5362                 }
5363         }
5364
5365
5366         /* now we are ready to call the
5367            peep hole optimizer */
5368         if (!options.nopeep)
5369                 peepHole (&lineHead);
5370
5371         /* now do the actual printing */
5372         printLine (lineHead, codeOutBuf);
5373         return;
5374 }