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