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