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 CLRC emitcode("clc","")
90 #define SETC emitcode("stc","")
92 #define IS_REGIDX(a,r) (a->type == AOP_REG && a->aopu.aop_reg[0]->rIdx == r)
94 static lineNode *lineHead = NULL;
95 static lineNode *lineCurr = NULL;
97 static unsigned char SLMask[] = { 0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
98 0xE0, 0xC0, 0x80, 0x00
100 static unsigned char SRMask[] = { 0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
101 0x07, 0x03, 0x01, 0x00
109 /*-----------------------------------------------------------------*/
110 /* emitcode - writes the code into a file : for now it is simple */
111 /*-----------------------------------------------------------------*/
113 emitcode (char *inst, char *fmt, ...)
116 char lb[MAX_INLINEASM];
123 sprintf (lb, "%s\t", inst);
125 sprintf (lb, "%s", inst);
126 vsprintf (lb + (strlen (lb)), fmt, ap);
129 vsprintf (lb, fmt, ap);
131 while (isspace (*lbp))
135 lineCurr = (lineCurr ?
136 connectLine (lineCurr, newLineNode (lb)) :
137 (lineHead = newLineNode (lb)));
138 lineCurr->isInline = _G.inLine;
139 lineCurr->isDebug = _G.debugLine;
143 /*-----------------------------------------------------------------*/
144 /* getFreePtr - returns X or Z whichever is free or can be pushed */
145 /*-----------------------------------------------------------------*/
147 getFreePtr (iCode * ic, asmop ** aopp, bool result, bool zonly)
149 bool xiu = FALSE, ziu = FALSE;
150 bool xou = FALSE, zou = FALSE;
152 /* the logic: if x & z used in the instruction
153 then we are in trouble otherwise */
155 /* first check if x & z are used by this
156 instruction, in which case we are in trouble */
157 if ((xiu = bitVectBitValue (ic->rUsed, X_IDX)) &&
158 (ziu = bitVectBitValue (ic->rUsed, Z_IDX))) {
162 xou = bitVectBitValue (ic->rMask, X_IDX);
163 zou = bitVectBitValue (ic->rMask, Z_IDX);
165 /* if no usage of Z then return it */
167 ic->rUsed = bitVectSetBit (ic->rUsed, Z_IDX);
168 (*aopp)->type = AOP_Z;
170 (*aopp)->aop_ptr2 = avr_regWithIdx (R31_IDX);
171 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R30_IDX);
174 /* if no usage of X then return it */
175 if (!xiu && !xou && !zonly) {
176 ic->rUsed = bitVectSetBit (ic->rUsed, X_IDX);
177 (*aopp)->type = AOP_X;
179 (*aopp)->aop_ptr2 = avr_regWithIdx (R27_IDX);
180 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R26_IDX);
183 /* if z not used then */
186 /* push it if not already pushed */
188 emitcode ("push", "%s",
189 avr_regWithIdx (R30_IDX)->dname);
190 emitcode ("push", "%s",
191 avr_regWithIdx (R31_IDX)->dname);
195 ic->rUsed = bitVectSetBit (ic->rUsed, Z_IDX);
196 (*aopp)->type = AOP_Z;
197 (*aopp)->aop_ptr2 = avr_regWithIdx (R31_IDX);
198 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R30_IDX);
201 /* now we know they both have usage */
202 /* if x not used in this instruction */
203 if (!xiu && !zonly) {
204 /* push it if not already pushed */
206 emitcode ("push", "%s",
207 avr_regWithIdx (R26_IDX)->dname);
208 emitcode ("push", "%s",
209 avr_regWithIdx (R27_IDX)->dname);
213 ic->rUsed = bitVectSetBit (ic->rUsed, X_IDX);
214 (*aopp)->type = AOP_X;
216 (*aopp)->aop_ptr2 = avr_regWithIdx (R27_IDX);
217 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R26_IDX);
222 /* I said end of world but not quite end of world yet */
223 /* if this is a result then we can push it on the stack */
225 (*aopp)->type = AOP_STK;
230 /* other wise this is true end of the world */
231 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
232 "getFreePtr should never reach here");
236 /*-----------------------------------------------------------------*/
237 /* newAsmop - creates a new asmOp */
238 /*-----------------------------------------------------------------*/
240 newAsmop (short type)
244 aop = Safe_calloc (1, sizeof (asmop));
249 /*-----------------------------------------------------------------*/
250 /* pointerCode - returns the code for a pointer type */
251 /*-----------------------------------------------------------------*/
253 pointerCode (sym_link * etype)
256 return PTR_TYPE (SPEC_OCLS (etype));
260 /*-----------------------------------------------------------------*/
261 /* aopForSym - for a true symbol */
262 /*-----------------------------------------------------------------*/
264 aopForSym (iCode * ic, symbol * sym, bool result)
267 memmap *space = SPEC_OCLS (sym->etype);
269 /* if already has one */
273 /* assign depending on the storage class */
274 /* if it is on the stack */
276 sym->aop = aop = newAsmop (0);
277 aop->size = getSize (sym->type);
279 /* we can use std / ldd instruction */
281 && (sym->stack + getSize (sym->type) - 1) <= 63) {
282 aop->type = AOP_STK_D;
283 aop->aopu.aop_stk = sym->stack;
287 /* otherwise get a free pointer register X/Z */
288 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result, FALSE);
290 /* now assign the address of the variable to
291 the pointer register */
292 if (aop->type != AOP_STK) {
293 emitcode ("movw", "%s,r28", aop->aopu.aop_ptr->name);
294 if (sym->stack < 0) {
295 if ((sym->stack - _G.nRegsSaved) > -63) {
296 emitcode ("sbiw", "%s,0x%02x",
297 aop->aopu.aop_ptr->name,
302 emitcode ("subi", "%s,lo8(%d)",
303 aop->aopu.aop_ptr->name,
304 sym->stack - _G.nRegsSaved);
305 emitcode ("sbci", "%s,hi8(%d)",
307 sym->stack - _G.nRegsSaved);
311 if (sym->stack <= 63) {
312 emitcode ("adiw", "%s,0x%02x",
313 aop->aopu.aop_ptr->name,
317 emitcode ("subi", "%s,lo8(-%d)",
318 aop->aopu.aop_ptr->name,
320 emitcode ("sbci", "%s,hi8(-%d)",
329 /* if in bit space */
330 if (IN_BITSPACE (space)) {
331 sym->aop = aop = newAsmop (AOP_CRY);
332 aop->aopu.aop_dir = sym->rname;
333 aop->size = getSize (sym->type);
336 /* if it is in direct space */
337 if (IN_DIRSPACE (space)) {
338 sym->aop = aop = newAsmop (AOP_DIR);
339 aop->aopu.aop_dir = sym->rname;
340 aop->size = getSize (sym->type);
344 /* special case for a function */
345 if (IS_FUNC (sym->type)) {
346 sym->aop = aop = newAsmop (AOP_IMMD);
347 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
348 strcpy (aop->aopu.aop_immd, sym->rname);
349 aop->size = FPTRSIZE;
353 /* only remaining is code / eeprom which will need pointer reg */
354 /* if it is in code space */
356 sym->aop = aop = newAsmop (0);
358 if (IN_CODESPACE (space))
361 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result, aop->code);
362 aop->size = getSize (sym->type);
363 emitcode ("ldi", "%s,lo8(%s)", aop->aopu.aop_ptr->name, sym->rname);
364 emitcode ("ldi", "%s,hi8(%s)", aop->aop_ptr2);
369 /*-----------------------------------------------------------------*/
370 /* aopForRemat - rematerialzes an object */
371 /*-----------------------------------------------------------------*/
373 aopForRemat (symbol * sym)
375 iCode *ic = sym->rematiCode;
376 asmop *aop = newAsmop (AOP_IMMD);
381 val += (int) operandLitValue (IC_RIGHT (ic));
382 else if (ic->op == '-')
383 val -= (int) operandLitValue (IC_RIGHT (ic));
387 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
391 sprintf (buffer, "(%s %c 0x%04x)",
392 OP_SYMBOL (IC_LEFT (ic))->rname,
393 val >= 0 ? '+' : '-', abs (val) & 0xffff);
395 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
397 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
398 strcpy (aop->aopu.aop_immd, buffer);
402 /*-----------------------------------------------------------------*/
403 /* regsInCommon - two operands have some registers in common */
404 /*-----------------------------------------------------------------*/
406 regsInCommon (operand * op1, operand * op2)
411 /* if they have registers in common */
412 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
415 sym1 = OP_SYMBOL (op1);
416 sym2 = OP_SYMBOL (op2);
418 if (sym1->nRegs == 0 || sym2->nRegs == 0)
421 for (i = 0; i < sym1->nRegs; i++) {
426 for (j = 0; j < sym2->nRegs; j++) {
430 if (sym2->regs[j] == sym1->regs[i])
438 /*-----------------------------------------------------------------*/
439 /* operandsEqu - equivalent */
440 /*-----------------------------------------------------------------*/
442 operandsEqu (operand * op1, operand * op2)
446 /* if they not symbols */
447 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
450 sym1 = OP_SYMBOL (op1);
451 sym2 = OP_SYMBOL (op2);
453 /* if both are itemps & one is spilt
454 and the other is not then false */
455 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
456 sym1->isspilt != sym2->isspilt) return FALSE;
458 /* if they are the same */
462 if (strcmp (sym1->rname, sym2->rname) == 0)
466 /* if left is a tmp & right is not */
467 if (IS_ITEMP (op1) &&
468 !IS_ITEMP (op2) && sym1->isspilt && (sym1->usl.spillLoc == sym2))
471 if (IS_ITEMP (op2) &&
473 sym2->isspilt && sym1->level > 0 && (sym2->usl.spillLoc == sym1))
479 /*-----------------------------------------------------------------*/
480 /* sameRegs - two asmops have the same registers */
481 /*-----------------------------------------------------------------*/
483 sameRegs (asmop * aop1, asmop * aop2)
490 if (aop1->type != AOP_REG || aop2->type != AOP_REG)
493 if (aop1->size != aop2->size)
496 for (i = 0; i < aop1->size; i++)
497 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
503 /*-----------------------------------------------------------------*/
504 /* isRegPair - for size 2 if this operand has a register pair */
505 /*-----------------------------------------------------------------*/
507 isRegPair (asmop * aop)
509 if (!aop || aop->size != 2)
511 if (aop->type == AOP_X || aop->type == AOP_Z)
513 if (aop->type != AOP_REG)
515 if ( ((aop->aopu.aop_reg[1]->rIdx - aop->aopu.aop_reg[0]->rIdx) == 1) &&
516 (aop->aopu.aop_reg[0]->rIdx & 1) == 0)
522 /*-----------------------------------------------------------------*/
523 /* aopOp - allocates an asmop for an operand : */
524 /*-----------------------------------------------------------------*/
526 aopOp (operand * op, iCode * ic, bool result)
535 /* if this a literal */
536 if (IS_OP_LITERAL (op)) {
537 op->aop = aop = newAsmop (AOP_LIT);
538 aop->aopu.aop_lit = op->operand.valOperand;
539 aop->size = getSize (operandType (op));
543 /* if already has a asmop then continue */
547 /* if the underlying symbol has a aop */
548 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop) {
549 op->aop = OP_SYMBOL (op)->aop;
553 /* if this is a true symbol */
554 if (IS_TRUE_SYMOP (op)) {
555 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
559 /* this is a temporary : this has
565 e) can be a return use only */
567 sym = OP_SYMBOL (op);
570 /* if the type is a conditional */
571 if (sym->regType == REG_CND) {
572 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
577 /* if it is spilt then two situations
579 b) has a spill location */
580 if (sym->isspilt || sym->nRegs == 0) {
582 /* rematerialize it NOW */
584 sym->aop = op->aop = aop = aopForRemat (sym);
585 aop->size = getSize (sym->type);
590 assert ("ACC_USE cannot happen in AVR\n");
595 aop = op->aop = sym->aop = newAsmop (AOP_STR);
596 aop->size = getSize (sym->type);
597 for (i = 0; i < (int) fAVRReturnSize; i++)
598 aop->aopu.aop_str[i] = fAVRReturn[i];
602 /* else spill location */
603 sym->aop = op->aop = aop =
604 aopForSym (ic, sym->usl.spillLoc, result);
605 aop->size = getSize (sym->type);
609 /* must be in a register */
610 sym->aop = op->aop = aop = newAsmop (AOP_REG);
611 aop->size = sym->nRegs;
612 for (i = 0; i < sym->nRegs; i++)
613 aop->aopu.aop_reg[i] = sym->regs[i];
616 /*-----------------------------------------------------------------*/
617 /* freeAsmop - free up the asmop given to an operand */
618 /*----------------------------------------------------------------*/
620 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
637 /* depending on the asmop type only three cases need work AOP_RO
638 , AOP_R1 && AOP_STK */
643 emitcode ("pop", "r26");
644 emitcode ("pop", "r27");
648 bitVectUnSetBit (ic->rUsed, X_IDX);
654 emitcode ("pop", "r30");
655 emitcode ("pop", "r31");
659 bitVectUnSetBit (ic->rUsed, Z_IDX);
665 int stk = aop->aopu.aop_stk + aop->size;
666 bitVectUnSetBit (ic->rUsed, X_IDX);
667 bitVectUnSetBit (ic->rUsed, Z_IDX);
669 getFreePtr (ic, &aop, FALSE, 0);
671 emitcode ("movw", "%s,r28");
673 if (stk <= 63 && stk > 0) {
674 emitcode ("adiw", "%s,0x%02x",
675 aop->aopu.aop_ptr->name,
679 emitcode ("subi", "%s,lo8(%d)",
680 aop->aopu.aop_ptr->name,
682 emitcode ("sbci", "%s,hi8(%d)",
689 emitcode ("pop", "r24");
690 emitcode ("st", "-%s,r24",
691 aop->type == AOP_X ? "X" : "Z");
696 freeAsmop (op, NULL, ic, TRUE);
698 emitcode ("pop", "r26");
699 emitcode ("pop", "r27");
704 emitcode ("pop", "r30");
705 emitcode ("pop", "r31");
712 /* all other cases just dealloc */
716 OP_SYMBOL (op)->aop = NULL;
717 /* if the symbol has a spill */
719 SPIL_LOC (op)->aop = NULL;
724 /*-----------------------------------------------------------------*/
725 /* aopGet - for fetching value of the aop */
726 /*-----------------------------------------------------------------*/
728 aopGet (asmop * aop, int offset)
733 /* offset is greater than
735 if (offset > (aop->size - 1) && aop->type != AOP_LIT)
738 /* depending on type */
742 if (offset > aop->coff) {
743 emitcode ("adiw", "%s,%d", aop->aopu.aop_ptr->name,
747 if (offset < aop->coff) {
748 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name,
753 emitcode ("ld", "%s,x",
754 (rs = ((offset & 1) ? "r25" : "r24")));
759 if (offset > aop->coff) {
760 emitcode ("adiw", "r30,%d",
764 emitcode ("sbiw", "r30,%d",
767 emitcode ("lpm", "%s,z",
768 (rs = ((offset & 1) ? "r25" : "r24")));
772 if (offset > aop->coff) {
773 emitcode ("ldd", "%s,z+%d",
775 ((offset & 1) ? "r25" : "r24")),
779 emitcode ("sbiw", "%s,%d",
780 aop->aopu.aop_ptr->name,
783 emitcode ("ld", "%s,z",
785 ((offset & 1) ? "r25" : "r24")));
792 emitcode ("lds", "%s,(%s)+%d",
793 (rs = ((offset & 1) ? "r25" : "r24")),
794 aop->aopu.aop_immd, offset);
798 emitcode ("lds", "%s,(%s)+%d",
799 (rs = ((offset & 1) ? "r25" : "r24")),
800 aop->aopu.aop_dir, offset);
804 return aop->aopu.aop_reg[offset]->name;
807 assert ("cannot be in bit space AOP_CRY\n");
811 s = aopLiteral (aop->aopu.aop_lit, offset);
812 emitcode ("ldi", "%s,lo8(%s)",
813 (rs = ((offset & 1) ? "r24" : "r25")), s);
818 return aop->aopu.aop_str[offset];
821 emitcode ("ldd", "%s,Y+%d",
822 (rs = ((offset & 1) ? "r25" : "r24")),
823 aop->aopu.aop_stk + offset);
827 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
828 "aopget got unsupported aop->type");
832 /*-----------------------------------------------------------------*/
833 /* aopPut - puts a string for a aop */
834 /*-----------------------------------------------------------------*/
836 aopPut (asmop * aop, char *s, int offset)
840 if (aop->size && offset > (aop->size - 1)) {
841 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
842 "aopPut got offset > aop->size");
846 /* will assign value to value */
847 /* depending on where it is ofcourse */
851 sprintf (d, "(%s)+%d", aop->aopu.aop_dir, offset);
854 sprintf (d, "%s", aop->aopu.aop_dir);
857 emitcode ("sts", "%s,%s", d, s);
861 if (toupper (*s) != 'R') {
863 emitcode ("clr", "%s",
864 aop->aopu.aop_reg[offset]->name);
867 emitcode ("ldi", "r25,%s", s);
868 emitcode ("mov", "%s,r35",
869 aop->aopu.aop_reg[offset]->name);
873 if (strcmp (aop->aopu.aop_reg[offset]->name, s)) {
874 emitcode ("mov", "%s,%s",
875 aop->aopu.aop_reg[offset]->name, s);
881 if (offset > aop->coff) {
882 emitcode ("adiw", "%s,%d", aop->aopu.aop_ptr->name,
886 if (offset < aop->coff) {
887 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name,
892 emitcode ("st", "x,%s", s);
897 if (offset > aop->coff) {
898 emitcode ("adiw", "r30,%d",
902 emitcode ("sbiw", "r30,%d",
905 emitcode ("lpm", "%s,z", s);
909 if (offset > aop->coff) {
910 emitcode ("sdd", "z+%d,%s",
911 offset - aop->coff, s);
914 emitcode ("sbiw", "%s,%d",
915 aop->aopu.aop_ptr->name,
918 emitcode ("ld", "%s,z", s);
924 emitcode ("push", "%s", s);
928 /* if used only for a condition code check */
929 assert (toupper (*s) == 'R');
931 emitcode ("xrl", "r0,r0");
932 emitcode ("cpi", "%s,0", s);
935 emitcode ("cpc", "r0,%s", s);
941 if (strcmp (aop->aopu.aop_str[offset], s))
942 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset],
947 emitcode ("std", "y+%d,%s", offset, s);
951 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
952 "aopPut got unsupported aop->type");
958 /*-----------------------------------------------------------------*/
959 /* reAdjustPreg - points a register back to where it should */
960 /*-----------------------------------------------------------------*/
962 reAdjustPreg (asmop * aop)
967 if ((size = aop->size) <= 1)
973 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name, size);
979 #define AOP(op) op->aop
980 #define AOP_TYPE(op) AOP(op)->type
981 #define AOP_SIZE(op) AOP(op)->size
982 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_X || \
983 AOP_TYPE(x) == AOP_Z))
984 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
985 ((x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R27_IDX)) || \
986 (x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R31_IDX)) )))
987 #define AOP_ISX(x) (x && (x->type == AOP_REG && \
988 ((x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R27_IDX)))))
989 #define AOP_ISZ(x) (x && (x->type == AOP_REG && \
990 ((x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R31_IDX)))))
992 /*-----------------------------------------------------------------*/
993 /* genNotFloat - generates not for float operations */
994 /*-----------------------------------------------------------------*/
996 genNotFloat (operand * op, operand * res)
1002 /* we will put 127 in the first byte of
1004 aopPut (AOP (res), "127", 0);
1005 size = AOP_SIZE (op) - 1;
1008 l = aopGet (op->aop, offset++);
1012 emitcode ("or", "R0,%s", aopGet (op->aop, offset++));
1014 tlbl = newiTempLabel (NULL);
1016 tlbl = newiTempLabel (NULL);
1017 aopPut (res->aop, zero, 1);
1018 emitcode ("cpi", "r0,0");
1019 emitcode ("breq", "L%05d", tlbl->key);
1020 aopPut (res->aop, one, 1);
1021 emitcode ("", "L%05d:", tlbl->key);
1023 size = res->aop->size - 2;
1025 /* put zeros in the rest */
1027 aopPut (res->aop, zero, offset++);
1030 /*-----------------------------------------------------------------*/
1031 /* opIsGptr: returns non-zero if the passed operand is */
1032 /* a generic pointer type. */
1033 /*-----------------------------------------------------------------*/
1035 opIsGptr (operand * op)
1037 sym_link *type = operandType (op);
1039 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type)) {
1045 /*-----------------------------------------------------------------*/
1046 /* getDataSize - get the operand data size */
1047 /*-----------------------------------------------------------------*/
1049 getDataSize (operand * op)
1052 size = AOP_SIZE (op);
1053 if (size == GPTRSIZE) {
1054 sym_link *type = operandType (op);
1055 if (IS_GENPTR (type)) {
1056 /* generic pointer; arithmetic operations
1057 * should ignore the high byte (pointer type).
1065 /*-----------------------------------------------------------------*/
1066 /* outAcc - output Acc */
1067 /*-----------------------------------------------------------------*/
1069 outAcc (operand * result)
1072 size = getDataSize (result);
1074 aopPut (AOP (result), "r0", 0);
1077 /* unsigned or positive */
1079 aopPut (AOP (result), zero, offset++);
1084 /*-----------------------------------------------------------------*/
1085 /* outBitC - output a bit C */
1086 /*-----------------------------------------------------------------*/
1088 outBitC (operand * result)
1090 emitcode ("clr", "r0");
1091 emitcode ("rol", "r0");
1095 /*-----------------------------------------------------------------*/
1096 /* toBoolean - emit code for orl a,operator(sizeop) */
1097 /*-----------------------------------------------------------------*/
1099 toBoolean (operand * oper, char *r, bool clr)
1101 int size = AOP_SIZE (oper);
1104 emitcode ("clr", "%s", r);
1106 emitcode ("or", "%s,%s", r, aopGet (AOP (oper), offset++));
1110 /*-----------------------------------------------------------------*/
1111 /* genNot - generate code for ! operation */
1112 /*-----------------------------------------------------------------*/
1117 sym_link *optype = operandType (IC_LEFT (ic));
1118 int size, offset = 1;
1120 /* assign asmOps to operand & result */
1121 aopOp (IC_LEFT (ic), ic, FALSE);
1122 aopOp (IC_RESULT (ic), ic, TRUE);
1124 /* if type float then do float */
1125 if (IS_FLOAT (optype)) {
1126 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1129 emitcode ("clr", "r0");
1130 tlbl = newiTempLabel (NULL);
1131 size = AOP_SIZE (IC_LEFT (ic));
1134 emitcode ("cpse", "%s,r0", aopGet (AOP (IC_LEFT (ic)), 0));
1139 emitcode ("cpc", "%s,r0",
1140 aopGet (AOP (IC_LEFT (ic)),
1143 emitcode ("cpi", "%s,0",
1144 aopGet (AOP (IC_LEFT (ic)),
1148 emitcode ("bne", "L%05d", tlbl->key);
1150 emitcode ("ldi", "r0,1");
1151 emitcode ("", "L%05d:", tlbl->key);
1152 aopPut (AOP (IC_RESULT (ic)), "r0", 0);
1153 size = AOP_SIZE (IC_RESULT (ic)) - 1;
1156 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
1160 /* release the aops */
1161 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1162 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1166 /*-----------------------------------------------------------------*/
1167 /* genCpl - generate code for complement */
1168 /*-----------------------------------------------------------------*/
1176 /* assign asmOps to operand & result */
1177 aopOp (IC_LEFT (ic), ic, FALSE);
1178 aopOp (IC_RESULT (ic), ic, TRUE);
1179 samer = sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)));
1180 size = AOP_SIZE (IC_RESULT (ic));
1182 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
1184 emitcode ("com", "%s", l);
1187 aopPut (AOP (IC_RESULT (ic)), l, offset);
1188 emitcode ("com", "%s",
1189 aopGet (AOP (IC_RESULT (ic)), offset));
1194 /* release the aops */
1195 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1196 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1199 /*-----------------------------------------------------------------*/
1200 /* genUminusFloat - unary minus for floating points */
1201 /*-----------------------------------------------------------------*/
1203 genUminusFloat (operand * op, operand * result)
1205 int size, offset = 0;
1207 /* for this we just need to flip the
1208 first it then copy the rest in place */
1209 size = AOP_SIZE (op) - 1;
1210 l = aopGet (AOP (op), 3);
1212 emitcode ("ldi", "r24,0x80");
1213 if (sameRegs (AOP (op), AOP (result))) {
1214 emitcode ("eor", "%s,r24", l);
1217 aopPut (AOP (result), l, 3);
1218 emitcode ("eor", "%s,r24", aopGet (AOP (result), 3));
1221 aopPut (AOP (result), aopGet (AOP (op), offset), offset);
1226 /*-----------------------------------------------------------------*/
1227 /* genUminus - unary minus code generation */
1228 /*-----------------------------------------------------------------*/
1230 genUminus (iCode * ic)
1233 sym_link *optype, *rtype;
1237 aopOp (IC_LEFT (ic), ic, FALSE);
1238 aopOp (IC_RESULT (ic), ic, TRUE);
1240 optype = operandType (IC_LEFT (ic));
1241 rtype = operandType (IC_RESULT (ic));
1243 /* if float then do float stuff */
1244 if (IS_FLOAT (optype)) {
1245 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1249 /* otherwise subtract from zero */
1250 size = AOP_SIZE (IC_LEFT (ic));
1252 samer = sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)));
1255 emitcode ("neg", "%s",
1256 aopGet (AOP (IC_LEFT (ic)), 0));
1259 aopPut (AOP (IC_RESULT (ic)),
1260 aopGet (AOP (IC_LEFT (ic)), 0), 0);
1261 emitcode ("neg", "%s",
1262 aopGet (AOP (IC_RESULT (ic)), 0));
1268 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
1270 aopPut (AOP (IC_RESULT (ic)), l, offset);
1271 l = aopGet (AOP (IC_RESULT (ic)), offset);
1274 emitcode ("com", "%s", l);
1276 emitcode ("neg", "%s", l);
1279 size = AOP_SIZE (IC_LEFT (ic)) - 1;
1282 emitcode ("sbci", "%s,lo8(-1)",
1283 aopGet (AOP (IC_RESULT (ic)), offset++));
1287 /* if any remaining bytes in the result */
1288 /* we just need to propagate the sign */
1289 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic))))) {
1290 symbol *tlbl = newiTempLabel (NULL);
1291 emitcode ("clr", "r0");
1292 emitcode ("brcc", "L%05d", tlbl->key);
1293 emitcode ("com", "r0");
1294 emitcode ("", "L%05d:", tlbl->key);
1296 aopPut (AOP (IC_RESULT (ic)), "r0", offset++);
1300 /* release the aops */
1301 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1302 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1305 /*-----------------------------------------------------------------*/
1306 /* assignResultValue - */
1307 /*-----------------------------------------------------------------*/
1309 assignResultValue (operand * oper)
1312 int size = AOP_SIZE (oper);
1314 aopPut (AOP (oper), fAVRReturn[offset], offset);
1319 /*-----------------------------------------------------------------*/
1320 /* saveZreg - if indirect call then save z-pointer register */
1321 /*-----------------------------------------------------------------*/
1323 saveZreg (iCode * ic)
1325 /* only if live accross this call */
1326 if (ic->regsSaved == 0 &&
1327 (bitVectBitValue (ic->rMask, R30_IDX) ||
1328 bitVectBitValue (ic->rMask, R31_IDX))) {
1330 emitcode ("push", "r30");
1331 emitcode ("push", "r31");
1335 /*-----------------------------------------------------------------*/
1336 /* popZreg - restore values of zreg */
1337 /*-----------------------------------------------------------------*/
1339 popZreg (iCode * ic)
1341 if (ic->regsSaved) {
1342 emitcode ("pop", "r31");
1343 emitcode ("pop", "r30");
1347 /*-----------------------------------------------------------------*/
1348 /* genIpush - genrate code for pushing this gets a little complex */
1349 /*-----------------------------------------------------------------*/
1351 genIpush (iCode * ic)
1353 int size, offset = 0;
1357 if (!ic->parmPush) {
1358 /* and the item is spilt then do nothing */
1359 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1364 for (lic = ic->next; lic; lic = lic->next)
1365 if (lic->op == PCALL)
1371 /* this is a paramter push */
1372 aopOp (IC_LEFT (ic), ic, FALSE);
1373 size = AOP_SIZE (IC_LEFT (ic));
1375 l = aopGet (AOP (IC_LEFT (ic)), offset++);
1376 emitcode ("push", "%s", l);
1379 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1382 /*-----------------------------------------------------------------*/
1383 /* genIpop - recover the registers: can happen only for spilling */
1384 /*-----------------------------------------------------------------*/
1386 genIpop (iCode * ic)
1391 /* if the temp was not pushed then */
1392 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1395 aopOp (IC_LEFT (ic), ic, FALSE);
1396 size = AOP_SIZE (IC_LEFT (ic));
1397 offset = (size - 1);
1399 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--));
1401 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1404 /*-----------------------------------------------------------------*/
1405 /* genCall - generates a call statement */
1406 /*-----------------------------------------------------------------*/
1408 genCall (iCode * ic)
1411 /* if send set is not empty the assign */
1415 for (sic = setFirstItem (_G.sendSet); sic;
1416 sic = setNextItem (_G.sendSet)) {
1417 int size, offset = 0;
1418 aopOp (IC_LEFT (sic), sic, FALSE);
1419 size = AOP_SIZE (IC_LEFT (sic));
1422 aopGet (AOP (IC_LEFT (sic)), offset);
1424 sprintf (buffer, "r%d", rnum++);
1426 emitcode ("mov", "%s,%s", b, l);
1429 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1434 emitcode ("call", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1435 OP_SYMBOL (IC_LEFT (ic))->rname :
1436 OP_SYMBOL (IC_LEFT (ic))->name));
1438 /* if we need assign a result value */
1439 if ((IS_ITEMP (IC_RESULT (ic)) &&
1440 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1441 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1442 IS_TRUE_SYMOP (IC_RESULT (ic))) {
1444 aopOp (IC_RESULT (ic), ic, FALSE);
1445 assignResultValue (IC_RESULT (ic));
1446 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1449 /* adjust the stack for parameters if required */
1450 if (IC_LEFT (ic)->parmBytes) {
1451 if (IC_LEFT (ic)->parmBytes > 63) {
1452 emitcode ("sbiw", "r28,%d", IC_LEFT (ic)->parmBytes);
1455 emitcode ("subi", "r28,lo8(%d)",
1456 IC_LEFT (ic)->parmBytes);
1457 emitcode ("sbci", "r29,hi8(%d)",
1458 IC_LEFT (ic)->parmBytes);
1464 /*-----------------------------------------------------------------*/
1465 /* genPcall - generates a call by pointer statement */
1466 /*-----------------------------------------------------------------*/
1468 genPcall (iCode * ic)
1474 aopOp (IC_LEFT (ic), ic, FALSE);
1475 emitcode ("mov", "r30", aopGet (AOP (IC_LEFT (ic)), 0));
1476 emitcode ("mov", "r31", aopGet (AOP (IC_RIGHT (ic)), 0));
1477 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1479 /* if send set is not empty the assign */
1483 for (sic = setFirstItem (_G.sendSet); sic;
1484 sic = setNextItem (_G.sendSet)) {
1485 int size, offset = 0;
1486 aopOp (IC_LEFT (sic), sic, FALSE);
1487 size = AOP_SIZE (IC_LEFT (sic));
1490 aopGet (AOP (IC_LEFT (sic)), offset);
1492 sprintf (b, "r%d", rnum++);
1494 emitcode ("mov", "%s,%s", b, l);
1497 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1502 emitcode ("icall", "");
1504 /* if we need assign a result value */
1505 if ((IS_ITEMP (IC_RESULT (ic)) &&
1506 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1507 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1508 IS_TRUE_SYMOP (IC_RESULT (ic))) {
1510 aopOp (IC_RESULT (ic), ic, FALSE);
1512 assignResultValue (IC_RESULT (ic));
1513 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1516 /* adjust the stack for parameters if
1518 if (IC_LEFT (ic)->parmBytes) {
1520 if (IC_LEFT (ic)->parmBytes > 3) {
1521 emitcode ("mov", "a,%s", spname);
1522 emitcode ("add", "a,#0x%02x",
1523 (-IC_LEFT (ic)->parmBytes) & 0xff);
1524 emitcode ("mov", "%s,a", spname);
1527 for (i = 0; i < IC_LEFT (ic)->parmBytes; i++)
1528 emitcode ("dec", "%s", spname);
1532 /* adjust the stack for parameters if required */
1533 if (IC_LEFT (ic)->parmBytes) {
1534 if (IC_LEFT (ic)->parmBytes > 63) {
1535 emitcode ("sbiw", "r28,%d", IC_LEFT (ic)->parmBytes);
1538 emitcode ("subi", "r28,lo8(%d)",
1539 IC_LEFT (ic)->parmBytes);
1540 emitcode ("sbci", "r29,hi8(%d)",
1541 IC_LEFT (ic)->parmBytes);
1548 /*-----------------------------------------------------------------*/
1549 /* resultRemat - result is rematerializable */
1550 /*-----------------------------------------------------------------*/
1552 resultRemat (iCode * ic)
1554 if (SKIP_IC (ic) || ic->op == IFX)
1557 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic))) {
1558 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
1559 if (sym->remat && !POINTER_SET (ic))
1566 #if defined(__BORLANDC__) || defined(_MSC_VER)
1567 #define STRCASECMP stricmp
1569 #define STRCASECMP strcasecmp
1572 /*-----------------------------------------------------------------*/
1573 /* inExcludeList - return 1 if the string is in exclude Reg list */
1574 /*-----------------------------------------------------------------*/
1576 inExcludeList (char *s)
1580 if (options.excludeRegs[i] &&
1581 STRCASECMP (options.excludeRegs[i], "none") == 0)
1584 for (i = 0; options.excludeRegs[i]; i++) {
1585 if (options.excludeRegs[i] &&
1586 STRCASECMP (s, options.excludeRegs[i]) == 0)
1592 /*-----------------------------------------------------------------*/
1593 /* genFunction - generated code for function entry */
1594 /*-----------------------------------------------------------------*/
1596 genFunction (iCode * ic)
1603 /* create the function header */
1604 emitcode (";", "-----------------------------------------");
1605 emitcode (";", " function %s",
1606 (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
1607 emitcode (";", "-----------------------------------------");
1609 emitcode ("", "%s:", sym->rname);
1610 fetype = getSpec (operandType (IC_LEFT (ic)));
1612 /* if critical function then turn interrupts off */
1613 if (SPEC_CRTCL (fetype))
1614 emitcode ("cli", "");
1616 if (IS_ISR (sym->etype)) {
1619 /* save the preserved registers that are used in this function */
1620 for (i = R2_IDX; i <= R15_IDX; i++) {
1621 if (bitVectBitValue (sym->regsUsed, i)) {
1623 emitcode ("push", "%s", avr_regWithIdx (i)->name);
1626 /* now for the pointer registers */
1627 if (bitVectBitValue (sym->regsUsed, R26_IDX)) {
1629 emitcode ("push", "r26");
1631 if (bitVectBitValue (sym->regsUsed, R27_IDX)) {
1633 emitcode ("push", "r27");
1635 if (bitVectBitValue (sym->regsUsed, R30_IDX)) {
1637 emitcode ("push", "r30");
1639 if (bitVectBitValue (sym->regsUsed, R31_IDX)) {
1641 emitcode ("push", "r31");
1643 /* adjust the stack for the function */
1645 emitcode ("push", "r28");
1646 emitcode ("push", "r29");
1647 emitcode ("in", "r28,__SP_L__");
1648 emitcode ("in", "r29,__SP_H__");
1649 if (sym->stack <= 63) {
1650 emitcode ("sbiw", "r28,%d", sym->stack);
1653 emitcode ("subi", "r28,lo8(%d)", sym->stack);
1654 emitcode ("sbci", "r29,hi8(%d)", sym->stack);
1656 emitcode ("out", "__SP_L__,r28");
1657 emitcode ("out", "__SP_H__,r29");
1661 /*-----------------------------------------------------------------*/
1662 /* genEndFunction - generates epilogue for functions */
1663 /*-----------------------------------------------------------------*/
1665 genEndFunction (iCode * ic)
1667 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
1670 /* restore stack pointer */
1672 if (sym->stack <= 63) {
1673 emitcode ("adiw", "r28,%d", sym->stack);
1676 emitcode ("subi", "r28,lo8(-%d)", sym->stack);
1677 emitcode ("sbci", "r29,hi8(-%d)", sym->stack);
1679 emitcode ("out", "__SP_L__,r28");
1680 emitcode ("out", "__SP_H__,r29");
1682 /* pop frame pointer */
1683 emitcode ("pop", "r29");
1684 emitcode ("pop", "r28");
1686 /* restore preserved registers */
1687 if (bitVectBitValue (sym->regsUsed, R31_IDX)) {
1689 emitcode ("pop", "r31");
1691 if (bitVectBitValue (sym->regsUsed, R30_IDX)) {
1693 emitcode ("pop", "r30");
1695 if (bitVectBitValue (sym->regsUsed, R27_IDX)) {
1697 emitcode ("push", "r27");
1699 if (bitVectBitValue (sym->regsUsed, R26_IDX)) {
1701 emitcode ("push", "r26");
1703 for (i = R15_IDX; i >= R2_IDX; i--) {
1704 if (bitVectBitValue (sym->regsUsed, i)) {
1706 emitcode ("pop", "%s", avr_regWithIdx (i)->name);
1710 if (SPEC_CRTCL (sym->etype))
1711 emitcode ("sti", "");
1713 if (IS_ISR (sym->etype)) {
1714 emitcode ("rti", "");
1717 emitcode ("ret", "");
1722 /*-----------------------------------------------------------------*/
1723 /* genRet - generate code for return statement */
1724 /*-----------------------------------------------------------------*/
1728 int size, offset = 0;
1730 /* if we have no return value then
1731 just generate the "ret" */
1735 /* we have something to return then
1736 move the return value into place */
1737 aopOp (IC_LEFT (ic), ic, FALSE);
1738 size = AOP_SIZE (IC_LEFT (ic));
1741 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) {
1742 emitcode ("ldi", "%s,%s(%d)", fAVRReturn[offset],
1744 (int) floatFromVal (AOP (IC_LEFT (ic))->
1745 aopu.aop_lit), offset);
1749 l = aopGet (AOP (IC_LEFT (ic)), offset);
1750 if (strcmp (fAVRReturn[offset], l))
1751 emitcode ("mov", "%s,%s", fAVRReturn[offset],
1757 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1760 /* generate a jump to the return label
1761 if the next is not the return statement */
1762 if (!(ic->next && ic->next->op == LABEL &&
1763 IC_LABEL (ic->next) == returnLabel))
1765 emitcode ("rjmp", "L%05d", returnLabel->key);
1769 /*-----------------------------------------------------------------*/
1770 /* genLabel - generates a label */
1771 /*-----------------------------------------------------------------*/
1773 genLabel (iCode * ic)
1775 /* special case never generate */
1776 if (IC_LABEL (ic) == entryLabel)
1779 emitcode ("", "L%05d:", IC_LABEL (ic)->key);
1782 /*-----------------------------------------------------------------*/
1783 /* genGoto - generates a ljmp */
1784 /*-----------------------------------------------------------------*/
1786 genGoto (iCode * ic)
1788 emitcode ("rjmp", "L%05d:", (IC_LABEL (ic)->key + 100));
1791 /*-----------------------------------------------------------------*/
1792 /* findLabelBackwards: walks back through the iCode chain looking */
1793 /* for the given label. Returns number of iCode instructions */
1794 /* between that label and given ic. */
1795 /* Returns zero if label not found. */
1796 /*-----------------------------------------------------------------*/
1798 findLabelBackwards (iCode * ic, int key)
1806 if (ic->op == LABEL && IC_LABEL (ic)->key == key) {
1807 /* printf("findLabelBackwards = %d\n", count); */
1815 /*-----------------------------------------------------------------*/
1816 /* genPlusIncr :- does addition with increment if possible */
1817 /*-----------------------------------------------------------------*/
1819 genPlusIncr (iCode * ic)
1821 unsigned int icount;
1823 /* will try to generate an increment */
1824 /* if the right side is not a literal
1826 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
1830 (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.
1833 /* if the sizes are greater than 2 or they are not the same regs
1835 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1838 /* so we know LEFT & RESULT in the same registers and add
1840 /* for short & char types */
1841 if (AOP_SIZE (IC_RESULT (ic)) < 2) {
1843 emitcode ("inc", "%s",
1844 aopGet (AOP (IC_LEFT (ic)), 0));
1847 emitcode ("subi", "%s,lo8(%d)",
1848 aopGet (AOP (IC_LEFT (ic)), 0), -icount);
1852 if (AOP_SIZE (IC_RESULT (ic)) <= 3) {
1853 /* if register pair and starts with 26/30 then adiw */
1854 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0
1856 && (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX)
1857 || IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX))) {
1858 emitcode ("adiw", "%s,%d",
1859 aopGet (AOP (IC_RESULT (ic)), 0), icount);
1864 emitcode ("subi", "%s,lo8(%d)",
1865 aopGet (AOP (IC_RESULT (ic)), 0), -icount);
1866 emitcode ("sbci", "%s,hi8(%d)",
1867 aopGet (AOP (IC_RESULT (ic)), 1), -icount);
1871 /* for 32 bit longs */
1872 emitcode ("subi", "%s,lo8(%d)", aopGet (AOP (IC_RESULT (ic)), 0),
1874 emitcode ("sbci", "%s,hi8(%d)", aopGet (AOP (IC_RESULT (ic)), 1),
1876 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2),
1878 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3),
1884 /* This is the pure and virtuous version of this code.
1885 * I'm pretty certain it's right, but not enough to toss the old
1889 adjustArithmeticResult (iCode * ic)
1891 if (opIsGptr (IC_RESULT (ic)) &&
1892 opIsGptr (IC_LEFT (ic)) &&
1893 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)))) {
1894 aopPut (AOP (IC_RESULT (ic)),
1895 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1),
1899 if (opIsGptr (IC_RESULT (ic)) &&
1900 opIsGptr (IC_RIGHT (ic)) &&
1901 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)))) {
1902 aopPut (AOP (IC_RESULT (ic)),
1903 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1),
1907 if (opIsGptr (IC_RESULT (ic)) &&
1908 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
1909 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
1910 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
1911 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)))) {
1913 sprintf (buffer, "%d",
1914 pointerCode (getSpec (operandType (IC_LEFT (ic)))));
1915 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
1919 /*-----------------------------------------------------------------*/
1920 /* genPlus - generates code for addition */
1921 /*-----------------------------------------------------------------*/
1923 genPlus (iCode * ic)
1925 int size, offset = 0;
1929 /* special cases :- */
1931 aopOp (IC_LEFT (ic), ic, FALSE);
1932 aopOp (IC_RIGHT (ic), ic, FALSE);
1933 aopOp (IC_RESULT (ic), ic, TRUE);
1935 /* if I can do an increment instead
1936 of add then GOOD for ME */
1937 if (genPlusIncr (ic) == TRUE)
1940 size = getDataSize (IC_RESULT (ic));
1941 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
1945 aopPut (AOP (IC_RESULT (ic)),
1946 aopGet (AOP (IC_LEFT (ic)), offset), offset);
1948 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
1955 emitcode (l, "%s,%s",
1956 aopGet (AOP (IC_RESULT (ic)), offset),
1957 aopGet (AOP (IC_RIGHT (ic)), offset));
1965 emitcode (l, "%s,%s(-%d)",
1966 aopGet (AOP (IC_RESULT (ic)), offset),
1968 (int) floatFromVal (AOP (IC_RIGHT (ic))->
1974 adjustArithmeticResult (ic);
1977 freeAsmop (IC_LEFT (ic), NULL, ic,
1978 (RESULTONSTACK (ic) ? FALSE : TRUE));
1979 freeAsmop (IC_RIGHT (ic), NULL, ic,
1980 (RESULTONSTACK (ic) ? FALSE : TRUE));
1981 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1984 /*-----------------------------------------------------------------*/
1985 /* genMinusDec :- does subtraction with deccrement if possible */
1986 /*-----------------------------------------------------------------*/
1988 genMinusDec (iCode * ic)
1990 unsigned int icount;
1992 /* will try to generate an increment */
1993 /* if the right side is not a literal
1995 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
1999 (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.
2002 /* if the sizes are greater than 2 or they are not the same regs
2004 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic))))
2007 /* so we know LEFT & RESULT in the same registers and add
2009 /* for short & char types */
2010 if (AOP_SIZE (IC_RESULT (ic)) < 2) {
2012 emitcode ("dec", "%s",
2013 aopGet (AOP (IC_LEFT (ic)), 0));
2016 emitcode ("subi", "%s,lo8(%d)",
2017 aopGet (AOP (IC_LEFT (ic)), 0), icount);
2021 if (AOP_SIZE (IC_RESULT (ic)) <= 3) {
2022 /* if register pair and starts with 26/30 then adiw */
2023 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0
2025 && (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX)
2026 || IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX))) {
2027 emitcode ("sbiw", "%s,%d",
2028 aopGet (AOP (IC_RESULT (ic)), 0), icount);
2033 emitcode ("subi", "%s,lo8(%d)",
2034 aopGet (AOP (IC_RESULT (ic)), 0), icount);
2035 emitcode ("sbci", "%s,hi8(%d)",
2036 aopGet (AOP (IC_RESULT (ic)), 1), icount);
2039 /* for 32 bit longs */
2040 emitcode ("subi", "%s,lo8(%d)", aopGet (AOP (IC_RESULT (ic)), 0),
2042 emitcode ("sbci", "%s,hi8(%d)", aopGet (AOP (IC_RESULT (ic)), 1),
2044 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2),
2046 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3),
2052 /*-----------------------------------------------------------------*/
2053 /* addSign - complete with sign */
2054 /*-----------------------------------------------------------------*/
2056 addSign (operand * result, int offset, int sign)
2058 int size = (getDataSize (result) - offset);
2061 emitcode ("rlc", "a");
2062 emitcode ("subb", "a,acc");
2064 aopPut (AOP (result), "a", offset++);
2068 aopPut (AOP (result), zero, offset++);
2072 /*-----------------------------------------------------------------*/
2073 /* genMinus - generates code for subtraction */
2074 /*-----------------------------------------------------------------*/
2076 genMinus (iCode * ic)
2078 int size, offset = 0, samer;
2081 aopOp (IC_LEFT (ic), ic, FALSE);
2082 aopOp (IC_RIGHT (ic), ic, FALSE);
2083 aopOp (IC_RESULT (ic), ic, TRUE);
2085 /* if I can do an decrement instead
2086 of subtract then GOOD for ME */
2087 if (genMinusDec (ic) == TRUE)
2090 size = getDataSize (IC_RESULT (ic));
2091 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2094 aopPut (AOP (IC_RESULT (ic)),
2095 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2097 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
2104 emitcode (l, "%s,%s",
2105 aopGet (AOP (IC_RESULT (ic)), offset),
2106 aopGet (AOP (IC_RIGHT (ic)), offset));
2114 emitcode (l, "%s,%s(%d)",
2115 aopGet (AOP (IC_RESULT (ic)), offset),
2117 (int) floatFromVal (AOP (IC_RIGHT (ic))->
2123 adjustArithmeticResult (ic);
2126 freeAsmop (IC_LEFT (ic), NULL, ic,
2127 (RESULTONSTACK (ic) ? FALSE : TRUE));
2128 freeAsmop (IC_RIGHT (ic), NULL, ic,
2129 (RESULTONSTACK (ic) ? FALSE : TRUE));
2130 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2133 /*-----------------------------------------------------------------*/
2134 /* genMultOneByte : 8 bit multiplication & division */
2135 /*-----------------------------------------------------------------*/
2137 genMultOneByte (operand * left, operand * right, operand * result)
2139 sym_link *opetype = operandType (result);
2143 /* (if two literals, the value is computed before) */
2144 /* if one literal, literal on the right */
2145 if (AOP_TYPE (left) == AOP_LIT) {
2151 size = AOP_SIZE (result);
2153 if (SPEC_USIGN (opetype)) {
2154 emitcode ("mul", "%s,%s", aopGet (AOP (left), 0),
2155 aopGet (AOP (right), 0));
2158 emitcode ("muls", "%s,%s", aopGet (AOP (left), 0),
2159 aopGet (AOP (right), 0));
2161 aopPut (AOP (result), "r0", 0);
2163 aopPut (AOP (result), "r1", 1);
2166 if (SPEC_USIGN (opetype)) {
2168 aopPut (AOP (result), zero, offset++);
2173 lbl = newiTempLabel (NULL);
2174 emitcode ("ldi", "r24,0");
2175 emitcode ("brcc", "L%05d", lbl->key);
2176 emitcode ("ldi", "r24,lo8(-1)");
2177 emitcode ("", "L%05d:", lbl->key);
2179 aopPut (AOP (result), "r24",
2187 /*-----------------------------------------------------------------*/
2188 /* genMult - generates code for multiplication */
2189 /*-----------------------------------------------------------------*/
2191 genMult (iCode * ic)
2193 operand *left = IC_LEFT (ic);
2194 operand *right = IC_RIGHT (ic);
2195 operand *result = IC_RESULT (ic);
2197 /* assign the amsops */
2198 aopOp (left, ic, FALSE);
2199 aopOp (right, ic, FALSE);
2200 aopOp (result, ic, TRUE);
2202 /* if both are of size == 1 */
2203 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1) {
2204 genMultOneByte (left, right, result);
2208 /* should have been converted to function call */
2212 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2213 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2214 freeAsmop (result, NULL, ic, TRUE);
2217 /*-----------------------------------------------------------------*/
2218 /* genDiv - generates code for division */
2219 /*-----------------------------------------------------------------*/
2223 /* should have been converted to function call */
2227 /*-----------------------------------------------------------------*/
2228 /* genMod - generates code for division */
2229 /*-----------------------------------------------------------------*/
2233 /* should have been converted to function call */
2245 /*-----------------------------------------------------------------*/
2246 /* revavrcnd - reverse a conditional for avr */
2247 /*-----------------------------------------------------------------*/
2249 revavrcnd (int type)
2261 for (i = 0; i < (sizeof (rar) / sizeof (rar[0])); i++) {
2262 if (rar[i].type == type)
2263 return rar[i].rtype;
2264 if (rar[i].rtype == type)
2267 assert (1); /* cannot happen */
2268 return 0; /* makes the compiler happy */
2271 static char *br_name[4] = { "breq", "brne", "brlt", "brge" };
2272 static char *br_uname[4] = { "breq", "brne", "brlo", "brcc" };
2274 /*-----------------------------------------------------------------*/
2275 /* genBranch - generate the branch instruction */
2276 /*-----------------------------------------------------------------*/
2278 genBranch (iCode * ifx, int br_type, int sign)
2280 int tj = (IC_TRUE (ifx) ? 1 : 0);
2282 if (tj) { /* if true jump */
2283 char *nm = (sign ? br_name[br_type] : br_uname[br_type]);
2284 emitcode (nm, "L%05d", IC_TRUE (ifx)->key);
2286 else { /* if false jump */
2287 int rtype = revavrcnd (br_type);
2288 char *nm = (sign ? br_name[rtype] : br_uname[rtype]);
2289 emitcode (nm, "L%05d", IC_FALSE (ifx)->key);
2294 /*-----------------------------------------------------------------*/
2295 /* genCmp - compare & jump */
2296 /*-----------------------------------------------------------------*/
2298 genCmp (iCode * ic, iCode * ifx, int br_type)
2300 operand *left, *right, *result;
2301 sym_link *letype, *retype;
2303 int sign, size, offset = 0;
2305 left = IC_LEFT (ic);
2306 right = IC_RIGHT (ic);
2307 result = IC_RESULT (ic);
2309 letype = getSpec (operandType (left));
2310 retype = getSpec (operandType (right));
2311 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
2313 /* assign the amsops */
2314 aopOp (left, ic, FALSE);
2315 aopOp (right, ic, FALSE);
2316 aopOp (result, ic, TRUE);
2317 size = AOP_SIZE (left);
2321 if (AOP_TYPE (right) == AOP_LIT) {
2322 emitcode ("cpi", "%s,lo8(%d)",
2323 aopGet (AOP (left), 0),
2325 floatFromVal (AOP (IC_RIGHT (ic))->
2327 genBranch (ifx, br_type, sign);
2329 else { /* right != literal */
2330 emitcode ("cp", "%s,%s",
2331 aopGet (AOP (left), 0),
2332 aopGet (AOP (right), 0));
2333 genBranch (ifx, br_type, sign);
2336 else { /* size != 1 */
2339 emitcode ("cp", "%s,%s",
2340 aopGet (AOP (left), 0),
2341 aopGet (AOP (right), 0));
2343 emitcode ("cpc", "%s,%s",
2344 aopGet (AOP (left), offset),
2345 aopGet (AOP (right),
2349 genBranch (ifx, br_type, sign);
2353 emitcode ("clr", "r0");
2356 emitcode ("cp", "%s,%s",
2357 aopGet (AOP (left), 0),
2358 aopGet (AOP (right), 0));
2360 emitcode ("cpc", "%s,%s",
2361 aopGet (AOP (left), offset),
2362 aopGet (AOP (right), offset));
2365 lbl = newiTempLabel (NULL);
2366 br_type = revavrcnd (br_type);
2368 emitcode (br_uname[br_type], "L%05d", lbl->key);
2370 emitcode (br_name[br_type], "L%05d", lbl->key);
2371 emitcode ("inc", "r0");
2372 emitcode ("", "L%05d:", lbl->key);
2373 aopPut (AOP (result), "r0", 0);
2374 size = AOP_SIZE (result) - 1;
2377 aopPut (AOP (result), zero, offset++);
2380 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2381 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2382 freeAsmop (result, NULL, ic, TRUE);
2385 /*-----------------------------------------------------------------*/
2386 /* genCmpGt :- greater than comparison */
2387 /*-----------------------------------------------------------------*/
2389 genCmpGt (iCode * ic, iCode * ifx)
2391 /* should have transformed by the parser */
2395 /*-----------------------------------------------------------------*/
2396 /* genCmpLt - less than comparisons */
2397 /*-----------------------------------------------------------------*/
2399 genCmpLt (iCode * ic, iCode * ifx)
2401 genCmp (ic, ifx, AVR_LT);
2404 /*-----------------------------------------------------------------*/
2405 /* genCmpEq - generates code for equal to */
2406 /*-----------------------------------------------------------------*/
2408 genCmpEq (iCode * ic, iCode * ifx)
2410 genCmp (ic, ifx, AVR_EQ);
2413 /*-----------------------------------------------------------------*/
2414 /* genCmpNe - generates code for not equal to */
2415 /*-----------------------------------------------------------------*/
2417 genCmpNe (iCode * ic, iCode * ifx)
2419 genCmp (ic, ifx, AVR_NE);
2422 /*-----------------------------------------------------------------*/
2423 /* genCmpGe - generates code for greater than equal to */
2424 /*-----------------------------------------------------------------*/
2426 genCmpGe (iCode * ic, iCode * ifx)
2428 genCmp (ic, ifx, AVR_GE);
2431 /*-----------------------------------------------------------------*/
2432 /* genCmpLe - generates code for less than equal to */
2433 /*-----------------------------------------------------------------*/
2435 genCmpLe (iCode * ic, iCode * ifx)
2437 operand *left = IC_LEFT (ic);
2438 operand *right = IC_RIGHT (ic);
2440 IC_RIGHT (ic) = left;
2441 IC_LEFT (ic) = right;
2442 genCmp (ic, ifx, AVR_GE);
2445 /*-----------------------------------------------------------------*/
2446 /* ifxForOp - returns the icode containing the ifx for operand */
2447 /*-----------------------------------------------------------------*/
2449 ifxForOp (operand * op, iCode * ic)
2451 /* if true symbol then needs to be assigned */
2452 if (IS_TRUE_SYMOP (op))
2455 /* if this has register type condition and
2456 the next instruction is ifx with the same operand
2457 and live to of the operand is upto the ifx only then */
2459 ic->next->op == IFX &&
2460 IC_COND (ic->next)->key == op->key &&
2461 OP_SYMBOL (op)->liveTo <= ic->next->seq) return ic->next;
2466 /*-----------------------------------------------------------------*/
2467 /* genAndOp - for && operation */
2468 /*-----------------------------------------------------------------*/
2470 genAndOp (iCode * ic)
2472 operand *left, *right, *result;
2476 /* note here that && operations that are in an
2477 if statement are taken away by backPatchLabels
2478 only those used in arthmetic operations remain */
2479 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2480 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2481 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
2483 tlbl = newiTempLabel (NULL);
2484 toBoolean (left, "r0", TRUE);
2485 toBoolean (right, "r1", TRUE);
2486 emitcode ("and", "r0,r1");
2487 emitcode ("ldi", "r24,1");
2488 emitcode ("breq", "L%05d", tlbl->key);
2489 emitcode ("dec", "r24");
2490 emitcode ("", "L%05d:", tlbl->key);
2491 aopPut (AOP (result), "r24", 0);
2492 size = AOP_SIZE (result) - 1;
2495 aopPut (AOP (result), zero, offset++);
2497 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2498 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2499 freeAsmop (result, NULL, ic, TRUE);
2503 /*-----------------------------------------------------------------*/
2504 /* genOrOp - for || operation */
2505 /*-----------------------------------------------------------------*/
2507 genOrOp (iCode * ic)
2509 operand *left, *right, *result;
2513 /* note here that || operations that are in an
2514 if statement are taken away by backPatchLabels
2515 only those used in arthmetic operations remain */
2516 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2517 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2518 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
2520 tlbl = newiTempLabel (NULL);
2521 toBoolean (left, "r0", TRUE);
2522 toBoolean (right, "r0", FALSE);
2523 emitcode ("ldi", "r24,1");
2524 emitcode ("breq", "L%05d", tlbl->key);
2525 emitcode ("dec", "r24");
2526 emitcode ("", "L%05d:", tlbl->key);
2527 aopPut (AOP (result), "r24", 0);
2528 size = AOP_SIZE (result) - 1;
2531 aopPut (AOP (result), zero, offset++);
2533 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2534 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2535 freeAsmop (result, NULL, ic, TRUE);
2538 /*-----------------------------------------------------------------*/
2539 /* isLiteralBit - test if lit == 2^n */
2540 /*-----------------------------------------------------------------*/
2542 isLiteralBit (unsigned long lit)
2544 unsigned long pw[32] = { 1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
2545 0x100L, 0x200L, 0x400L, 0x800L,
2546 0x1000L, 0x2000L, 0x4000L, 0x8000L,
2547 0x10000L, 0x20000L, 0x40000L, 0x80000L,
2548 0x100000L, 0x200000L, 0x400000L, 0x800000L,
2549 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
2550 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L
2554 for (idx = 0; idx < 32; idx++)
2561 AVR_AND = 0, AVR_OR, AVR_XOR
2563 static char *bopnames_lit[] = { "andi", "ori" };
2564 static char *bopnames[] = { "and", "or", "eor" };
2565 /*-----------------------------------------------------------------*/
2566 /* genBitWise - generate bitwise operations */
2567 /*-----------------------------------------------------------------*/
2569 genBitWise (iCode * ic, iCode * ifx, int bitop)
2571 operand *left, *right, *result;
2572 int size, offset = 0;
2577 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2578 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2579 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
2581 size = AOP_SIZE (left);
2583 if (ifx) { /* used only for jumps */
2584 if (AOP_TYPE (right) == AOP_LIT &&
2585 (bitop == AVR_AND || bitop == AVR_OR)) {
2587 (int) floatFromVal (AOP (right)->aopu.
2589 int p2 = powof2 (lit);
2590 if (bitop == AVR_AND && p2) { /* right side is a power of 2 */
2591 l = aopGet (AOP (left), p2 / 8);
2592 if (IC_TRUE (ifx)) {
2593 emitcode ("sbrc", "%s,%d", l,
2595 emitcode ("rjmp", "L%05d",
2596 IC_TRUE (ifx)->key);
2599 emitcode ("sbrs", "%s,%d", l,
2601 emitcode ("rjmp", "L%05d",
2602 IC_FALSE (ifx)->key);
2605 else { /* right not power of two */
2606 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2609 emitcode (bopnames_lit[bitop],
2618 (AOP (IC_LEFT (ic)),
2620 emitcode (bopnames_lit[bitop],
2623 lbl = newiTempLabel (NULL);
2624 if (IC_TRUE (ifx)) {
2625 emitcode ("breq", "L%05d",
2627 emitcode ("rjmp", "L%05d",
2628 IC_TRUE (ifx)->key);
2631 emitcode ("brne", "L%05d",
2633 emitcode ("rjmp", "L%05d",
2637 emitcode ("", "L%05d:", lbl->key);
2639 else if (size == 2) {
2640 emitcode ("mov", "r24,%s",
2641 aopGet (AOP (IC_LEFT (ic)),
2643 emitcode ("mov", "r25,%s",
2644 aopGet (AOP (IC_LEFT (ic)),
2646 emitcode (bopnames_lit[bitop],
2647 "r24,lo8(%d)", lit);
2648 emitcode (bopnames_lit[bitop],
2649 "r25,hi8(%d)", lit);
2650 emitcode ("sbiw", "r24,0");
2651 lbl = newiTempLabel (NULL);
2652 if (IC_TRUE (ifx)) {
2653 emitcode ("breq", "L%05d",
2655 emitcode ("rjmp", "L%05d",
2656 IC_TRUE (ifx)->key);
2659 emitcode ("brne", "L%05d",
2661 emitcode ("rjmp", "L%05d",
2665 emitcode ("", "L%05d:", lbl->key);
2668 lbl = newiTempLabel (NULL);
2669 lbl1 = newiTempLabel (NULL);
2672 emitcode (bopnames_lit
2691 emitcode ("brne", "L%05d",
2697 emitcode ("rjmp", "L%05d",
2701 emitcode ("rjmp", "L%05d",
2703 emitcode ("", "L%05d:", lbl->key);
2706 emitcode ("rjmp", "L%05d",
2707 IC_TRUE (ifx)->key);
2708 emitcode ("", "L%05d:", lbl1->key);
2713 else { /* right is not a literal */
2714 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2715 int reh = OP_SYMBOL (right)->liveTo <= ic->seq;
2718 emitcode (bopnames[bitop], "%s,%s",
2719 aopGet (AOP (IC_LEFT (ic)),
2721 aopGet (AOP (IC_RIGHT (ic)),
2725 emitcode (bopnames[bitop], "%s,%s",
2726 aopGet (AOP (IC_RIGHT (ic)),
2728 aopGet (AOP (IC_LEFT (ic)),
2733 (AOP (IC_LEFT (ic)), 0));
2734 emitcode (bopnames[bitop], "r0,%s",
2735 aopGet (AOP (IC_RIGHT (ic)),
2738 lbl = newiTempLabel (NULL);
2739 if (IC_TRUE (ifx)) {
2740 emitcode ("breq", "L%05d", lbl->key);
2741 emitcode ("rjmp", "L%05d",
2742 IC_TRUE (ifx)->key);
2745 emitcode ("brne", "L%05d", lbl->key);
2746 emitcode ("rjmp", "L%05d",
2747 IC_FALSE (ifx)->key);
2749 emitcode ("", "L%05d:", lbl->key);
2751 else if (size == 2) {
2752 emitcode ("mov", "r24,%s",
2753 aopGet (AOP (IC_LEFT (ic)), 0));
2754 emitcode ("mov", "r25,%s",
2755 aopGet (AOP (IC_LEFT (ic)), 1));
2756 emitcode (bopnames[bitop], "r24,%s",
2757 aopGet (AOP (IC_RIGHT (ic)), 0));
2758 emitcode (bopnames[bitop], "r25,%s",
2759 aopGet (AOP (IC_RIGHT (ic)), 1));
2760 emitcode ("sbiw", "r24,0");
2761 lbl = newiTempLabel (NULL);
2762 if (IC_TRUE (ifx)) {
2763 emitcode ("breq", "L%05d", lbl->key);
2764 emitcode ("rjmp", "L%05d",
2765 IC_TRUE (ifx)->key);
2768 emitcode ("brne", "L%05d", lbl->key);
2769 emitcode ("rjmp", "L%05d",
2770 IC_FALSE (ifx)->key);
2772 emitcode ("", "L%05d:", lbl->key);
2775 lbl = newiTempLabel (NULL);
2776 lbl1 = newiTempLabel (NULL);
2779 emitcode (bopnames[bitop],
2791 emitcode (bopnames[bitop],
2804 (AOP (IC_LEFT (ic)),
2806 emitcode (bopnames[bitop],
2813 emitcode ("brne", "L%05d", lbl->key);
2818 emitcode ("rjmp", "L%05d",
2819 IC_FALSE (ifx)->key);
2821 emitcode ("rjmp", "L%05d", lbl1->key);
2822 emitcode ("", "L%05d:", lbl->key);
2825 emitcode ("rjmp", "L%05d",
2826 IC_TRUE (ifx)->key);
2827 emitcode ("", "L%05d:", lbl1->key);
2834 /* result needs to go a register */
2835 samerl = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2836 samerr = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)));
2838 if (AOP_TYPE (right) == AOP_LIT) {
2840 (int) floatFromVal (AOP (right)->aopu.
2842 if (((lit >> (8 * offset)) & 0xff) == 0) {
2843 if (bitop == AVR_AND) {
2844 aopPut (AOP (result), zero, offset++);
2847 else if (bitop == AVR_OR) {
2849 aopPut (AOP (result),
2859 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT
2860 && (bitop == AVR_AND || bitop == AVR_OR)) {
2861 emitcode (bopnames_lit[bitop], "%s,%s(%d)",
2862 aopGet (AOP (IC_LEFT (ic)), offset),
2864 (int) floatFromVal (AOP (right)->
2868 emitcode (bopnames[bitop], "%s,%s",
2869 aopGet (AOP (IC_LEFT (ic)), offset),
2870 aopGet (AOP (IC_RIGHT (ic)),
2875 emitcode (bopnames[bitop], "%s,%s",
2876 aopGet (AOP (IC_RIGHT (ic)), offset),
2877 aopGet (AOP (IC_LEFT (ic)), offset));
2880 aopPut (AOP (IC_RESULT (ic)),
2881 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2882 emitcode (bopnames[bitop],
2883 aopGet (AOP (IC_RESULT (ic)), offset),
2884 aopGet (AOP (IC_RIGHT (ic)), offset));
2889 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2890 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2891 freeAsmop (result, NULL, ic, TRUE);
2894 /*-----------------------------------------------------------------*/
2895 /* genAnd - code for and */
2896 /*-----------------------------------------------------------------*/
2898 genAnd (iCode * ic, iCode * ifx)
2900 genBitWise (ic, ifx, AVR_AND);
2903 /*-----------------------------------------------------------------*/
2904 /* genOr - code for or */
2905 /*-----------------------------------------------------------------*/
2907 genOr (iCode * ic, iCode * ifx)
2909 genBitWise (ic, ifx, AVR_OR);
2912 /*-----------------------------------------------------------------*/
2913 /* genXor - code for xclusive or */
2914 /*-----------------------------------------------------------------*/
2916 genXor (iCode * ic, iCode * ifx)
2918 genBitWise (ic, ifx, AVR_XOR);
2921 /*-----------------------------------------------------------------*/
2922 /* genInline - write the inline code out */
2923 /*-----------------------------------------------------------------*/
2925 genInline (iCode * ic)
2927 char buffer[MAX_INLINEASM];
2931 _G.inLine += (!options.asmpeep);
2932 strcpy (buffer, IC_INLINE (ic));
2934 /* emit each line as a code */
2955 /* emitcode("",buffer); */
2956 _G.inLine -= (!options.asmpeep);
2959 /*-----------------------------------------------------------------*/
2960 /* genRotC - rotate right/left with carry , lr = 1 rotate right */
2961 /*-----------------------------------------------------------------*/
2963 genRotC (iCode * ic, int lr)
2965 operand *left, *result;
2966 int size, offset = 0;
2968 /* rotate right with carry */
2969 left = IC_LEFT (ic);
2970 result = IC_RESULT (ic);
2971 aopOp (left, ic, FALSE);
2972 aopOp (result, ic, FALSE);
2974 /* move it to the result */
2975 size = AOP_SIZE (result);
2976 if (!sameRegs (AOP (left), AOP (result))) {
2979 aopPut (AOP (result),
2980 aopGet (AOP (left), offset), offset);
2983 size = AOP_SIZE (result);
2991 emitcode ("sbrc", "%s,%d", aopGet (AOP (result), offset),
2993 emitcode ("sec", "");
2996 emitcode ((lr ? "ror" : "rol"), "%s",
2997 aopGet (AOP (result), offset));
3003 freeAsmop (left, NULL, ic, TRUE);
3004 freeAsmop (result, NULL, ic, TRUE);
3007 /*-----------------------------------------------------------------*/
3008 /* genRRC - rotate right with carry */
3009 /*-----------------------------------------------------------------*/
3016 /*-----------------------------------------------------------------*/
3017 /* genRLC - generate code for rotate left with carry */
3018 /*-----------------------------------------------------------------*/
3025 /*-----------------------------------------------------------------*/
3026 /* genGetHbit - generates code get highest order bit */
3027 /*-----------------------------------------------------------------*/
3029 genGetHbit (iCode * ic)
3031 operand *left, *result;
3034 left = IC_LEFT (ic);
3035 result = IC_RESULT (ic);
3036 aopOp (left, ic, FALSE);
3037 aopOp (result, ic, FALSE);
3039 size = AOP_SIZE (result);
3040 if (!sameRegs (AOP (left), AOP (result))) {
3041 emitcode ("clr", "%s", aopGet (AOP (result), size - 1));
3042 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3043 emitcode ("subi", "%s,lo8(-1)",
3044 aopGet (AOP (result), size - 1));
3047 emitcode ("clr", "r0");
3048 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3049 emitcode ("subi", "r0,lo8(-1)");
3050 aopPut (AOP (result), "r0", 0);
3055 emitcode ("clr", aopGet (AOP (result), offset++));
3057 freeAsmop (left, NULL, ic, TRUE);
3058 freeAsmop (result, NULL, ic, TRUE);
3061 /*-----------------------------------------------------------------*/
3062 /* genShiftLeftLit - shift left by a known amount */
3063 /*-----------------------------------------------------------------*/
3065 genShiftLeftLit (iCode * ic)
3067 operand *left, *right, *result;
3068 int size, shCount, offset = 0;
3071 right = IC_RIGHT (ic);
3072 left = IC_LEFT (ic);
3073 result = IC_RESULT (ic);
3075 aopOp (left, ic, FALSE);
3076 aopOp (result, ic, FALSE);
3077 size = AOP_SIZE (result);
3078 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3080 if (shCount > (size * 8 - 1)) {
3082 aopPut (AOP (result), zero, offset++);
3087 if (!sameRegs (AOP (left), AOP (result)))
3088 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3090 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3091 emitcode ("andi", "%s,0xf0");
3095 emitcode ("add", "%s,%s", aopGet (AOP (result), 0),
3096 aopGet (AOP (result), 0));
3100 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3103 if (shCount >= 12) {
3104 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3105 aopPut (AOP (result), zero, 0);
3106 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3107 emitcode ("andi", "%s,0xf0",
3108 aopGet (AOP (result), 1));
3113 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3114 aopPut (AOP (result), zero, 0);
3120 if (!sameRegs (AOP (left), AOP (result))) {
3121 aopPut (AOP (result), aopGet (AOP (left), 0),
3123 aopPut (AOP (result), aopGet (AOP (left), 1),
3126 emitcode ("mov", "r1,%s", aopGet (AOP (result), 0));
3127 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3128 emitcode ("andi", "%s,0xf0",
3129 aopGet (AOP (result), 0));
3130 emitcode ("andi", "r1,0x0f");
3131 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3132 emitcode ("andi", "%s,0xf0",
3133 aopGet (AOP (result), 1));
3134 emitcode ("or", "%s,r1", aopGet (AOP (result), 1));
3136 emitcode ("lsl", "%s",
3137 aopGet (AOP (result), 0));
3138 emitcode ("rol", "%s",
3139 aopGet (AOP (result), 1));
3142 if (!lByteZ && !sameRegs (AOP (result), AOP (left))
3146 aopPut (AOP (result),
3147 aopGet (AOP (left), offset), offset);
3153 emitcode ("lsl", "%s",
3154 aopGet (AOP (result), 1));
3157 emitcode ("lsl", "%s",
3158 aopGet (AOP (result), 0));
3159 emitcode ("rol", "%s",
3160 aopGet (AOP (result), 1));
3165 assert ("shifting generic pointer ?\n");
3168 /* 32 bits we do only byte boundaries */
3169 if (shCount >= 24) {
3170 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3171 aopPut (AOP (result), zero, 2);
3172 aopPut (AOP (result), zero, 1);
3173 aopPut (AOP (result), zero, 0);
3177 if (shCount >= 16) {
3178 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3179 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3180 aopPut (AOP (result), zero, 1);
3181 aopPut (AOP (result), zero, 0);
3186 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3187 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3188 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3189 aopPut (AOP (result), zero, 0);
3193 if (!lByteZ && !sameRegs (AOP (left), AOP (right))) {
3196 aopPut (AOP (result),
3197 aopGet (AOP (left), offset), offset);
3201 size = AOP_SIZE (result);
3207 emitcode ("lsl", "%s",
3208 aopGet (AOP (result), 0));
3209 emitcode ("rol", "%s",
3210 aopGet (AOP (result), 1));
3211 emitcode ("rol", "%s",
3212 aopGet (AOP (result), 2));
3213 emitcode ("rol", "%s",
3214 aopGet (AOP (result), 3));
3219 emitcode ("lsl", "%s",
3220 aopGet (AOP (result), 1));
3221 emitcode ("rol", "%s",
3222 aopGet (AOP (result), 2));
3223 emitcode ("rol", "%s",
3224 aopGet (AOP (result), 3));
3229 emitcode ("lsl", "%s",
3230 aopGet (AOP (result), 2));
3231 emitcode ("rol", "%s",
3232 aopGet (AOP (result), 3));
3237 emitcode ("lsl", "%s",
3238 aopGet (AOP (result), 3));
3246 freeAsmop (left, NULL, ic, TRUE);
3247 freeAsmop (right, NULL, ic, TRUE);
3248 freeAsmop (result, NULL, ic, TRUE);
3251 /*-----------------------------------------------------------------*/
3252 /* genLeftShift - generates code for left shifting */
3253 /*-----------------------------------------------------------------*/
3255 genLeftShift (iCode * ic)
3257 operand *left, *right, *result;
3261 right = IC_RIGHT (ic);
3262 left = IC_LEFT (ic);
3263 result = IC_RESULT (ic);
3265 aopOp (right, ic, FALSE);
3267 if (AOP_TYPE (right) == AOP_LIT) {
3268 genShiftLeftLit (ic);
3273 aopOp (left, ic, FALSE);
3274 aopOp (result, ic, FALSE);
3275 size = AOP_SIZE (result);
3277 if (AOP_SIZE (right) > 1) {
3278 if (isRegPair (AOP (right))) {
3279 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3282 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3283 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3287 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3289 if (!sameRegs (AOP (left), AOP (result))) {
3291 aopPut (AOP (result), aopGet (AOP (left), offset),
3295 size = AOP_SIZE (result);
3297 tlbl = newiTempLabel (NULL);
3298 emitcode ("", "L%05d:", tlbl->key);
3302 emitcode ("rol", "%s", aopGet (AOP (result), offset));
3304 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3307 if (AOP_SIZE (right) > 1)
3308 emitcode ("sbiw", "r24,1");
3310 emitcode ("dec", "r24");
3311 emitcode ("brne", "L%05d", tlbl->key);
3313 freeAsmop (left, NULL, ic, TRUE);
3314 freeAsmop (right, NULL, ic, TRUE);
3315 freeAsmop (result, NULL, ic, TRUE);
3318 /*-----------------------------------------------------------------*/
3319 /* genShiftRightLit - generate for right shift with known count */
3320 /*-----------------------------------------------------------------*/
3322 genShiftRightLit (iCode * ic)
3324 operand *left = IC_LEFT (ic)
3325 , *right = IC_RIGHT (ic)
3326 , *result = IC_RESULT (ic);
3327 int size, shCount, offset = 0;
3329 sym_link *letype = getSpec (operandType (left));
3330 int sign = !SPEC_USIGN (letype);
3332 right = IC_RIGHT (ic);
3333 left = IC_LEFT (ic);
3334 result = IC_RESULT (ic);
3336 aopOp (left, ic, FALSE);
3337 aopOp (result, ic, FALSE);
3338 size = AOP_SIZE (result);
3339 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3341 /* if signed then give up and use a loop to shift */
3344 if (!sameRegs (AOP (left), AOP (result))) {
3346 aopPut (AOP (result),
3347 aopGet (AOP (left), offset), offset);
3350 size = size = AOP_SIZE (result);
3353 /* be as economical as possible */
3358 size = AOP_SIZE (result);
3360 if (offset == (size - 1))
3361 emitcode ("asr", "%s",
3366 emitcode ("lsr", "%s",
3375 emitcode ("ldi", "r24,lo8(%d)", shCount);
3376 tlbl = newiTempLabel (NULL);
3377 emitcode ("", "L%05d:", tlbl->key);
3380 if (offset == (size - 1))
3381 emitcode ("asr", "%s",
3382 aopGet (AOP (result),
3385 emitcode ("lsr", "%s",
3386 aopGet (AOP (result),
3390 emitcode ("dec", "r24");
3391 emitcode ("brne", "L%05d", tlbl->key);
3395 if (shCount > (size * 8 - 1)) {
3397 aopPut (AOP (result), zero, offset++);
3400 /* for unsigned we can much more efficient */
3403 if (!sameRegs (AOP (left), AOP (result)))
3404 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3406 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3407 emitcode ("andi", "%s,0x0f");
3411 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3414 if (shCount >= 12) {
3415 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3416 aopPut (AOP (result), zero, 1);
3417 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3418 emitcode ("andi", "%s,0x0f",
3419 aopGet (AOP (result), 0));
3424 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3425 aopPut (AOP (result), zero, 1);
3431 if (!sameRegs (AOP (left), AOP (result))) {
3432 aopPut (AOP (result), aopGet (AOP (left), 0),
3434 aopPut (AOP (result), aopGet (AOP (left), 1),
3437 emitcode ("mov", "r1,%s", aopGet (AOP (result), 1));
3438 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3439 emitcode ("andi", "%s,0x0f",
3440 aopGet (AOP (result), 0));
3441 emitcode ("andi", "r1,0xf0");
3442 emitcode ("or", "%s,r1", aopGet (AOP (result), 0));
3443 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3444 emitcode ("andi", "%s,0x0f",
3445 aopGet (AOP (result), 1));
3447 emitcode ("lsr", "%s",
3448 aopGet (AOP (result), 1));
3449 emitcode ("ror", "%s",
3450 aopGet (AOP (result), 0));
3454 if (!hByteZ && !sameRegs (AOP (result), AOP (left))
3458 aopPut (AOP (result),
3459 aopGet (AOP (left), offset), offset);
3465 emitcode ("lsr", "%s",
3466 aopGet (AOP (result), 0));
3469 emitcode ("lsr", "%s",
3470 aopGet (AOP (result), 1));
3471 emitcode ("ror", "%s",
3472 aopGet (AOP (result), 0));
3478 assert ("shifting generic pointer ?\n");
3481 /* 32 bits we do only byte boundaries */
3482 if (shCount >= 24) {
3483 aopPut (AOP (result), aopGet (AOP (left), 3), 0);
3484 aopPut (AOP (result), zero, 1);
3485 aopPut (AOP (result), zero, 2);
3486 aopPut (AOP (result), zero, 3);
3490 if (shCount >= 16) {
3491 aopPut (AOP (result), aopGet (AOP (left), 3), 1);
3492 aopPut (AOP (result), aopGet (AOP (left), 2), 0);
3493 aopPut (AOP (result), zero, 2);
3494 aopPut (AOP (result), zero, 3);
3499 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3500 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3501 aopPut (AOP (result), aopGet (AOP (left), 3), 2);
3502 aopPut (AOP (result), zero, 3);
3506 if (!hByteZ && !sameRegs (AOP (left), AOP (right))) {
3509 aopPut (AOP (result),
3510 aopGet (AOP (left), offset), offset);
3514 size = AOP_SIZE (result);
3520 emitcode ("lsr", "%s",
3521 aopGet (AOP (result), 3));
3522 emitcode ("ror", "%s",
3523 aopGet (AOP (result), 2));
3524 emitcode ("ror", "%s",
3525 aopGet (AOP (result), 1));
3526 emitcode ("ror", "%s",
3527 aopGet (AOP (result), 0));
3532 emitcode ("lsr", "%s",
3533 aopGet (AOP (result), 2));
3534 emitcode ("ror", "%s",
3535 aopGet (AOP (result), 1));
3536 emitcode ("ror", "%s",
3537 aopGet (AOP (result), 0));
3542 emitcode ("lsr", "%s",
3543 aopGet (AOP (result), 1));
3544 emitcode ("ror", "%s",
3545 aopGet (AOP (result), 0));
3550 emitcode ("lsr", "%s",
3551 aopGet (AOP (result), 0));
3558 freeAsmop (left, NULL, ic, TRUE);
3559 freeAsmop (right, NULL, ic, TRUE);
3560 freeAsmop (result, NULL, ic, TRUE);
3563 /*-----------------------------------------------------------------*/
3564 /* genRightShift - generate code for right shifting */
3565 /*-----------------------------------------------------------------*/
3567 genRightShift (iCode * ic)
3569 operand *right, *left, *result;
3572 int sign = 0, first = 1;
3575 aopOp (right = IC_RIGHT (ic), ic, FALSE);
3577 if (AOP_TYPE (right) == AOP_LIT) {
3578 genShiftRightLit (ic);
3582 if (AOP_SIZE (right) > 1) {
3583 if (isRegPair (AOP (right))) {
3584 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3587 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3588 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3592 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3594 aopOp (left = IC_LEFT (ic), ic, FALSE);
3595 aopOp (result = IC_RESULT (ic), ic, FALSE);
3596 size = AOP_SIZE (result);
3597 tlbl = newiTempLabel (NULL);
3598 emitcode ("", "L%05d:", tlbl->key);
3600 letype = getSpec (operandType (left));
3601 sign = !SPEC_USIGN (letype);
3602 if (!sameRegs (AOP (left), AOP (result))) {
3604 aopPut (AOP (result), aopGet (AOP (left), offset),
3608 size = AOP_SIZE (result);
3610 size = AOP_SIZE (result);
3614 emitcode ("asr", "%s",
3615 aopGet (AOP (result), offset));
3617 emitcode ("lsr", "%s",
3618 aopGet (AOP (result), offset));
3622 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3625 if (AOP_SIZE (right) > 1)
3626 emitcode ("sbiw", "r24,1");
3628 emitcode ("dec", "r24");
3629 emitcode ("brne", "L%05d", tlbl->key);
3631 freeAsmop (left, NULL, ic, TRUE);
3632 freeAsmop (result, NULL, ic, TRUE);
3635 /*-----------------------------------------------------------------*/
3636 /* R0Rsh - shift right r0 by known count */
3637 /*-----------------------------------------------------------------*/
3641 shCount &= 0x0007; // shCount : 0..7
3647 emitcode ("lsr", "r0");
3650 emitcode ("lsr", "r0");
3651 emitcode ("lsr", "r0");
3654 emitcode ("swap", "r0");
3655 emitcode ("lsl", "r0");
3658 emitcode ("swap", "r0");
3661 emitcode ("swap", "r0");
3662 emitcode ("lsr", "r0");
3665 emitcode ("swap", "r0");
3666 emitcode ("lsr", "r0");
3667 emitcode ("lsr", "r0");
3670 emitcode ("swap", "r0");
3671 emitcode ("lsr", "r0");
3672 emitcode ("lsr", "r0");
3673 emitcode ("lsr", "r0");
3678 /*-----------------------------------------------------------------*/
3679 /* genUnpackBits - generates code for unpacking bits */
3680 /*-----------------------------------------------------------------*/
3682 genUnpackBits (operand * result, char *rname, int ptype)
3690 etype = getSpec (operandType (result));
3691 rsize = getSize (operandType (result));
3692 /* read the first byte */
3699 emitcode ("ld", "r0,%s+", rname);
3703 emitcode ("lpm", "r0,%s+", rname);
3707 emitcode ("call","__gptrget_pi");
3711 rlen = SPEC_BLEN (etype);
3713 /* if we have bitdisplacement then it fits */
3714 /* into this byte completely or if length is */
3715 /* less than a byte */
3716 if ((shCnt = SPEC_BSTR (etype)) || (SPEC_BLEN (etype) <= 8)) {
3718 /* shift right acc */
3721 emitcode ("andi", "r0,lo(0x%x)",
3722 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
3723 aopPut (AOP (result), "r0", offset++);
3727 /* bit field did not fit in a byte */
3728 aopPut (AOP (result), "r0", offset++);
3738 emitcode ("ld", "r0,%s+");
3742 emitcode ("lpm", "r0,%s+");
3746 emitcode ("call", "__gptrget_pi");
3751 /* if we are done */
3755 aopPut (AOP (result), "r0", offset++);
3760 aopPut (AOP (result), "r0", offset++);
3764 if (offset < rsize) {
3767 aopPut (AOP (result), zero, offset++);
3772 /*-----------------------------------------------------------------*/
3773 /* genDataPointerGet - generates code when ptr offset is known */
3774 /*-----------------------------------------------------------------*/
3776 genDataPointerGet (operand * left, operand * result, iCode * ic)
3780 int size, offset = 0;
3781 aopOp (result, ic, TRUE);
3783 /* get the string representation of the name */
3784 l = aopGet (AOP (left), 0);
3785 size = AOP_SIZE (result);
3788 sprintf (buffer, "(%s + %d)", l + 1, offset);
3790 sprintf (buffer, "%s", l + 1);
3791 emitcode ("lds", "%s,%s", aopGet (AOP (result), offset++),
3795 freeAsmop (left, NULL, ic, TRUE);
3796 freeAsmop (result, NULL, ic, TRUE);
3799 /*-----------------------------------------------------------------*/
3800 /* genNearPointerGet - emitcode for near pointer fetch */
3801 /*-----------------------------------------------------------------*/
3803 genMemPointerGet (operand * left, operand * result, iCode * ic)
3808 char *rname, *frname = NULL;
3809 sym_link *rtype, *retype;
3810 sym_link *ltype = operandType (left);
3812 rtype = operandType (result);
3813 retype = getSpec (rtype);
3815 aopOp (left, ic, FALSE);
3817 /* if left is rematerialisable and
3818 result is not bit variable type and
3819 the left is pointer to data space i.e
3820 lower 128 bytes of space */
3821 if (AOP_TYPE (left) == AOP_IMMD &&
3822 !IS_BITVAR (retype) && DCL_TYPE (ltype) == POINTER) {
3823 genDataPointerGet (left, result, ic);
3827 /* if the value is already in a pointer register
3828 then don't need anything more */
3829 if (!AOP_INPREG (AOP (left))) {
3830 /* otherwise get a free pointer register */
3832 preg = getFreePtr (ic, &aop, FALSE, 0);
3833 if (isRegPair (AOP (left) )) {
3834 emitcode ("movw", "%s,%s",aop->aopu.aop_ptr->name);
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 freeAsmop (left, NULL, ic, TRUE);
3858 aopOp (result, ic, FALSE);
3860 /* if bitfield then unpack the bits */
3861 if (IS_BITVAR (retype))
3862 genUnpackBits (result, rname, POINTER);
3864 /* we have can just get the values */
3865 int size = AOP_SIZE (result);
3870 emitcode ("ld","%s,%s+",aopGet(AOP(result),offset), rname);
3872 emitcode ("ld","%s,%s",aopGet(AOP(result),offset), rname);
3877 /* now some housekeeping stuff */
3879 /* we had to allocate for this iCode */
3880 freeAsmop (NULL, aop, ic, TRUE);
3883 /* we did not allocate which means left
3884 already in a pointer register, then
3885 if size > 0 && this could be used again
3886 we have to point it back to where it
3888 if (AOP_SIZE (result) > 1 &&
3889 !OP_SYMBOL (left)->remat &&
3890 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
3891 int size = AOP_SIZE (result) - 1;
3892 emitcode ("sbiw", "%s,%d",frname,size);
3897 freeAsmop (result, NULL, ic, TRUE);
3901 /*-----------------------------------------------------------------*/
3902 /* genCodePointerGet - gget value from code space */
3903 /*-----------------------------------------------------------------*/
3905 genCodePointerGet (operand * left, operand * result, iCode * ic)
3908 sym_link *retype = getSpec (operandType (result));
3911 aopOp (left, ic, FALSE);
3913 /* if the operand is already in Z register
3914 then we do nothing else we move the value to Z register */
3915 if (AOP_ISZ(AOP(left))) {
3919 getFreePtr(ic,&aop,FALSE,TRUE);
3920 if (isRegPair(AOP (left))) {
3921 emitcode ("movw","r30,%s",aopGet (AOP (left), 0));
3923 emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
3924 emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
3927 aopOp (result, ic, FALSE);
3929 /* if bit then unpack */
3930 if (IS_BITVAR (retype))
3931 genUnpackBits (result, "Z", CPOINTER);
3933 size = AOP_SIZE (result);
3937 emitcode ("clr", "a");
3938 emitcode ("movc", "a,@a+dptr");
3939 aopPut (AOP (result), "a", offset++);
3941 emitcode ("inc", "dptr");
3945 freeAsmop (left, NULL, ic, TRUE);
3946 freeAsmop (result, NULL, ic, TRUE);
3949 /*-----------------------------------------------------------------*/
3950 /* genGenPointerGet - gget value from generic pointer space */
3951 /*-----------------------------------------------------------------*/
3953 genGenPointerGet (operand * left, operand * result, iCode * ic)
3956 sym_link *retype = getSpec (operandType (result));
3958 aopOp (left, ic, FALSE);
3960 /* if the operand is already in dptr
3961 then we do nothing else we move the value to dptr */
3962 if (AOP_TYPE (left) != AOP_STR) {
3963 /* if this is remateriazable */
3964 if (AOP_TYPE (left) == AOP_IMMD) {
3965 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0));
3966 emitcode ("mov", "b,#%d", pointerCode (retype));
3968 else { /* we need to get it byte by byte */
3969 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0));
3970 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1));
3971 if (options.model == MODEL_FLAT24) {
3972 emitcode ("mov", "dpx,%s",
3973 aopGet (AOP (left), 2));
3974 emitcode ("mov", "b,%s",
3975 aopGet (AOP (left), 3));
3978 emitcode ("mov", "b,%s",
3979 aopGet (AOP (left), 2));
3983 /* so dptr know contains the address */
3984 freeAsmop (left, NULL, ic, TRUE);
3985 aopOp (result, ic, FALSE);
3987 /* if bit then unpack */
3988 if (IS_BITVAR (retype))
3989 genUnpackBits (result, "dptr", GPOINTER);
3991 size = AOP_SIZE (result);
3995 emitcode ("lcall", "__gptrget");
3996 aopPut (AOP (result), "a", offset++);
3998 emitcode ("inc", "dptr");
4002 freeAsmop (result, NULL, ic, TRUE);
4005 /*-----------------------------------------------------------------*/
4006 /* genPointerGet - generate code for pointer get */
4007 /*-----------------------------------------------------------------*/
4009 genPointerGet (iCode * ic)
4011 operand *left, *result;
4012 sym_link *type, *etype;
4015 left = IC_LEFT (ic);
4016 result = IC_RESULT (ic);
4018 /* depending on the type of pointer we need to
4019 move it to the correct pointer register */
4020 type = operandType (left);
4021 etype = getSpec (type);
4022 /* if left is of type of pointer then it is simple */
4023 if (IS_PTR (type) && !IS_FUNC (type->next))
4024 p_type = DCL_TYPE (type);
4026 /* we have to go by the storage class */
4027 p_type = PTR_TYPE (SPEC_OCLS (etype));
4032 /* now that we have the pointer type we assign
4033 the pointer values */
4040 genMemPointerGet (left, result, ic);
4044 genCodePointerGet (left, result, ic);
4048 genGenPointerGet (left, result, ic);
4054 /*-----------------------------------------------------------------*/
4055 /* genPackBits - generates code for packed bit storage */
4056 /*-----------------------------------------------------------------*/
4058 genPackBits (sym_link * etype, operand * right, char *rname, int p_type)
4066 blen = SPEC_BLEN (etype);
4067 bstr = SPEC_BSTR (etype);
4069 l = aopGet (AOP (right), offset++);
4072 /* if the bit lenth is less than or */
4073 /* it exactly fits a byte then */
4074 if (SPEC_BLEN (etype) <= 8) {
4075 shCount = SPEC_BSTR (etype);
4077 /* shift left acc */
4080 if (SPEC_BLEN (etype) < 8) { /* if smaller than a byte */
4085 emitcode ("mov", "b,a");
4086 emitcode ("mov", "a,@%s", rname);
4090 emitcode ("mov", "b,a");
4091 emitcode ("movx", "a,@dptr");
4095 emitcode ("push", "b");
4096 emitcode ("push", "acc");
4097 emitcode ("lcall", "__gptrget");
4098 emitcode ("pop", "b");
4102 emitcode ("anl", "a,#0x%02x", (unsigned char)
4103 ((unsigned char) (0xFF << (blen + bstr)) |
4104 (unsigned char) (0xFF >> (8 - bstr))));
4105 emitcode ("orl", "a,b");
4106 if (p_type == GPOINTER)
4107 emitcode ("pop", "b");
4113 emitcode ("mov", "@%s,a", rname);
4117 emitcode ("movx", "@dptr,a");
4121 emitcode ("lcall", "__gptrput");
4126 if (SPEC_BLEN (etype) <= 8)
4129 emitcode ("inc", "%s", rname);
4130 rLen = SPEC_BLEN (etype);
4132 /* now generate for lengths greater than one byte */
4135 l = aopGet (AOP (right), offset++);
4145 emitcode ("mov", "@%s,a", rname);
4148 emitcode ("mov", "@%s,%s", rname, l);
4153 emitcode ("movx", "@dptr,a");
4158 emitcode ("lcall", "__gptrput");
4161 emitcode ("inc", "%s", rname);
4166 /* last last was not complete */
4168 /* save the byte & read byte */
4171 emitcode ("mov", "b,a");
4172 emitcode ("mov", "a,@%s", rname);
4176 emitcode ("mov", "b,a");
4177 emitcode ("movx", "a,@dptr");
4181 emitcode ("push", "b");
4182 emitcode ("push", "acc");
4183 emitcode ("lcall", "__gptrget");
4184 emitcode ("pop", "b");
4188 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << -rLen));
4189 emitcode ("orl", "a,b");
4192 if (p_type == GPOINTER)
4193 emitcode ("pop", "b");
4198 emitcode ("mov", "@%s,a", rname);
4202 emitcode ("movx", "@dptr,a");
4206 emitcode ("lcall", "__gptrput");
4211 /*-----------------------------------------------------------------*/
4212 /* genDataPointerSet - remat pointer to data space */
4213 /*-----------------------------------------------------------------*/
4215 genDataPointerSet (operand * right, operand * result, iCode * ic)
4217 int size, offset = 0;
4218 char *l, buffer[256];
4220 aopOp (right, ic, FALSE);
4222 l = aopGet (AOP (result), 0);
4223 size = AOP_SIZE (right);
4226 sprintf (buffer, "(%s + %d)", l + 1, offset);
4228 sprintf (buffer, "%s", l + 1);
4229 emitcode ("mov", "%s,%s", buffer,
4230 aopGet (AOP (right), offset++));
4233 freeAsmop (right, NULL, ic, TRUE);
4234 freeAsmop (result, NULL, ic, TRUE);
4237 /*-----------------------------------------------------------------*/
4238 /* genNearPointerSet - emitcode for near pointer put */
4239 /*-----------------------------------------------------------------*/
4241 genNearPointerSet (operand * right, operand * result, iCode * ic)
4247 sym_link *ptype = operandType (result);
4249 retype = getSpec (operandType (right));
4251 aopOp (result, ic, FALSE);
4253 /* if the result is rematerializable &
4254 in data space & not a bit variable */
4255 if (AOP_TYPE (result) == AOP_IMMD &&
4256 DCL_TYPE (ptype) == POINTER && !IS_BITVAR (retype)) {
4257 genDataPointerSet (right, result, ic);
4261 /* if the value is already in a pointer register
4262 then don't need anything more */
4263 if (!AOP_INPREG (AOP (result))) {
4264 /* otherwise get a free pointer register */
4266 preg = getFreePtr (ic, &aop, FALSE, 0);
4267 emitcode ("mov", "%s,%s",
4268 preg->name, aopGet (AOP (result), 0));
4272 rname = aopGet (AOP (result), 0);
4274 freeAsmop (result, NULL, ic, TRUE);
4275 aopOp (right, ic, FALSE);
4277 /* if bitfield then unpack the bits */
4278 if (IS_BITVAR (retype))
4279 genPackBits (retype, right, rname, POINTER);
4281 /* we have can just get the values */
4282 int size = AOP_SIZE (right);
4286 l = aopGet (AOP (right), offset);
4289 emitcode ("mov", "@%s,a", rname);
4292 emitcode ("mov", "@%s,%s", rname, l);
4294 emitcode ("inc", "%s", rname);
4299 /* now some housekeeping stuff */
4301 /* we had to allocate for this iCode */
4302 freeAsmop (NULL, aop, ic, TRUE);
4305 /* we did not allocate which means left
4306 already in a pointer register, then
4307 if size > 0 && this could be used again
4308 we have to point it back to where it
4310 if (AOP_SIZE (right) > 1 &&
4311 !OP_SYMBOL (result)->remat &&
4312 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
4313 int size = AOP_SIZE (right) - 1;
4315 emitcode ("dec", "%s", rname);
4320 freeAsmop (right, NULL, ic, TRUE);
4325 /*-----------------------------------------------------------------*/
4326 /* genPagedPointerSet - emitcode for Paged pointer put */
4327 /*-----------------------------------------------------------------*/
4329 genPagedPointerSet (operand * right, operand * result, iCode * ic)
4336 retype = getSpec (operandType (right));
4338 aopOp (result, ic, FALSE);
4340 /* if the value is already in a pointer register
4341 then don't need anything more */
4342 if (!AOP_INPREG (AOP (result))) {
4343 /* otherwise get a free pointer register */
4345 preg = getFreePtr (ic, &aop, FALSE, 0);
4346 emitcode ("mov", "%s,%s",
4347 preg->name, aopGet (AOP (result), 0));
4351 rname = aopGet (AOP (result), 0);
4353 freeAsmop (result, NULL, ic, TRUE);
4354 aopOp (right, ic, FALSE);
4356 /* if bitfield then unpack the bits */
4357 if (IS_BITVAR (retype))
4358 genPackBits (retype, right, rname, PPOINTER);
4360 /* we have can just get the values */
4361 int size = AOP_SIZE (right);
4365 l = aopGet (AOP (right), offset);
4368 emitcode ("movx", "@%s,a", rname);
4371 emitcode ("inc", "%s", rname);
4377 /* now some housekeeping stuff */
4379 /* we had to allocate for this iCode */
4380 freeAsmop (NULL, aop, ic, TRUE);
4383 /* we did not allocate which means left
4384 already in a pointer register, then
4385 if size > 0 && this could be used again
4386 we have to point it back to where it
4388 if (AOP_SIZE (right) > 1 &&
4389 !OP_SYMBOL (result)->remat &&
4390 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
4391 int size = AOP_SIZE (right) - 1;
4393 emitcode ("dec", "%s", rname);
4398 freeAsmop (right, NULL, ic, TRUE);
4403 /*-----------------------------------------------------------------*/
4404 /* genFarPointerSet - set value from far space */
4405 /*-----------------------------------------------------------------*/
4407 genFarPointerSet (operand * right, operand * result, iCode * ic)
4410 sym_link *retype = getSpec (operandType (right));
4412 aopOp (result, ic, FALSE);
4414 /* if the operand is already in dptr
4415 then we do nothing else we move the value to dptr */
4416 if (AOP_TYPE (result) != AOP_STR) {
4417 /* if this is remateriazable */
4418 if (AOP_TYPE (result) == AOP_IMMD)
4419 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0));
4420 else { /* we need to get it byte by byte */
4421 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0));
4422 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1));
4423 if (options.model == MODEL_FLAT24) {
4424 emitcode ("mov", "dpx,%s",
4425 aopGet (AOP (result), 2));
4429 /* so dptr know contains the address */
4430 freeAsmop (result, NULL, ic, TRUE);
4431 aopOp (right, ic, FALSE);
4433 /* if bit then unpack */
4434 if (IS_BITVAR (retype))
4435 genPackBits (retype, right, "dptr", FPOINTER);
4437 size = AOP_SIZE (right);
4441 char *l = aopGet (AOP (right), offset++);
4443 emitcode ("movx", "@dptr,a");
4445 emitcode ("inc", "dptr");
4449 freeAsmop (right, NULL, ic, TRUE);
4452 /*-----------------------------------------------------------------*/
4453 /* genGenPointerSet - set value from generic pointer space */
4454 /*-----------------------------------------------------------------*/
4456 genGenPointerSet (operand * right, operand * result, iCode * ic)
4459 sym_link *retype = getSpec (operandType (right));
4461 aopOp (result, ic, FALSE);
4463 /* if the operand is already in dptr
4464 then we do nothing else we move the value to dptr */
4465 if (AOP_TYPE (result) != AOP_STR) {
4466 /* if this is remateriazable */
4467 if (AOP_TYPE (result) == AOP_IMMD) {
4468 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0));
4469 emitcode ("mov", "b,%s + 1",
4470 aopGet (AOP (result), 0));
4472 else { /* we need to get it byte by byte */
4473 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0));
4474 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1));
4475 if (options.model == MODEL_FLAT24) {
4476 emitcode ("mov", "dpx,%s",
4477 aopGet (AOP (result), 2));
4478 emitcode ("mov", "b,%s",
4479 aopGet (AOP (result), 3));
4482 emitcode ("mov", "b,%s",
4483 aopGet (AOP (result), 2));
4487 /* so dptr know contains the address */
4488 freeAsmop (result, NULL, ic, TRUE);
4489 aopOp (right, ic, FALSE);
4491 /* if bit then unpack */
4492 if (IS_BITVAR (retype))
4493 genPackBits (retype, right, "dptr", GPOINTER);
4495 size = AOP_SIZE (right);
4499 char *l = aopGet (AOP (right), offset++);
4501 emitcode ("lcall", "__gptrput");
4503 emitcode ("inc", "dptr");
4507 freeAsmop (right, NULL, ic, TRUE);
4510 /*-----------------------------------------------------------------*/
4511 /* genPointerSet - stores the value into a pointer location */
4512 /*-----------------------------------------------------------------*/
4514 genPointerSet (iCode * ic)
4516 operand *right, *result;
4517 sym_link *type, *etype;
4520 right = IC_RIGHT (ic);
4521 result = IC_RESULT (ic);
4523 /* depending on the type of pointer we need to
4524 move it to the correct pointer register */
4525 type = operandType (result);
4526 etype = getSpec (type);
4527 /* if left is of type of pointer then it is simple */
4528 if (IS_PTR (type) && !IS_FUNC (type->next)) {
4529 p_type = DCL_TYPE (type);
4532 /* we have to go by the storage class */
4533 p_type = PTR_TYPE (SPEC_OCLS (etype));
4535 /* if (SPEC_OCLS(etype)->codesp ) { */
4536 /* p_type = CPOINTER ; */
4539 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
4540 /* p_type = FPOINTER ; */
4542 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
4543 /* p_type = PPOINTER ; */
4545 /* if (SPEC_OCLS(etype) == idata ) */
4546 /* p_type = IPOINTER ; */
4548 /* p_type = POINTER ; */
4551 /* now that we have the pointer type we assign
4552 the pointer values */
4557 genNearPointerSet (right, result, ic);
4561 genPagedPointerSet (right, result, ic);
4565 genFarPointerSet (right, result, ic);
4569 genGenPointerSet (right, result, ic);
4575 /*-----------------------------------------------------------------*/
4576 /* genIfx - generate code for Ifx statement */
4577 /*-----------------------------------------------------------------*/
4579 genIfx (iCode * ic, iCode * popIc)
4581 operand *cond = IC_COND (ic);
4584 aopOp (cond, ic, FALSE);
4586 /* get the value into acc */
4587 if (AOP_TYPE (cond) != AOP_CRY)
4588 toBoolean (cond, "", 0);
4591 /* the result is now in the accumulator */
4592 freeAsmop (cond, NULL, ic, TRUE);
4594 /* if there was something to be popped then do it */
4598 /* if the condition is a bit variable */
4599 /* if (isbit && IS_ITEMP(cond) && SPIL_LOC(cond)) { */
4600 /* // genIfxJump(ic,SPIL_LOC(cond)->rname); */
4603 /* if (isbit && !IS_ITEMP(cond)) */
4604 /* // genIfxJump(ic,OP_SYMBOL(cond)->rname); */
4606 /* // genIfxJump(ic,"a"); */
4611 /*-----------------------------------------------------------------*/
4612 /* genAddrOf - generates code for address of */
4613 /*-----------------------------------------------------------------*/
4615 genAddrOf (iCode * ic)
4617 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
4620 aopOp (IC_RESULT (ic), ic, FALSE);
4622 /* if the operand is on the stack then we
4623 need to get the stack offset of this
4626 /* if it has an offset then we need to compute
4629 emitcode ("mov", "a,_bp");
4630 emitcode ("add", "a,#0x%02x",
4631 ((char) sym->stack & 0xff));
4632 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4635 /* we can just move _bp */
4636 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
4638 /* fill the result with zero */
4639 size = AOP_SIZE (IC_RESULT (ic)) - 1;
4642 if (options.stack10bit && size < (FPTRSIZE - 1)) {
4644 "*** warning: pointer to stack var truncated.\n");
4650 if (options.stack10bit && offset == 2) {
4651 aopPut (AOP (IC_RESULT (ic)), "#0x40",
4655 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
4662 /* object not on stack then we need the name */
4663 size = AOP_SIZE (IC_RESULT (ic));
4667 char s[SDCC_NAME_MAX];
4669 sprintf (s, "#(%s >> %d)", sym->rname, offset * 8);
4671 sprintf (s, "#%s", sym->rname);
4672 aopPut (AOP (IC_RESULT (ic)), s, offset++);
4676 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4680 /*-----------------------------------------------------------------*/
4681 /* genFarFarAssign - assignment when both are in far space */
4682 /*-----------------------------------------------------------------*/
4684 genFarFarAssign (operand * result, operand * right, iCode * ic)
4686 int size = AOP_SIZE (right);
4689 /* first push the right side on to the stack */
4691 l = aopGet (AOP (right), offset++);
4693 emitcode ("push", "acc");
4696 freeAsmop (right, NULL, ic, FALSE);
4697 /* now assign DPTR to result */
4698 aopOp (result, ic, FALSE);
4699 size = AOP_SIZE (result);
4701 emitcode ("pop", "acc");
4702 aopPut (AOP (result), "a", --offset);
4704 freeAsmop (result, NULL, ic, FALSE);
4708 /*-----------------------------------------------------------------*/
4709 /* genAssign - generate code for assignment */
4710 /*-----------------------------------------------------------------*/
4712 genAssign (iCode * ic)
4714 operand *result, *right;
4716 unsigned long lit = 0L;
4718 result = IC_RESULT (ic);
4719 right = IC_RIGHT (ic);
4721 /* if they are the same */
4722 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4725 aopOp (right, ic, FALSE);
4727 /* special case both in far space */
4728 if (AOP_TYPE (right) == AOP_DPTR &&
4729 IS_TRUE_SYMOP (result) && isOperandInFarSpace (result)) {
4731 genFarFarAssign (result, right, ic);
4735 aopOp (result, ic, TRUE);
4737 /* if they are the same registers */
4738 if (sameRegs (AOP (right), AOP (result)))
4741 /* if the result is a bit */
4742 if (AOP_TYPE (result) == AOP_CRY) {
4744 /* if the right size is a literal then
4745 we know what the value is */
4746 if (AOP_TYPE (right) == AOP_LIT) {
4747 if (((int) operandLitValue (right)))
4748 aopPut (AOP (result), one, 0);
4750 aopPut (AOP (result), zero, 0);
4754 /* the right is also a bit variable */
4755 if (AOP_TYPE (right) == AOP_CRY) {
4756 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4757 aopPut (AOP (result), "c", 0);
4762 toBoolean (right, "", 0);
4763 aopPut (AOP (result), "a", 0);
4767 /* bit variables done */
4769 size = AOP_SIZE (result);
4771 if (AOP_TYPE (right) == AOP_LIT)
4773 (unsigned long) floatFromVal (AOP (right)->aopu.
4775 if ((size > 1) && (AOP_TYPE (result) != AOP_REG)
4776 && (AOP_TYPE (right) == AOP_LIT)
4777 && !IS_FLOAT (operandType (right)) && (lit < 256L)) {
4778 emitcode ("clr", "a");
4780 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) ==
4781 0) aopPut (AOP (result), "a", size);
4783 aopPut (AOP (result),
4784 aopGet (AOP (right), size), size);
4789 aopPut (AOP (result),
4790 aopGet (AOP (right), offset), offset);
4796 freeAsmop (right, NULL, ic, FALSE);
4797 freeAsmop (result, NULL, ic, TRUE);
4800 /*-----------------------------------------------------------------*/
4801 /* genJumpTab - genrates code for jump table */
4802 /*-----------------------------------------------------------------*/
4804 genJumpTab (iCode * ic)
4809 aopOp (IC_JTCOND (ic), ic, FALSE);
4810 /* get the condition into accumulator */
4811 l = aopGet (AOP (IC_JTCOND (ic)), 0);
4813 /* multiply by three */
4814 emitcode ("add", "a,acc");
4815 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0));
4816 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
4818 jtab = newiTempLabel (NULL);
4819 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
4820 emitcode ("jmp", "@a+dptr");
4821 emitcode ("", "%05d$:", jtab->key + 100);
4822 /* now generate the jump labels */
4823 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
4824 jtab = setNextItem (IC_JTLABELS (ic)))
4825 emitcode ("ljmp", "%05d$", jtab->key + 100);
4829 /*-----------------------------------------------------------------*/
4830 /* genCast - gen code for casting */
4831 /*-----------------------------------------------------------------*/
4833 genCast (iCode * ic)
4835 operand *result = IC_RESULT (ic);
4836 sym_link *ctype = operandType (IC_LEFT (ic));
4837 sym_link *rtype = operandType (IC_RIGHT (ic));
4838 operand *right = IC_RIGHT (ic);
4841 /* if they are equivalent then do nothing */
4842 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4845 aopOp (right, ic, FALSE);
4846 aopOp (result, ic, FALSE);
4848 /* if the result is a bit */
4849 if (AOP_TYPE (result) == AOP_CRY) {
4850 /* if the right size is a literal then
4851 we know what the value is */
4852 if (AOP_TYPE (right) == AOP_LIT) {
4853 if (((int) operandLitValue (right)))
4854 aopPut (AOP (result), one, 0);
4856 aopPut (AOP (result), zero, 0);
4861 /* the right is also a bit variable */
4862 if (AOP_TYPE (right) == AOP_CRY) {
4863 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4864 aopPut (AOP (result), "c", 0);
4869 toBoolean (right, "", 0);
4870 aopPut (AOP (result), "a", 0);
4874 /* if they are the same size : or less */
4875 if (AOP_SIZE (result) <= AOP_SIZE (right)) {
4877 /* if they are in the same place */
4878 if (sameRegs (AOP (right), AOP (result)))
4881 /* if they in different places then copy */
4882 size = AOP_SIZE (result);
4885 aopPut (AOP (result),
4886 aopGet (AOP (right), offset), offset);
4893 /* if the result is of type pointer */
4894 if (IS_PTR (ctype)) {
4897 sym_link *type = operandType (right);
4898 sym_link *etype = getSpec (type);
4900 /* pointer to generic pointer */
4901 if (IS_GENPTR (ctype)) {
4905 p_type = DCL_TYPE (type);
4907 /* we have to go by the storage class */
4908 p_type = PTR_TYPE (SPEC_OCLS (etype));
4911 /* the first two bytes are known */
4912 size = GPTRSIZE - 1;
4915 aopPut (AOP (result),
4916 aopGet (AOP (right), offset), offset);
4919 /* the last byte depending on type */
4936 /* this should never happen */
4937 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4938 "got unknown pointer type");
4941 aopPut (AOP (result), l, GPTRSIZE - 1);
4945 /* just copy the pointers */
4946 size = AOP_SIZE (result);
4949 aopPut (AOP (result),
4950 aopGet (AOP (right), offset), offset);
4956 /* so we now know that the size of destination is greater
4957 than the size of the source */
4958 /* we move to result for the size of source */
4959 size = AOP_SIZE (right);
4962 aopPut (AOP (result), aopGet (AOP (right), offset), offset);
4966 /* now depending on the sign of the source && destination */
4967 size = AOP_SIZE (result) - AOP_SIZE (right);
4968 /* if unsigned or not an integral type */
4969 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype)) {
4971 aopPut (AOP (result), zero, offset++);
4974 /* we need to extend the sign :{ */
4975 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1);
4977 emitcode ("rlc", "a");
4978 emitcode ("subb", "a,acc");
4980 aopPut (AOP (result), "a", offset++);
4983 /* we are done hurray !!!! */
4986 freeAsmop (right, NULL, ic, TRUE);
4987 freeAsmop (result, NULL, ic, TRUE);
4991 /*-----------------------------------------------------------------*/
4992 /* genDjnz - generate decrement & jump if not zero instrucion */
4993 /*-----------------------------------------------------------------*/
4995 genDjnz (iCode * ic, iCode * ifx)
5001 /* if the if condition has a false label
5002 then we cannot save */
5006 /* if the minus is not of the form
5008 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
5009 !IS_OP_LITERAL (IC_RIGHT (ic)))
5012 if (operandLitValue (IC_RIGHT (ic)) != 1)
5015 /* if the size of this greater than one then no
5017 if (getSize (operandType (IC_RESULT (ic))) > 1)
5020 /* otherwise we can save BIG */
5021 lbl = newiTempLabel (NULL);
5022 lbl1 = newiTempLabel (NULL);
5024 aopOp (IC_RESULT (ic), ic, FALSE);
5026 if (IS_AOP_PREG (IC_RESULT (ic))) {
5027 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0));
5028 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0));
5029 emitcode ("jnz", "%05d$", lbl->key + 100);
5032 emitcode ("djnz", "%s,%05d$",
5033 aopGet (AOP (IC_RESULT (ic)), 0), lbl->key + 100);
5035 emitcode ("sjmp", "%05d$", lbl1->key + 100);
5036 emitcode ("", "%05d$:", lbl->key + 100);
5037 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5038 emitcode ("", "%05d$:", lbl1->key + 100);
5040 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5045 static char *recvregs[8] = {
5046 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23"
5050 /*-----------------------------------------------------------------*/
5051 /* genReceive - generate code for a receive iCode */
5052 /*-----------------------------------------------------------------*/
5054 genReceive (iCode * ic)
5056 int size, offset = 0;
5057 aopOp (IC_RESULT (ic), ic, FALSE);
5058 size = AOP_SIZE (IC_RESULT (ic));
5060 aopPut (AOP (IC_RESULT (ic)), recvregs[recvCnt++], offset);
5063 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5066 /*-----------------------------------------------------------------*/
5067 /* gen51Code - generate code for 8051 based controllers */
5068 /*-----------------------------------------------------------------*/
5070 genAVRCode (iCode * lic)
5075 lineHead = lineCurr = NULL;
5077 /* print the allocation information */
5079 printAllocInfo (currFunc, codeOutFile);
5080 /* if debug information required */
5081 /* if (options.debug && currFunc) { */
5083 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
5085 emitcode ("", ".type %s,@function", currFunc->name);
5088 /* stack pointer name */
5092 for (ic = lic; ic; ic = ic->next) {
5094 if (cln != ic->lineno) {
5095 if (options.debug) {
5097 emitcode ("", "C$%s$%d$%d$%d ==.",
5098 FileBaseName (ic->filename),
5099 ic->lineno, ic->level, ic->block);
5102 emitcode (";", "%s %d", ic->filename, ic->lineno);
5105 /* if the result is marked as
5106 spilt and rematerializable or code for
5107 this has already been generated then
5109 if (resultRemat (ic) || ic->generated)
5112 /* depending on the operation */
5131 /* IPOP happens only when trying to restore a
5132 spilt live range, if there is an ifx statement
5133 following this pop then the if statement might
5134 be using some of the registers being popped which
5135 would destory the contents of the register so
5136 we need to check for this condition and handle it */
5138 ic->next->op == IFX &&
5139 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
5140 genIfx (ic->next, ic);
5158 genEndFunction (ic);
5178 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
5195 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
5199 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
5203 genCmpLe (ic, ifxForOp (IC_RESULT (ic), ic));
5207 genCmpGe (ic, ifxForOp (IC_RESULT (ic), ic));
5211 genCmpNe (ic, ifxForOp (IC_RESULT (ic), ic));
5215 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
5227 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
5231 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
5235 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
5262 case GET_VALUE_AT_ADDRESS:
5267 if (POINTER_SET (ic))
5294 addSet (&_G.sendSet, ic);
5299 /* piCode(ic,stdout); */
5305 /* now we are ready to call the
5306 peep hole optimizer */
5307 if (!options.nopeep)
5308 peepHole (&lineHead);
5310 /* now do the actual printing */
5311 printLine (lineHead, codeOutFile);