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