1 /*-------------------------------------------------------------------------
2 avrgen.c - source file for code generation for ATMEL AVR
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (2000)
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
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.
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.
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!
25 -------------------------------------------------------------------------*/
31 #include "SDCCglobl.h"
34 #ifdef HAVE_SYS_ISA_DEFS_H
35 #include <sys/isa_defs.h>
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"
48 #include "SDCCpeeph.h"
52 char *aopLiteral (value * val, int offset);
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 */
60 static char *zero = "0x00";
61 static char *one = "0x01";
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" };
80 extern int avr_ptrRegReq;
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 )
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","")
94 #define IS_REGIDX(a,r) (a->type == AOP_REG && a->aopu.aop_reg[0]->rIdx == r)
96 static lineNode *lineHead = NULL;
97 static lineNode *lineCurr = NULL;
99 static unsigned char SLMask[] = { 0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
100 0xE0, 0xC0, 0x80, 0x00
102 static unsigned char SRMask[] = { 0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
103 0x07, 0x03, 0x01, 0x00
111 /*-----------------------------------------------------------------*/
112 /* emitcode - writes the code into a file : for now it is simple */
113 /*-----------------------------------------------------------------*/
115 emitcode (char *inst, char *fmt, ...)
118 char lb[MAX_INLINEASM];
125 sprintf (lb, "%s\t", inst);
127 sprintf (lb, "%s", inst);
128 vsprintf (lb + (strlen (lb)), fmt, ap);
131 vsprintf (lb, fmt, ap);
133 while (isspace (*lbp))
137 lineCurr = (lineCurr ?
138 connectLine (lineCurr, newLineNode (lb)) :
139 (lineHead = newLineNode (lb)));
140 lineCurr->isInline = _G.inLine;
141 lineCurr->isDebug = _G.debugLine;
145 /*-----------------------------------------------------------------*/
146 /* hasInc - operand is incremented before any other use */
147 /*-----------------------------------------------------------------*/
149 hasInc (operand *op, iCode *ic)
151 sym_link *type = operandType(op);
152 sym_link *retype = getSpec (type);
153 iCode *lic = ic->next;
156 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
157 isize = getSize(type->next);
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) {
166 /* if the operand used or deffed */
167 if (bitVectBitValue(ic->uses,op->key) || ic->defKey == op->key) {
175 /*-----------------------------------------------------------------*/
176 /* getFreePtr - returns X or Z whichever is free or can be pushed */
177 /*-----------------------------------------------------------------*/
179 getFreePtr (iCode * ic, asmop ** aopp, bool result, bool zonly)
181 bool xiu = FALSE, ziu = FALSE;
182 bool xou = FALSE, zou = FALSE;
184 /* the logic: if x & z used in the instruction
185 then we are in trouble otherwise */
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))) {
194 xou = bitVectBitValue (ic->rMask, X_IDX);
195 zou = bitVectBitValue (ic->rMask, Z_IDX);
197 /* if no usage of Z then return it */
199 ic->rUsed = bitVectSetBit (ic->rUsed, Z_IDX);
200 (*aopp)->type = AOP_Z;
202 (*aopp)->aop_ptr2 = avr_regWithIdx (R31_IDX);
203 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R30_IDX);
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;
211 (*aopp)->aop_ptr2 = avr_regWithIdx (R27_IDX);
212 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R26_IDX);
215 /* if z not used then */
218 /* push it if not already pushed */
220 emitcode ("push", "%s",
221 avr_regWithIdx (R30_IDX)->dname);
222 emitcode ("push", "%s",
223 avr_regWithIdx (R31_IDX)->dname);
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);
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 */
238 emitcode ("push", "%s",
239 avr_regWithIdx (R26_IDX)->dname);
240 emitcode ("push", "%s",
241 avr_regWithIdx (R27_IDX)->dname);
245 ic->rUsed = bitVectSetBit (ic->rUsed, X_IDX);
246 (*aopp)->type = AOP_X;
248 (*aopp)->aop_ptr2 = avr_regWithIdx (R27_IDX);
249 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R26_IDX);
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 */
257 (*aopp)->type = AOP_STK;
262 /* other wise this is true end of the world */
263 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
264 "getFreePtr should never reach here");
268 /*-----------------------------------------------------------------*/
269 /* newAsmop - creates a new asmOp */
270 /*-----------------------------------------------------------------*/
272 newAsmop (short type)
276 aop = Safe_calloc (1, sizeof (asmop));
281 /*-----------------------------------------------------------------*/
282 /* pointerCode - returns the code for a pointer type */
283 /*-----------------------------------------------------------------*/
285 pointerCode (sym_link * etype)
288 return PTR_TYPE (SPEC_OCLS (etype));
292 /*-----------------------------------------------------------------*/
293 /* aopForSym - for a true symbol */
294 /*-----------------------------------------------------------------*/
296 aopForSym (iCode * ic, symbol * sym, bool result)
299 memmap *space = SPEC_OCLS (sym->etype);
301 /* if already has one */
305 /* assign depending on the storage class */
306 /* if it is on the stack */
308 sym->aop = aop = newAsmop (0);
309 aop->size = getSize (sym->type);
311 /* we can use std / ldd instruction */
313 && (sym->stack + getSize (sym->type) - 1) <= 63) {
314 aop->type = AOP_STK_D;
315 aop->aopu.aop_stk = sym->stack;
319 /* otherwise get a free pointer register X/Z */
320 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result, FALSE);
322 /* now assign the address of the variable to
323 the pointer register */
324 if (aop->type != AOP_STK) {
325 emitcode ("movw", "%s,r28", aop->aopu.aop_ptr->name);
326 if (sym->stack < 0) {
327 if ((sym->stack - _G.nRegsSaved) > -63) {
328 emitcode ("sbiw", "%s,0x%02x",
329 aop->aopu.aop_ptr->name,
334 emitcode ("subi", "%s,lo8(%d)",
335 aop->aopu.aop_ptr->name,
336 sym->stack - _G.nRegsSaved);
337 emitcode ("sbci", "%s,hi8(%d)",
339 sym->stack - _G.nRegsSaved);
343 if (sym->stack <= 63) {
344 emitcode ("adiw", "%s,0x%02x",
345 aop->aopu.aop_ptr->name,
349 emitcode ("subi", "%s,lo8(-%d)",
350 aop->aopu.aop_ptr->name,
352 emitcode ("sbci", "%s,hi8(-%d)",
361 /* if in bit space */
362 if (IN_BITSPACE (space)) {
363 sym->aop = aop = newAsmop (AOP_CRY);
364 aop->aopu.aop_dir = sym->rname;
365 aop->size = getSize (sym->type);
368 /* if it is in direct space */
369 if (IN_DIRSPACE (space)) {
370 sym->aop = aop = newAsmop (AOP_DIR);
371 aop->aopu.aop_dir = sym->rname;
372 aop->size = getSize (sym->type);
376 /* special case for a function */
377 if (IS_FUNC (sym->type)) {
378 sym->aop = aop = newAsmop (AOP_IMMD);
379 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
380 strcpy (aop->aopu.aop_immd, sym->rname);
381 aop->size = FPTRSIZE;
385 /* only remaining is code / eeprom which will need pointer reg */
386 /* if it is in code space */
388 sym->aop = aop = newAsmop (0);
390 if (IN_CODESPACE (space))
393 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result, aop->code);
394 aop->size = getSize (sym->type);
395 emitcode ("ldi", "%s,lo8(%s)", aop->aopu.aop_ptr->name, sym->rname);
396 emitcode ("ldi", "%s,hi8(%s)", aop->aop_ptr2);
401 /*-----------------------------------------------------------------*/
402 /* aopForRemat - rematerialzes an object */
403 /*-----------------------------------------------------------------*/
405 aopForRemat (symbol * sym)
407 iCode *ic = sym->rematiCode;
408 asmop *aop = newAsmop (AOP_IMMD);
413 val += (int) operandLitValue (IC_RIGHT (ic));
414 else if (ic->op == '-')
415 val -= (int) operandLitValue (IC_RIGHT (ic));
419 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
423 sprintf (buffer, "(%s %c 0x%04x)",
424 OP_SYMBOL (IC_LEFT (ic))->rname,
425 val >= 0 ? '+' : '-', abs (val) & 0xffff);
427 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
429 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
430 strcpy (aop->aopu.aop_immd, buffer);
434 /*-----------------------------------------------------------------*/
435 /* regsInCommon - two operands have some registers in common */
436 /*-----------------------------------------------------------------*/
438 regsInCommon (operand * op1, operand * op2)
443 /* if they have registers in common */
444 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
447 sym1 = OP_SYMBOL (op1);
448 sym2 = OP_SYMBOL (op2);
450 if (sym1->nRegs == 0 || sym2->nRegs == 0)
453 for (i = 0; i < sym1->nRegs; i++) {
458 for (j = 0; j < sym2->nRegs; j++) {
462 if (sym2->regs[j] == sym1->regs[i])
470 /*-----------------------------------------------------------------*/
471 /* operandsEqu - equivalent */
472 /*-----------------------------------------------------------------*/
474 operandsEqu (operand * op1, operand * op2)
478 /* if they not symbols */
479 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
482 sym1 = OP_SYMBOL (op1);
483 sym2 = OP_SYMBOL (op2);
485 /* if both are itemps & one is spilt
486 and the other is not then false */
487 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
488 sym1->isspilt != sym2->isspilt) return FALSE;
490 /* if they are the same */
494 if (strcmp (sym1->rname, sym2->rname) == 0)
498 /* if left is a tmp & right is not */
499 if (IS_ITEMP (op1) &&
500 !IS_ITEMP (op2) && sym1->isspilt && (sym1->usl.spillLoc == sym2))
503 if (IS_ITEMP (op2) &&
505 sym2->isspilt && sym1->level > 0 && (sym2->usl.spillLoc == sym1))
511 /*-----------------------------------------------------------------*/
512 /* sameRegs - two asmops have the same registers */
513 /*-----------------------------------------------------------------*/
515 sameRegs (asmop * aop1, asmop * aop2)
522 if (aop1->type != AOP_REG || aop2->type != AOP_REG)
525 if (aop1->size != aop2->size)
528 for (i = 0; i < aop1->size; i++)
529 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
535 /*-----------------------------------------------------------------*/
536 /* isRegPair - for size 2 if this operand has a register pair */
537 /*-----------------------------------------------------------------*/
539 isRegPair (asmop * aop)
541 if (!aop || aop->size != 2)
543 if (aop->type == AOP_X || aop->type == AOP_Z)
545 if (aop->type != AOP_REG)
547 if ( ((aop->aopu.aop_reg[1]->rIdx - aop->aopu.aop_reg[0]->rIdx) == 1) &&
548 (aop->aopu.aop_reg[0]->rIdx & 1) == 0)
554 /*-----------------------------------------------------------------*/
555 /* aopOp - allocates an asmop for an operand : */
556 /*-----------------------------------------------------------------*/
558 aopOp (operand * op, iCode * ic, bool result)
567 /* if this a literal */
568 if (IS_OP_LITERAL (op)) {
569 op->aop = aop = newAsmop (AOP_LIT);
570 aop->aopu.aop_lit = op->operand.valOperand;
571 aop->size = getSize (operandType (op));
575 /* if already has a asmop then continue */
579 /* if the underlying symbol has a aop */
580 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop) {
581 op->aop = OP_SYMBOL (op)->aop;
585 /* if this is a true symbol */
586 if (IS_TRUE_SYMOP (op)) {
587 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
591 /* this is a temporary : this has
597 e) can be a return use only */
599 sym = OP_SYMBOL (op);
602 /* if the type is a conditional */
603 if (sym->regType == REG_CND) {
604 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
609 /* if it is spilt then two situations
611 b) has a spill location */
612 if (sym->isspilt || sym->nRegs == 0) {
614 /* rematerialize it NOW */
616 sym->aop = op->aop = aop = aopForRemat (sym);
617 aop->size = getSize (sym->type);
622 assert ("ACC_USE cannot happen in AVR\n");
627 aop = op->aop = sym->aop = newAsmop (AOP_STR);
628 aop->size = getSize (sym->type);
629 for (i = 0; i < (int) fAVRReturnSize; i++)
630 aop->aopu.aop_str[i] = fAVRReturn[i];
634 /* else spill location */
635 sym->aop = op->aop = aop =
636 aopForSym (ic, sym->usl.spillLoc, result);
637 aop->size = getSize (sym->type);
641 /* must be in a register */
642 sym->aop = op->aop = aop = newAsmop (AOP_REG);
643 aop->size = sym->nRegs;
644 for (i = 0; i < sym->nRegs; i++)
645 aop->aopu.aop_reg[i] = sym->regs[i];
648 /*-----------------------------------------------------------------*/
649 /* freeAsmop - free up the asmop given to an operand */
650 /*----------------------------------------------------------------*/
652 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
669 /* depending on the asmop type only three cases need work AOP_RO
670 , AOP_R1 && AOP_STK */
675 emitcode ("pop", "r26");
676 emitcode ("pop", "r27");
680 bitVectUnSetBit (ic->rUsed, X_IDX);
686 emitcode ("pop", "r30");
687 emitcode ("pop", "r31");
691 bitVectUnSetBit (ic->rUsed, Z_IDX);
697 int stk = aop->aopu.aop_stk + aop->size;
698 bitVectUnSetBit (ic->rUsed, X_IDX);
699 bitVectUnSetBit (ic->rUsed, Z_IDX);
701 getFreePtr (ic, &aop, FALSE, 0);
703 emitcode ("movw", "%s,r28");
705 if (stk <= 63 && stk > 0) {
706 emitcode ("adiw", "%s,0x%02x",
707 aop->aopu.aop_ptr->name,
711 emitcode ("subi", "%s,lo8(%d)",
712 aop->aopu.aop_ptr->name,
714 emitcode ("sbci", "%s,hi8(%d)",
721 emitcode ("pop", "r24");
722 emitcode ("st", "-%s,r24",
723 aop->type == AOP_X ? "X" : "Z");
728 freeAsmop (op, NULL, ic, TRUE);
730 emitcode ("pop", "r26");
731 emitcode ("pop", "r27");
736 emitcode ("pop", "r30");
737 emitcode ("pop", "r31");
744 /* all other cases just dealloc */
748 OP_SYMBOL (op)->aop = NULL;
749 /* if the symbol has a spill */
751 SPIL_LOC (op)->aop = NULL;
756 /*-----------------------------------------------------------------*/
757 /* aopGet - for fetching value of the aop */
758 /*-----------------------------------------------------------------*/
760 aopGet (asmop * aop, int offset)
765 /* offset is greater than
767 if (offset > (aop->size - 1) && aop->type != AOP_LIT)
770 /* depending on type */
774 if (offset > aop->coff) {
775 emitcode ("adiw", "%s,%d", aop->aopu.aop_ptr->name,
779 if (offset < aop->coff) {
780 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name,
785 emitcode ("ld", "%s,x",
786 (rs = ((offset & 1) ? "r25" : "r24")));
791 if (offset > aop->coff) {
792 emitcode ("adiw", "r30,%d",
796 emitcode ("sbiw", "r30,%d",
799 emitcode ("lpm", "%s,z",
800 (rs = ((offset & 1) ? "r25" : "r24")));
804 if (offset > aop->coff) {
805 emitcode ("ldd", "%s,z+%d",
807 ((offset & 1) ? "r25" : "r24")),
811 emitcode ("sbiw", "%s,%d",
812 aop->aopu.aop_ptr->name,
815 emitcode ("ld", "%s,z",
817 ((offset & 1) ? "r25" : "r24")));
824 emitcode ("lds", "%s,(%s)+%d",
825 (rs = ((offset & 1) ? "r25" : "r24")),
826 aop->aopu.aop_immd, offset);
830 emitcode ("lds", "%s,(%s)+%d",
831 (rs = ((offset & 1) ? "r25" : "r24")),
832 aop->aopu.aop_dir, offset);
836 return aop->aopu.aop_reg[offset]->name;
839 assert ("cannot be in bit space AOP_CRY\n");
843 s = aopLiteral (aop->aopu.aop_lit, offset);
844 emitcode ("ldi", "%s,lo8(%s)",
845 (rs = ((offset & 1) ? "r24" : "r25")), s);
850 return aop->aopu.aop_str[offset];
853 emitcode ("ldd", "%s,Y+%d",
854 (rs = ((offset & 1) ? "r25" : "r24")),
855 aop->aopu.aop_stk + offset);
859 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
860 "aopget got unsupported aop->type");
864 /*-----------------------------------------------------------------*/
865 /* aopPut - puts a string for a aop */
866 /*-----------------------------------------------------------------*/
868 aopPut (asmop * aop, char *s, int offset)
872 if (aop->size && offset > (aop->size - 1)) {
873 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
874 "aopPut got offset > aop->size");
878 /* will assign value to value */
879 /* depending on where it is ofcourse */
883 sprintf (d, "(%s)+%d", aop->aopu.aop_dir, offset);
886 sprintf (d, "%s", aop->aopu.aop_dir);
889 emitcode ("sts", "%s,%s", d, s);
893 if (toupper (*s) != 'R') {
895 emitcode ("clr", "%s",
896 aop->aopu.aop_reg[offset]->name);
899 emitcode ("ldi", "r25,%s", s);
900 emitcode ("mov", "%s,r35",
901 aop->aopu.aop_reg[offset]->name);
905 if (strcmp (aop->aopu.aop_reg[offset]->name, s)) {
906 emitcode ("mov", "%s,%s",
907 aop->aopu.aop_reg[offset]->name, s);
913 if (offset > aop->coff) {
914 emitcode ("adiw", "%s,%d", aop->aopu.aop_ptr->name,
918 if (offset < aop->coff) {
919 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name,
924 emitcode ("st", "x,%s", s);
929 if (offset > aop->coff) {
930 emitcode ("adiw", "r30,%d",
934 emitcode ("sbiw", "r30,%d",
937 emitcode ("lpm", "%s,z", s);
941 if (offset > aop->coff) {
942 emitcode ("sdd", "z+%d,%s",
943 offset - aop->coff, s);
946 emitcode ("sbiw", "%s,%d",
947 aop->aopu.aop_ptr->name,
950 emitcode ("ld", "%s,z", s);
956 emitcode ("push", "%s", s);
960 /* if used only for a condition code check */
961 assert (toupper (*s) == 'R');
963 emitcode ("xrl", "r0,r0");
964 emitcode ("cpi", "%s,0", s);
967 emitcode ("cpc", "r0,%s", s);
973 if (strcmp (aop->aopu.aop_str[offset], s))
974 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset],
979 emitcode ("std", "y+%d,%s", offset, s);
983 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
984 "aopPut got unsupported aop->type");
990 /*-----------------------------------------------------------------*/
991 /* reAdjustPreg - points a register back to where it should */
992 /*-----------------------------------------------------------------*/
994 reAdjustPreg (asmop * aop)
999 if ((size = aop->size) <= 1)
1002 switch (aop->type) {
1005 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name, size);
1011 #define AOP(op) op->aop
1012 #define AOP_TYPE(op) AOP(op)->type
1013 #define AOP_SIZE(op) AOP(op)->size
1014 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_X || \
1015 AOP_TYPE(x) == AOP_Z))
1016 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1017 ((x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R27_IDX)) || \
1018 (x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R31_IDX)) )))
1019 #define AOP_ISX(x) (x && (x->type == AOP_REG && \
1020 ((x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R27_IDX)))))
1021 #define AOP_ISZ(x) (x && (x->type == AOP_REG && \
1022 ((x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R31_IDX)))))
1024 /*-----------------------------------------------------------------*/
1025 /* genNotFloat - generates not for float operations */
1026 /*-----------------------------------------------------------------*/
1028 genNotFloat (operand * op, operand * res)
1034 /* we will put 127 in the first byte of
1036 aopPut (AOP (res), "127", 0);
1037 size = AOP_SIZE (op) - 1;
1040 l = aopGet (op->aop, offset++);
1044 emitcode ("or", "R0,%s", aopGet (op->aop, offset++));
1046 tlbl = newiTempLabel (NULL);
1048 tlbl = newiTempLabel (NULL);
1049 aopPut (res->aop, zero, 1);
1050 emitcode ("cpi", "r0,0");
1051 emitcode ("breq", "L%05d", tlbl->key);
1052 aopPut (res->aop, one, 1);
1053 emitcode ("", "L%05d:", tlbl->key);
1055 size = res->aop->size - 2;
1057 /* put zeros in the rest */
1059 aopPut (res->aop, zero, offset++);
1062 /*-----------------------------------------------------------------*/
1063 /* opIsGptr: returns non-zero if the passed operand is */
1064 /* a generic pointer type. */
1065 /*-----------------------------------------------------------------*/
1067 opIsGptr (operand * op)
1069 sym_link *type = operandType (op);
1071 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type)) {
1077 /*-----------------------------------------------------------------*/
1078 /* getDataSize - get the operand data size */
1079 /*-----------------------------------------------------------------*/
1081 getDataSize (operand * op)
1084 size = AOP_SIZE (op);
1085 if (size == GPTRSIZE) {
1086 sym_link *type = operandType (op);
1087 if (IS_GENPTR (type)) {
1088 /* generic pointer; arithmetic operations
1089 * should ignore the high byte (pointer type).
1097 /*-----------------------------------------------------------------*/
1098 /* outAcc - output Acc */
1099 /*-----------------------------------------------------------------*/
1101 outAcc (operand * result)
1104 size = getDataSize (result);
1106 aopPut (AOP (result), "r0", 0);
1109 /* unsigned or positive */
1111 aopPut (AOP (result), zero, offset++);
1116 /*-----------------------------------------------------------------*/
1117 /* outBitC - output a bit C */
1118 /*-----------------------------------------------------------------*/
1120 outBitC (operand * result)
1122 emitcode ("clr", "r0");
1123 emitcode ("rol", "r0");
1127 /*-----------------------------------------------------------------*/
1128 /* toBoolean - emit code for orl a,operator(sizeop) */
1129 /*-----------------------------------------------------------------*/
1131 toBoolean (operand * oper, char *r, bool clr)
1133 int size = AOP_SIZE (oper);
1136 emitcode ("clr", "%s", r);
1138 emitcode ("or", "%s,%s", r, aopGet (AOP (oper), offset++));
1142 /*-----------------------------------------------------------------*/
1143 /* genNot - generate code for ! operation */
1144 /*-----------------------------------------------------------------*/
1149 sym_link *optype = operandType (IC_LEFT (ic));
1150 int size, offset = 1;
1152 /* assign asmOps to operand & result */
1153 aopOp (IC_LEFT (ic), ic, FALSE);
1154 aopOp (IC_RESULT (ic), ic, TRUE);
1156 /* if type float then do float */
1157 if (IS_FLOAT (optype)) {
1158 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1161 emitcode ("clr", "r24");
1162 tlbl = newiTempLabel (NULL);
1163 size = AOP_SIZE (IC_LEFT (ic));
1166 emitcode ("cpse", "%s,r24", aopGet (AOP (IC_LEFT (ic)), 0));
1171 emitcode ("cpc", "%s,r24",
1172 aopGet (AOP (IC_LEFT (ic)),
1175 emitcode ("cpi", "%s,0",
1176 aopGet (AOP (IC_LEFT (ic)),
1180 emitcode ("bne", "L%05d", tlbl->key);
1182 emitcode ("ldi", "r24,1");
1183 emitcode ("", "L%05d:", tlbl->key);
1184 aopPut (AOP (IC_RESULT (ic)), "r24", 0);
1185 size = AOP_SIZE (IC_RESULT (ic)) - 1;
1188 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
1192 /* release the aops */
1193 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1194 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1198 /*-----------------------------------------------------------------*/
1199 /* genCpl - generate code for complement */
1200 /*-----------------------------------------------------------------*/
1208 /* assign asmOps to operand & result */
1209 aopOp (IC_LEFT (ic), ic, FALSE);
1210 aopOp (IC_RESULT (ic), ic, TRUE);
1211 samer = sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)));
1212 size = AOP_SIZE (IC_RESULT (ic));
1214 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
1216 emitcode ("com", "%s", l);
1219 aopPut (AOP (IC_RESULT (ic)), l, offset);
1220 emitcode ("com", "%s",
1221 aopGet (AOP (IC_RESULT (ic)), offset));
1226 /* release the aops */
1227 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1228 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1231 /*-----------------------------------------------------------------*/
1232 /* genUminusFloat - unary minus for floating points */
1233 /*-----------------------------------------------------------------*/
1235 genUminusFloat (operand * op, operand * result)
1237 int size, offset = 0;
1239 /* for this we just need to flip the
1240 first it then copy the rest in place */
1241 size = AOP_SIZE (op) - 1;
1242 l = aopGet (AOP (op), 3);
1244 emitcode ("ldi", "r24,0x80");
1245 if (sameRegs (AOP (op), AOP (result))) {
1246 emitcode ("eor", "%s,r24", l);
1249 aopPut (AOP (result), l, 3);
1250 emitcode ("eor", "%s,r24", aopGet (AOP (result), 3));
1253 aopPut (AOP (result), aopGet (AOP (op), offset), offset);
1258 /*-----------------------------------------------------------------*/
1259 /* genUminus - unary minus code generation */
1260 /*-----------------------------------------------------------------*/
1262 genUminus (iCode * ic)
1265 sym_link *optype, *rtype;
1269 aopOp (IC_LEFT (ic), ic, FALSE);
1270 aopOp (IC_RESULT (ic), ic, TRUE);
1272 optype = operandType (IC_LEFT (ic));
1273 rtype = operandType (IC_RESULT (ic));
1275 /* if float then do float stuff */
1276 if (IS_FLOAT (optype)) {
1277 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1281 /* otherwise subtract from zero */
1282 size = AOP_SIZE (IC_LEFT (ic));
1284 samer = sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)));
1287 emitcode ("neg", "%s",
1288 aopGet (AOP (IC_LEFT (ic)), 0));
1291 aopPut (AOP (IC_RESULT (ic)),
1292 aopGet (AOP (IC_LEFT (ic)), 0), 0);
1293 emitcode ("neg", "%s",
1294 aopGet (AOP (IC_RESULT (ic)), 0));
1300 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
1302 aopPut (AOP (IC_RESULT (ic)), l, offset);
1303 l = aopGet (AOP (IC_RESULT (ic)), offset);
1306 emitcode ("com", "%s", l);
1308 emitcode ("neg", "%s", l);
1311 size = AOP_SIZE (IC_LEFT (ic)) - 1;
1314 emitcode ("sbci", "%s,lo8(-1)",
1315 aopGet (AOP (IC_RESULT (ic)), offset++));
1319 /* if any remaining bytes in the result */
1320 /* we just need to propagate the sign */
1321 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic))))) {
1322 symbol *tlbl = newiTempLabel (NULL);
1323 emitcode ("clr", "r0");
1324 emitcode ("brcc", "L%05d", tlbl->key);
1325 emitcode ("com", "r0");
1326 emitcode ("", "L%05d:", tlbl->key);
1328 aopPut (AOP (IC_RESULT (ic)), "r0", offset++);
1332 /* release the aops */
1333 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1334 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1337 /*-----------------------------------------------------------------*/
1338 /* assignResultValue - */
1339 /*-----------------------------------------------------------------*/
1341 assignResultValue (operand * oper)
1344 int size = AOP_SIZE (oper);
1346 aopPut (AOP (oper), fAVRReturn[offset], offset);
1351 /*-----------------------------------------------------------------*/
1352 /* saveZreg - if indirect call then save z-pointer register */
1353 /*-----------------------------------------------------------------*/
1355 saveZreg (iCode * ic)
1357 /* only if live accross this call */
1358 if (ic->regsSaved == 0 &&
1359 (bitVectBitValue (ic->rMask, R30_IDX) ||
1360 bitVectBitValue (ic->rMask, R31_IDX))) {
1362 emitcode ("push", "r30");
1363 emitcode ("push", "r31");
1367 /*-----------------------------------------------------------------*/
1368 /* popZreg - restore values of zreg */
1369 /*-----------------------------------------------------------------*/
1371 popZreg (iCode * ic)
1373 if (ic->regsSaved) {
1374 emitcode ("pop", "r31");
1375 emitcode ("pop", "r30");
1379 /*-----------------------------------------------------------------*/
1380 /* genIpush - genrate code for pushing this gets a little complex */
1381 /*-----------------------------------------------------------------*/
1383 genIpush (iCode * ic)
1385 int size, offset = 0;
1389 if (!ic->parmPush) {
1390 /* and the item is spilt then do nothing */
1391 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1396 for (lic = ic->next; lic; lic = lic->next)
1397 if (lic->op == PCALL)
1403 /* this is a paramter push */
1404 aopOp (IC_LEFT (ic), ic, FALSE);
1405 size = AOP_SIZE (IC_LEFT (ic));
1407 l = aopGet (AOP (IC_LEFT (ic)), offset++);
1408 emitcode ("push", "%s", l);
1411 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1414 /*-----------------------------------------------------------------*/
1415 /* genIpop - recover the registers: can happen only for spilling */
1416 /*-----------------------------------------------------------------*/
1418 genIpop (iCode * ic)
1423 /* if the temp was not pushed then */
1424 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1427 aopOp (IC_LEFT (ic), ic, FALSE);
1428 size = AOP_SIZE (IC_LEFT (ic));
1429 offset = (size - 1);
1431 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--));
1433 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1436 /*-----------------------------------------------------------------*/
1437 /* genCall - generates a call statement */
1438 /*-----------------------------------------------------------------*/
1440 genCall (iCode * ic)
1443 /* if send set is not empty the assign */
1447 for (sic = setFirstItem (_G.sendSet); sic;
1448 sic = setNextItem (_G.sendSet)) {
1449 int size, offset = 0;
1450 aopOp (IC_LEFT (sic), sic, FALSE);
1451 size = AOP_SIZE (IC_LEFT (sic));
1454 aopGet (AOP (IC_LEFT (sic)), offset);
1456 sprintf (buffer, "r%d", rnum++);
1458 emitcode ("mov", "%s,%s", b, l);
1461 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1466 emitcode ("call", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1467 OP_SYMBOL (IC_LEFT (ic))->rname :
1468 OP_SYMBOL (IC_LEFT (ic))->name));
1470 /* if we need assign a result value */
1471 if ((IS_ITEMP (IC_RESULT (ic)) &&
1472 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1473 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1474 IS_TRUE_SYMOP (IC_RESULT (ic))) {
1476 aopOp (IC_RESULT (ic), ic, FALSE);
1477 assignResultValue (IC_RESULT (ic));
1478 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1481 /* adjust the stack for parameters if required */
1482 if (ic->parmBytes) {
1483 if (ic->parmBytes > 63) {
1484 emitcode ("sbiw", "r28,%d", ic->parmBytes);
1487 emitcode ("subi", "r28,lo8(%d)",
1489 emitcode ("sbci", "r29,hi8(%d)",
1496 /*-----------------------------------------------------------------*/
1497 /* genPcall - generates a call by pointer statement */
1498 /*-----------------------------------------------------------------*/
1500 genPcall (iCode * ic)
1506 aopOp (IC_LEFT (ic), ic, FALSE);
1507 emitcode ("mov", "r30", aopGet (AOP (IC_LEFT (ic)), 0));
1508 emitcode ("mov", "r31", aopGet (AOP (IC_RIGHT (ic)), 0));
1509 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1511 /* if send set is not empty the assign */
1515 for (sic = setFirstItem (_G.sendSet); sic;
1516 sic = setNextItem (_G.sendSet)) {
1517 int size, offset = 0;
1518 aopOp (IC_LEFT (sic), sic, FALSE);
1519 size = AOP_SIZE (IC_LEFT (sic));
1522 aopGet (AOP (IC_LEFT (sic)), offset);
1524 sprintf (b, "r%d", rnum++);
1526 emitcode ("mov", "%s,%s", b, l);
1529 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1534 emitcode ("icall", "");
1536 /* if we need assign a result value */
1537 if ((IS_ITEMP (IC_RESULT (ic)) &&
1538 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1539 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1540 IS_TRUE_SYMOP (IC_RESULT (ic))) {
1542 aopOp (IC_RESULT (ic), ic, FALSE);
1544 assignResultValue (IC_RESULT (ic));
1545 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1548 /* adjust the stack for parameters if
1550 if (ic->parmBytes) {
1552 if (ic->parmBytes > 3) {
1553 emitcode ("mov", "a,%s", spname);
1554 emitcode ("add", "a,#0x%02x",
1555 (-ic->parmBytes) & 0xff);
1556 emitcode ("mov", "%s,a", spname);
1559 for (i = 0; i < ic->parmBytes; i++)
1560 emitcode ("dec", "%s", spname);
1564 /* adjust the stack for parameters if required */
1565 if (ic->parmBytes) {
1566 if (ic->parmBytes > 63) {
1567 emitcode ("sbiw", "r28,%d", ic->parmBytes);
1570 emitcode ("subi", "r28,lo8(%d)",
1572 emitcode ("sbci", "r29,hi8(%d)",
1580 /*-----------------------------------------------------------------*/
1581 /* resultRemat - result is rematerializable */
1582 /*-----------------------------------------------------------------*/
1584 resultRemat (iCode * ic)
1586 if (SKIP_IC (ic) || ic->op == IFX)
1589 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic))) {
1590 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
1591 if (sym->remat && !POINTER_SET (ic))
1598 #if defined(__BORLANDC__) || defined(_MSC_VER)
1599 #define STRCASECMP stricmp
1601 #define STRCASECMP strcasecmp
1604 /*-----------------------------------------------------------------*/
1605 /* inExcludeList - return 1 if the string is in exclude Reg list */
1606 /*-----------------------------------------------------------------*/
1608 inExcludeList (char *s)
1612 if (options.excludeRegs[i] &&
1613 STRCASECMP (options.excludeRegs[i], "none") == 0)
1616 for (i = 0; options.excludeRegs[i]; i++) {
1617 if (options.excludeRegs[i] &&
1618 STRCASECMP (s, options.excludeRegs[i]) == 0)
1624 /*-----------------------------------------------------------------*/
1625 /* genFunction - generated code for function entry */
1626 /*-----------------------------------------------------------------*/
1628 genFunction (iCode * ic)
1635 /* create the function header */
1636 emitcode (";", "-----------------------------------------");
1637 emitcode (";", " function %s",
1638 (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
1639 emitcode (";", "-----------------------------------------");
1641 emitcode ("", "%s:", sym->rname);
1642 fetype = getSpec (operandType (IC_LEFT (ic)));
1644 /* if critical function then turn interrupts off */
1645 if (SPEC_CRTCL (fetype))
1646 emitcode ("cli", "");
1648 if (IS_ISR (sym->etype)) {
1651 /* save the preserved registers that are used in this function */
1652 for (i = R2_IDX; i <= R15_IDX; i++) {
1653 if (bitVectBitValue (sym->regsUsed, i)) {
1655 emitcode ("push", "%s", avr_regWithIdx (i)->name);
1658 /* now for the pointer registers */
1659 if (bitVectBitValue (sym->regsUsed, R26_IDX)) {
1661 emitcode ("push", "r26");
1663 if (bitVectBitValue (sym->regsUsed, R27_IDX)) {
1665 emitcode ("push", "r27");
1667 if (bitVectBitValue (sym->regsUsed, R30_IDX)) {
1669 emitcode ("push", "r30");
1671 if (bitVectBitValue (sym->regsUsed, R31_IDX)) {
1673 emitcode ("push", "r31");
1675 /* adjust the stack for the function */
1677 emitcode ("push", "r28");
1678 emitcode ("push", "r29");
1679 emitcode ("in", "r28,__SP_L__");
1680 emitcode ("in", "r29,__SP_H__");
1681 if (sym->stack <= 63) {
1682 emitcode ("sbiw", "r28,%d", sym->stack);
1685 emitcode ("subi", "r28,lo8(%d)", sym->stack);
1686 emitcode ("sbci", "r29,hi8(%d)", sym->stack);
1688 emitcode ("out", "__SP_L__,r28");
1689 emitcode ("out", "__SP_H__,r29");
1693 /*-----------------------------------------------------------------*/
1694 /* genEndFunction - generates epilogue for functions */
1695 /*-----------------------------------------------------------------*/
1697 genEndFunction (iCode * ic)
1699 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
1702 /* restore stack pointer */
1704 if (sym->stack <= 63) {
1705 emitcode ("adiw", "r28,%d", sym->stack);
1708 emitcode ("subi", "r28,lo8(-%d)", sym->stack);
1709 emitcode ("sbci", "r29,hi8(-%d)", sym->stack);
1711 emitcode ("out", "__SP_L__,r28");
1712 emitcode ("out", "__SP_H__,r29");
1714 /* pop frame pointer */
1715 emitcode ("pop", "r29");
1716 emitcode ("pop", "r28");
1718 /* restore preserved registers */
1719 if (bitVectBitValue (sym->regsUsed, R31_IDX)) {
1721 emitcode ("pop", "r31");
1723 if (bitVectBitValue (sym->regsUsed, R30_IDX)) {
1725 emitcode ("pop", "r30");
1727 if (bitVectBitValue (sym->regsUsed, R27_IDX)) {
1729 emitcode ("pop", "r27");
1731 if (bitVectBitValue (sym->regsUsed, R26_IDX)) {
1733 emitcode ("pop", "r26");
1735 for (i = R15_IDX; i >= R2_IDX; i--) {
1736 if (bitVectBitValue (sym->regsUsed, i)) {
1738 emitcode ("pop", "%s", avr_regWithIdx (i)->name);
1742 if (SPEC_CRTCL (sym->etype))
1743 emitcode ("sti", "");
1745 if (IS_ISR (sym->etype)) {
1746 emitcode ("rti", "");
1749 emitcode ("ret", "");
1754 /*-----------------------------------------------------------------*/
1755 /* genRet - generate code for return statement */
1756 /*-----------------------------------------------------------------*/
1760 int size, offset = 0;
1762 /* if we have no return value then
1763 just generate the "ret" */
1767 /* we have something to return then
1768 move the return value into place */
1769 aopOp (IC_LEFT (ic), ic, FALSE);
1770 size = AOP_SIZE (IC_LEFT (ic));
1773 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) {
1774 emitcode ("ldi", "%s,%s(%d)", fAVRReturn[offset],
1776 (int) floatFromVal (AOP (IC_LEFT (ic))->
1777 aopu.aop_lit), offset);
1781 l = aopGet (AOP (IC_LEFT (ic)), offset);
1782 if (strcmp (fAVRReturn[offset], l))
1783 emitcode ("mov", "%s,%s", fAVRReturn[offset],
1789 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1792 /* generate a jump to the return label
1793 if the next is not the return statement */
1794 if (!(ic->next && ic->next->op == LABEL &&
1795 IC_LABEL (ic->next) == returnLabel))
1797 emitcode ("rjmp", "L%05d", returnLabel->key);
1801 /*-----------------------------------------------------------------*/
1802 /* genLabel - generates a label */
1803 /*-----------------------------------------------------------------*/
1805 genLabel (iCode * ic)
1807 /* special case never generate */
1808 if (IC_LABEL (ic) == entryLabel)
1811 emitcode ("", "L%05d:", IC_LABEL (ic)->key);
1814 /*-----------------------------------------------------------------*/
1815 /* genGoto - generates a ljmp */
1816 /*-----------------------------------------------------------------*/
1818 genGoto (iCode * ic)
1820 emitcode ("rjmp", "L%05d:", (IC_LABEL (ic)->key + 100));
1823 /*-----------------------------------------------------------------*/
1824 /* findLabelBackwards: walks back through the iCode chain looking */
1825 /* for the given label. Returns number of iCode instructions */
1826 /* between that label and given ic. */
1827 /* Returns zero if label not found. */
1828 /*-----------------------------------------------------------------*/
1830 findLabelBackwards (iCode * ic, int key)
1838 if (ic->op == LABEL && IC_LABEL (ic)->key == key) {
1839 /* printf("findLabelBackwards = %d\n", count); */
1847 /*-----------------------------------------------------------------*/
1848 /* genPlusIncr :- does addition with increment if possible */
1849 /*-----------------------------------------------------------------*/
1851 genPlusIncr (iCode * ic)
1853 unsigned int icount;
1855 /* will try to generate an increment */
1856 /* if the right side is not a literal
1858 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
1862 (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.
1865 /* if the sizes are greater than 2 or they are not the same regs
1867 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1870 /* so we know LEFT & RESULT in the same registers and add
1872 /* for short & char types */
1873 if (AOP_SIZE (IC_RESULT (ic)) < 2) {
1875 emitcode ("inc", "%s",
1876 aopGet (AOP (IC_LEFT (ic)), 0));
1879 emitcode ("subi", "%s,lo8(%d)",
1880 aopGet (AOP (IC_LEFT (ic)), 0), -icount);
1884 if (AOP_SIZE (IC_RESULT (ic)) <= 3) {
1885 /* if register pair and starts with 26/30 then adiw */
1886 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0
1888 && (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX)
1889 || IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX))) {
1890 emitcode ("adiw", "%s,%d",
1891 aopGet (AOP (IC_RESULT (ic)), 0), icount);
1896 emitcode ("subi", "%s,lo8(%d)",
1897 aopGet (AOP (IC_RESULT (ic)), 0), -icount);
1898 emitcode ("sbci", "%s,hi8(%d)",
1899 aopGet (AOP (IC_RESULT (ic)), 1), -icount);
1903 /* for 32 bit longs */
1904 emitcode ("subi", "%s,lo8(%d)", aopGet (AOP (IC_RESULT (ic)), 0),
1906 emitcode ("sbci", "%s,hi8(%d)", aopGet (AOP (IC_RESULT (ic)), 1),
1908 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2),
1910 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3),
1916 /* This is the pure and virtuous version of this code.
1917 * I'm pretty certain it's right, but not enough to toss the old
1921 adjustArithmeticResult (iCode * ic)
1923 if (opIsGptr (IC_RESULT (ic)) &&
1924 opIsGptr (IC_LEFT (ic)) &&
1925 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)))) {
1926 aopPut (AOP (IC_RESULT (ic)),
1927 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1),
1931 if (opIsGptr (IC_RESULT (ic)) &&
1932 opIsGptr (IC_RIGHT (ic)) &&
1933 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)))) {
1934 aopPut (AOP (IC_RESULT (ic)),
1935 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1),
1939 if (opIsGptr (IC_RESULT (ic)) &&
1940 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
1941 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
1942 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
1943 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)))) {
1945 sprintf (buffer, "%d",
1946 pointerCode (getSpec (operandType (IC_LEFT (ic)))));
1947 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
1951 /*-----------------------------------------------------------------*/
1952 /* genPlus - generates code for addition */
1953 /*-----------------------------------------------------------------*/
1955 genPlus (iCode * ic)
1957 int size, offset = 0;
1961 /* special cases :- */
1963 aopOp (IC_LEFT (ic), ic, FALSE);
1964 aopOp (IC_RIGHT (ic), ic, FALSE);
1965 aopOp (IC_RESULT (ic), ic, TRUE);
1967 /* if I can do an increment instead
1968 of add then GOOD for ME */
1969 if (genPlusIncr (ic) == TRUE)
1972 size = getDataSize (IC_RESULT (ic));
1973 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
1977 aopPut (AOP (IC_RESULT (ic)),
1978 aopGet (AOP (IC_LEFT (ic)), offset), offset);
1980 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
1987 emitcode (l, "%s,%s",
1988 aopGet (AOP (IC_RESULT (ic)), offset),
1989 aopGet (AOP (IC_RIGHT (ic)), offset));
1997 emitcode (l, "%s,%s(-%d)",
1998 aopGet (AOP (IC_RESULT (ic)), offset),
2000 (int) floatFromVal (AOP (IC_RIGHT (ic))->
2006 adjustArithmeticResult (ic);
2009 freeAsmop (IC_LEFT (ic), NULL, ic,
2010 (RESULTONSTACK (ic) ? FALSE : TRUE));
2011 freeAsmop (IC_RIGHT (ic), NULL, ic,
2012 (RESULTONSTACK (ic) ? FALSE : TRUE));
2013 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2016 /*-----------------------------------------------------------------*/
2017 /* genMinusDec :- does subtraction with deccrement if possible */
2018 /*-----------------------------------------------------------------*/
2020 genMinusDec (iCode * ic)
2022 unsigned int icount;
2024 /* will try to generate an increment */
2025 /* if the right side is not a literal
2027 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2031 (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.
2034 /* if the sizes are greater than 2 or they are not the same regs
2036 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic))))
2039 /* so we know LEFT & RESULT in the same registers and add
2041 /* for short & char types */
2042 if (AOP_SIZE (IC_RESULT (ic)) < 2) {
2044 emitcode ("dec", "%s",
2045 aopGet (AOP (IC_LEFT (ic)), 0));
2048 emitcode ("subi", "%s,lo8(%d)",
2049 aopGet (AOP (IC_LEFT (ic)), 0), icount);
2053 if (AOP_SIZE (IC_RESULT (ic)) <= 3) {
2054 /* if register pair and starts with 26/30 then adiw */
2055 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0
2057 && (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX)
2058 || IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX))) {
2059 emitcode ("sbiw", "%s,%d",
2060 aopGet (AOP (IC_RESULT (ic)), 0), icount);
2065 emitcode ("subi", "%s,lo8(%d)",
2066 aopGet (AOP (IC_RESULT (ic)), 0), icount);
2067 emitcode ("sbci", "%s,hi8(%d)",
2068 aopGet (AOP (IC_RESULT (ic)), 1), icount);
2071 /* for 32 bit longs */
2072 emitcode ("subi", "%s,lo8(%d)", aopGet (AOP (IC_RESULT (ic)), 0),
2074 emitcode ("sbci", "%s,hi8(%d)", aopGet (AOP (IC_RESULT (ic)), 1),
2076 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2),
2078 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3),
2084 /*-----------------------------------------------------------------*/
2085 /* addSign - complete with sign */
2086 /*-----------------------------------------------------------------*/
2088 addSign (operand * result, int offset, int sign)
2090 int size = (getDataSize (result) - offset);
2093 emitcode ("rlc", "a");
2094 emitcode ("subb", "a,acc");
2096 aopPut (AOP (result), "a", offset++);
2100 aopPut (AOP (result), zero, offset++);
2104 /*-----------------------------------------------------------------*/
2105 /* genMinus - generates code for subtraction */
2106 /*-----------------------------------------------------------------*/
2108 genMinus (iCode * ic)
2110 int size, offset = 0, samer;
2113 aopOp (IC_LEFT (ic), ic, FALSE);
2114 aopOp (IC_RIGHT (ic), ic, FALSE);
2115 aopOp (IC_RESULT (ic), ic, TRUE);
2117 /* if I can do an decrement instead
2118 of subtract then GOOD for ME */
2119 if (genMinusDec (ic) == TRUE)
2122 size = getDataSize (IC_RESULT (ic));
2123 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2126 aopPut (AOP (IC_RESULT (ic)),
2127 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2129 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
2136 emitcode (l, "%s,%s",
2137 aopGet (AOP (IC_RESULT (ic)), offset),
2138 aopGet (AOP (IC_RIGHT (ic)), offset));
2146 emitcode (l, "%s,%s(%d)",
2147 aopGet (AOP (IC_RESULT (ic)), offset),
2149 (int) floatFromVal (AOP (IC_RIGHT (ic))->
2155 adjustArithmeticResult (ic);
2158 freeAsmop (IC_LEFT (ic), NULL, ic,
2159 (RESULTONSTACK (ic) ? FALSE : TRUE));
2160 freeAsmop (IC_RIGHT (ic), NULL, ic,
2161 (RESULTONSTACK (ic) ? FALSE : TRUE));
2162 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2165 /*-----------------------------------------------------------------*/
2166 /* genMultOneByte : 8 bit multiplication & division */
2167 /*-----------------------------------------------------------------*/
2169 genMultOneByte (operand * left, operand * right, operand * result)
2171 sym_link *opetype = operandType (result);
2175 /* (if two literals, the value is computed before) */
2176 /* if one literal, literal on the right */
2177 if (AOP_TYPE (left) == AOP_LIT) {
2183 size = AOP_SIZE (result);
2185 if (SPEC_USIGN (opetype)) {
2186 emitcode ("mul", "%s,%s", aopGet (AOP (left), 0),
2187 aopGet (AOP (right), 0));
2190 emitcode ("muls", "%s,%s", aopGet (AOP (left), 0),
2191 aopGet (AOP (right), 0));
2193 aopPut (AOP (result), "r0", 0);
2195 aopPut (AOP (result), "r1", 1);
2198 if (SPEC_USIGN (opetype)) {
2200 aopPut (AOP (result), zero, offset++);
2205 lbl = newiTempLabel (NULL);
2206 emitcode ("ldi", "r24,0");
2207 emitcode ("brcc", "L%05d", lbl->key);
2208 emitcode ("ldi", "r24,lo8(-1)");
2209 emitcode ("", "L%05d:", lbl->key);
2211 aopPut (AOP (result), "r24",
2219 /*-----------------------------------------------------------------*/
2220 /* genMult - generates code for multiplication */
2221 /*-----------------------------------------------------------------*/
2223 genMult (iCode * ic)
2225 operand *left = IC_LEFT (ic);
2226 operand *right = IC_RIGHT (ic);
2227 operand *result = IC_RESULT (ic);
2229 /* assign the amsops */
2230 aopOp (left, ic, FALSE);
2231 aopOp (right, ic, FALSE);
2232 aopOp (result, ic, TRUE);
2234 /* if both are of size == 1 */
2235 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1) {
2236 genMultOneByte (left, right, result);
2240 /* should have been converted to function call */
2244 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2245 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2246 freeAsmop (result, NULL, ic, TRUE);
2249 /*-----------------------------------------------------------------*/
2250 /* genDiv - generates code for division */
2251 /*-----------------------------------------------------------------*/
2255 /* should have been converted to function call */
2259 /*-----------------------------------------------------------------*/
2260 /* genMod - generates code for division */
2261 /*-----------------------------------------------------------------*/
2265 /* should have been converted to function call */
2277 /*-----------------------------------------------------------------*/
2278 /* revavrcnd - reverse a conditional for avr */
2279 /*-----------------------------------------------------------------*/
2281 revavrcnd (int type)
2293 for (i = 0; i < (sizeof (rar) / sizeof (rar[0])); i++) {
2294 if (rar[i].type == type)
2295 return rar[i].rtype;
2296 if (rar[i].rtype == type)
2299 assert (1); /* cannot happen */
2300 return 0; /* makes the compiler happy */
2303 static char *br_name[4] = { "breq", "brne", "brlt", "brge" };
2304 static char *br_uname[4] = { "breq", "brne", "brlo", "brcc" };
2306 /*-----------------------------------------------------------------*/
2307 /* genBranch - generate the branch instruction */
2308 /*-----------------------------------------------------------------*/
2310 genBranch (iCode * ifx, int br_type, int sign)
2312 int tj = (IC_TRUE (ifx) ? 1 : 0);
2314 if (tj) { /* if true jump */
2315 char *nm = (sign ? br_name[br_type] : br_uname[br_type]);
2316 emitcode (nm, "L%05d", IC_TRUE (ifx)->key);
2318 else { /* if false jump */
2319 int rtype = revavrcnd (br_type);
2320 char *nm = (sign ? br_name[rtype] : br_uname[rtype]);
2321 emitcode (nm, "L%05d", IC_FALSE (ifx)->key);
2326 /*-----------------------------------------------------------------*/
2327 /* genCmp - compare & jump */
2328 /*-----------------------------------------------------------------*/
2330 genCmp (iCode * ic, iCode * ifx, int br_type)
2332 operand *left, *right, *result;
2333 sym_link *letype, *retype;
2335 int sign, size, offset = 0;
2337 left = IC_LEFT (ic);
2338 right = IC_RIGHT (ic);
2339 result = IC_RESULT (ic);
2341 letype = getSpec (operandType (left));
2342 retype = getSpec (operandType (right));
2343 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
2345 /* assign the amsops */
2346 aopOp (left, ic, FALSE);
2347 aopOp (right, ic, FALSE);
2348 aopOp (result, ic, TRUE);
2349 size = AOP_SIZE (left);
2353 if (AOP_TYPE (right) == AOP_LIT) {
2354 emitcode ("cpi", "%s,lo8(%d)",
2355 aopGet (AOP (left), 0),
2357 floatFromVal (AOP (IC_RIGHT (ic))->
2359 genBranch (ifx, br_type, sign);
2361 else { /* right != literal */
2362 emitcode ("cp", "%s,%s",
2363 aopGet (AOP (left), 0),
2364 aopGet (AOP (right), 0));
2365 genBranch (ifx, br_type, sign);
2368 else { /* size != 1 */
2371 emitcode ("cp", "%s,%s",
2372 aopGet (AOP (left), 0),
2373 aopGet (AOP (right), 0));
2375 emitcode ("cpc", "%s,%s",
2376 aopGet (AOP (left), offset),
2377 aopGet (AOP (right),
2381 genBranch (ifx, br_type, sign);
2385 emitcode ("clr", "r0");
2388 emitcode ("cp", "%s,%s",
2389 aopGet (AOP (left), 0),
2390 aopGet (AOP (right), 0));
2392 emitcode ("cpc", "%s,%s",
2393 aopGet (AOP (left), offset),
2394 aopGet (AOP (right), offset));
2397 lbl = newiTempLabel (NULL);
2398 br_type = revavrcnd (br_type);
2400 emitcode (br_uname[br_type], "L%05d", lbl->key);
2402 emitcode (br_name[br_type], "L%05d", lbl->key);
2403 emitcode ("inc", "r0");
2404 emitcode ("", "L%05d:", lbl->key);
2405 aopPut (AOP (result), "r0", 0);
2406 size = AOP_SIZE (result) - 1;
2409 aopPut (AOP (result), zero, offset++);
2412 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2413 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2414 freeAsmop (result, NULL, ic, TRUE);
2417 /*-----------------------------------------------------------------*/
2418 /* genCmpGt :- greater than comparison */
2419 /*-----------------------------------------------------------------*/
2421 genCmpGt (iCode * ic, iCode * ifx)
2423 /* should have transformed by the parser */
2427 /*-----------------------------------------------------------------*/
2428 /* genCmpLt - less than comparisons */
2429 /*-----------------------------------------------------------------*/
2431 genCmpLt (iCode * ic, iCode * ifx)
2433 genCmp (ic, ifx, AVR_LT);
2436 /*-----------------------------------------------------------------*/
2437 /* genCmpEq - generates code for equal to */
2438 /*-----------------------------------------------------------------*/
2440 genCmpEq (iCode * ic, iCode * ifx)
2442 genCmp (ic, ifx, AVR_EQ);
2445 /*-----------------------------------------------------------------*/
2446 /* genCmpNe - generates code for not equal to */
2447 /*-----------------------------------------------------------------*/
2449 genCmpNe (iCode * ic, iCode * ifx)
2451 genCmp (ic, ifx, AVR_NE);
2454 /*-----------------------------------------------------------------*/
2455 /* genCmpGe - generates code for greater than equal to */
2456 /*-----------------------------------------------------------------*/
2458 genCmpGe (iCode * ic, iCode * ifx)
2460 genCmp (ic, ifx, AVR_GE);
2463 /*-----------------------------------------------------------------*/
2464 /* genCmpLe - generates code for less than equal to */
2465 /*-----------------------------------------------------------------*/
2467 genCmpLe (iCode * ic, iCode * ifx)
2469 operand *left = IC_LEFT (ic);
2470 operand *right = IC_RIGHT (ic);
2472 IC_RIGHT (ic) = left;
2473 IC_LEFT (ic) = right;
2474 genCmp (ic, ifx, AVR_GE);
2477 /*-----------------------------------------------------------------*/
2478 /* ifxForOp - returns the icode containing the ifx for operand */
2479 /*-----------------------------------------------------------------*/
2481 ifxForOp (operand * op, iCode * ic)
2483 /* if true symbol then needs to be assigned */
2484 if (IS_TRUE_SYMOP (op))
2487 /* if this has register type condition and
2488 the next instruction is ifx with the same operand
2489 and live to of the operand is upto the ifx only then */
2491 ic->next->op == IFX &&
2492 IC_COND (ic->next)->key == op->key &&
2493 OP_SYMBOL (op)->liveTo <= ic->next->seq) return ic->next;
2498 /*-----------------------------------------------------------------*/
2499 /* genAndOp - for && operation */
2500 /*-----------------------------------------------------------------*/
2502 genAndOp (iCode * ic)
2504 operand *left, *right, *result;
2508 /* note here that && operations that are in an
2509 if statement are taken away by backPatchLabels
2510 only those used in arthmetic operations remain */
2511 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2512 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2513 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
2515 tlbl = newiTempLabel (NULL);
2516 toBoolean (left, "r0", TRUE);
2517 toBoolean (right, "r1", TRUE);
2518 emitcode ("and", "r0,r1");
2519 emitcode ("ldi", "r24,1");
2520 emitcode ("breq", "L%05d", tlbl->key);
2521 emitcode ("dec", "r24");
2522 emitcode ("", "L%05d:", tlbl->key);
2523 aopPut (AOP (result), "r24", 0);
2524 size = AOP_SIZE (result) - 1;
2527 aopPut (AOP (result), zero, offset++);
2529 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2530 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2531 freeAsmop (result, NULL, ic, TRUE);
2535 /*-----------------------------------------------------------------*/
2536 /* genOrOp - for || operation */
2537 /*-----------------------------------------------------------------*/
2539 genOrOp (iCode * ic)
2541 operand *left, *right, *result;
2545 /* note here that || operations that are in an
2546 if statement are taken away by backPatchLabels
2547 only those used in arthmetic operations remain */
2548 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2549 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2550 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
2552 tlbl = newiTempLabel (NULL);
2553 toBoolean (left, "r0", TRUE);
2554 toBoolean (right, "r0", FALSE);
2555 emitcode ("ldi", "r24,1");
2556 emitcode ("breq", "L%05d", tlbl->key);
2557 emitcode ("dec", "r24");
2558 emitcode ("", "L%05d:", tlbl->key);
2559 aopPut (AOP (result), "r24", 0);
2560 size = AOP_SIZE (result) - 1;
2563 aopPut (AOP (result), zero, offset++);
2565 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2566 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2567 freeAsmop (result, NULL, ic, TRUE);
2570 /*-----------------------------------------------------------------*/
2571 /* isLiteralBit - test if lit == 2^n */
2572 /*-----------------------------------------------------------------*/
2574 isLiteralBit (unsigned long lit)
2576 unsigned long pw[32] = { 1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
2577 0x100L, 0x200L, 0x400L, 0x800L,
2578 0x1000L, 0x2000L, 0x4000L, 0x8000L,
2579 0x10000L, 0x20000L, 0x40000L, 0x80000L,
2580 0x100000L, 0x200000L, 0x400000L, 0x800000L,
2581 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
2582 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L
2586 for (idx = 0; idx < 32; idx++)
2593 AVR_AND = 0, AVR_OR, AVR_XOR
2595 static char *bopnames_lit[] = { "andi", "ori" };
2596 static char *bopnames[] = { "and", "or", "eor" };
2597 /*-----------------------------------------------------------------*/
2598 /* genBitWise - generate bitwise operations */
2599 /*-----------------------------------------------------------------*/
2601 genBitWise (iCode * ic, iCode * ifx, int bitop)
2603 operand *left, *right, *result;
2604 int size, offset = 0;
2609 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2610 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2611 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
2613 size = AOP_SIZE (left);
2615 if (ifx) { /* used only for jumps */
2616 if (AOP_TYPE (right) == AOP_LIT &&
2617 (bitop == AVR_AND || bitop == AVR_OR)) {
2619 (int) floatFromVal (AOP (right)->aopu.
2621 int p2 = powof2 (lit);
2622 if (bitop == AVR_AND && p2) { /* right side is a power of 2 */
2623 l = aopGet (AOP (left), p2 / 8);
2624 if (IC_TRUE (ifx)) {
2625 emitcode ("sbrc", "%s,%d", l,
2627 emitcode ("rjmp", "L%05d",
2628 IC_TRUE (ifx)->key);
2631 emitcode ("sbrs", "%s,%d", l,
2633 emitcode ("rjmp", "L%05d",
2634 IC_FALSE (ifx)->key);
2637 else { /* right not power of two */
2638 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2640 if (eh && AOP_ISHIGHREG(AOP(IC_LEFT(ic)),0)) {
2641 emitcode (bopnames_lit[bitop],
2643 aopGet (AOP (IC_LEFT (ic)), 0), lit);
2646 MOVR24 (aopGet (AOP (IC_LEFT (ic)), 0));
2647 emitcode (bopnames_lit[bitop], "r24,lo8(%d)", lit);
2649 lbl = newiTempLabel (NULL);
2650 if (IC_TRUE (ifx)) {
2651 emitcode ("breq", "L%05d", lbl->key);
2652 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2655 emitcode ("brne", "L%05d", lbl->key);
2656 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)-> key);
2658 emitcode ("", "L%05d:", lbl->key);
2660 else if (size == 2) {
2661 emitcode ("mov", "r24,%s", aopGet (AOP (IC_LEFT (ic)), 0));
2662 emitcode ("mov", "r25,%s", aopGet (AOP (IC_LEFT (ic)), 1));
2663 emitcode (bopnames_lit[bitop], "r24,lo8(%d)", lit);
2664 emitcode (bopnames_lit[bitop], "r25,hi8(%d)", lit);
2665 emitcode ("sbiw", "r24,0");
2666 lbl = newiTempLabel (NULL);
2667 if (IC_TRUE (ifx)) {
2668 emitcode ("breq", "L%05d", lbl->key);
2669 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2672 emitcode ("brne", "L%05d", lbl->key);
2673 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2675 emitcode ("", "L%05d:", lbl->key);
2678 lbl = newiTempLabel (NULL);
2679 lbl1 = newiTempLabel (NULL);
2681 if (eh && AOP_ISHIGHREG(AOP(IC_LEFT(ic)),offset)) {
2682 emitcode (bopnames_lit [bitop], "%s,lo8(%d)",
2683 aopGet (AOP (IC_LEFT (ic)), offset),
2687 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
2689 emitcode ("andi", "r24,lo8(%d)", lit);
2691 emitcode ("brne", "L%05d", lbl->key);
2696 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)-> key);
2698 emitcode ("rjmp", "L%05d", lbl1->key);
2699 emitcode ("", "L%05d:", lbl->key);
2702 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2703 emitcode ("", "L%05d:", lbl1->key);
2708 else { /* right is not a literal */
2709 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2710 int reh = OP_SYMBOL (right)->liveTo <= ic->seq;
2713 emitcode (bopnames[bitop], "%s,%s", aopGet (AOP (IC_LEFT (ic)), 0),
2714 aopGet (AOP (IC_RIGHT (ic)), 0));
2717 emitcode (bopnames[bitop], "%s,%s",
2718 aopGet (AOP (IC_RIGHT (ic)), 0),
2719 aopGet (AOP (IC_LEFT (ic)), 0));
2722 MOVR0 (aopGet (AOP (IC_LEFT (ic)), 0));
2723 emitcode (bopnames[bitop], "r0,%s",
2724 aopGet (AOP (IC_RIGHT (ic)), 0));
2726 lbl = newiTempLabel (NULL);
2727 if (IC_TRUE (ifx)) {
2728 emitcode ("breq", "L%05d", lbl->key);
2729 emitcode ("rjmp", "L%05d",
2730 IC_TRUE (ifx)->key);
2733 emitcode ("brne", "L%05d", lbl->key);
2734 emitcode ("rjmp", "L%05d",
2735 IC_FALSE (ifx)->key);
2737 emitcode ("", "L%05d:", lbl->key);
2739 else if (size == 2) {
2740 emitcode ("mov", "r24,%s",
2741 aopGet (AOP (IC_LEFT (ic)), 0));
2742 emitcode ("mov", "r25,%s",
2743 aopGet (AOP (IC_LEFT (ic)), 1));
2744 emitcode (bopnames[bitop], "r24,%s",
2745 aopGet (AOP (IC_RIGHT (ic)), 0));
2746 emitcode (bopnames[bitop], "r25,%s",
2747 aopGet (AOP (IC_RIGHT (ic)), 1));
2748 emitcode ("sbiw", "r24,0");
2749 lbl = newiTempLabel (NULL);
2750 if (IC_TRUE (ifx)) {
2751 emitcode ("breq", "L%05d", lbl->key);
2752 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2755 emitcode ("brne", "L%05d", lbl->key);
2756 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2758 emitcode ("", "L%05d:", lbl->key);
2761 lbl = newiTempLabel (NULL);
2762 lbl1 = newiTempLabel (NULL);
2765 emitcode (bopnames[bitop], "%s,%s",
2766 aopGet (AOP (IC_LEFT (ic)), offset),
2767 aopGet (AOP (IC_RIGHT (ic)), offset));
2770 emitcode (bopnames[bitop], "%s,%s",
2771 aopGet (AOP (IC_RIGHT (ic)), offset),
2772 aopGet (AOP (IC_LEFT (ic)), offset));
2775 MOVR0 (aopGet (AOP (IC_LEFT (ic)), offset));
2776 emitcode (bopnames[bitop], "r0,%s",
2777 aopGet (AOP (IC_RIGHT (ic)), offset));
2779 emitcode ("brne", "L%05d", lbl->key);
2784 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2786 emitcode ("rjmp", "L%05d", lbl1->key);
2787 emitcode ("", "L%05d:", lbl->key);
2790 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2791 emitcode ("", "L%05d:", lbl1->key);
2798 /* result needs to go a register */
2799 samerl = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2800 samerr = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)));
2802 if (AOP_TYPE (right) == AOP_LIT) {
2804 (int) floatFromVal (AOP (right)->aopu.
2806 if (((lit >> (8 * offset)) & 0xff) == 0) {
2807 if (bitop == AVR_AND) {
2808 aopPut (AOP (result), zero, offset++);
2811 else if (bitop == AVR_OR) {
2813 aopPut (AOP (result),
2823 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT &&
2824 AOP_ISHIGHREG(AOP(IC_LEFT(ic)),offset) &&
2825 (bitop == AVR_AND || bitop == AVR_OR)) {
2826 emitcode (bopnames_lit[bitop], "%s,%s(%d)",
2827 aopGet (AOP (IC_LEFT (ic)), offset),
2829 (int) floatFromVal (AOP (right)-> aopu.aop_lit));
2832 emitcode (bopnames[bitop], "%s,%s",
2833 aopGet (AOP (IC_LEFT (ic)), offset),
2834 aopGet (AOP (IC_RIGHT (ic)), offset));
2838 emitcode (bopnames[bitop], "%s,%s",
2839 aopGet (AOP (IC_RIGHT (ic)), offset),
2840 aopGet (AOP (IC_LEFT (ic)), offset));
2843 aopPut (AOP (IC_RESULT (ic)),
2844 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2845 emitcode (bopnames[bitop],
2846 aopGet (AOP (IC_RESULT (ic)), offset),
2847 aopGet (AOP (IC_RIGHT (ic)), offset));
2852 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2853 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2854 freeAsmop (result, NULL, ic, TRUE);
2857 /*-----------------------------------------------------------------*/
2858 /* genAnd - code for and */
2859 /*-----------------------------------------------------------------*/
2861 genAnd (iCode * ic, iCode * ifx)
2863 genBitWise (ic, ifx, AVR_AND);
2866 /*-----------------------------------------------------------------*/
2867 /* genOr - code for or */
2868 /*-----------------------------------------------------------------*/
2870 genOr (iCode * ic, iCode * ifx)
2872 genBitWise (ic, ifx, AVR_OR);
2875 /*-----------------------------------------------------------------*/
2876 /* genXor - code for xclusive or */
2877 /*-----------------------------------------------------------------*/
2879 genXor (iCode * ic, iCode * ifx)
2881 genBitWise (ic, ifx, AVR_XOR);
2884 /*-----------------------------------------------------------------*/
2885 /* genInline - write the inline code out */
2886 /*-----------------------------------------------------------------*/
2888 genInline (iCode * ic)
2890 char buffer[MAX_INLINEASM];
2894 _G.inLine += (!options.asmpeep);
2895 strcpy (buffer, IC_INLINE (ic));
2897 /* emit each line as a code */
2918 /* emitcode("",buffer); */
2919 _G.inLine -= (!options.asmpeep);
2922 /*-----------------------------------------------------------------*/
2923 /* genRotC - rotate right/left with carry , lr = 1 rotate right */
2924 /*-----------------------------------------------------------------*/
2926 genRotC (iCode * ic, int lr)
2928 operand *left, *result;
2929 int size, offset = 0;
2931 /* rotate right with carry */
2932 left = IC_LEFT (ic);
2933 result = IC_RESULT (ic);
2934 aopOp (left, ic, FALSE);
2935 aopOp (result, ic, FALSE);
2937 /* move it to the result */
2938 size = AOP_SIZE (result);
2939 if (!sameRegs (AOP (left), AOP (result))) {
2942 aopPut (AOP (result),
2943 aopGet (AOP (left), offset), offset);
2946 size = AOP_SIZE (result);
2954 emitcode ("sbrc", "%s,%d", aopGet (AOP (result), offset),
2956 emitcode ("sec", "");
2959 emitcode ((lr ? "ror" : "rol"), "%s",
2960 aopGet (AOP (result), offset));
2966 freeAsmop (left, NULL, ic, TRUE);
2967 freeAsmop (result, NULL, ic, TRUE);
2970 /*-----------------------------------------------------------------*/
2971 /* genRRC - rotate right with carry */
2972 /*-----------------------------------------------------------------*/
2979 /*-----------------------------------------------------------------*/
2980 /* genRLC - generate code for rotate left with carry */
2981 /*-----------------------------------------------------------------*/
2988 /*-----------------------------------------------------------------*/
2989 /* genGetHbit - generates code get highest order bit */
2990 /*-----------------------------------------------------------------*/
2992 genGetHbit (iCode * ic)
2994 operand *left, *result;
2997 left = IC_LEFT (ic);
2998 result = IC_RESULT (ic);
2999 aopOp (left, ic, FALSE);
3000 aopOp (result, ic, FALSE);
3002 size = AOP_SIZE (result);
3003 if (!sameRegs (AOP (left), AOP (result))) {
3004 emitcode ("clr", "%s", aopGet (AOP (result), size - 1));
3005 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3006 emitcode ("subi", "%s,lo8(-1)",
3007 aopGet (AOP (result), size - 1));
3010 emitcode ("clr", "r0");
3011 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3012 emitcode ("subi", "r0,lo8(-1)");
3013 aopPut (AOP (result), "r0", 0);
3018 emitcode ("clr", aopGet (AOP (result), offset++));
3020 freeAsmop (left, NULL, ic, TRUE);
3021 freeAsmop (result, NULL, ic, TRUE);
3024 /*-----------------------------------------------------------------*/
3025 /* genShiftLeftLit - shift left by a known amount */
3026 /*-----------------------------------------------------------------*/
3028 genShiftLeftLit (iCode * ic)
3030 operand *left, *right, *result;
3031 int size, shCount, offset = 0;
3034 right = IC_RIGHT (ic);
3035 left = IC_LEFT (ic);
3036 result = IC_RESULT (ic);
3038 aopOp (left, ic, FALSE);
3039 aopOp (result, ic, FALSE);
3040 size = AOP_SIZE (result);
3041 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3043 if (shCount > (size * 8 - 1)) {
3045 aopPut (AOP (result), zero, offset++);
3050 if (!sameRegs (AOP (left), AOP (result)))
3051 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3053 if (AOP_ISHIGHREG(AOP(result),0)) {
3054 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3055 emitcode ("andi", "%s,0xf0");
3057 emitcode ("ldi","r24,0xf0");
3058 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3059 emitcode ("and", "%s,r24");
3064 emitcode ("add", "%s,%s", aopGet (AOP (result), 0),
3065 aopGet (AOP (result), 0));
3069 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3072 if (shCount >= 12) {
3073 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3074 aopPut (AOP (result), zero, 0);
3075 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3076 if (AOP_ISHIGHREG(AOP(result),1)) {
3077 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3079 emitcode ("ldi","r24,0xf0");
3080 emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
3086 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3087 aopPut (AOP (result), zero, 0);
3093 if (!sameRegs (AOP (left), AOP (result))) {
3094 aopPut (AOP (result), aopGet (AOP (left), 0),
3096 aopPut (AOP (result), aopGet (AOP (left), 1),
3099 emitcode ("mov", "r24,%s", aopGet (AOP (result), 0));
3100 emitcode ("andi", "r24,0x0f");
3101 if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
3102 emitcode("ldi","r25,0xf0");
3104 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3105 if (AOP_ISHIGHREG(AOP(result),0)) {
3106 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 0));
3108 emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
3110 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3111 if (AOP_ISHIGHREG(AOP(result),1)) {
3112 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3114 emitcode ("and", "%s,r25", aopGet (AOP (result), 1));
3116 emitcode ("or", "%s,r24", aopGet (AOP (result), 1));
3118 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3119 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3122 if (!lByteZ && !sameRegs (AOP (result), AOP (left))
3126 aopPut (AOP (result),
3127 aopGet (AOP (left), offset), offset);
3133 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3136 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3137 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3142 assert ("shifting generic pointer ?\n");
3145 /* 32 bits we do only byte boundaries */
3146 if (shCount >= 24) {
3147 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3148 aopPut (AOP (result), zero, 2);
3149 aopPut (AOP (result), zero, 1);
3150 aopPut (AOP (result), zero, 0);
3154 if (shCount >= 16) {
3155 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3156 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3157 aopPut (AOP (result), zero, 1);
3158 aopPut (AOP (result), zero, 0);
3163 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3164 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3165 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3166 aopPut (AOP (result), zero, 0);
3170 if (!lByteZ && !sameRegs (AOP (left), AOP (right))) {
3173 aopPut (AOP (result),
3174 aopGet (AOP (left), offset), offset);
3178 size = AOP_SIZE (result);
3184 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3185 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3186 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3187 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3192 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3193 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3194 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3199 emitcode ("lsl", "%s", aopGet (AOP (result), 2));
3200 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3205 emitcode ("lsl", "%s", aopGet (AOP (result), 3));
3213 freeAsmop (left, NULL, ic, TRUE);
3214 freeAsmop (right, NULL, ic, TRUE);
3215 freeAsmop (result, NULL, ic, TRUE);
3218 /*-----------------------------------------------------------------*/
3219 /* genLeftShift - generates code for left shifting */
3220 /*-----------------------------------------------------------------*/
3222 genLeftShift (iCode * ic)
3224 operand *left, *right, *result;
3228 right = IC_RIGHT (ic);
3229 left = IC_LEFT (ic);
3230 result = IC_RESULT (ic);
3232 aopOp (right, ic, FALSE);
3234 if (AOP_TYPE (right) == AOP_LIT) {
3235 genShiftLeftLit (ic);
3240 aopOp (left, ic, FALSE);
3241 aopOp (result, ic, FALSE);
3242 size = AOP_SIZE (result);
3244 if (AOP_SIZE (right) > 1) {
3245 if (isRegPair (AOP (right))) {
3246 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3249 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3250 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3254 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3256 if (!sameRegs (AOP (left), AOP (result))) {
3258 aopPut (AOP (result), aopGet (AOP (left), offset),
3262 size = AOP_SIZE (result);
3264 tlbl = newiTempLabel (NULL);
3265 emitcode ("", "L%05d:", tlbl->key);
3269 emitcode ("rol", "%s", aopGet (AOP (result), offset));
3271 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3274 if (AOP_SIZE (right) > 1)
3275 emitcode ("sbiw", "r24,1");
3277 emitcode ("dec", "r24");
3278 emitcode ("brne", "L%05d", tlbl->key);
3280 freeAsmop (left, NULL, ic, TRUE);
3281 freeAsmop (right, NULL, ic, TRUE);
3282 freeAsmop (result, NULL, ic, TRUE);
3285 /*-----------------------------------------------------------------*/
3286 /* genShiftRightLit - generate for right shift with known count */
3287 /*-----------------------------------------------------------------*/
3289 genShiftRightLit (iCode * ic)
3291 operand *left = IC_LEFT (ic)
3292 , *right = IC_RIGHT (ic)
3293 , *result = IC_RESULT (ic);
3294 int size, shCount, offset = 0;
3296 sym_link *letype = getSpec (operandType (left));
3297 int sign = !SPEC_USIGN (letype);
3299 right = IC_RIGHT (ic);
3300 left = IC_LEFT (ic);
3301 result = IC_RESULT (ic);
3303 aopOp (left, ic, FALSE);
3304 aopOp (result, ic, FALSE);
3305 size = AOP_SIZE (result);
3306 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3308 /* if signed then give up and use a loop to shift */
3311 if (!sameRegs (AOP (left), AOP (result))) {
3313 aopPut (AOP (result),
3314 aopGet (AOP (left), offset), offset);
3317 size = size = AOP_SIZE (result);
3320 /* be as economical as possible */
3325 size = AOP_SIZE (result);
3327 if (offset == (size - 1))
3328 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3330 emitcode ("lsr", "%s", aopGet (AOP (result), offset));
3336 emitcode ("ldi", "r24,lo8(%d)", shCount);
3337 tlbl = newiTempLabel (NULL);
3338 emitcode ("", "L%05d:", tlbl->key);
3341 if (offset == (size - 1))
3342 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3344 emitcode ("lsr", "%s", aopGet (AOP (result), offset));
3347 emitcode ("dec", "r24");
3348 emitcode ("brne", "L%05d", tlbl->key);
3352 if (shCount > (size * 8 - 1)) {
3354 aopPut (AOP (result), zero, offset++);
3357 /* for unsigned we can much more efficient */
3360 if (!sameRegs (AOP (left), AOP (result)))
3361 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3363 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3364 if (AOP_ISHIGHREG(AOP(result),0)) {
3365 emitcode ("andi", "%s,0x0f",aopGet(AOP(result),0));
3367 emitcode ("ldi","r24,0x0f");
3368 emitcode ("and", "%s,r24",aopGet(AOP(result),0));
3373 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3376 if (shCount >= 12) {
3377 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3378 aopPut (AOP (result), zero, 1);
3379 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3380 if (AOP_ISHIGHREG(AOP(result),0)) {
3381 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3383 emitcode ("ldi","r24,0x0f");
3384 emitcode ("and", "%s,r24",aopGet(AOP(result),0));
3390 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3391 aopPut (AOP (result), zero, 1);
3397 if (!sameRegs (AOP (left), AOP (result))) {
3398 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3399 aopPut (AOP (result), aopGet (AOP (left), 1), 1);
3401 if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
3402 emitcode("ldi","r25,0x0f");
3404 emitcode ("mov", "r24,%s", aopGet (AOP (result), 1));
3405 emitcode ("andi", "r24,0xf0");
3406 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3407 if (AOP_ISHIGHREG(AOP(result),0)) {
3408 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3410 emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
3412 emitcode ("or", "%s,r24", aopGet (AOP (result), 0));
3413 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3414 if (AOP_ISHIGHREG(AOP(result),1)) {
3415 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 1));
3417 emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
3420 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3421 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3425 if (!hByteZ && !sameRegs (AOP (result), AOP (left))
3429 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3435 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3438 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3439 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3445 assert ("shifting generic pointer ?\n");
3448 /* 32 bits we do only byte boundaries */
3449 if (shCount >= 24) {
3450 aopPut (AOP (result), aopGet (AOP (left), 3), 0);
3451 aopPut (AOP (result), zero, 1);
3452 aopPut (AOP (result), zero, 2);
3453 aopPut (AOP (result), zero, 3);
3457 if (shCount >= 16) {
3458 aopPut (AOP (result), aopGet (AOP (left), 3), 1);
3459 aopPut (AOP (result), aopGet (AOP (left), 2), 0);
3460 aopPut (AOP (result), zero, 2);
3461 aopPut (AOP (result), zero, 3);
3466 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3467 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3468 aopPut (AOP (result), aopGet (AOP (left), 3), 2);
3469 aopPut (AOP (result), zero, 3);
3473 if (!hByteZ && !sameRegs (AOP (left), AOP (right))) {
3476 aopPut (AOP (result),
3477 aopGet (AOP (left), offset), offset);
3481 size = AOP_SIZE (result);
3487 emitcode ("lsr", "%s", aopGet (AOP (result), 3));
3488 emitcode ("ror", "%s", aopGet (AOP (result), 2));
3489 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3490 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3495 emitcode ("lsr", "%s", aopGet (AOP (result), 2));
3496 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3497 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3502 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3503 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3508 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3515 freeAsmop (left, NULL, ic, TRUE);
3516 freeAsmop (right, NULL, ic, TRUE);
3517 freeAsmop (result, NULL, ic, TRUE);
3520 /*-----------------------------------------------------------------*/
3521 /* genRightShift - generate code for right shifting */
3522 /*-----------------------------------------------------------------*/
3524 genRightShift (iCode * ic)
3526 operand *right, *left, *result;
3529 int sign = 0, first = 1;
3532 aopOp (right = IC_RIGHT (ic), ic, FALSE);
3534 if (AOP_TYPE (right) == AOP_LIT) {
3535 genShiftRightLit (ic);
3539 if (AOP_SIZE (right) > 1) {
3540 if (isRegPair (AOP (right))) {
3541 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3544 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3545 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3549 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3551 aopOp (left = IC_LEFT (ic), ic, FALSE);
3552 aopOp (result = IC_RESULT (ic), ic, FALSE);
3553 size = AOP_SIZE (result);
3554 tlbl = newiTempLabel (NULL);
3555 emitcode ("", "L%05d:", tlbl->key);
3557 letype = getSpec (operandType (left));
3558 sign = !SPEC_USIGN (letype);
3559 if (!sameRegs (AOP (left), AOP (result))) {
3561 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3564 size = AOP_SIZE (result);
3566 size = AOP_SIZE (result);
3570 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3572 emitcode ("lsr", "%s", aopGet (AOP (result), offset));
3576 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3579 if (AOP_SIZE (right) > 1)
3580 emitcode ("sbiw", "r24,1");
3582 emitcode ("dec", "r24");
3583 emitcode ("brne", "L%05d", tlbl->key);
3585 freeAsmop (left, NULL, ic, TRUE);
3586 freeAsmop (result, NULL, ic, TRUE);
3589 /*-----------------------------------------------------------------*/
3590 /* RRsh - shift right rn by known count */
3591 /*-----------------------------------------------------------------*/
3593 RRsh (int shCount,int reg)
3595 shCount &= 0x0007; // shCount : 0..7
3601 emitcode ("lsr", "r%d",reg);
3604 emitcode ("lsr", "r%d",reg);
3605 emitcode ("lsr", "r%d",reg);
3608 emitcode ("swap", "r%d",reg);
3609 emitcode ("lsl", "r%d",reg);
3612 emitcode ("swap", "r%d",reg);
3615 emitcode ("swap", "r%d",reg);
3616 emitcode ("lsr", "r%d",reg);
3619 emitcode ("swap","r%d",reg);
3620 emitcode ("lsr", "r%d",reg);
3621 emitcode ("lsr", "r%d",reg);
3624 emitcode ("swap","r%d",reg);
3625 emitcode ("lsr", "r%d",reg);
3626 emitcode ("lsr", "r%d",reg);
3627 emitcode ("lsr", "r%d",reg);
3632 /*-----------------------------------------------------------------*/
3633 /* RLsh - shift left rn by known count */
3634 /*-----------------------------------------------------------------*/
3636 RLsh (int shCount, int reg)
3638 shCount &= 0x0007; // shCount : 0..7
3644 emitcode ("lsl", "r%d",reg);
3647 emitcode ("lsl", "r%d",reg);
3648 emitcode ("lsl", "r%d",reg);
3651 emitcode ("swap","r%d",reg);
3652 emitcode ("lsr", "r%d",reg);
3655 emitcode ("swap", "r%d",reg);
3658 emitcode ("swap","r%d",reg);
3659 emitcode ("lsl", "r%d",reg);
3662 emitcode ("swap","r%d",reg);
3663 emitcode ("lsl", "r%d",reg);
3664 emitcode ("lsl", "r%d",reg);
3667 emitcode ("swap","r%d",reg);
3668 emitcode ("lsl", "r%d",reg);
3669 emitcode ("lsl", "r%d",reg);
3670 emitcode ("lsl", "r%d",reg);
3675 /*-----------------------------------------------------------------*/
3676 /* genUnpackBits - generates code for unpacking bits */
3677 /*-----------------------------------------------------------------*/
3679 genUnpackBits (operand * result, char *rname, int ptype)
3687 etype = getSpec (operandType (result));
3688 rsize = getSize (operandType (result));
3689 /* read the first byte */
3696 emitcode ("ld", "r24,%s+", rname);
3700 emitcode ("lpm", "r24,%s+", rname);
3704 emitcode ("call","__gptrget_pi");
3705 emitcode ("mov","r24,r0");
3709 rlen = SPEC_BLEN (etype);
3711 /* if we have bitdisplacement then it fits */
3712 /* into this byte completely or if length is */
3713 /* less than a byte */
3714 if ((shCnt = SPEC_BSTR (etype)) || (SPEC_BLEN (etype) <= 8)) {
3716 /* shift right acc */
3719 emitcode ("andi", "r24,lo(0x%x)",
3720 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
3721 aopPut (AOP (result), "r24", offset++);
3725 /* bit field did not fit in a byte */
3726 aopPut (AOP (result), "r24", offset++);
3736 emitcode ("ld", "r24,%s+");
3740 emitcode ("lpm", "r24,%s+");
3744 emitcode ("call", "__gptrget_pi");
3749 /* if we are done */
3753 aopPut (AOP (result), "r24", offset++);
3758 aopPut (AOP (result), "r24", offset++);
3762 if (offset < rsize) {
3765 aopPut (AOP (result), zero, offset++);
3770 /*-----------------------------------------------------------------*/
3771 /* genDataPointerGet - generates code when ptr offset is known */
3772 /*-----------------------------------------------------------------*/
3774 genDataPointerGet (operand * left, operand * result, iCode * ic)
3778 int size, offset = 0;
3779 aopOp (result, ic, TRUE);
3781 /* get the string representation of the name */
3782 l = aopGet (AOP (left), 0);
3783 size = AOP_SIZE (result);
3786 sprintf (buffer, "(%s + %d)", l, offset);
3788 sprintf (buffer, "%s", l);
3789 emitcode ("lds", "%s,%s", aopGet (AOP (result), offset++),
3793 freeAsmop (left, NULL, ic, TRUE);
3794 freeAsmop (result, NULL, ic, TRUE);
3797 /*-----------------------------------------------------------------*/
3798 /* genNearPointerGet - emitcode for near pointer fetch */
3799 /*-----------------------------------------------------------------*/
3801 genMemPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
3806 char *rname, *frname = NULL;
3807 sym_link *rtype, *retype;
3808 sym_link *ltype = operandType (left);
3810 rtype = operandType (result);
3811 retype = getSpec (rtype);
3813 aopOp (left, ic, FALSE);
3815 /* if left is rematerialisable and
3816 result is not bit variable type and
3817 the left is pointer to data space i.e
3818 lower 128 bytes of space */
3819 if (AOP_TYPE (left) == AOP_IMMD &&
3820 !IS_BITVAR (retype) && DCL_TYPE (ltype) == POINTER) {
3821 genDataPointerGet (left, result, ic);
3825 /* if the value is already in a pointer register
3826 then don't need anything more */
3827 if (!AOP_INPREG (AOP (left))) {
3828 /* otherwise get a free pointer register */
3830 preg = getFreePtr (ic, &aop, FALSE, 0);
3831 if (isRegPair (AOP (left) )) {
3832 emitcode ("movw", "%s,%s",
3833 aop->aopu.aop_ptr->name,
3834 aopGet(AOP(left),0));
3836 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
3837 aopGet (AOP (left), 0));
3838 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
3839 aopGet (AOP (left), 1));
3845 frname = aopGet(aop,0);
3849 } else if (AOP_ISZ(aop)) {
3852 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
3853 "pointer not in correct register");
3857 aopOp (result, ic, FALSE);
3859 /* if bitfield then unpack the bits */
3860 if (IS_BITVAR (retype))
3861 genUnpackBits (result, rname, POINTER);
3863 /* we have can just get the values */
3864 int size = AOP_SIZE (result);
3869 emitcode ("ld","%s,%s+",aopGet(AOP(result),offset), rname);
3871 emitcode ("ld","%s,%s",aopGet(AOP(result),offset), rname);
3876 /* now some housekeeping stuff */
3878 /* we had to allocate for this iCode */
3880 if (isRegPair (AOP (left) )) {
3881 emitcode ("movw", "%s,%s",
3882 aopGet (AOP(left),0),
3883 aop->aopu.aop_ptr->name);
3885 emitcode ("mov", "%s,%s",
3886 aopGet (AOP (left), 0),
3887 aop->aopu.aop_ptr->name);
3888 emitcode ("mov", "%s,%s",
3889 aopGet (AOP (left), 1),
3890 aop->aop_ptr2->name);
3893 freeAsmop (NULL, aop, ic, TRUE);
3896 /* we did not allocate which means left
3897 already in a pointer register, then
3898 if size > 0 && this could be used again
3899 we have to point it back to where it
3901 if ((AOP_SIZE (result) > 1 &&
3902 !OP_SYMBOL (left)->remat &&
3903 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) && !pi) {
3904 int size = AOP_SIZE (result) - 1;
3905 emitcode ("sbiw", "%s,%d",frname,size);
3910 if (pi) pi->generated = 1;
3911 freeAsmop (left, NULL, ic, TRUE);
3912 freeAsmop (result, NULL, ic, TRUE);
3916 /*-----------------------------------------------------------------*/
3917 /* genCodePointerGet - gget value from code space */
3918 /*-----------------------------------------------------------------*/
3920 genCodePointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
3923 sym_link *retype = getSpec (operandType (result));
3927 aopOp (left, ic, FALSE);
3929 /* if the operand is already in Z register
3930 then we do nothing else we move the value to Z register */
3931 if (AOP_ISZ(AOP(left))) {
3935 getFreePtr(ic,&aop,FALSE,TRUE);
3936 if (isRegPair(AOP (left))) {
3937 emitcode ("movw","r30,%s",aopGet (AOP (left), 0));
3939 emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
3940 emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
3945 aopOp (result, ic, FALSE);
3947 /* if bit then unpack */
3948 if (IS_BITVAR (retype))
3949 genUnpackBits (result, "Z", CPOINTER);
3951 size = AOP_SIZE (result);
3956 emitcode ("lpm","%s,Z+",aopGet(AOP(result),offset++));
3958 emitcode ("lpm","%s,Z",aopGet(AOP(result),offset++));
3963 /* now some housekeeping stuff */
3965 /* we had to allocate for this iCode */
3967 if (isRegPair(AOP (left))) {
3968 emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
3970 emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
3971 emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
3974 freeAsmop (NULL, aop, ic, TRUE);
3977 /* we did not allocate which means left
3978 already in a pointer register, then
3979 if size > 0 && this could be used again
3980 we have to point it back to where it
3982 if ((AOP_SIZE (result) > 1 &&
3983 !OP_SYMBOL (left)->remat &&
3984 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) &&
3986 int size = AOP_SIZE (result) - 1;
3987 emitcode ("sbiw", "r30,%d",size);
3992 if (pi) pi->generated=1;
3993 freeAsmop (left, NULL, ic, TRUE);
3994 freeAsmop (result, NULL, ic, TRUE);
3998 /*-----------------------------------------------------------------*/
3999 /* genGenPointerGet - gget value from generic pointer space */
4000 /*-----------------------------------------------------------------*/
4002 genGenPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
4006 sym_link *retype = getSpec (operandType (result));
4009 aopOp (left, ic, FALSE);
4011 /* if the operand is already in dptr
4012 then we do nothing else we move the value to dptr */
4013 if (AOP_ISZ(AOP(left))) {
4017 getFreePtr(ic,&aop,FALSE,TRUE);
4019 emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
4020 emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
4021 emitcode ("mov", "r0,%s", aopGet (AOP (left), 2));
4025 /* so Z register now contains the address */
4027 aopOp (result, ic, FALSE);
4029 /* if bit then unpack */
4030 if (IS_BITVAR (retype))
4031 genUnpackBits (result, "Z", GPOINTER);
4033 size = AOP_SIZE (result);
4038 emitcode ("call", "__gptrget_pi");
4040 emitcode ("call", "__gptrget");
4041 aopPut (AOP (result), "r0", offset++);
4046 /* now some housekeeping stuff */
4048 /* we had to allocate for this iCode */
4050 if (isRegPair(AOP (left))) {
4051 emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
4053 emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
4054 emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
4057 freeAsmop (NULL, aop, ic, TRUE);
4060 /* we did not allocate which means left
4061 already in a pointer register, then
4062 if size > 0 && this could be used again
4063 we have to point it back to where it
4065 if ((AOP_SIZE (result) > 1 &&
4066 !OP_SYMBOL (left)->remat &&
4067 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) &&
4069 int size = AOP_SIZE (result) - 1;
4070 emitcode ("sbiw", "r30,%d",size);
4073 if (pi) pi->generated=1;
4074 freeAsmop (left, NULL, ic, TRUE);
4075 freeAsmop (result, NULL, ic, TRUE);
4078 /*-----------------------------------------------------------------*/
4079 /* genPointerGet - generate code for pointer get */
4080 /*-----------------------------------------------------------------*/
4082 genPointerGet (iCode * ic, iCode *pi)
4084 operand *left, *result;
4085 sym_link *type, *etype;
4088 left = IC_LEFT (ic);
4089 result = IC_RESULT (ic);
4091 /* depending on the type of pointer we need to
4092 move it to the correct pointer register */
4093 type = operandType (left);
4094 etype = getSpec (type);
4095 /* if left is of type of pointer then it is simple */
4096 if (IS_PTR (type) && !IS_FUNC (type->next))
4097 p_type = DCL_TYPE (type);
4099 /* we have to go by the storage class */
4100 p_type = PTR_TYPE (SPEC_OCLS (etype));
4105 /* now that we have the pointer type we assign
4106 the pointer values */
4113 genMemPointerGet (left, result, ic, pi);
4117 genCodePointerGet (left, result, ic, pi);
4121 genGenPointerGet (left, result, ic, pi);
4127 /*-----------------------------------------------------------------*/
4128 /* genPackBits - generates code for packed bit storage */
4129 /*-----------------------------------------------------------------*/
4131 genPackBits (sym_link * etype,
4133 char *rname, int p_type)
4141 blen = SPEC_BLEN (etype);
4142 bstr = SPEC_BSTR (etype);
4144 l = aopGet (AOP (right), offset++);
4147 /* if the bit lenth is less than or */
4148 /* it exactly fits a byte then */
4149 if (SPEC_BLEN (etype) <= 8) {
4150 shCount = SPEC_BSTR (etype);
4152 /* shift left acc */
4155 if (SPEC_BLEN (etype) < 8) { /* if smaller than a byte */
4162 emitcode ("ld", "r1,%s",rname);
4166 emitcode ("push", "r1");
4167 emitcode ("push", "r24");
4168 emitcode ("call", "__gptrget");
4169 emitcode ("pop", "r1");
4170 emitcode ("mov","r24,r0");
4174 emitcode ("andi", "r24,#0x%02x", (unsigned char)
4175 ((unsigned char) (0xFF << (blen + bstr)) |
4176 (unsigned char) (0xFF >> (8 - bstr))));
4177 emitcode ("or", "r24,r1");
4178 if (p_type == GPOINTER)
4179 emitcode ("pop", "r1");
4188 emitcode("st","%s+,r24");
4192 emitcode("mov","r0,r24");
4193 emitcode ("call", "__gptrput_pi");
4198 if (SPEC_BLEN (etype) <= 8)
4201 rLen = SPEC_BLEN (etype);
4203 /* now generate for lengths greater than one byte */
4206 l = aopGet (AOP (right), offset++);
4217 emitcode ("st", "%s+,%s",rname,l);
4222 emitcode ("lcall", "__gptrput_pi");
4229 /* last last was not complete */
4231 /* save the byte & read byte */
4237 emitcode ("st","%s+,r24",rname);
4240 emitcode ("push", "r1");
4241 emitcode ("push", "r24");
4242 emitcode ("lcall", "__gptrget");
4243 emitcode ("mov","r24,r0");
4244 emitcode ("pop", "r1");
4248 emitcode ("andi", "r24,0x%02x", (((unsigned char) -1 << rLen) & 0xff));
4249 emitcode ("or", "r24,r1");
4252 if (p_type == GPOINTER)
4253 emitcode ("pop", "r1");
4261 emitcode ("st", "%s,r24", rname);
4265 emitcode ("mov","r0,r24");
4266 emitcode ("call", "__gptrput");
4271 /*-----------------------------------------------------------------*/
4272 /* genDataPointerSet - remat pointer to data space */
4273 /*-----------------------------------------------------------------*/
4275 genDataPointerSet (operand * right, operand * result, iCode * ic)
4277 int size, offset = 0;
4278 char *l, buffer[256];
4280 aopOp (right, ic, FALSE);
4282 l = aopGet (AOP (result), 0);
4283 size = AOP_SIZE (right);
4286 sprintf (buffer, "(%s + %d)", l, offset);
4288 sprintf (buffer, "%s", l);
4289 emitcode ("sts", "%s,%s", buffer,
4290 aopGet (AOP (right), offset++));
4293 freeAsmop (right, NULL, ic, TRUE);
4294 freeAsmop (result, NULL, ic, TRUE);
4297 /*-----------------------------------------------------------------*/
4298 /* genNearPointerSet - emitcode for near pointer put */
4299 /*-----------------------------------------------------------------*/
4301 genMemPointerSet (operand * right, operand * result, iCode * ic, iCode *pi)
4304 char *frname = NULL, *rname, *l;
4307 sym_link *ptype = operandType (result);
4309 retype = getSpec (operandType (right));
4311 aopOp (result, ic, FALSE);
4313 /* if the result is rematerializable &
4314 in data space & not a bit variable */
4315 if (AOP_TYPE (result) == AOP_IMMD &&
4316 DCL_TYPE (ptype) == POINTER && !IS_BITVAR (retype)) {
4317 genDataPointerSet (right, result, ic);
4320 if (!AOP_INPREG(AOP(result))) {
4321 /* otherwise get a free pointer register */
4323 getFreePtr (ic, &aop, FALSE, 0);
4324 if (isRegPair (AOP (result) )) {
4325 emitcode ("movw", "%s,%s",aop->aopu.aop_ptr->name,
4326 aopGet(AOP (result), 0));
4328 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
4329 aopGet (AOP (result), 0));
4330 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
4331 aopGet (AOP (result), 1));
4336 frname = aopGet(aop,0);
4339 aopOp (right, ic, FALSE);
4342 } else if (AOP_ISZ(aop)) {
4345 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4346 "pointer not in correct register");
4349 /* if bitfield then unpack the bits */
4350 if (IS_BITVAR (retype))
4351 genPackBits (retype, right, rname, POINTER);
4353 /* we have can just get the values */
4354 int size = AOP_SIZE (right);
4358 l = aopGet (AOP (right), offset);
4360 emitcode ("st", "%s+,%s", rname,l);
4362 emitcode ("st", "%s,%s", rname,l);
4367 /* now some housekeeping stuff */
4369 /* we had to allocate for this iCode */
4371 if (isRegPair (AOP (result) )) {
4372 emitcode ("movw", "%s,%s",
4373 aopGet(AOP(result),0),
4374 aop->aopu.aop_ptr->name);
4376 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
4377 aopGet (AOP (result), 0));
4378 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
4379 aopGet (AOP (result), 1));
4382 freeAsmop (NULL, aop, ic, TRUE);
4385 /* we did not allocate which means left
4386 already in a pointer register, then
4387 if size > 0 && this could be used again
4388 we have to point it back to where it
4390 if ((AOP_SIZE (right) > 1 &&
4391 !OP_SYMBOL (result)->remat &&
4392 (OP_SYMBOL (right)->liveTo > ic->seq || ic->depth)) && !pi) {
4393 int size = AOP_SIZE (right) - 1;
4394 emitcode ("sbiw", "%s,%d",frname,size);
4399 if (pi) pi->generated = 1;
4400 freeAsmop (result, NULL, ic, TRUE);
4401 freeAsmop (right, NULL, ic, TRUE);
4404 /*-----------------------------------------------------------------*/
4405 /* genGenPointerSet - set value from generic pointer space */
4406 /*-----------------------------------------------------------------*/
4408 genGenPointerSet (operand * right, operand * result, iCode * ic, iCode *pi)
4412 sym_link *retype = getSpec (operandType (right));
4415 aopOp (result, ic, FALSE);
4417 /* if the operand is already in dptr
4418 then we do nothing else we move the value to dptr */
4419 if (AOP_ISZ(AOP(result))) {
4423 getFreePtr(ic,&aop,FALSE,TRUE);
4424 if (isRegPair(AOP(result))) {
4425 emitcode ("movw", "r30,%s", aopGet (AOP (result), 0));
4427 emitcode ("mov", "r30,%s", aopGet (AOP (result), 0));
4428 emitcode ("mov", "r31,%s", aopGet (AOP (result), 1));
4430 emitcode ("mov", "r24,%s", aopGet (AOP (result), 2));
4434 /* so Z register now contains the address */
4435 aopOp (right, ic, FALSE);
4437 /* if bit then unpack */
4438 if (IS_BITVAR (retype))
4439 genUnpackBits (result, "Z", GPOINTER);
4441 size = AOP_SIZE (right);
4445 char *l = aopGet(AOP (right), offset++);
4449 emitcode ("call", "__gptrput_pi");
4451 emitcode ("call", "__gptrput");
4455 /* now some housekeeping stuff */
4457 /* we had to allocate for this iCode */
4459 if (isRegPair(AOP(result))) {
4460 emitcode ("movw", "%s,r30", aopGet (AOP (result), 0));
4462 emitcode ("mov", "%s,r30", aopGet (AOP (result), 0));
4463 emitcode ("mov", "%s,r31", aopGet (AOP (result), 1));
4466 freeAsmop (NULL, aop, ic, TRUE);
4469 /* we did not allocate which means left
4470 already in a pointer register, then
4471 if size > 0 && this could be used again
4472 we have to point it back to where it
4474 if ((AOP_SIZE (right) > 1 &&
4475 !OP_SYMBOL (result)->remat &&
4476 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) && !pi) {
4477 int size = AOP_SIZE (right) - 1;
4478 emitcode ("sbiw", "r30,%d",size);
4481 if (pi) pi->generated = 1;
4482 freeAsmop (right, NULL, ic, TRUE);
4483 freeAsmop (result, NULL, ic, TRUE);
4486 /*-----------------------------------------------------------------*/
4487 /* genPointerSet - stores the value into a pointer location */
4488 /*-----------------------------------------------------------------*/
4490 genPointerSet (iCode * ic, iCode *pi)
4492 operand *right, *result;
4493 sym_link *type, *etype;
4496 right = IC_RIGHT (ic);
4497 result = IC_RESULT (ic);
4499 /* depending on the type of pointer we need to
4500 move it to the correct pointer register */
4501 type = operandType (result);
4502 etype = getSpec (type);
4503 /* if left is of type of pointer then it is simple */
4504 if (IS_PTR (type) && !IS_FUNC (type->next)) {
4505 p_type = DCL_TYPE (type);
4508 /* we have to go by the storage class */
4509 p_type = PTR_TYPE (SPEC_OCLS (etype));
4513 /* now that we have the pointer type we assign
4514 the pointer values */
4521 genMemPointerSet (right, result, ic, pi);
4525 genGenPointerSet (right, result, ic, pi);
4531 /*-----------------------------------------------------------------*/
4532 /* genIfx - generate code for Ifx statement */
4533 /*-----------------------------------------------------------------*/
4535 genIfx (iCode * ic, iCode * popIc)
4537 operand *cond = IC_COND (ic);
4541 aopOp (cond, ic, FALSE);
4543 /* get the value into acc */
4544 if (AOP_SIZE(cond) == 1 && AOP_ISHIGHREG(AOP(cond),0)) {
4545 cname = aopGet(AOP(cond),0);
4547 toBoolean (cond, "r24", 1);
4550 /* the result is now in the accumulator */
4551 freeAsmop (cond, NULL, ic, TRUE);
4553 /* if there was something to be popped then do it */
4557 emitcode("cpi","%s,0",cname);
4558 lbl = newiTempLabel(NULL);
4560 emitcode ("brne","L%05d",lbl->key);
4561 emitcode ("jmp","L%05d",IC_TRUE(ic)->key);
4562 emitcode ("","L%05d:",lbl->key);
4564 emitcode ("breq","L%05d",lbl->key);
4565 emitcode ("jmp","L%05d",IC_FALSE(ic)->key);
4566 emitcode ("","L%05d:",lbl->key);
4571 /*-----------------------------------------------------------------*/
4572 /* genAddrOf - generates code for address of */
4573 /*-----------------------------------------------------------------*/
4575 genAddrOf (iCode * ic)
4577 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
4580 aopOp (IC_RESULT (ic), ic, FALSE);
4582 /* if the operand is on the stack then we
4583 need to get the stack offset of this
4586 /* if it has an offset then we need to compute
4589 emitcode ("mov", "a,_bp");
4590 emitcode ("add", "a,#0x%02x",
4591 ((char) sym->stack & 0xff));
4592 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4595 /* we can just move _bp */
4596 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
4598 /* fill the result with zero */
4599 size = AOP_SIZE (IC_RESULT (ic)) - 1;
4602 if (options.stack10bit && size < (FPTRSIZE - 1)) {
4604 "*** warning: pointer to stack var truncated.\n");
4610 if (options.stack10bit && offset == 2) {
4611 aopPut (AOP (IC_RESULT (ic)), "#0x40",
4615 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
4622 /* object not on stack then we need the name */
4623 size = AOP_SIZE (IC_RESULT (ic));
4627 char s[SDCC_NAME_MAX];
4629 sprintf (s, "#(%s >> %d)", sym->rname, offset * 8);
4631 sprintf (s, "#%s", sym->rname);
4632 aopPut (AOP (IC_RESULT (ic)), s, offset++);
4636 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4640 /*-----------------------------------------------------------------*/
4641 /* genFarFarAssign - assignment when both are in far space */
4642 /*-----------------------------------------------------------------*/
4644 genFarFarAssign (operand * result, operand * right, iCode * ic)
4646 int size = AOP_SIZE (right);
4649 /* first push the right side on to the stack */
4651 l = aopGet (AOP (right), offset++);
4653 emitcode ("push", "acc");
4656 freeAsmop (right, NULL, ic, FALSE);
4657 /* now assign DPTR to result */
4658 aopOp (result, ic, FALSE);
4659 size = AOP_SIZE (result);
4661 emitcode ("pop", "acc");
4662 aopPut (AOP (result), "a", --offset);
4664 freeAsmop (result, NULL, ic, FALSE);
4668 /*-----------------------------------------------------------------*/
4669 /* genAssign - generate code for assignment */
4670 /*-----------------------------------------------------------------*/
4672 genAssign (iCode * ic)
4674 operand *result, *right;
4676 unsigned long lit = 0L;
4678 result = IC_RESULT (ic);
4679 right = IC_RIGHT (ic);
4681 /* if they are the same */
4682 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4685 aopOp (right, ic, FALSE);
4687 /* special case both in far space */
4688 if (AOP_TYPE (right) == AOP_DPTR &&
4689 IS_TRUE_SYMOP (result) && isOperandInFarSpace (result)) {
4691 genFarFarAssign (result, right, ic);
4695 aopOp (result, ic, TRUE);
4697 /* if they are the same registers */
4698 if (sameRegs (AOP (right), AOP (result)))
4701 /* if the result is a bit */
4702 if (AOP_TYPE (result) == AOP_CRY) {
4704 /* if the right size is a literal then
4705 we know what the value is */
4706 if (AOP_TYPE (right) == AOP_LIT) {
4707 if (((int) operandLitValue (right)))
4708 aopPut (AOP (result), one, 0);
4710 aopPut (AOP (result), zero, 0);
4714 /* the right is also a bit variable */
4715 if (AOP_TYPE (right) == AOP_CRY) {
4716 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4717 aopPut (AOP (result), "c", 0);
4722 toBoolean (right, "", 0);
4723 aopPut (AOP (result), "a", 0);
4727 /* bit variables done */
4729 size = AOP_SIZE (result);
4731 if (AOP_TYPE (right) == AOP_LIT)
4733 (unsigned long) floatFromVal (AOP (right)->aopu.
4735 if ((size > 1) && (AOP_TYPE (result) != AOP_REG)
4736 && (AOP_TYPE (right) == AOP_LIT)
4737 && !IS_FLOAT (operandType (right)) && (lit < 256L)) {
4738 emitcode ("clr", "a");
4740 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) ==
4741 0) aopPut (AOP (result), "a", size);
4743 aopPut (AOP (result),
4744 aopGet (AOP (right), size), size);
4749 aopPut (AOP (result),
4750 aopGet (AOP (right), offset), offset);
4756 freeAsmop (right, NULL, ic, FALSE);
4757 freeAsmop (result, NULL, ic, TRUE);
4760 /*-----------------------------------------------------------------*/
4761 /* genJumpTab - genrates code for jump table */
4762 /*-----------------------------------------------------------------*/
4764 genJumpTab (iCode * ic)
4769 aopOp (IC_JTCOND (ic), ic, FALSE);
4770 /* get the condition into accumulator */
4771 l = aopGet (AOP (IC_JTCOND (ic)), 0);
4773 /* multiply by three */
4774 emitcode ("add", "a,acc");
4775 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0));
4776 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
4778 jtab = newiTempLabel (NULL);
4779 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
4780 emitcode ("jmp", "@a+dptr");
4781 emitcode ("", "%05d$:", jtab->key + 100);
4782 /* now generate the jump labels */
4783 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
4784 jtab = setNextItem (IC_JTLABELS (ic)))
4785 emitcode ("ljmp", "%05d$", jtab->key + 100);
4789 /*-----------------------------------------------------------------*/
4790 /* genCast - gen code for casting */
4791 /*-----------------------------------------------------------------*/
4793 genCast (iCode * ic)
4795 operand *result = IC_RESULT (ic);
4796 sym_link *ctype = operandType (IC_LEFT (ic));
4797 sym_link *rtype = operandType (IC_RIGHT (ic));
4798 operand *right = IC_RIGHT (ic);
4801 /* if they are equivalent then do nothing */
4802 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4805 aopOp (right, ic, FALSE);
4806 aopOp (result, ic, FALSE);
4808 /* if the result is a bit */
4809 if (AOP_TYPE (result) == AOP_CRY) {
4810 /* if the right size is a literal then
4811 we know what the value is */
4812 if (AOP_TYPE (right) == AOP_LIT) {
4813 if (((int) operandLitValue (right)))
4814 aopPut (AOP (result), one, 0);
4816 aopPut (AOP (result), zero, 0);
4821 /* the right is also a bit variable */
4822 if (AOP_TYPE (right) == AOP_CRY) {
4823 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4824 aopPut (AOP (result), "c", 0);
4829 toBoolean (right, "", 0);
4830 aopPut (AOP (result), "a", 0);
4834 /* if they are the same size : or less */
4835 if (AOP_SIZE (result) <= AOP_SIZE (right)) {
4837 /* if they are in the same place */
4838 if (sameRegs (AOP (right), AOP (result)))
4841 /* if they in different places then copy */
4842 size = AOP_SIZE (result);
4845 aopPut (AOP (result),
4846 aopGet (AOP (right), offset), offset);
4853 /* if the result is of type pointer */
4854 if (IS_PTR (ctype)) {
4857 sym_link *type = operandType (right);
4858 sym_link *etype = getSpec (type);
4860 /* pointer to generic pointer */
4861 if (IS_GENPTR (ctype)) {
4865 p_type = DCL_TYPE (type);
4867 /* we have to go by the storage class */
4868 p_type = PTR_TYPE (SPEC_OCLS (etype));
4871 /* the first two bytes are known */
4872 size = GPTRSIZE - 1;
4875 aopPut (AOP (result),
4876 aopGet (AOP (right), offset), offset);
4879 /* the last byte depending on type */
4896 /* this should never happen */
4897 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4898 "got unknown pointer type");
4901 aopPut (AOP (result), l, GPTRSIZE - 1);
4905 /* just copy the pointers */
4906 size = AOP_SIZE (result);
4909 aopPut (AOP (result),
4910 aopGet (AOP (right), offset), offset);
4916 /* so we now know that the size of destination is greater
4917 than the size of the source */
4918 /* we move to result for the size of source */
4919 size = AOP_SIZE (right);
4922 aopPut (AOP (result), aopGet (AOP (right), offset), offset);
4926 /* now depending on the sign of the source && destination */
4927 size = AOP_SIZE (result) - AOP_SIZE (right);
4928 /* if unsigned or not an integral type */
4929 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype)) {
4931 aopPut (AOP (result), zero, offset++);
4934 /* we need to extend the sign :{ */
4935 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1);
4937 emitcode ("rlc", "a");
4938 emitcode ("subb", "a,acc");
4940 aopPut (AOP (result), "a", offset++);
4943 /* we are done hurray !!!! */
4946 freeAsmop (right, NULL, ic, TRUE);
4947 freeAsmop (result, NULL, ic, TRUE);
4951 /*-----------------------------------------------------------------*/
4952 /* genDjnz - generate decrement & jump if not zero instrucion */
4953 /*-----------------------------------------------------------------*/
4955 genDjnz (iCode * ic, iCode * ifx)
4961 /* if the if condition has a false label
4962 then we cannot save */
4966 /* if the minus is not of the form
4968 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
4969 !IS_OP_LITERAL (IC_RIGHT (ic)))
4972 if (operandLitValue (IC_RIGHT (ic)) != 1)
4975 /* if the size of this greater than one then no
4977 if (getSize (operandType (IC_RESULT (ic))) > 1)
4980 /* otherwise we can save BIG */
4981 lbl = newiTempLabel (NULL);
4982 lbl1 = newiTempLabel (NULL);
4984 aopOp (IC_RESULT (ic), ic, FALSE);
4986 if (IS_AOP_PREG (IC_RESULT (ic))) {
4987 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0));
4988 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0));
4989 emitcode ("jnz", "%05d$", lbl->key + 100);
4992 emitcode ("djnz", "%s,%05d$",
4993 aopGet (AOP (IC_RESULT (ic)), 0), lbl->key + 100);
4995 emitcode ("sjmp", "%05d$", lbl1->key + 100);
4996 emitcode ("", "%05d$:", lbl->key + 100);
4997 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4998 emitcode ("", "%05d$:", lbl1->key + 100);
5000 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5005 static char *recvregs[8] = {
5006 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23"
5010 /*-----------------------------------------------------------------*/
5011 /* genReceive - generate code for a receive iCode */
5012 /*-----------------------------------------------------------------*/
5014 genReceive (iCode * ic)
5016 int size, offset = 0;
5017 aopOp (IC_RESULT (ic), ic, FALSE);
5018 size = AOP_SIZE (IC_RESULT (ic));
5020 aopPut (AOP (IC_RESULT (ic)), recvregs[recvCnt++], offset);
5023 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5026 /*-----------------------------------------------------------------*/
5027 /* gen51Code - generate code for 8051 based controllers */
5028 /*-----------------------------------------------------------------*/
5030 genAVRCode (iCode * lic)
5035 lineHead = lineCurr = NULL;
5037 /* print the allocation information */
5039 printAllocInfo (currFunc, codeOutFile);
5040 /* if debug information required */
5041 /* if (options.debug && currFunc) { */
5043 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
5045 emitcode ("", ".type %s,@function", currFunc->name);
5048 /* stack pointer name */
5052 for (ic = lic; ic; ic = ic->next) {
5054 if (cln != ic->lineno) {
5055 if (options.debug) {
5057 emitcode ("", "C$%s$%d$%d$%d ==.",
5058 FileBaseName (ic->filename),
5059 ic->lineno, ic->level, ic->block);
5062 emitcode (";", "%s %d", ic->filename, ic->lineno);
5065 /* if the result is marked as
5066 spilt and rematerializable or code for
5067 this has already been generated then
5069 if (resultRemat (ic) || ic->generated)
5072 /* depending on the operation */
5091 /* IPOP happens only when trying to restore a
5092 spilt live range, if there is an ifx statement
5093 following this pop then the if statement might
5094 be using some of the registers being popped which
5095 would destory the contents of the register so
5096 we need to check for this condition and handle it */
5098 ic->next->op == IFX &&
5099 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
5100 genIfx (ic->next, ic);
5118 genEndFunction (ic);
5138 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
5155 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
5159 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
5163 genCmpLe (ic, ifxForOp (IC_RESULT (ic), ic));
5167 genCmpGe (ic, ifxForOp (IC_RESULT (ic), ic));
5171 genCmpNe (ic, ifxForOp (IC_RESULT (ic), ic));
5175 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
5187 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
5191 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
5195 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
5222 case GET_VALUE_AT_ADDRESS:
5223 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
5227 if (POINTER_SET (ic))
5228 genPointerSet (ic, hasInc(IC_RESULT(ic),ic));
5254 addSet (&_G.sendSet, ic);
5259 /* piCode(ic,stdout); */
5265 /* now we are ready to call the
5266 peep hole optimizer */
5267 if (!options.nopeep)
5268 peepHole (&lineHead);
5270 /* now do the actual printing */
5271 printLine (lineHead, codeOutFile);