1 /*-------------------------------------------------------------------------
2 gen.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"
35 #include "SDCCpeeph.h"
39 char *aopLiteral (value * val, int offset);
42 /* this is the down and dirty file with all kinds of
43 kludgy & hacky stuff. This is what it is all about
44 CODE GENERATION for a specific MCU . some of the
45 routines may be reusable, will have to see */
47 static char *zero = "0x00";
48 static char *one = "0x01";
51 char *fReturnAVR[] = { "r16", "r17", "r18", "r19" };
52 unsigned fAVRReturnSize = 4; /* shared with ralloc.c */
53 char **fAVRReturn = fReturnAVR;
54 static char *larray[4] = { ">", "<", "hlo8", "hhi8" };
66 extern int avr_ptrRegReq;
68 extern FILE *codeOutFile;
69 #define RESULTONSTACK(x) \
70 (IC_RESULT(x) && IC_RESULT(x)->aop && \
71 IC_RESULT(x)->aop->type == AOP_STK )
73 #define MOVR0(x) if (strcmp(x,"r0")) emitcode("mov","r0,%s",x);
74 #define MOVR24(x) if (strcmp(x,"r24")) emitcode("mov","r24,%s",x);
75 #define AOP_ISHIGHREG(a,n) (a->type == AOP_REG && a->aopu.aop_reg[n] && a->aopu.aop_reg[n]->rIdx >= R16_IDX)
76 #define CLRC emitcode("clc","")
77 #define SETC emitcode("stc","")
79 #define IS_REGIDX(a,r) (a->type == AOP_REG && a->aopu.aop_reg[0]->rIdx == r)
81 static lineNode *lineHead = NULL;
82 static lineNode *lineCurr = NULL;
91 /*-----------------------------------------------------------------*/
92 /* reAdjustPreg - points a register back to where it should */
93 /*-----------------------------------------------------------------*/
95 reAdjustPreg (asmop * aop)
100 if ((size = aop->size) <= 1)
106 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name, size);
112 /*-----------------------------------------------------------------*/
113 /* outBitC - output a bit C */
114 /*-----------------------------------------------------------------*/
116 outBitC (operand * result)
118 emitcode ("clr", "r0");
119 emitcode ("rol", "r0");
123 /*-----------------------------------------------------------------*/
124 /* inExcludeList - return 1 if the string is in exclude Reg list */
125 /*-----------------------------------------------------------------*/
127 inExcludeList (char *s)
131 if (options.excludeRegs[i] &&
132 STRCASECMP (options.excludeRegs[i], "none") == 0)
135 for (i = 0; options.excludeRegs[i]; i++) {
136 if (options.excludeRegs[i] &&
137 STRCASECMP (s, options.excludeRegs[i]) == 0)
143 /*-----------------------------------------------------------------*/
144 /* findLabelBackwards: walks back through the iCode chain looking */
145 /* for the given label. Returns number of iCode instructions */
146 /* between that label and given ic. */
147 /* Returns zero if label not found. */
148 /*-----------------------------------------------------------------*/
150 findLabelBackwards (iCode * ic, int key)
158 if (ic->op == LABEL && IC_LABEL (ic)->key == key) {
159 /* printf("findLabelBackwards = %d\n", count); */
167 /*-----------------------------------------------------------------*/
168 /* addSign - complete with sign */
169 /*-----------------------------------------------------------------*/
171 addSign (operand * result, int offset, int sign)
173 int size = (getDataSize (result) - offset);
176 emitcode ("rlc", "a");
177 emitcode ("subb", "a,acc");
179 aopPut (AOP (result), "a", offset++);
183 aopPut (AOP (result), zero, offset++);
187 /*-----------------------------------------------------------------*/
188 /* isLiteralBit - test if lit == 2^n */
189 /*-----------------------------------------------------------------*/
191 isLiteralBit (unsigned long lit)
193 unsigned long pw[32] = { 1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
194 0x100L, 0x200L, 0x400L, 0x800L,
195 0x1000L, 0x2000L, 0x4000L, 0x8000L,
196 0x10000L, 0x20000L, 0x40000L, 0x80000L,
197 0x100000L, 0x200000L, 0x400000L, 0x800000L,
198 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
199 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L
203 for (idx = 0; idx < 32; idx++)
209 /*-----------------------------------------------------------------*/
210 /* outAcc - output Acc */
211 /*-----------------------------------------------------------------*/
213 outAcc (operand * result)
216 size = getDataSize (result);
218 aopPut (AOP (result), "r0", 0);
221 /* unsigned or positive */
223 aopPut (AOP (result), zero, offset++);
228 #endif // End Unused code section
230 /*-----------------------------------------------------------------*/
231 /* emitcode - writes the code into a file : for now it is simple */
232 /*-----------------------------------------------------------------*/
234 emitcode (char *inst, char *fmt, ...)
237 char lb[INITIAL_INLINEASM];
244 sprintf (lb, "%s\t", inst);
246 sprintf (lb, "%s", inst);
247 vsprintf (lb + (strlen (lb)), fmt, ap);
250 vsprintf (lb, fmt, ap);
252 while (isspace (*lbp))
256 lineCurr = (lineCurr ?
257 connectLine (lineCurr, newLineNode (lb)) :
258 (lineHead = newLineNode (lb)));
259 lineCurr->isInline = _G.inLine;
260 lineCurr->isDebug = _G.debugLine;
264 /*-----------------------------------------------------------------*/
265 /* avr_emitDebuggerSymbol - associate the current code location */
266 /* with a debugger symbol */
267 /*-----------------------------------------------------------------*/
269 avr_emitDebuggerSymbol (char * debugSym)
272 emitcode ("", "%s ==.", debugSym);
276 /*-----------------------------------------------------------------*/
277 /* hasInc - operand is incremented before any other use */
278 /*-----------------------------------------------------------------*/
280 hasInc (operand *op, iCode *ic)
282 sym_link *type = operandType(op);
283 sym_link *retype = getSpec (type);
284 iCode *lic = ic->next;
287 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
288 if (IS_AGGREGATE(type->next)) return NULL;
289 isize = getSize(type->next);
291 /* if operand of the form op = op + <sizeof *op> */
292 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
293 isOperandEqual(IC_RESULT(lic),op) &&
294 isOperandLiteral(IC_RIGHT(lic)) &&
295 operandLitValue(IC_RIGHT(lic)) == isize) {
298 /* if the operand used or deffed */
299 if (bitVectBitValue(OP_USES(op),lic->key) || (lic->defKey == op->key)) {
307 /*-----------------------------------------------------------------*/
308 /* getFreePtr - returns X or Z whichever is free or can be pushed */
309 /*-----------------------------------------------------------------*/
311 getFreePtr (iCode * ic, asmop ** aopp, bool result, bool zonly)
313 bool xiu = FALSE, ziu = FALSE;
314 bool xou = FALSE, zou = FALSE;
316 /* the logic: if x & z used in the instruction
317 then we are in trouble otherwise */
319 /* first check if x & z are used by this
320 instruction, in which case we are in trouble */
321 if ((xiu = bitVectBitValue (ic->rUsed, X_IDX)) &&
322 (ziu = bitVectBitValue (ic->rUsed, Z_IDX))) {
326 xou = bitVectBitValue (ic->rMask, X_IDX);
327 zou = bitVectBitValue (ic->rMask, Z_IDX);
329 /* if no usage of Z then return it */
331 ic->rUsed = bitVectSetBit (ic->rUsed, Z_IDX);
332 (*aopp)->type = AOP_Z;
334 (*aopp)->aop_ptr2 = avr_regWithIdx (R31_IDX);
335 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R30_IDX);
338 /* if no usage of X then return it */
339 if (!xiu && !xou && !zonly) {
340 ic->rUsed = bitVectSetBit (ic->rUsed, X_IDX);
341 (*aopp)->type = AOP_X;
343 (*aopp)->aop_ptr2 = avr_regWithIdx (R27_IDX);
344 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R26_IDX);
347 /* if z not used then */
350 /* push it if not already pushed */
352 emitcode ("push", "%s",
353 avr_regWithIdx (R30_IDX)->dname);
354 emitcode ("push", "%s",
355 avr_regWithIdx (R31_IDX)->dname);
359 ic->rUsed = bitVectSetBit (ic->rUsed, Z_IDX);
360 (*aopp)->type = AOP_Z;
361 (*aopp)->aop_ptr2 = avr_regWithIdx (R31_IDX);
362 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R30_IDX);
365 /* now we know they both have usage */
366 /* if x not used in this instruction */
367 if (!xiu && !zonly) {
368 /* push it if not already pushed */
370 emitcode ("push", "%s",
371 avr_regWithIdx (R26_IDX)->dname);
372 emitcode ("push", "%s",
373 avr_regWithIdx (R27_IDX)->dname);
377 ic->rUsed = bitVectSetBit (ic->rUsed, X_IDX);
378 (*aopp)->type = AOP_X;
380 (*aopp)->aop_ptr2 = avr_regWithIdx (R27_IDX);
381 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R26_IDX);
386 /* I said end of world but not quite end of world yet */
387 /* if this is a result then we can push it on the stack */
389 (*aopp)->type = AOP_STK;
393 /* other wise this is true end of the world */
394 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
395 "getFreePtr should never reach here");
399 /*-----------------------------------------------------------------*/
400 /* newAsmop - creates a new asmOp */
401 /*-----------------------------------------------------------------*/
403 newAsmop (short type)
407 aop = Safe_calloc (1, sizeof (asmop));
412 /*-----------------------------------------------------------------*/
413 /* pointerCode - returns the code for a pointer type */
414 /*-----------------------------------------------------------------*/
416 pointerCode (sym_link * etype)
419 return PTR_TYPE (SPEC_OCLS (etype));
423 /*-----------------------------------------------------------------*/
424 /* aopForSym - for a true symbol */
425 /*-----------------------------------------------------------------*/
427 aopForSym (iCode * ic, symbol * sym, bool result)
430 memmap *space = SPEC_OCLS (sym->etype);
432 /* if already has one */
436 /* assign depending on the storage class */
437 /* if it is on the stack */
439 sym->aop = aop = newAsmop (0);
440 aop->size = getSize (sym->type);
442 /* we can use std / ldd instruction */
444 && (sym->stack + getSize (sym->type) - 1) <= 63) {
445 aop->type = AOP_STK_D;
446 aop->aopu.aop_stk = sym->stack;
450 /* otherwise get a free pointer register X/Z */
451 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result, FALSE);
453 /* now assign the address of the variable to
454 the pointer register */
455 if (aop->type != AOP_STK) {
456 emitcode ("movw", "%s,r28", aop->aopu.aop_ptr->name);
457 if (sym->stack < 0) {
458 if ((sym->stack - _G.nRegsSaved) > -63) {
459 emitcode ("sbiw", "%s,0x%02x",
460 aop->aopu.aop_ptr->name,
465 emitcode ("subi", "%s,<(%d)",
466 aop->aopu.aop_ptr->name,
467 sym->stack - _G.nRegsSaved);
468 emitcode ("sbci", "%s,>(%d)",
470 sym->stack - _G.nRegsSaved);
474 if (sym->stack <= 63) {
475 emitcode ("adiw", "%s,0x%02x",
476 aop->aopu.aop_ptr->name,
480 emitcode ("subi", "%s,<(-%d)",
481 aop->aopu.aop_ptr->name,
483 emitcode ("sbci", "%s,>(-%d)",
492 /* if in bit space */
493 if (IN_BITSPACE (space)) {
494 sym->aop = aop = newAsmop (AOP_CRY);
495 aop->aopu.aop_dir = sym->rname;
496 aop->size = getSize (sym->type);
499 /* if it is in direct space */
500 if (IN_DIRSPACE (space)) {
501 sym->aop = aop = newAsmop (AOP_DIR);
502 aop->aopu.aop_dir = sym->rname;
503 aop->size = getSize (sym->type);
507 /* special case for a function */
508 if (IS_FUNC (sym->type)) {
509 sym->aop = aop = newAsmop (AOP_IMMD);
510 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
511 strcpy (aop->aopu.aop_immd, sym->rname);
512 aop->size = FPTRSIZE;
516 /* only remaining is code / eeprom which will need pointer reg */
517 /* if it is in code space */
519 sym->aop = aop = newAsmop (0);
521 if (IN_CODESPACE (space))
524 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result, aop->code);
525 aop->size = getSize (sym->type);
526 emitcode ("ldi", "%s,<(%s)", aop->aopu.aop_ptr->name, sym->rname);
527 emitcode ("ldi", "%s,>(%s)", aop->aop_ptr2);
532 /*-----------------------------------------------------------------*/
533 /* aopForRemat - rematerialzes an object */
534 /*-----------------------------------------------------------------*/
536 aopForRemat (symbol * sym)
538 iCode *ic = sym->rematiCode;
539 asmop *aop = newAsmop (AOP_IMMD);
544 val += (int) operandLitValue (IC_RIGHT (ic));
545 else if (ic->op == '-')
546 val -= (int) operandLitValue (IC_RIGHT (ic));
550 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
554 sprintf (buffer, "(%s %c 0x%04x)",
555 OP_SYMBOL (IC_LEFT (ic))->rname,
556 val >= 0 ? '+' : '-', abs (val) & 0xffff);
558 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
560 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
561 strcpy (aop->aopu.aop_immd, buffer);
565 /*-----------------------------------------------------------------*/
566 /* regsInCommon - two operands have some registers in common */
567 /*-----------------------------------------------------------------*/
569 regsInCommon (operand * op1, operand * op2)
574 /* if they have registers in common */
575 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
578 sym1 = OP_SYMBOL (op1);
579 sym2 = OP_SYMBOL (op2);
581 if (sym1->nRegs == 0 || sym2->nRegs == 0)
584 for (i = 0; i < sym1->nRegs; i++) {
589 for (j = 0; j < sym2->nRegs; j++) {
593 if (sym2->regs[j] == sym1->regs[i])
601 /*-----------------------------------------------------------------*/
602 /* operandsEqu - equivalent */
603 /*-----------------------------------------------------------------*/
605 operandsEqu (operand * op1, operand * op2)
609 /* if they not symbols */
610 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
613 sym1 = OP_SYMBOL (op1);
614 sym2 = OP_SYMBOL (op2);
616 /* if both are itemps & one is spilt
617 and the other is not then false */
618 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
619 sym1->isspilt != sym2->isspilt) return FALSE;
621 /* if they are the same */
625 if (strcmp (sym1->rname, sym2->rname) == 0)
629 /* if left is a tmp & right is not */
630 if (IS_ITEMP (op1) &&
631 !IS_ITEMP (op2) && sym1->isspilt && (sym1->usl.spillLoc == sym2))
634 if (IS_ITEMP (op2) &&
636 sym2->isspilt && sym1->level > 0 && (sym2->usl.spillLoc == sym1))
642 /*-----------------------------------------------------------------*/
643 /* sameRegs - two asmops have the same registers */
644 /*-----------------------------------------------------------------*/
646 sameRegs (asmop * aop1, asmop * aop2)
653 if (aop1->type != AOP_REG || aop2->type != AOP_REG)
656 if (aop1->size != aop2->size)
659 for (i = 0; i < aop1->size; i++)
660 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
666 /*-----------------------------------------------------------------*/
667 /* isRegPair - for size 2 if this operand has a register pair */
668 /*-----------------------------------------------------------------*/
670 isRegPair (asmop * aop)
672 if (!aop || aop->size < 2)
674 if (aop->type == AOP_X || aop->type == AOP_Z)
676 if (aop->type != AOP_REG)
678 if ( ((aop->aopu.aop_reg[1]->rIdx - aop->aopu.aop_reg[0]->rIdx) == 1) &&
679 (aop->aopu.aop_reg[0]->rIdx & 1) == 0)
685 /*-----------------------------------------------------------------*/
686 /* allHigh - all registers are high registers */
687 /*-----------------------------------------------------------------*/
688 static int allHigh (asmop * aop)
692 if (aop->type == AOP_X || aop->type == AOP_Z)
694 if (aop->type != AOP_REG)
696 for (i=0; i < aop->size ; i++ )
697 if (aop->aopu.aop_reg[i]->rIdx < R16_IDX) return 0;
701 /*-----------------------------------------------------------------*/
702 /* aopOp - allocates an asmop for an operand : */
703 /*-----------------------------------------------------------------*/
705 aopOp (operand * op, iCode * ic, bool result)
714 /* if this a literal */
715 if (IS_OP_LITERAL (op)) {
716 op->aop = aop = newAsmop (AOP_LIT);
717 aop->aopu.aop_lit = op->operand.valOperand;
718 aop->size = getSize (operandType (op));
722 /* if already has a asmop then continue */
726 /* if the underlying symbol has a aop */
727 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop) {
728 op->aop = OP_SYMBOL (op)->aop;
732 /* if this is a true symbol */
733 if (IS_TRUE_SYMOP (op)) {
734 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
738 /* this is a temporary : this has
744 e) can be a return use only */
746 sym = OP_SYMBOL (op);
749 /* if the type is a conditional */
750 if (sym->regType & REG_CND) {
751 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
756 /* if it is spilt then two situations
758 b) has a spill location */
759 if (sym->isspilt || sym->nRegs == 0) {
761 /* rematerialize it NOW */
763 sym->aop = op->aop = aop = aopForRemat (sym);
764 aop->size = getSize (sym->type);
769 assert ("ACC_USE cannot happen in AVR\n");
774 aop = op->aop = sym->aop = newAsmop (AOP_STR);
775 aop->size = getSize (sym->type);
776 for (i = 0; i < (int) fAVRReturnSize; i++)
777 aop->aopu.aop_str[i] = fAVRReturn[i];
781 /* else spill location */
782 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
783 /* force a new aop if sizes differ */
784 sym->usl.spillLoc->aop = NULL;
786 sym->aop = op->aop = aop =
787 aopForSym (ic, sym->usl.spillLoc, result);
788 aop->size = getSize (sym->type);
792 /* must be in a register */
793 sym->aop = op->aop = aop = newAsmop (AOP_REG);
794 aop->size = sym->nRegs;
795 for (i = 0; i < sym->nRegs; i++)
796 aop->aopu.aop_reg[i] = sym->regs[i];
799 /*-----------------------------------------------------------------*/
800 /* freeAsmop - free up the asmop given to an operand */
801 /*----------------------------------------------------------------*/
803 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
820 /* depending on the asmop type only three cases need work AOP_RO
821 , AOP_R1 && AOP_STK */
826 emitcode ("pop", "r26");
827 emitcode ("pop", "r27");
831 bitVectUnSetBit (ic->rUsed, X_IDX);
837 emitcode ("pop", "r30");
838 emitcode ("pop", "r31");
842 bitVectUnSetBit (ic->rUsed, Z_IDX);
848 int stk = aop->aopu.aop_stk + aop->size;
849 bitVectUnSetBit (ic->rUsed, X_IDX);
850 bitVectUnSetBit (ic->rUsed, Z_IDX);
852 getFreePtr (ic, &aop, FALSE, 0);
854 emitcode ("movw", "%s,r28");
856 if (stk <= 63 && stk > 0) {
857 emitcode ("adiw", "%s,0x%02x",
858 aop->aopu.aop_ptr->name,
862 emitcode ("subi", "%s,<(%d)",
863 aop->aopu.aop_ptr->name,
865 emitcode ("sbci", "%s,>(%d)",
872 emitcode ("pop", "r24");
873 emitcode ("st", "-%s,r24",
874 aop->type == AOP_X ? "X" : "Z");
879 freeAsmop (op, NULL, ic, TRUE);
881 emitcode ("pop", "r26");
882 emitcode ("pop", "r27");
887 emitcode ("pop", "r30");
888 emitcode ("pop", "r31");
895 /* all other cases just dealloc */
899 OP_SYMBOL (op)->aop = NULL;
900 /* if the symbol has a spill */
902 SPIL_LOC (op)->aop = NULL;
907 /*-----------------------------------------------------------------*/
908 /* aopGet - for fetching value of the aop */
909 /*-----------------------------------------------------------------*/
911 aopGet (asmop * aop, int offset)
916 /* offset is greater than
918 if (offset > (aop->size - 1) && aop->type != AOP_LIT)
921 /* depending on type */
925 if (offset > aop->coff) {
926 emitcode ("adiw", "%s,%d", aop->aopu.aop_ptr->name,
930 if (offset < aop->coff) {
931 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name,
936 emitcode ("ld", "%s,x",
937 (rs = ((offset & 1) ? "r25" : "r24")));
942 if (offset > aop->coff) {
943 emitcode ("adiw", "r30,%d",
947 emitcode ("sbiw", "r30,%d",
950 emitcode ("lpm", "%s,z",
951 (rs = ((offset & 1) ? "r25" : "r24")));
955 if (offset > aop->coff) {
956 emitcode ("ldd", "%s,z+%d",
958 ((offset & 1) ? "r25" : "r24")),
962 emitcode ("sbiw", "%s,%d",
963 aop->aopu.aop_ptr->name,
966 emitcode ("ld", "%s,z",
968 ((offset & 1) ? "r25" : "r24")));
975 emitcode ("lds", "%s,(%s)+%d",
976 (rs = ((offset & 1) ? "r25" : "r24")),
977 aop->aopu.aop_immd, offset);
981 emitcode ("lds", "%s,(%s)+%d",
982 (rs = ((offset & 1) ? "r25" : "r24")),
983 aop->aopu.aop_dir, offset);
987 return aop->aopu.aop_reg[offset]->name;
990 assert ("cannot be in bit space AOP_CRY\n");
994 s = aopLiteral (aop->aopu.aop_lit, offset);
995 emitcode ("ldi", "%s,<(%s)",
996 (rs = ((offset & 1) ? "r24" : "r25")), s);
1001 return aop->aopu.aop_str[offset];
1004 emitcode ("ldd", "%s,Y+%d",
1005 (rs = ((offset & 1) ? "r25" : "r24")),
1006 aop->aopu.aop_stk + offset);
1010 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1011 "aopget got unsupported aop->type");
1015 /*-----------------------------------------------------------------*/
1016 /* aopPut - puts a string for a aop */
1017 /*-----------------------------------------------------------------*/
1019 aopPut (asmop * aop, char *s, int offset)
1023 if (aop->size && offset > (aop->size - 1)) {
1024 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1025 "aopPut got offset > aop->size");
1029 /* will assign value to value */
1030 /* depending on where it is ofcourse */
1031 switch (aop->type) {
1034 sprintf (d, "(%s)+%d", aop->aopu.aop_dir, offset);
1037 sprintf (d, "%s", aop->aopu.aop_dir);
1040 emitcode ("sts", "%s,%s", d, s);
1044 if (toupper (*s) != 'R') {
1046 emitcode ("clr", "%s",
1047 aop->aopu.aop_reg[offset]->name);
1050 emitcode ("ldi", "r25,%s", s);
1051 emitcode ("mov", "%s,r35",
1052 aop->aopu.aop_reg[offset]->name);
1056 if (strcmp (aop->aopu.aop_reg[offset]->name, s)) {
1057 emitcode ("mov", "%s,%s",
1058 aop->aopu.aop_reg[offset]->name, s);
1064 if (offset > aop->coff) {
1065 emitcode ("adiw", "%s,%d", aop->aopu.aop_ptr->name,
1066 offset - aop->coff);
1069 if (offset < aop->coff) {
1070 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name,
1071 aop->coff - offset);
1075 emitcode ("st", "x,%s", s);
1080 if (offset > aop->coff) {
1081 emitcode ("adiw", "r30,%d",
1082 offset - aop->coff);
1085 emitcode ("sbiw", "r30,%d",
1086 aop->coff - offset);
1088 emitcode ("lpm", "%s,z", s);
1091 /* we can use lds */
1092 if (offset > aop->coff) {
1093 emitcode ("sdd", "z+%d,%s",
1094 offset - aop->coff, s);
1097 emitcode ("sbiw", "%s,%d",
1098 aop->aopu.aop_ptr->name,
1099 aop->coff - offset);
1101 emitcode ("ld", "%s,z", s);
1107 emitcode ("push", "%s", s);
1111 /* if used only for a condition code check */
1112 assert (toupper (*s) == 'R');
1114 emitcode ("xrl", "r0,r0");
1115 emitcode ("cpi", "%s,0", s);
1118 emitcode ("cpc", "r0,%s", s);
1124 if (strcmp (aop->aopu.aop_str[offset], s))
1125 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset],
1130 emitcode ("std", "y+%d,%s", offset, s);
1134 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1135 "aopPut got unsupported aop->type");
1141 #define AOP(op) op->aop
1142 #define AOP_TYPE(op) AOP(op)->type
1143 #define AOP_SIZE(op) AOP(op)->size
1144 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_X || \
1145 AOP_TYPE(x) == AOP_Z))
1146 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1147 ((x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R27_IDX)) || \
1148 (x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R31_IDX)) )))
1149 #define AOP_ISX(x) (x && (x->type == AOP_REG && \
1150 ((x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R27_IDX)))))
1151 #define AOP_ISZ(x) (x && (x->type == AOP_REG && \
1152 ((x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R31_IDX)))))
1154 /*-----------------------------------------------------------------*/
1155 /* genNotFloat - generates not for float operations */
1156 /*-----------------------------------------------------------------*/
1158 genNotFloat (operand * op, operand * res)
1164 /* we will put 127 in the first byte of
1166 aopPut (AOP (res), "127", 0);
1167 size = AOP_SIZE (op) - 1;
1170 l = aopGet (op->aop, offset++);
1174 emitcode ("or", "R0,%s", aopGet (op->aop, offset++));
1176 tlbl = newiTempLabel (NULL);
1178 tlbl = newiTempLabel (NULL);
1179 aopPut (res->aop, zero, 1);
1180 emitcode ("cpi", "r0,0");
1181 emitcode ("breq", "L%05d", tlbl->key);
1182 aopPut (res->aop, one, 1);
1183 emitcode ("", "L%05d:", tlbl->key);
1185 size = res->aop->size - 2;
1187 /* put zeros in the rest */
1189 aopPut (res->aop, zero, offset++);
1192 /*-----------------------------------------------------------------*/
1193 /* opIsGptr: returns non-zero if the passed operand is */
1194 /* a generic pointer type. */
1195 /*-----------------------------------------------------------------*/
1197 opIsGptr (operand * op)
1199 sym_link *type = operandType (op);
1201 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type)) {
1207 /*-----------------------------------------------------------------*/
1208 /* getDataSize - get the operand data size */
1209 /*-----------------------------------------------------------------*/
1211 getDataSize (operand * op)
1214 size = AOP_SIZE (op);
1215 if (size == GPTRSIZE) {
1216 sym_link *type = operandType (op);
1217 if (IS_GENPTR (type)) {
1218 /* generic pointer; arithmetic operations
1219 * should ignore the high byte (pointer type).
1227 /*-----------------------------------------------------------------*/
1228 /* toBoolean - emit code for orl a,operator(sizeop) */
1229 /*-----------------------------------------------------------------*/
1231 toBoolean (operand * oper, char *r, bool clr)
1233 int size = AOP_SIZE (oper);
1236 emitcode ("clr", "%s", r);
1238 emitcode ("or", "%s,%s", r, aopGet (AOP (oper), offset++));
1241 emitcode("mov","%s,%s",r,aopGet (AOP (oper), offset++));
1242 if (size) while (size--) emitcode ("or", "%s,%s", r, aopGet (AOP (oper), offset++));
1247 /*-----------------------------------------------------------------*/
1248 /* genNot - generate code for ! operation */
1249 /*-----------------------------------------------------------------*/
1254 sym_link *optype = operandType (IC_LEFT (ic));
1255 int size, offset = 1;
1257 /* assign asmOps to operand & result */
1258 aopOp (IC_LEFT (ic), ic, FALSE);
1259 aopOp (IC_RESULT (ic), ic, TRUE);
1261 /* if type float then do float */
1262 if (IS_FLOAT (optype)) {
1263 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1266 emitcode ("clr", "r24");
1267 tlbl = newiTempLabel (NULL);
1268 size = AOP_SIZE (IC_LEFT (ic));
1271 emitcode ("cpse", "%s,r24", aopGet (AOP (IC_LEFT (ic)), 0));
1276 emitcode ("cpc", "%s,r24",
1277 aopGet (AOP (IC_LEFT (ic)),
1280 emitcode ("cpi", "%s,0",
1281 aopGet (AOP (IC_LEFT (ic)),
1285 emitcode ("bne", "L%05d", tlbl->key);
1287 emitcode ("ldi", "r24,1");
1288 emitcode ("", "L%05d:", tlbl->key);
1289 aopPut (AOP (IC_RESULT (ic)), "r24", 0);
1290 size = AOP_SIZE (IC_RESULT (ic)) - 1;
1293 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
1297 /* release the aops */
1298 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1299 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1303 /*-----------------------------------------------------------------*/
1304 /* genCpl - generate code for complement */
1305 /*-----------------------------------------------------------------*/
1313 /* assign asmOps to operand & result */
1314 aopOp (IC_LEFT (ic), ic, FALSE);
1315 aopOp (IC_RESULT (ic), ic, TRUE);
1316 samer = sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)));
1317 size = AOP_SIZE (IC_RESULT (ic));
1319 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
1321 emitcode ("com", "%s", l);
1324 aopPut (AOP (IC_RESULT (ic)), l, offset);
1325 emitcode ("com", "%s",
1326 aopGet (AOP (IC_RESULT (ic)), offset));
1331 /* release the aops */
1332 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1333 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1336 /*-----------------------------------------------------------------*/
1337 /* genUminusFloat - unary minus for floating points */
1338 /*-----------------------------------------------------------------*/
1340 genUminusFloat (operand * op, operand * result)
1342 int size, offset = 0;
1344 /* for this we just need to flip the
1345 first it then copy the rest in place */
1346 size = AOP_SIZE (op) - 1;
1347 l = aopGet (AOP (op), 3);
1349 emitcode ("ldi", "r24,0x80");
1350 if (sameRegs (AOP (op), AOP (result))) {
1351 emitcode ("eor", "%s,r24", l);
1354 aopPut (AOP (result), l, 3);
1355 emitcode ("eor", "%s,r24", aopGet (AOP (result), 3));
1358 aopPut (AOP (result), aopGet (AOP (op), offset), offset);
1363 /*-----------------------------------------------------------------*/
1364 /* genUminus - unary minus code generation */
1365 /*-----------------------------------------------------------------*/
1367 genUminus (iCode * ic)
1370 sym_link *optype, *rtype;
1374 aopOp (IC_LEFT (ic), ic, FALSE);
1375 aopOp (IC_RESULT (ic), ic, TRUE);
1377 optype = operandType (IC_LEFT (ic));
1378 rtype = operandType (IC_RESULT (ic));
1380 /* if float then do float stuff */
1381 if (IS_FLOAT (optype)) {
1382 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1386 /* otherwise subtract from zero */
1387 size = AOP_SIZE (IC_LEFT (ic));
1389 samer = sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)));
1392 emitcode ("neg", "%s",
1393 aopGet (AOP (IC_LEFT (ic)), 0));
1396 aopPut (AOP (IC_RESULT (ic)),
1397 aopGet (AOP (IC_LEFT (ic)), 0), 0);
1398 emitcode ("neg", "%s",
1399 aopGet (AOP (IC_RESULT (ic)), 0));
1405 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
1407 aopPut (AOP (IC_RESULT (ic)), l, offset);
1408 l = aopGet (AOP (IC_RESULT (ic)), offset);
1411 emitcode ("com", "%s", l);
1413 emitcode ("neg", "%s", l);
1416 size = AOP_SIZE (IC_LEFT (ic)) - 1;
1419 emitcode ("sbci", "%s,0xff",
1420 aopGet (AOP (IC_RESULT (ic)), offset++));
1424 /* if any remaining bytes in the result */
1425 /* we just need to propagate the sign */
1426 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic))))) {
1427 symbol *tlbl = newiTempLabel (NULL);
1428 emitcode ("clr", "r0");
1429 emitcode ("brcc", "L%05d", tlbl->key);
1430 emitcode ("com", "r0");
1431 emitcode ("", "L%05d:", tlbl->key);
1433 aopPut (AOP (IC_RESULT (ic)), "r0", offset++);
1437 /* release the aops */
1438 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1439 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1442 /*-----------------------------------------------------------------*/
1443 /* assignResultValue - */
1444 /*-----------------------------------------------------------------*/
1446 assignResultValue (operand * oper)
1449 int size = AOP_SIZE (oper);
1451 aopPut (AOP (oper), fAVRReturn[offset], offset);
1456 /*-----------------------------------------------------------------*/
1457 /* saveZreg - if indirect call then save z-pointer register */
1458 /*-----------------------------------------------------------------*/
1460 saveZreg (iCode * ic)
1462 /* only if live accross this call */
1463 if (ic->regsSaved == 0 &&
1464 (bitVectBitValue (ic->rMask, R30_IDX) ||
1465 bitVectBitValue (ic->rMask, R31_IDX))) {
1467 emitcode ("push", "r30");
1468 emitcode ("push", "r31");
1472 /*-----------------------------------------------------------------*/
1473 /* popZreg - restore values of zreg */
1474 /*-----------------------------------------------------------------*/
1476 popZreg (iCode * ic)
1478 if (ic->regsSaved) {
1479 emitcode ("pop", "r31");
1480 emitcode ("pop", "r30");
1484 /*-----------------------------------------------------------------*/
1485 /* genIpush - genrate code for pushing this gets a little complex */
1486 /*-----------------------------------------------------------------*/
1488 genIpush (iCode * ic)
1490 int size, offset = 0;
1494 if (!ic->parmPush) {
1495 /* and the item is spilt then do nothing */
1496 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1501 for (lic = ic->next; lic; lic = lic->next)
1502 if (lic->op == PCALL)
1508 /* this is a paramter push */
1509 aopOp (IC_LEFT (ic), ic, FALSE);
1510 size = AOP_SIZE (IC_LEFT (ic));
1512 l = aopGet (AOP (IC_LEFT (ic)), offset++);
1513 emitcode ("push", "%s", l);
1516 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1519 /*-----------------------------------------------------------------*/
1520 /* genIpop - recover the registers: can happen only for spilling */
1521 /*-----------------------------------------------------------------*/
1523 genIpop (iCode * ic)
1528 /* if the temp was not pushed then */
1529 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1532 aopOp (IC_LEFT (ic), ic, FALSE);
1533 size = AOP_SIZE (IC_LEFT (ic));
1534 offset = (size - 1);
1536 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--));
1538 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1541 /*-----------------------------------------------------------------*/
1542 /* genCall - generates a call statement */
1543 /*-----------------------------------------------------------------*/
1545 genCall (iCode * ic)
1548 /* if send set is not empty then assign */
1552 for (sic = setFirstItem (_G.sendSet); sic;
1553 sic = setNextItem (_G.sendSet)) {
1554 int size, offset = 0;
1555 aopOp (IC_LEFT (sic), sic, FALSE);
1556 size = AOP_SIZE (IC_LEFT (sic));
1559 aopGet (AOP (IC_LEFT (sic)), offset);
1561 sprintf (buffer, "r%d", rnum++);
1563 emitcode ("mov", "%s,%s", b, l);
1566 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1571 emitcode ("call", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1572 OP_SYMBOL (IC_LEFT (ic))->rname :
1573 OP_SYMBOL (IC_LEFT (ic))->name));
1575 /* if we need assign a result value */
1576 if ((IS_ITEMP (IC_RESULT (ic)) &&
1577 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1578 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1579 IS_TRUE_SYMOP (IC_RESULT (ic))) {
1581 aopOp (IC_RESULT (ic), ic, FALSE);
1582 assignResultValue (IC_RESULT (ic));
1583 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1586 /* adjust the stack for parameters if required */
1587 if (ic->parmBytes) {
1588 if (ic->parmBytes > 63) {
1589 emitcode ("sbiw", "r28,%d", ic->parmBytes);
1592 emitcode ("subi", "r28,<(%d)",
1594 emitcode ("sbci", "r29,>(%d)",
1601 /*-----------------------------------------------------------------*/
1602 /* genPcall - generates a call by pointer statement */
1603 /*-----------------------------------------------------------------*/
1605 genPcall (iCode * ic)
1611 aopOp (IC_LEFT (ic), ic, FALSE);
1612 emitcode ("mov", "r30", aopGet (AOP (IC_LEFT (ic)), 0));
1613 emitcode ("mov", "r31", aopGet (AOP (IC_RIGHT (ic)), 0));
1614 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1616 /* if send set is not empty the assign */
1620 for (sic = setFirstItem (_G.sendSet); sic;
1621 sic = setNextItem (_G.sendSet)) {
1622 int size, offset = 0;
1623 aopOp (IC_LEFT (sic), sic, FALSE);
1624 size = AOP_SIZE (IC_LEFT (sic));
1627 aopGet (AOP (IC_LEFT (sic)), offset);
1629 sprintf (b, "r%d", rnum++);
1631 emitcode ("mov", "%s,%s", b, l);
1634 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1639 emitcode ("icall", "");
1641 /* if we need assign a result value */
1642 if ((IS_ITEMP (IC_RESULT (ic)) &&
1643 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1644 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1645 IS_TRUE_SYMOP (IC_RESULT (ic))) {
1647 aopOp (IC_RESULT (ic), ic, FALSE);
1649 assignResultValue (IC_RESULT (ic));
1650 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1653 /* adjust the stack for parameters if
1655 if (ic->parmBytes) {
1657 if (ic->parmBytes > 3) {
1658 emitcode ("mov", "a,%s", spname);
1659 emitcode ("add", "a,#0x%02x",
1660 (-ic->parmBytes) & 0xff);
1661 emitcode ("mov", "%s,a", spname);
1664 for (i = 0; i < ic->parmBytes; i++)
1665 emitcode ("dec", "%s", spname);
1669 /* adjust the stack for parameters if required */
1670 if (ic->parmBytes) {
1671 if (ic->parmBytes > 63) {
1672 emitcode ("sbiw", "r28,%d", ic->parmBytes);
1675 emitcode ("subi", "r28,<(%d)",
1677 emitcode ("sbci", "r29,>(%d)",
1685 /*-----------------------------------------------------------------*/
1686 /* resultRemat - result is rematerializable */
1687 /*-----------------------------------------------------------------*/
1689 resultRemat (iCode * ic)
1691 if (SKIP_IC (ic) || ic->op == IFX)
1694 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic))) {
1695 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
1696 if (sym->remat && !POINTER_SET (ic))
1703 #if defined(__BORLANDC__) || defined(_MSC_VER)
1704 #define STRCASECMP stricmp
1706 #define STRCASECMP strcasecmp
1709 /*-----------------------------------------------------------------*/
1710 /* genFunction - generated code for function entry */
1711 /*-----------------------------------------------------------------*/
1713 genFunction (iCode * ic)
1720 /* create the function header */
1721 emitcode (";", "-----------------------------------------");
1722 emitcode (";", " function %s",
1723 (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
1724 emitcode (";", "-----------------------------------------");
1726 emitcode ("", "%s:", sym->rname);
1727 ftype = operandType (IC_LEFT (ic));
1729 /* if critical function then turn interrupts off */
1730 if (IFFUNC_ISCRITICAL (ftype))
1731 emitcode ("cli", "");
1733 if (IFFUNC_ISISR (sym->type)) {
1736 /* save the preserved registers that are used in this function */
1737 for (i = R2_IDX; i <= R15_IDX; i++) {
1738 if (bitVectBitValue (sym->regsUsed, i)) {
1740 emitcode ("push", "%s", avr_regWithIdx (i)->name);
1743 /* now for the pointer registers */
1744 if (bitVectBitValue (sym->regsUsed, R26_IDX)) {
1746 emitcode ("push", "r26");
1748 if (bitVectBitValue (sym->regsUsed, R27_IDX)) {
1750 emitcode ("push", "r27");
1752 if (bitVectBitValue (sym->regsUsed, R30_IDX)) {
1754 emitcode ("push", "r30");
1756 if (bitVectBitValue (sym->regsUsed, R31_IDX)) {
1758 emitcode ("push", "r31");
1760 /* adjust the stack for the function */
1762 emitcode ("push", "r28");
1763 emitcode ("push", "r29");
1764 emitcode ("in", "r28,__SP_L__");
1765 emitcode ("in", "r29,__SP_H__");
1766 if (sym->stack <= 63) {
1767 emitcode ("sbiw", "r28,%d", sym->stack);
1770 emitcode ("subi", "r28,<(%d)", sym->stack);
1771 emitcode ("sbci", "r29,>(%d)", sym->stack);
1773 emitcode ("out", "__SP_L__,r28");
1774 emitcode ("out", "__SP_H__,r29");
1778 /*-----------------------------------------------------------------*/
1779 /* genEndFunction - generates epilogue for functions */
1780 /*-----------------------------------------------------------------*/
1782 genEndFunction (iCode * ic)
1784 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
1787 /* restore stack pointer */
1789 if (sym->stack <= 63) {
1790 emitcode ("adiw", "r28,%d", sym->stack);
1793 emitcode ("subi", "r28,<(-%d)", sym->stack);
1794 emitcode ("sbci", "r29,>(-%d)", sym->stack);
1796 emitcode ("out", "__SP_L__,r28");
1797 emitcode ("out", "__SP_H__,r29");
1799 /* pop frame pointer */
1800 emitcode ("pop", "r29");
1801 emitcode ("pop", "r28");
1803 /* restore preserved registers */
1804 if (bitVectBitValue (sym->regsUsed, R31_IDX)) {
1806 emitcode ("pop", "r31");
1808 if (bitVectBitValue (sym->regsUsed, R30_IDX)) {
1810 emitcode ("pop", "r30");
1812 if (bitVectBitValue (sym->regsUsed, R27_IDX)) {
1814 emitcode ("pop", "r27");
1816 if (bitVectBitValue (sym->regsUsed, R26_IDX)) {
1818 emitcode ("pop", "r26");
1820 for (i = R15_IDX; i >= R2_IDX; i--) {
1821 if (bitVectBitValue (sym->regsUsed, i)) {
1823 emitcode ("pop", "%s", avr_regWithIdx (i)->name);
1827 if (IFFUNC_ISCRITICAL (sym->type))
1828 emitcode ("sti", "");
1830 if (options.debug && currFunc) {
1831 debugFile->writeEndFunction (currFunc, ic, 1);
1834 if (IFFUNC_ISISR (sym->type)) {
1835 emitcode ("rti", "");
1838 emitcode ("ret", "");
1843 /*-----------------------------------------------------------------*/
1844 /* genRet - generate code for return statement */
1845 /*-----------------------------------------------------------------*/
1849 int size, offset = 0;
1851 /* if we have no return value then
1852 just generate the "ret" */
1856 /* we have something to return then
1857 move the return value into place */
1858 aopOp (IC_LEFT (ic), ic, FALSE);
1859 size = AOP_SIZE (IC_LEFT (ic));
1862 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) {
1863 emitcode ("ldi", "%s,%s(%d)", fAVRReturn[offset],
1865 (int) floatFromVal (AOP (IC_LEFT (ic))->
1866 aopu.aop_lit), offset);
1870 l = aopGet (AOP (IC_LEFT (ic)), offset);
1871 if (strcmp (fAVRReturn[offset], l))
1872 emitcode ("mov", "%s,%s", fAVRReturn[offset],
1878 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1881 /* generate a jump to the return label
1882 if the next is not the return statement */
1883 if (!(ic->next && ic->next->op == LABEL &&
1884 IC_LABEL (ic->next) == returnLabel))
1886 emitcode ("rjmp", "L%05d", returnLabel->key);
1890 /*-----------------------------------------------------------------*/
1891 /* genLabel - generates a label */
1892 /*-----------------------------------------------------------------*/
1894 genLabel (iCode * ic)
1896 /* special case never generate */
1897 if (IC_LABEL (ic) == entryLabel)
1900 emitcode ("", "L%05d:", IC_LABEL (ic)->key);
1903 /*-----------------------------------------------------------------*/
1904 /* genGoto - generates a ljmp */
1905 /*-----------------------------------------------------------------*/
1907 genGoto (iCode * ic)
1909 emitcode ("rjmp", "L%05d", (IC_LABEL (ic)->key));
1912 /*-----------------------------------------------------------------*/
1913 /* genPlusIncr :- does addition with increment if possible */
1914 /*-----------------------------------------------------------------*/
1916 genPlusIncr (iCode * ic)
1918 unsigned int icount;
1921 /* will try to generate an increment */
1922 /* if the right side is not a literal
1924 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
1927 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.
1930 /* if the sizes are greater than 2 or they are not the same regs
1932 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1935 /* so we know LEFT & RESULT in the same registers and add
1937 /* for short & char types */
1938 if (AOP_SIZE (IC_RESULT (ic)) < 2) {
1940 emitcode ("inc", "%s",
1941 aopGet (AOP (IC_LEFT (ic)), 0));
1944 if (AOP_ISHIGHREG( AOP (IC_LEFT (ic)),0)) {
1945 emitcode ("subi", "%s,<(%d)",
1946 aopGet (AOP (IC_LEFT (ic)), 0), 0-icount);
1951 for (offset = 0 ; offset < AOP_SIZE(IC_RESULT(ic)) ; offset++) {
1952 if (!(AOP_ISHIGHREG(AOP(IC_RESULT(ic)),offset))) return FALSE;
1955 if (AOP_SIZE (IC_RESULT (ic)) <= 3) {
1956 /* if register pair and starts with 26/30 then adiw */
1957 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0
1959 && (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX) ||
1960 IS_REGIDX (AOP (IC_RESULT (ic)), R24_IDX) ||
1961 IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX))) {
1962 emitcode ("adiw", "%s,%d",
1963 aopGet (AOP (IC_RESULT (ic)), 0), icount);
1968 emitcode ("subi", "%s,<(%d)",
1969 aopGet (AOP (IC_RESULT (ic)), 0), 0-icount);
1970 emitcode ("sbci", "%s,>(%d)",
1971 aopGet (AOP (IC_RESULT (ic)), 1), 0-icount);
1975 /* for 32 bit longs */
1976 emitcode ("subi", "%s,<(%d)", aopGet (AOP (IC_RESULT (ic)), 0),
1978 emitcode ("sbci", "%s,>(%d)", aopGet (AOP (IC_RESULT (ic)), 1),
1980 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2),
1982 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3),
1988 /* This is the pure and virtuous version of this code.
1989 * I'm pretty certain it's right, but not enough to toss the old
1993 adjustArithmeticResult (iCode * ic)
1995 if (opIsGptr (IC_RESULT (ic)) &&
1996 opIsGptr (IC_LEFT (ic)) &&
1997 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)))) {
1998 aopPut (AOP (IC_RESULT (ic)),
1999 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1),
2003 if (opIsGptr (IC_RESULT (ic)) &&
2004 opIsGptr (IC_RIGHT (ic)) &&
2005 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)))) {
2006 aopPut (AOP (IC_RESULT (ic)),
2007 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1),
2011 if (opIsGptr (IC_RESULT (ic)) &&
2012 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2013 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2014 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2015 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)))) {
2017 sprintf (buffer, "%d",
2018 pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2019 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2023 /*-----------------------------------------------------------------*/
2024 /* genPlus - generates code for addition */
2025 /*-----------------------------------------------------------------*/
2027 genPlus (iCode * ic)
2029 int size, offset = 0;
2033 /* special cases :- */
2035 aopOp (IC_LEFT (ic), ic, FALSE);
2036 aopOp (IC_RIGHT (ic), ic, FALSE);
2037 aopOp (IC_RESULT (ic), ic, TRUE);
2039 /* if I can do an increment instead
2040 of add then GOOD for ME */
2041 if (genPlusIncr (ic) == TRUE)
2044 size = getDataSize (IC_RESULT (ic));
2045 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2049 aopPut (AOP (IC_RESULT (ic)),
2050 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2052 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
2059 emitcode (l, "%s,%s",
2060 aopGet (AOP (IC_RESULT (ic)), offset),
2061 aopGet (AOP (IC_RIGHT (ic)), offset));
2064 if (AOP_ISHIGHREG( AOP( IC_RESULT(ic)),offset)) {
2070 emitcode (l, "%s,%s(-%d)",
2071 aopGet (AOP (IC_RESULT (ic)), offset),
2073 (int) floatFromVal (AOP (IC_RIGHT (ic))->
2081 emitcode (l, "%s,%s",
2082 aopGet (AOP (IC_RESULT (ic)), offset),
2083 aopGet (AOP (IC_RIGHT (ic)), offset));
2089 adjustArithmeticResult (ic);
2092 freeAsmop (IC_LEFT (ic), NULL, ic,
2093 (RESULTONSTACK (ic) ? FALSE : TRUE));
2094 freeAsmop (IC_RIGHT (ic), NULL, ic,
2095 (RESULTONSTACK (ic) ? FALSE : TRUE));
2096 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2099 /*-----------------------------------------------------------------*/
2100 /* genMinusDec :- does subtraction with deccrement if possible */
2101 /*-----------------------------------------------------------------*/
2103 genMinusDec (iCode * ic)
2105 unsigned int icount;
2108 /* will try to generate an increment */
2109 /* if the right side is not a literal
2111 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2115 (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.
2118 /* if the sizes are greater than 2 or they are not the same regs
2120 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2123 /* so we know LEFT & RESULT in the same registers and add
2125 /* for short & char types */
2126 if (AOP_SIZE (IC_RESULT (ic)) < 2) {
2128 emitcode ("dec", "%s",
2129 aopGet (AOP (IC_LEFT (ic)), 0));
2132 if (AOP_ISHIGHREG( AOP ( IC_LEFT(ic)),0)) {
2133 emitcode ("subi", "%s,<(%d)",
2134 aopGet (AOP (IC_LEFT (ic)), 0), icount);
2139 for (offset = 0 ; offset < AOP_SIZE(IC_RESULT(ic)) ; offset++) {
2140 if (!(AOP_ISHIGHREG(AOP(IC_RESULT(ic)),offset))) return FALSE;
2143 if (AOP_SIZE (IC_RESULT (ic)) <= 3) {
2144 /* if register pair and starts with 26/30 then adiw */
2145 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0
2147 && (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX) ||
2148 IS_REGIDX (AOP (IC_RESULT (ic)), R24_IDX) ||
2149 IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX))) {
2150 emitcode ("sbiw", "%s,%d",
2151 aopGet (AOP (IC_RESULT (ic)), 0), icount);
2156 emitcode ("subi", "%s,<(%d)",
2157 aopGet (AOP (IC_RESULT (ic)), 0), icount);
2158 emitcode ("sbci", "%s,>(%d)",
2159 aopGet (AOP (IC_RESULT (ic)), 1), icount);
2162 /* for 32 bit longs */
2163 emitcode ("subi", "%s,<(%d)", aopGet (AOP (IC_RESULT (ic)), 0),
2165 emitcode ("sbci", "%s,>(%d)", aopGet (AOP (IC_RESULT (ic)), 1),
2167 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2),
2169 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3),
2175 /*-----------------------------------------------------------------*/
2176 /* genMinus - generates code for subtraction */
2177 /*-----------------------------------------------------------------*/
2179 genMinus (iCode * ic)
2181 int size, offset = 0, samer;
2184 aopOp (IC_LEFT (ic), ic, FALSE);
2185 aopOp (IC_RIGHT (ic), ic, FALSE);
2186 aopOp (IC_RESULT (ic), ic, TRUE);
2188 /* if I can do an decrement instead
2189 of subtract then GOOD for ME */
2190 if (genMinusDec (ic) == TRUE)
2193 size = getDataSize (IC_RESULT (ic));
2194 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2197 aopPut (AOP (IC_RESULT (ic)),
2198 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2200 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
2207 emitcode (l, "%s,%s",
2208 aopGet (AOP (IC_RESULT (ic)), offset),
2209 aopGet (AOP (IC_RIGHT (ic)), offset));
2212 if (AOP_ISHIGHREG(AOP (IC_RESULT (ic)),offset)) {
2218 emitcode (l, "%s,%s(%d)",
2219 aopGet (AOP (IC_RESULT (ic)), offset),
2221 (int) floatFromVal (AOP (IC_RIGHT (ic))->
2229 emitcode (l, "%s,%s",
2230 aopGet (AOP (IC_RESULT (ic)), offset),
2231 aopGet (AOP (IC_RIGHT (ic)), offset));
2237 adjustArithmeticResult (ic);
2240 freeAsmop (IC_LEFT (ic), NULL, ic,
2241 (RESULTONSTACK (ic) ? FALSE : TRUE));
2242 freeAsmop (IC_RIGHT (ic), NULL, ic,
2243 (RESULTONSTACK (ic) ? FALSE : TRUE));
2244 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2247 /*-----------------------------------------------------------------*/
2248 /* genMultOneByte : 8 bit multiplication & division */
2249 /*-----------------------------------------------------------------*/
2251 genMultOneByte (operand * left, operand * right, operand * result)
2253 sym_link *opetype = operandType (result);
2257 /* (if two literals, the value is computed before) */
2258 /* if one literal, literal on the right */
2259 if (AOP_TYPE (left) == AOP_LIT) {
2265 size = AOP_SIZE (result);
2267 if (SPEC_USIGN (opetype)) {
2268 emitcode ("mul", "%s,%s", aopGet (AOP (left), 0),
2269 aopGet (AOP (right), 0));
2272 emitcode ("muls", "%s,%s", aopGet (AOP (left), 0),
2273 aopGet (AOP (right), 0));
2275 aopPut (AOP (result), "r0", 0);
2277 aopPut (AOP (result), "r1", 1);
2280 if (SPEC_USIGN (opetype)) {
2282 aopPut (AOP (result), zero, offset++);
2287 lbl = newiTempLabel (NULL);
2288 emitcode ("ldi", "r24,0");
2289 emitcode ("brcc", "L%05d", lbl->key);
2290 emitcode ("ldi", "r24,0xff)");
2291 emitcode ("", "L%05d:", lbl->key);
2293 aopPut (AOP (result), "r24",
2301 /*-----------------------------------------------------------------*/
2302 /* genMult - generates code for multiplication */
2303 /*-----------------------------------------------------------------*/
2305 genMult (iCode * ic)
2307 operand *left = IC_LEFT (ic);
2308 operand *right = IC_RIGHT (ic);
2309 operand *result = IC_RESULT (ic);
2311 /* assign the amsops */
2312 aopOp (left, ic, FALSE);
2313 aopOp (right, ic, FALSE);
2314 aopOp (result, ic, TRUE);
2316 /* if both are of size == 1 */
2317 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1) {
2318 genMultOneByte (left, right, result);
2322 /* should have been converted to function call */
2326 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2327 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2328 freeAsmop (result, NULL, ic, TRUE);
2331 /*-----------------------------------------------------------------*/
2332 /* genDiv - generates code for division */
2333 /*-----------------------------------------------------------------*/
2337 /* should have been converted to function call */
2341 /*-----------------------------------------------------------------*/
2342 /* genMod - generates code for division */
2343 /*-----------------------------------------------------------------*/
2347 /* should have been converted to function call */
2359 /*-----------------------------------------------------------------*/
2360 /* revavrcnd - reverse a conditional for avr */
2361 /*-----------------------------------------------------------------*/
2363 revavrcnd (int type)
2375 for (i = 0; i < (sizeof (rar) / sizeof (rar[0])); i++) {
2376 if (rar[i].type == type)
2377 return rar[i].rtype;
2378 if (rar[i].rtype == type)
2381 assert (0); /* cannot happen */
2382 return 0; /* makes the compiler happy */
2385 static char *br_name[4] = { "breq", "brne", "brlt", "brge" };
2386 static char *br_uname[4] = { "breq", "brne", "brlo", "brcc" };
2388 /*-----------------------------------------------------------------*/
2389 /* genBranch - generate the branch instruction */
2390 /*-----------------------------------------------------------------*/
2392 genBranch (iCode * ifx, int br_type, int sign)
2394 int tj = (IC_TRUE (ifx) ? 1 : 0);
2396 if (tj) { /* if true jump */
2397 char *nm = (sign ? br_name[br_type] : br_uname[br_type]);
2398 emitcode (nm, "L%05d", IC_TRUE (ifx)->key);
2400 else { /* if false jump */
2401 int rtype = revavrcnd (br_type);
2402 char *nm = (sign ? br_name[rtype] : br_uname[rtype]);
2403 emitcode (nm, "L%05d", IC_FALSE (ifx)->key);
2408 /*-----------------------------------------------------------------*/
2409 /* genCmp - compare & jump */
2410 /*-----------------------------------------------------------------*/
2412 genCmp (iCode * ic, iCode * ifx, int br_type)
2414 operand *left, *right, *result;
2415 sym_link *letype, *retype;
2417 int sign, size, offset = 0;
2419 left = IC_LEFT (ic);
2420 right = IC_RIGHT (ic);
2421 result = IC_RESULT (ic);
2423 letype = getSpec (operandType (left));
2424 retype = getSpec (operandType (right));
2425 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
2427 /* assign the amsops */
2428 aopOp (left, ic, FALSE);
2429 aopOp (right, ic, FALSE);
2430 aopOp (result, ic, TRUE);
2431 size = AOP_SIZE (left);
2435 if (AOP_TYPE (right) == AOP_LIT) {
2436 emitcode ("cpi", "%s,<(%d)",
2437 aopGet (AOP (left), 0),
2439 floatFromVal (AOP (IC_RIGHT (ic))->
2441 genBranch (ifx, br_type, sign);
2443 else { /* right != literal */
2444 emitcode ("cp", "%s,%s",
2445 aopGet (AOP (left), 0),
2446 aopGet (AOP (right), 0));
2447 genBranch (ifx, br_type, sign);
2450 else { /* size != 1 */
2453 emitcode ("cp", "%s,%s",
2454 aopGet (AOP (left), 0),
2455 aopGet (AOP (right), 0));
2457 emitcode ("cpc", "%s,%s",
2458 aopGet (AOP (left), offset),
2459 aopGet (AOP (right),
2463 genBranch (ifx, br_type, sign);
2467 emitcode ("clr", "r0");
2470 emitcode ("cp", "%s,%s",
2471 aopGet (AOP (left), 0),
2472 aopGet (AOP (right), 0));
2474 emitcode ("cpc", "%s,%s",
2475 aopGet (AOP (left), offset),
2476 aopGet (AOP (right), offset));
2479 lbl = newiTempLabel (NULL);
2480 br_type = revavrcnd (br_type);
2482 emitcode (br_uname[br_type], "L%05d", lbl->key);
2484 emitcode (br_name[br_type], "L%05d", lbl->key);
2485 emitcode ("inc", "r0");
2486 emitcode ("", "L%05d:", lbl->key);
2487 aopPut (AOP (result), "r0", 0);
2488 size = AOP_SIZE (result) - 1;
2491 aopPut (AOP (result), zero, offset++);
2494 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2495 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2496 freeAsmop (result, NULL, ic, TRUE);
2499 /*-----------------------------------------------------------------*/
2500 /* genCmpGt :- greater than comparison */
2501 /*-----------------------------------------------------------------*/
2503 genCmpGt (iCode * ic, iCode * ifx)
2505 /* should have transformed by the parser */
2509 /*-----------------------------------------------------------------*/
2510 /* genCmpLt - less than comparisons */
2511 /*-----------------------------------------------------------------*/
2513 genCmpLt (iCode * ic, iCode * ifx)
2515 genCmp (ic, ifx, AVR_LT);
2518 /*-----------------------------------------------------------------*/
2519 /* genCmpEq - generates code for equal to */
2520 /*-----------------------------------------------------------------*/
2522 genCmpEq (iCode * ic, iCode * ifx)
2524 genCmp (ic, ifx, AVR_EQ);
2527 /*-----------------------------------------------------------------*/
2528 /* genCmpNe - generates code for not equal to */
2529 /*-----------------------------------------------------------------*/
2531 genCmpNe (iCode * ic, iCode * ifx)
2533 genCmp (ic, ifx, AVR_NE);
2536 /*-----------------------------------------------------------------*/
2537 /* genCmpGe - generates code for greater than equal to */
2538 /*-----------------------------------------------------------------*/
2540 genCmpGe (iCode * ic, iCode * ifx)
2542 genCmp (ic, ifx, AVR_GE);
2545 /*-----------------------------------------------------------------*/
2546 /* genCmpLe - generates code for less than equal to */
2547 /*-----------------------------------------------------------------*/
2549 genCmpLe (iCode * ic, iCode * ifx)
2551 operand *left = IC_LEFT (ic);
2552 operand *right = IC_RIGHT (ic);
2554 IC_RIGHT (ic) = left;
2555 IC_LEFT (ic) = right;
2556 genCmp (ic, ifx, AVR_GE);
2559 /*-----------------------------------------------------------------*/
2560 /* ifxForOp - returns the icode containing the ifx for operand */
2561 /*-----------------------------------------------------------------*/
2563 ifxForOp (operand * op, iCode * ic)
2565 /* if true symbol then needs to be assigned */
2566 if (IS_TRUE_SYMOP (op))
2569 /* if this has register type condition and
2570 the next instruction is ifx with the same operand
2571 and live to of the operand is upto the ifx only then */
2573 ic->next->op == IFX &&
2574 IC_COND (ic->next)->key == op->key &&
2575 OP_SYMBOL (op)->liveTo <= ic->next->seq) return ic->next;
2580 /*-----------------------------------------------------------------*/
2581 /* genAndOp - for && operation */
2582 /*-----------------------------------------------------------------*/
2584 genAndOp (iCode * ic)
2586 operand *left, *right, *result;
2590 /* note here that && operations that are in an
2591 if statement are taken away by backPatchLabels
2592 only those used in arthmetic operations remain */
2593 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2594 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2595 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
2597 tlbl = newiTempLabel (NULL);
2598 toBoolean (left, "r0", TRUE);
2599 toBoolean (right, "r1", TRUE);
2600 emitcode ("and", "r0,r1");
2601 emitcode ("ldi", "r24,1");
2602 emitcode ("breq", "L%05d", tlbl->key);
2603 emitcode ("dec", "r24");
2604 emitcode ("", "L%05d:", tlbl->key);
2605 aopPut (AOP (result), "r24", 0);
2606 size = AOP_SIZE (result) - 1;
2609 aopPut (AOP (result), zero, offset++);
2611 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2612 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2613 freeAsmop (result, NULL, ic, TRUE);
2617 /*-----------------------------------------------------------------*/
2618 /* genOrOp - for || operation */
2619 /*-----------------------------------------------------------------*/
2621 genOrOp (iCode * ic)
2623 operand *left, *right, *result;
2627 /* note here that || operations that are in an
2628 if statement are taken away by backPatchLabels
2629 only those used in arthmetic operations remain */
2630 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2631 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2632 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
2634 tlbl = newiTempLabel (NULL);
2635 toBoolean (left, "r0", TRUE);
2636 toBoolean (right, "r0", FALSE);
2637 emitcode ("ldi", "r24,1");
2638 emitcode ("breq", "L%05d", tlbl->key);
2639 emitcode ("dec", "r24");
2640 emitcode ("", "L%05d:", tlbl->key);
2641 aopPut (AOP (result), "r24", 0);
2642 size = AOP_SIZE (result) - 1;
2645 aopPut (AOP (result), zero, offset++);
2647 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2648 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2649 freeAsmop (result, NULL, ic, TRUE);
2653 AVR_AND = 0, AVR_OR, AVR_XOR
2655 static char *bopnames_lit[] = { "andi", "ori" };
2656 static char *bopnames[] = { "and", "or", "eor" };
2657 /*-----------------------------------------------------------------*/
2658 /* genBitWise - generate bitwise operations */
2659 /*-----------------------------------------------------------------*/
2661 genBitWise (iCode * ic, iCode * ifx, int bitop)
2663 operand *left, *right, *result;
2664 int size, offset = 0;
2669 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2670 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2671 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
2673 size = AOP_SIZE (left);
2675 if (ifx) { /* used only for jumps */
2676 if (AOP_TYPE (right) == AOP_LIT &&
2677 (bitop == AVR_AND || bitop == AVR_OR)) {
2679 (int) floatFromVal (AOP (right)->aopu.
2681 int p2 = powof2 (lit);
2682 if (bitop == AVR_AND && p2) { /* right side is a power of 2 */
2683 l = aopGet (AOP (left), p2 / 8);
2684 if (IC_TRUE (ifx)) {
2685 emitcode ("sbrc", "%s,%d", l,
2687 emitcode ("rjmp", "L%05d",
2688 IC_TRUE (ifx)->key);
2691 emitcode ("sbrs", "%s,%d", l,
2693 emitcode ("rjmp", "L%05d",
2694 IC_FALSE (ifx)->key);
2697 else { /* right not power of two */
2698 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2700 if (eh && AOP_ISHIGHREG(AOP(IC_LEFT(ic)),0)) {
2701 emitcode (bopnames_lit[bitop],
2703 aopGet (AOP (IC_LEFT (ic)), 0), lit);
2706 MOVR24 (aopGet (AOP (IC_LEFT (ic)), 0));
2707 emitcode (bopnames_lit[bitop], "r24,<(%d)", lit);
2709 lbl = newiTempLabel (NULL);
2710 if (IC_TRUE (ifx)) {
2711 emitcode ("breq", "L%05d", lbl->key);
2712 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2715 emitcode ("brne", "L%05d", lbl->key);
2716 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)-> key);
2718 emitcode ("", "L%05d:", lbl->key);
2720 else if (size == 2) {
2721 emitcode ("mov", "r24,%s", aopGet (AOP (IC_LEFT (ic)), 0));
2722 emitcode ("mov", "r25,%s", aopGet (AOP (IC_LEFT (ic)), 1));
2723 emitcode (bopnames_lit[bitop], "r24,<(%d)", lit);
2724 emitcode (bopnames_lit[bitop], "r25,>(%d)", lit);
2725 emitcode ("sbiw", "r24,0");
2726 lbl = newiTempLabel (NULL);
2727 if (IC_TRUE (ifx)) {
2728 emitcode ("breq", "L%05d", lbl->key);
2729 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2732 emitcode ("brne", "L%05d", lbl->key);
2733 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2735 emitcode ("", "L%05d:", lbl->key);
2738 lbl = newiTempLabel (NULL);
2739 lbl1 = newiTempLabel (NULL);
2741 if (eh && AOP_ISHIGHREG(AOP(IC_LEFT(ic)),offset)) {
2742 emitcode (bopnames_lit [bitop], "%s,<(%d)",
2743 aopGet (AOP (IC_LEFT (ic)), offset),
2747 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
2749 emitcode ("andi", "r24,<(%d)", lit);
2751 emitcode ("brne", "L%05d", lbl->key);
2756 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)-> key);
2758 emitcode ("rjmp", "L%05d", lbl1->key);
2759 emitcode ("", "L%05d:", lbl->key);
2762 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2763 emitcode ("", "L%05d:", lbl1->key);
2768 else { /* right is not a literal */
2769 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2770 int reh = OP_SYMBOL (right)->liveTo <= ic->seq;
2773 emitcode (bopnames[bitop], "%s,%s", aopGet (AOP (IC_LEFT (ic)), 0),
2774 aopGet (AOP (IC_RIGHT (ic)), 0));
2777 emitcode (bopnames[bitop], "%s,%s",
2778 aopGet (AOP (IC_RIGHT (ic)), 0),
2779 aopGet (AOP (IC_LEFT (ic)), 0));
2782 MOVR0 (aopGet (AOP (IC_LEFT (ic)), 0));
2783 emitcode (bopnames[bitop], "r0,%s",
2784 aopGet (AOP (IC_RIGHT (ic)), 0));
2786 lbl = newiTempLabel (NULL);
2787 if (IC_TRUE (ifx)) {
2788 emitcode ("breq", "L%05d", lbl->key);
2789 emitcode ("rjmp", "L%05d",
2790 IC_TRUE (ifx)->key);
2793 emitcode ("brne", "L%05d", lbl->key);
2794 emitcode ("rjmp", "L%05d",
2795 IC_FALSE (ifx)->key);
2797 emitcode ("", "L%05d:", lbl->key);
2799 else if (size == 2) {
2800 emitcode ("mov", "r24,%s",
2801 aopGet (AOP (IC_LEFT (ic)), 0));
2802 emitcode ("mov", "r25,%s",
2803 aopGet (AOP (IC_LEFT (ic)), 1));
2804 emitcode (bopnames[bitop], "r24,%s",
2805 aopGet (AOP (IC_RIGHT (ic)), 0));
2806 emitcode (bopnames[bitop], "r25,%s",
2807 aopGet (AOP (IC_RIGHT (ic)), 1));
2808 emitcode ("sbiw", "r24,0");
2809 lbl = newiTempLabel (NULL);
2810 if (IC_TRUE (ifx)) {
2811 emitcode ("breq", "L%05d", lbl->key);
2812 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2815 emitcode ("brne", "L%05d", lbl->key);
2816 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2818 emitcode ("", "L%05d:", lbl->key);
2821 lbl = newiTempLabel (NULL);
2822 lbl1 = newiTempLabel (NULL);
2825 emitcode (bopnames[bitop], "%s,%s",
2826 aopGet (AOP (IC_LEFT (ic)), offset),
2827 aopGet (AOP (IC_RIGHT (ic)), offset));
2830 emitcode (bopnames[bitop], "%s,%s",
2831 aopGet (AOP (IC_RIGHT (ic)), offset),
2832 aopGet (AOP (IC_LEFT (ic)), offset));
2835 MOVR0 (aopGet (AOP (IC_LEFT (ic)), offset));
2836 emitcode (bopnames[bitop], "r0,%s",
2837 aopGet (AOP (IC_RIGHT (ic)), offset));
2839 emitcode ("brne", "L%05d", lbl->key);
2844 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2846 emitcode ("rjmp", "L%05d", lbl1->key);
2847 emitcode ("", "L%05d:", lbl->key);
2850 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2851 emitcode ("", "L%05d:", lbl1->key);
2858 /* result needs to go a register */
2859 samerl = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2860 samerr = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)));
2862 if (AOP_TYPE (right) == AOP_LIT) {
2864 (int) floatFromVal (AOP (right)->aopu.
2866 if (((lit >> (8 * offset)) & 0xff) == 0) {
2867 if (bitop == AVR_AND) {
2868 aopPut (AOP (result), zero, offset++);
2871 else if (bitop == AVR_OR) {
2873 aopPut (AOP (result),
2883 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT &&
2884 AOP_ISHIGHREG(AOP(IC_LEFT(ic)),offset) &&
2885 (bitop == AVR_AND || bitop == AVR_OR)) {
2886 emitcode (bopnames_lit[bitop], "%s,%s(%d)",
2887 aopGet (AOP (IC_LEFT (ic)), offset),
2889 (int) floatFromVal (AOP (right)-> aopu.aop_lit));
2892 emitcode (bopnames[bitop], "%s,%s",
2893 aopGet (AOP (IC_LEFT (ic)), offset),
2894 aopGet (AOP (IC_RIGHT (ic)), offset));
2898 emitcode (bopnames[bitop], "%s,%s",
2899 aopGet (AOP (IC_RIGHT (ic)), offset),
2900 aopGet (AOP (IC_LEFT (ic)), offset));
2903 aopPut (AOP (IC_RESULT (ic)),
2904 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2905 emitcode (bopnames[bitop],
2906 aopGet (AOP (IC_RESULT (ic)), offset),
2907 aopGet (AOP (IC_RIGHT (ic)), offset));
2912 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2913 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2914 freeAsmop (result, NULL, ic, TRUE);
2917 /*-----------------------------------------------------------------*/
2918 /* genAnd - code for and */
2919 /*-----------------------------------------------------------------*/
2921 genAnd (iCode * ic, iCode * ifx)
2923 genBitWise (ic, ifx, AVR_AND);
2926 /*-----------------------------------------------------------------*/
2927 /* genOr - code for or */
2928 /*-----------------------------------------------------------------*/
2930 genOr (iCode * ic, iCode * ifx)
2932 genBitWise (ic, ifx, AVR_OR);
2935 /*-----------------------------------------------------------------*/
2936 /* genXor - code for xclusive or */
2937 /*-----------------------------------------------------------------*/
2939 genXor (iCode * ic, iCode * ifx)
2941 genBitWise (ic, ifx, AVR_XOR);
2944 /*-----------------------------------------------------------------*/
2945 /* genInline - write the inline code out */
2946 /*-----------------------------------------------------------------*/
2948 genInline (iCode * ic)
2950 char *buffer, *bp, *bp1;
2952 _G.inLine += (!options.asmpeep);
2954 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
2955 strcpy (buffer, IC_INLINE (ic));
2957 /* emit each line as a code */
2978 /* emitcode("",buffer); */
2979 _G.inLine -= (!options.asmpeep);
2982 /*-----------------------------------------------------------------*/
2983 /* genRotC - rotate right/left with carry , lr = 1 rotate right */
2984 /*-----------------------------------------------------------------*/
2986 genRotC (iCode * ic, int lr)
2988 operand *left, *result;
2989 int size, offset = 0;
2991 /* rotate right with carry */
2992 left = IC_LEFT (ic);
2993 result = IC_RESULT (ic);
2994 aopOp (left, ic, FALSE);
2995 aopOp (result, ic, FALSE);
2997 /* move it to the result */
2998 size = AOP_SIZE (result);
2999 if (!sameRegs (AOP (left), AOP (result))) {
3002 aopPut (AOP (result),
3003 aopGet (AOP (left), offset), offset);
3006 size = AOP_SIZE (result);
3014 emitcode ("sbrc", "%s,%d", aopGet (AOP (result), offset),
3016 emitcode ("sec", "");
3019 emitcode ((lr ? "ror" : "rol"), "%s",
3020 aopGet (AOP (result), offset));
3026 freeAsmop (left, NULL, ic, TRUE);
3027 freeAsmop (result, NULL, ic, TRUE);
3030 /*-----------------------------------------------------------------*/
3031 /* genRRC - rotate right with carry */
3032 /*-----------------------------------------------------------------*/
3039 /*-----------------------------------------------------------------*/
3040 /* genRLC - generate code for rotate left with carry */
3041 /*-----------------------------------------------------------------*/
3048 /*-----------------------------------------------------------------*/
3049 /* genGetHbit - generates code get highest order bit */
3050 /*-----------------------------------------------------------------*/
3052 genGetHbit (iCode * ic)
3054 operand *left, *result;
3057 left = IC_LEFT (ic);
3058 result = IC_RESULT (ic);
3059 aopOp (left, ic, FALSE);
3060 aopOp (result, ic, FALSE);
3062 size = AOP_SIZE (result);
3063 if (!sameRegs (AOP (left), AOP (result))) {
3064 emitcode ("clr", "%s", aopGet (AOP (result), size - 1));
3065 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3066 emitcode ("subi", "%s,<(-1)",
3067 aopGet (AOP (result), size - 1));
3070 emitcode ("clr", "r0");
3071 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3072 emitcode ("subi", "r0,<(-1)");
3073 aopPut (AOP (result), "r0", 0);
3078 emitcode ("clr", aopGet (AOP (result), offset++));
3080 freeAsmop (left, NULL, ic, TRUE);
3081 freeAsmop (result, NULL, ic, TRUE);
3084 /*-----------------------------------------------------------------*/
3085 /* genShiftLeftLit - shift left by a known amount */
3086 /*-----------------------------------------------------------------*/
3088 genShiftLeftLit (iCode * ic)
3090 operand *left, *right, *result;
3091 int size, shCount, offset = 0;
3094 right = IC_RIGHT (ic);
3095 left = IC_LEFT (ic);
3096 result = IC_RESULT (ic);
3098 aopOp (left, ic, FALSE);
3099 aopOp (result, ic, FALSE);
3100 size = AOP_SIZE (result);
3101 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3103 if (shCount > (size * 8 - 1)) {
3105 aopPut (AOP (result), zero, offset++);
3110 if (!sameRegs (AOP (left), AOP (result)))
3111 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3113 if (AOP_ISHIGHREG(AOP(result),0)) {
3114 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3115 emitcode ("andi", "%s,0xf0");
3117 emitcode ("ldi","r24,0xf0");
3118 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3119 emitcode ("and", "%s,r24");
3124 emitcode ("add", "%s,%s", aopGet (AOP (result), 0),
3125 aopGet (AOP (result), 0));
3129 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3132 if (shCount >= 12) {
3133 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3134 aopPut (AOP (result), zero, 0);
3135 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3136 if (AOP_ISHIGHREG(AOP(result),1)) {
3137 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3139 emitcode ("ldi","r24,0xf0");
3140 emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
3146 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3147 aopPut (AOP (result), zero, 0);
3153 if (!sameRegs (AOP (left), AOP (result))) {
3154 aopPut (AOP (result), aopGet (AOP (left), 0),
3156 aopPut (AOP (result), aopGet (AOP (left), 1),
3159 emitcode ("mov", "r24,%s", aopGet (AOP (result), 0));
3160 emitcode ("andi", "r24,0x0f");
3161 if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
3162 emitcode("ldi","r25,0xf0");
3164 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3165 if (AOP_ISHIGHREG(AOP(result),0)) {
3166 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 0));
3168 emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
3170 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3171 if (AOP_ISHIGHREG(AOP(result),1)) {
3172 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3174 emitcode ("and", "%s,r25", aopGet (AOP (result), 1));
3176 emitcode ("or", "%s,r24", aopGet (AOP (result), 1));
3178 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3179 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3182 if (!lByteZ && !sameRegs (AOP (result), AOP (left))
3186 aopPut (AOP (result),
3187 aopGet (AOP (left), offset), offset);
3193 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3196 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3197 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3202 assert ("shifting generic pointer ?\n");
3205 /* 32 bits we do only byte boundaries */
3206 if (shCount >= 24) {
3207 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3208 aopPut (AOP (result), zero, 2);
3209 aopPut (AOP (result), zero, 1);
3210 aopPut (AOP (result), zero, 0);
3214 if (shCount >= 16) {
3215 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3216 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3217 aopPut (AOP (result), zero, 1);
3218 aopPut (AOP (result), zero, 0);
3223 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3224 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3225 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3226 aopPut (AOP (result), zero, 0);
3230 if (!lByteZ && !sameRegs (AOP (left), AOP (right))) {
3233 aopPut (AOP (result),
3234 aopGet (AOP (left), offset), offset);
3238 size = AOP_SIZE (result);
3244 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3245 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3246 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3247 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3252 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3253 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3254 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3259 emitcode ("lsl", "%s", aopGet (AOP (result), 2));
3260 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3265 emitcode ("lsl", "%s", aopGet (AOP (result), 3));
3273 freeAsmop (left, NULL, ic, TRUE);
3274 freeAsmop (right, NULL, ic, TRUE);
3275 freeAsmop (result, NULL, ic, TRUE);
3278 /*-----------------------------------------------------------------*/
3279 /* genLeftShift - generates code for left shifting */
3280 /*-----------------------------------------------------------------*/
3282 genLeftShift (iCode * ic)
3284 operand *left, *right, *result;
3288 right = IC_RIGHT (ic);
3289 left = IC_LEFT (ic);
3290 result = IC_RESULT (ic);
3292 aopOp (right, ic, FALSE);
3294 if (AOP_TYPE (right) == AOP_LIT) {
3295 genShiftLeftLit (ic);
3300 aopOp (left, ic, FALSE);
3301 aopOp (result, ic, FALSE);
3302 size = AOP_SIZE (result);
3304 if (AOP_SIZE (right) > 1) {
3305 if (isRegPair (AOP (right))) {
3306 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3309 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3310 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3314 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3316 if (!sameRegs (AOP (left), AOP (result))) {
3318 aopPut (AOP (result), aopGet (AOP (left), offset),
3322 size = AOP_SIZE (result);
3324 tlbl = newiTempLabel (NULL);
3325 emitcode ("", "L%05d:", tlbl->key);
3329 emitcode ("rol", "%s", aopGet (AOP (result), offset));
3331 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3334 if (AOP_SIZE (right) > 1)
3335 emitcode ("sbiw", "r24,1");
3337 emitcode ("dec", "r24");
3338 emitcode ("brne", "L%05d", tlbl->key);
3340 freeAsmop (left, NULL, ic, TRUE);
3341 freeAsmop (right, NULL, ic, TRUE);
3342 freeAsmop (result, NULL, ic, TRUE);
3345 /*-----------------------------------------------------------------*/
3346 /* genShiftRightLit - generate for right shift with known count */
3347 /*-----------------------------------------------------------------*/
3349 genShiftRightLit (iCode * ic)
3351 operand *left = IC_LEFT (ic)
3352 , *right = IC_RIGHT (ic)
3353 , *result = IC_RESULT (ic);
3354 int size, shCount, offset = 0;
3356 sym_link *letype = getSpec (operandType (left));
3357 int sign = !SPEC_USIGN (letype);
3359 right = IC_RIGHT (ic);
3360 left = IC_LEFT (ic);
3361 result = IC_RESULT (ic);
3363 aopOp (left, ic, FALSE);
3364 aopOp (result, ic, FALSE);
3365 size = AOP_SIZE (result);
3366 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3368 /* if signed then give up and use a loop to shift */
3371 if (!sameRegs (AOP (left), AOP (result))) {
3373 aopPut (AOP (result),
3374 aopGet (AOP (left), offset), offset);
3377 size = AOP_SIZE (result);
3380 /* be as economical as possible */
3383 size = AOP_SIZE (result);
3386 /* highest order byte */
3387 if (offset == (AOP_SIZE(result)-1))
3388 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3390 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3396 emitcode ("ldi", "r24,<(%d)", shCount);
3397 tlbl = newiTempLabel (NULL);
3398 emitcode ("", "L%05d:", tlbl->key);
3401 if (offset == (AOP_SIZE(result) - 1))
3402 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3404 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3407 emitcode ("dec", "r24");
3408 emitcode ("brne", "L%05d", tlbl->key);
3412 if (shCount > (size * 8 - 1)) {
3414 aopPut (AOP (result), zero, offset++);
3417 /* for unsigned we can much more efficient */
3420 if (!sameRegs (AOP (left), AOP (result)))
3421 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3423 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3424 if (AOP_ISHIGHREG(AOP(result),0)) {
3425 emitcode ("andi", "%s,0x0f",aopGet(AOP(result),0));
3427 emitcode ("ldi","r24,0x0f");
3428 emitcode ("and", "%s,r24",aopGet(AOP(result),0));
3433 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3436 if (shCount >= 12) {
3437 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3438 aopPut (AOP (result), zero, 1);
3439 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3440 if (AOP_ISHIGHREG(AOP(result),0)) {
3441 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3443 emitcode ("ldi","r24,0x0f");
3444 emitcode ("and", "%s,r24",aopGet(AOP(result),0));
3450 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3451 aopPut (AOP (result), zero, 1);
3457 if (!sameRegs (AOP (left), AOP (result))) {
3458 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3459 aopPut (AOP (result), aopGet (AOP (left), 1), 1);
3461 if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
3462 emitcode("ldi","r25,0x0f");
3464 emitcode ("mov", "r24,%s", aopGet (AOP (result), 1));
3465 emitcode ("andi", "r24,0xf0");
3466 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3467 if (AOP_ISHIGHREG(AOP(result),0)) {
3468 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3470 emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
3472 emitcode ("or", "%s,r24", aopGet (AOP (result), 0));
3473 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3474 if (AOP_ISHIGHREG(AOP(result),1)) {
3475 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 1));
3477 emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
3480 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3481 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3485 if (!hByteZ && !sameRegs (AOP (result), AOP (left))
3489 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3495 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3498 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3499 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3505 assert ("shifting generic pointer ?\n");
3508 /* 32 bits we do only byte boundaries */
3509 if (shCount >= 24) {
3510 aopPut (AOP (result), aopGet (AOP (left), 3), 0);
3511 aopPut (AOP (result), zero, 1);
3512 aopPut (AOP (result), zero, 2);
3513 aopPut (AOP (result), zero, 3);
3517 if (shCount >= 16) {
3518 aopPut (AOP (result), aopGet (AOP (left), 3), 1);
3519 aopPut (AOP (result), aopGet (AOP (left), 2), 0);
3520 aopPut (AOP (result), zero, 2);
3521 aopPut (AOP (result), zero, 3);
3526 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3527 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3528 aopPut (AOP (result), aopGet (AOP (left), 3), 2);
3529 aopPut (AOP (result), zero, 3);
3533 if (!hByteZ && !sameRegs (AOP (left), AOP (right))) {
3536 aopPut (AOP (result),
3537 aopGet (AOP (left), offset), offset);
3541 size = AOP_SIZE (result);
3547 emitcode ("lsr", "%s", aopGet (AOP (result), 3));
3548 emitcode ("ror", "%s", aopGet (AOP (result), 2));
3549 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3550 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3555 emitcode ("lsr", "%s", aopGet (AOP (result), 2));
3556 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3557 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3562 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3563 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3568 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3575 freeAsmop (left, NULL, ic, TRUE);
3576 freeAsmop (right, NULL, ic, TRUE);
3577 freeAsmop (result, NULL, ic, TRUE);
3580 /*-----------------------------------------------------------------*/
3581 /* genRightShift - generate code for right shifting */
3582 /*-----------------------------------------------------------------*/
3584 genRightShift (iCode * ic)
3586 operand *right, *left, *result;
3589 int sign = 0, first = 1;
3592 aopOp (right = IC_RIGHT (ic), ic, FALSE);
3594 if (AOP_TYPE (right) == AOP_LIT) {
3595 genShiftRightLit (ic);
3599 if (AOP_SIZE (right) > 1) {
3600 if (isRegPair (AOP (right))) {
3601 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3604 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3605 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3609 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3611 aopOp (left = IC_LEFT (ic), ic, FALSE);
3612 aopOp (result = IC_RESULT (ic), ic, FALSE);
3613 size = AOP_SIZE (result);
3614 tlbl = newiTempLabel (NULL);
3615 emitcode ("", "L%05d:", tlbl->key);
3617 letype = getSpec (operandType (left));
3618 sign = !SPEC_USIGN (letype);
3619 if (!sameRegs (AOP (left), AOP (result))) {
3621 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3624 size = AOP_SIZE (result);
3626 size = AOP_SIZE (result);
3630 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3632 emitcode ("lsr", "%s", aopGet (AOP (result), offset));
3636 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3639 if (AOP_SIZE (right) > 1)
3640 emitcode ("sbiw", "r24,1");
3642 emitcode ("dec", "r24");
3643 emitcode ("brne", "L%05d", tlbl->key);
3645 freeAsmop (left, NULL, ic, TRUE);
3646 freeAsmop (result, NULL, ic, TRUE);
3649 /*-----------------------------------------------------------------*/
3650 /* RRsh - shift right rn by known count */
3651 /*-----------------------------------------------------------------*/
3653 RRsh (int shCount,int reg)
3655 shCount &= 0x0007; // shCount : 0..7
3661 emitcode ("lsr", "r%d",reg);
3664 emitcode ("lsr", "r%d",reg);
3665 emitcode ("lsr", "r%d",reg);
3668 emitcode ("swap", "r%d",reg);
3669 emitcode ("lsl", "r%d",reg);
3672 emitcode ("swap", "r%d",reg);
3675 emitcode ("swap", "r%d",reg);
3676 emitcode ("lsr", "r%d",reg);
3679 emitcode ("swap","r%d",reg);
3680 emitcode ("lsr", "r%d",reg);
3681 emitcode ("lsr", "r%d",reg);
3684 emitcode ("swap","r%d",reg);
3685 emitcode ("lsr", "r%d",reg);
3686 emitcode ("lsr", "r%d",reg);
3687 emitcode ("lsr", "r%d",reg);
3692 /*-----------------------------------------------------------------*/
3693 /* RLsh - shift left rn by known count */
3694 /*-----------------------------------------------------------------*/
3696 RLsh (int shCount, int reg)
3698 shCount &= 0x0007; // shCount : 0..7
3704 emitcode ("lsl", "r%d",reg);
3707 emitcode ("lsl", "r%d",reg);
3708 emitcode ("lsl", "r%d",reg);
3711 emitcode ("swap","r%d",reg);
3712 emitcode ("lsr", "r%d",reg);
3715 emitcode ("swap", "r%d",reg);
3718 emitcode ("swap","r%d",reg);
3719 emitcode ("lsl", "r%d",reg);
3722 emitcode ("swap","r%d",reg);
3723 emitcode ("lsl", "r%d",reg);
3724 emitcode ("lsl", "r%d",reg);
3727 emitcode ("swap","r%d",reg);
3728 emitcode ("lsl", "r%d",reg);
3729 emitcode ("lsl", "r%d",reg);
3730 emitcode ("lsl", "r%d",reg);
3735 /*-----------------------------------------------------------------*/
3736 /* genUnpackBits - generates code for unpacking bits */
3737 /*-----------------------------------------------------------------*/
3739 genUnpackBits (operand * result, char *rname, int ptype)
3747 etype = getSpec (operandType (result));
3748 rsize = getSize (operandType (result));
3749 /* read the first byte */
3756 emitcode ("ld", "r24,%s+", rname);
3760 emitcode ("lpm", "r24,%s+", rname);
3764 emitcode ("call","__gptrget_pi");
3765 emitcode ("mov","r24,r0");
3769 rlen = SPEC_BLEN (etype);
3771 /* if we have bitdisplacement then it fits */
3772 /* into this byte completely or if length is */
3773 /* less than a byte */
3774 if ((shCnt = SPEC_BSTR (etype)) || (SPEC_BLEN (etype) <= 8)) {
3776 /* shift right acc */
3779 emitcode ("andi", "r24,lo(0x%x)",
3780 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
3781 aopPut (AOP (result), "r24", offset++);
3785 /* bit field did not fit in a byte */
3786 aopPut (AOP (result), "r24", offset++);
3796 emitcode ("ld", "r24,%s+");
3800 emitcode ("lpm", "r24,%s+");
3804 emitcode ("call", "__gptrget_pi");
3809 /* if we are done */
3813 aopPut (AOP (result), "r24", offset++);
3818 aopPut (AOP (result), "r24", offset++);
3822 if (offset < rsize) {
3825 aopPut (AOP (result), zero, offset++);
3830 /*-----------------------------------------------------------------*/
3831 /* genDataPointerGet - generates code when ptr offset is known */
3832 /*-----------------------------------------------------------------*/
3834 genDataPointerGet (operand * left, operand * result, iCode * ic)
3838 int size, offset = 0;
3839 aopOp (result, ic, TRUE);
3841 /* get the string representation of the name */
3842 l = aopGet (AOP (left), 0);
3843 size = AOP_SIZE (result);
3846 sprintf (buffer, "(%s + %d)", l, offset);
3848 sprintf (buffer, "%s", l);
3849 emitcode ("lds", "%s,%s", aopGet (AOP (result), offset++),
3853 freeAsmop (left, NULL, ic, TRUE);
3854 freeAsmop (result, NULL, ic, TRUE);
3857 /*-----------------------------------------------------------------*/
3858 /* genNearPointerGet - emitcode for near pointer fetch */
3859 /*-----------------------------------------------------------------*/
3861 genMemPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
3866 char *rname, *frname = NULL;
3867 sym_link *rtype, *retype;
3868 sym_link *ltype = operandType (left);
3870 rtype = operandType (result);
3871 retype = getSpec (rtype);
3873 aopOp (left, ic, FALSE);
3875 /* if left is rematerialisable and
3876 result is not bit variable type and
3877 the left is pointer to data space i.e
3878 lower 128 bytes of space */
3879 if (AOP_TYPE (left) == AOP_IMMD &&
3880 !IS_BITVAR (retype) && DCL_TYPE (ltype) == POINTER) {
3881 genDataPointerGet (left, result, ic);
3885 /* if the value is already in a pointer register
3886 then don't need anything more */
3887 if (!AOP_INPREG (AOP (left))) {
3888 /* otherwise get a free pointer register */
3890 preg = getFreePtr (ic, &aop, FALSE, 0);
3891 if (isRegPair (AOP (left) )) {
3892 emitcode ("movw", "%s,%s",
3893 aop->aopu.aop_ptr->name,
3894 aopGet(AOP(left),0));
3896 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
3897 aopGet (AOP (left), 0));
3898 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
3899 aopGet (AOP (left), 1));
3905 frname = aopGet(aop,0);
3909 } else if (AOP_ISZ(aop)) {
3912 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
3913 "pointer not in correct register");
3917 aopOp (result, ic, FALSE);
3919 /* if bitfield then unpack the bits */
3920 if (IS_BITVAR (retype))
3921 genUnpackBits (result, rname, POINTER);
3923 /* we have can just get the values */
3924 int size = AOP_SIZE (result);
3929 emitcode ("ld","%s,%s+",aopGet(AOP(result),offset), rname);
3931 emitcode ("ld","%s,%s",aopGet(AOP(result),offset), rname);
3936 /* now some housekeeping stuff */
3938 /* we had to allocate for this iCode */
3940 if (isRegPair (AOP (left) )) {
3941 emitcode ("movw", "%s,%s",
3942 aopGet (AOP(left),0),
3943 aop->aopu.aop_ptr->name);
3945 emitcode ("mov", "%s,%s",
3946 aopGet (AOP (left), 0),
3947 aop->aopu.aop_ptr->name);
3948 emitcode ("mov", "%s,%s",
3949 aopGet (AOP (left), 1),
3950 aop->aop_ptr2->name);
3953 freeAsmop (NULL, aop, ic, TRUE);
3956 /* we did not allocate which means left
3957 already in a pointer register, then
3958 if size > 0 && this could be used again
3959 we have to point it back to where it
3961 if ((AOP_SIZE (result) > 1 &&
3962 !OP_SYMBOL (left)->remat &&
3963 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) && !pi) {
3964 int size = AOP_SIZE (result) - 1;
3965 emitcode ("sbiw", "%s,%d",frname,size);
3970 if (pi) pi->generated = 1;
3971 freeAsmop (left, NULL, ic, TRUE);
3972 freeAsmop (result, NULL, ic, TRUE);
3976 /*-----------------------------------------------------------------*/
3977 /* genCodePointerGet - gget value from code space */
3978 /*-----------------------------------------------------------------*/
3980 genCodePointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
3983 sym_link *retype = getSpec (operandType (result));
3987 aopOp (left, ic, FALSE);
3989 /* if the operand is already in Z register
3990 then we do nothing else we move the value to Z register */
3991 if (AOP_ISZ(AOP(left))) {
3995 getFreePtr(ic,&aop,FALSE,TRUE);
3996 if (isRegPair(AOP (left))) {
3997 emitcode ("movw","r30,%s",aopGet (AOP (left), 0));
3999 emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
4000 emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
4005 aopOp (result, ic, FALSE);
4007 /* if bit then unpack */
4008 if (IS_BITVAR (retype))
4009 genUnpackBits (result, "Z", CPOINTER);
4011 size = AOP_SIZE (result);
4016 emitcode ("lpm","%s,Z+",aopGet(AOP(result),offset++));
4018 emitcode ("lpm","%s,Z",aopGet(AOP(result),offset++));
4023 /* now some housekeeping stuff */
4025 /* we had to allocate for this iCode */
4027 if (isRegPair(AOP (left))) {
4028 emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
4030 emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
4031 emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
4034 freeAsmop (NULL, aop, ic, TRUE);
4037 /* we did not allocate which means left
4038 already in a pointer register, then
4039 if size > 0 && this could be used again
4040 we have to point it back to where it
4042 if ((AOP_SIZE (result) > 1 &&
4043 !OP_SYMBOL (left)->remat &&
4044 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) &&
4046 int size = AOP_SIZE (result) - 1;
4047 emitcode ("sbiw", "r30,%d",size);
4052 if (pi) pi->generated=1;
4053 freeAsmop (left, NULL, ic, TRUE);
4054 freeAsmop (result, NULL, ic, TRUE);
4058 /*-----------------------------------------------------------------*/
4059 /* genGenPointerGet - gget value from generic pointer space */
4060 /*-----------------------------------------------------------------*/
4062 genGenPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
4066 sym_link *retype = getSpec (operandType (result));
4069 aopOp (left, ic, FALSE);
4071 /* if the operand is already in dptr
4072 then we do nothing else we move the value to dptr */
4073 if (AOP_ISZ(AOP(left))) {
4077 getFreePtr(ic,&aop,FALSE,TRUE);
4078 if (isRegPair(AOP(left))) {
4079 emitcode ("movw", "r30,%s", aopGet (AOP (left), 0));
4081 emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
4082 emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
4084 emitcode ("mov", "r24,%s", aopGet (AOP (left), 2));
4088 /* so Z register now contains the address */
4090 aopOp (result, ic, FALSE);
4092 /* if bit then unpack */
4093 if (IS_BITVAR (retype))
4094 genUnpackBits (result, "Z", GPOINTER);
4096 size = AOP_SIZE (result);
4101 emitcode ("call", "__gptrget_pi");
4103 emitcode ("call", "__gptrget");
4104 aopPut (AOP (result), "r0", offset++);
4109 /* now some housekeeping stuff */
4111 /* we had to allocate for this iCode */
4113 if (isRegPair(AOP (left))) {
4114 emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
4116 emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
4117 emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
4120 freeAsmop (NULL, aop, ic, TRUE);
4123 /* we did not allocate which means left
4124 already in a pointer register, then
4125 if size > 0 && this could be used again
4126 we have to point it back to where it
4128 if ((AOP_SIZE (result) > 1 &&
4129 !OP_SYMBOL (left)->remat &&
4130 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) &&
4132 int size = AOP_SIZE (result) - 1;
4133 emitcode ("sbiw", "r30,%d",size);
4136 if (pi) pi->generated=1;
4137 freeAsmop (left, NULL, ic, TRUE);
4138 freeAsmop (result, NULL, ic, TRUE);
4141 /*-----------------------------------------------------------------*/
4142 /* genPointerGet - generate code for pointer get */
4143 /*-----------------------------------------------------------------*/
4145 genPointerGet (iCode * ic, iCode *pi)
4147 operand *left, *result;
4148 sym_link *type, *etype;
4151 left = IC_LEFT (ic);
4152 result = IC_RESULT (ic);
4154 /* depending on the type of pointer we need to
4155 move it to the correct pointer register */
4156 type = operandType (left);
4157 etype = getSpec (type);
4158 /* if left is of type of pointer then it is simple */
4159 if (IS_PTR (type) && !IS_FUNC (type->next))
4160 p_type = DCL_TYPE (type);
4162 /* we have to go by the storage class */
4163 p_type = PTR_TYPE (SPEC_OCLS (etype));
4168 /* now that we have the pointer type we assign
4169 the pointer values */
4176 genMemPointerGet (left, result, ic, pi);
4180 genCodePointerGet (left, result, ic, pi);
4184 genGenPointerGet (left, result, ic, pi);
4190 /*-----------------------------------------------------------------*/
4191 /* genPackBits - generates code for packed bit storage */
4192 /*-----------------------------------------------------------------*/
4194 genPackBits (sym_link * etype,
4196 char *rname, int p_type)
4204 blen = SPEC_BLEN (etype);
4205 bstr = SPEC_BSTR (etype);
4207 l = aopGet (AOP (right), offset++);
4210 /* if the bit lenth is less than or */
4211 /* it exactly fits a byte then */
4212 if (SPEC_BLEN (etype) <= 8) {
4213 shCount = SPEC_BSTR (etype);
4215 /* shift left acc */
4218 if (SPEC_BLEN (etype) < 8) { /* if smaller than a byte */
4225 emitcode ("ld", "r1,%s",rname);
4229 emitcode ("push", "r1");
4230 emitcode ("push", "r24");
4231 emitcode ("call", "__gptrget");
4232 emitcode ("pop", "r1");
4233 emitcode ("mov","r24,r0");
4237 emitcode ("andi", "r24,#0x%02x", (unsigned char)
4238 ((unsigned char) (0xFF << (blen + bstr)) |
4239 (unsigned char) (0xFF >> (8 - bstr))));
4240 emitcode ("or", "r24,r1");
4241 if (p_type == GPOINTER)
4242 emitcode ("pop", "r1");
4251 emitcode("st","%s+,r24");
4255 emitcode("mov","r0,r24");
4256 emitcode ("call", "__gptrput_pi");
4261 if (SPEC_BLEN (etype) <= 8)
4264 rLen = SPEC_BLEN (etype);
4266 /* now generate for lengths greater than one byte */
4269 l = aopGet (AOP (right), offset++);
4280 emitcode ("st", "%s+,%s",rname,l);
4285 emitcode ("lcall", "__gptrput_pi");
4292 /* last last was not complete */
4294 /* save the byte & read byte */
4300 emitcode ("st","%s+,r24",rname);
4303 emitcode ("push", "r1");
4304 emitcode ("push", "r24");
4305 emitcode ("lcall", "__gptrget");
4306 emitcode ("mov","r24,r0");
4307 emitcode ("pop", "r1");
4311 emitcode ("andi", "r24,0x%02x", (((unsigned char) -1 << rLen) & 0xff));
4312 emitcode ("or", "r24,r1");
4315 if (p_type == GPOINTER)
4316 emitcode ("pop", "r1");
4324 emitcode ("st", "%s,r24", rname);
4328 emitcode ("mov","r0,r24");
4329 emitcode ("call", "__gptrput");
4334 /*-----------------------------------------------------------------*/
4335 /* genDataPointerSet - remat pointer to data space */
4336 /*-----------------------------------------------------------------*/
4338 genDataPointerSet (operand * right, operand * result, iCode * ic)
4340 int size, offset = 0;
4341 char *l, buffer[256];
4343 aopOp (right, ic, FALSE);
4345 l = aopGet (AOP (result), 0);
4346 size = AOP_SIZE (right);
4349 sprintf (buffer, "(%s + %d)", l, offset);
4351 sprintf (buffer, "%s", l);
4352 emitcode ("sts", "%s,%s", buffer,
4353 aopGet (AOP (right), offset++));
4356 freeAsmop (right, NULL, ic, TRUE);
4357 freeAsmop (result, NULL, ic, TRUE);
4360 /*-----------------------------------------------------------------*/
4361 /* genNearPointerSet - emitcode for near pointer put */
4362 /*-----------------------------------------------------------------*/
4364 genMemPointerSet (operand * right, operand * result, iCode * ic, iCode *pi)
4367 char *frname = NULL, *rname, *l;
4370 sym_link *ptype = operandType (result);
4372 retype = getSpec (operandType (right));
4374 aopOp (result, ic, FALSE);
4376 /* if the result is rematerializable &
4377 in data space & not a bit variable */
4378 if (AOP_TYPE (result) == AOP_IMMD &&
4379 DCL_TYPE (ptype) == POINTER && !IS_BITVAR (retype)) {
4380 genDataPointerSet (right, result, ic);
4383 if (!AOP_INPREG(AOP(result))) {
4384 /* otherwise get a free pointer register */
4386 getFreePtr (ic, &aop, FALSE, 0);
4387 if (isRegPair (AOP (result) )) {
4388 emitcode ("movw", "%s,%s",aop->aopu.aop_ptr->name,
4389 aopGet(AOP (result), 0));
4391 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
4392 aopGet (AOP (result), 0));
4393 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
4394 aopGet (AOP (result), 1));
4399 frname = aopGet(aop,0);
4402 aopOp (right, ic, FALSE);
4405 } else if (AOP_ISZ(aop)) {
4408 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4409 "pointer not in correct register");
4412 /* if bitfield then unpack the bits */
4413 if (IS_BITVAR (retype))
4414 genPackBits (retype, right, rname, POINTER);
4416 /* we have can just get the values */
4417 int size = AOP_SIZE (right);
4421 l = aopGet (AOP (right), offset);
4423 emitcode ("st", "%s+,%s", rname,l);
4425 emitcode ("st", "%s,%s", rname,l);
4430 /* now some housekeeping stuff */
4432 /* we had to allocate for this iCode */
4434 if (isRegPair (AOP (result) )) {
4435 emitcode ("movw", "%s,%s",
4436 aopGet(AOP(result),0),
4437 aop->aopu.aop_ptr->name);
4439 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
4440 aopGet (AOP (result), 0));
4441 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
4442 aopGet (AOP (result), 1));
4445 freeAsmop (NULL, aop, ic, TRUE);
4448 /* we did not allocate which means left
4449 already in a pointer register, then
4450 if size > 0 && this could be used again
4451 we have to point it back to where it
4453 if ((AOP_SIZE (right) > 1 &&
4454 !OP_SYMBOL (result)->remat &&
4455 (OP_SYMBOL (right)->liveTo > ic->seq || ic->depth)) && !pi) {
4456 int size = AOP_SIZE (right) - 1;
4457 emitcode ("sbiw", "%s,%d",frname,size);
4462 if (pi) pi->generated = 1;
4463 freeAsmop (result, NULL, ic, TRUE);
4464 freeAsmop (right, NULL, ic, TRUE);
4467 /*-----------------------------------------------------------------*/
4468 /* genGenPointerSet - set value from generic pointer space */
4469 /*-----------------------------------------------------------------*/
4471 genGenPointerSet (operand * right, operand * result, iCode * ic, iCode *pi)
4475 sym_link *retype = getSpec (operandType (right));
4478 aopOp (result, ic, FALSE);
4480 /* if the operand is already in dptr
4481 then we do nothing else we move the value to dptr */
4482 if (AOP_ISZ(AOP(result))) {
4486 getFreePtr(ic,&aop,FALSE,TRUE);
4487 if (isRegPair(AOP(result))) {
4488 emitcode ("movw", "r30,%s", aopGet (AOP (result), 0));
4490 emitcode ("mov", "r30,%s", aopGet (AOP (result), 0));
4491 emitcode ("mov", "r31,%s", aopGet (AOP (result), 1));
4493 emitcode ("mov", "r24,%s", aopGet (AOP (result), 2));
4497 /* so Z register now contains the address */
4498 aopOp (right, ic, FALSE);
4500 /* if bit then unpack */
4501 if (IS_BITVAR (retype))
4502 genUnpackBits (result, "Z", GPOINTER);
4504 size = AOP_SIZE (right);
4508 char *l = aopGet(AOP (right), offset++);
4512 emitcode ("call", "__gptrput_pi");
4514 emitcode ("call", "__gptrput");
4518 /* now some housekeeping stuff */
4520 /* we had to allocate for this iCode */
4522 if (isRegPair(AOP(result))) {
4523 emitcode ("movw", "%s,r30", aopGet (AOP (result), 0));
4525 emitcode ("mov", "%s,r30", aopGet (AOP (result), 0));
4526 emitcode ("mov", "%s,r31", aopGet (AOP (result), 1));
4529 freeAsmop (NULL, aop, ic, TRUE);
4532 /* we did not allocate which means left
4533 already in a pointer register, then
4534 if size > 0 && this could be used again
4535 we have to point it back to where it
4537 if ((AOP_SIZE (right) > 1 &&
4538 !OP_SYMBOL (result)->remat &&
4539 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) && !pi) {
4540 int size = AOP_SIZE (right) - 1;
4541 emitcode ("sbiw", "r30,%d",size);
4544 if (pi) pi->generated = 1;
4545 freeAsmop (right, NULL, ic, TRUE);
4546 freeAsmop (result, NULL, ic, TRUE);
4549 /*-----------------------------------------------------------------*/
4550 /* genPointerSet - stores the value into a pointer location */
4551 /*-----------------------------------------------------------------*/
4553 genPointerSet (iCode * ic, iCode *pi)
4555 operand *right, *result;
4556 sym_link *type, *etype;
4559 right = IC_RIGHT (ic);
4560 result = IC_RESULT (ic);
4562 /* depending on the type of pointer we need to
4563 move it to the correct pointer register */
4564 type = operandType (result);
4565 etype = getSpec (type);
4566 /* if left is of type of pointer then it is simple */
4567 if (IS_PTR (type) && !IS_FUNC (type->next)) {
4568 p_type = DCL_TYPE (type);
4571 /* we have to go by the storage class */
4572 p_type = PTR_TYPE (SPEC_OCLS (etype));
4576 /* now that we have the pointer type we assign
4577 the pointer values */
4584 genMemPointerSet (right, result, ic, pi);
4588 genGenPointerSet (right, result, ic, pi);
4592 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4593 "genPointerSet: illegal pointer type");
4598 /*-----------------------------------------------------------------*/
4599 /* genIfx - generate code for Ifx statement */
4600 /*-----------------------------------------------------------------*/
4602 genIfx (iCode * ic, iCode * popIc)
4604 operand *cond = IC_COND (ic);
4609 aopOp (cond, ic, FALSE);
4611 /* get the value into acc */
4612 if (AOP_SIZE(cond) == 1 && AOP_ISHIGHREG(AOP(cond),0)) {
4613 cname = aopGet(AOP(cond),0);
4615 toBoolean (cond, "r24", 0);
4619 /* the result is now in the accumulator */
4620 freeAsmop (cond, NULL, ic, TRUE);
4622 /* if there was something to be popped then do it */
4625 emitcode("cpi","%s,0",cname);
4626 } else if (!tob) emitcode("cpi","%s,0",cname);
4628 lbl = newiTempLabel(NULL);
4630 emitcode ("breq","L%05d",lbl->key);
4631 emitcode ("jmp","L%05d",IC_TRUE(ic)->key);
4632 emitcode ("","L%05d:",lbl->key);
4634 emitcode ("brne","L%05d",lbl->key);
4635 emitcode ("jmp","L%05d",IC_FALSE(ic)->key);
4636 emitcode ("","L%05d:",lbl->key);
4641 /*-----------------------------------------------------------------*/
4642 /* genAddrOf - generates code for address of */
4643 /*-----------------------------------------------------------------*/
4645 genAddrOf (iCode * ic)
4647 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
4650 aopOp (IC_RESULT (ic), ic, FALSE);
4651 assert(AOP_SIZE(IC_RESULT(ic)) >= 2);
4652 /* if the operand is on the stack then we
4653 need to get the stack offset of this
4656 /* if it has an offset then we need to compute it */
4658 if (allHigh(AOP(IC_RESULT(ic)))) {
4659 if (isRegPair (AOP(IC_RESULT(ic)))) {
4660 emitcode ("movw","%s,r28",aopGet(AOP(IC_RESULT(ic)),0));
4662 emitcode ("mov","%s,r28",aopGet(AOP(IC_RESULT(ic)),0));
4663 emitcode ("mov","%s,r29",aopGet(AOP(IC_RESULT(ic)),1));
4665 if (sym->stack < 0) {
4666 emitcode("subi","%s,<(%d)",aopGet(AOP(IC_RESULT(ic)),0),-sym->stack);
4667 emitcode("sbci","%s,>(%d)",aopGet(AOP(IC_RESULT(ic)),1),-sym->stack);
4669 emitcode("subi","%s,<(-%d)",aopGet(AOP(IC_RESULT(ic)),0),sym->stack);
4670 emitcode("sbci","%s,>(-%d)",aopGet(AOP(IC_RESULT(ic)),1),sym->stack);
4673 emitcode("movw","r24,r28");
4674 if (sym->stack > -63 && sym->stack < 63) {
4676 emitcode("sbiw","r24,%d",-sym->stack);
4678 emitcode("sbiw","r24,%d",sym->stack);
4680 if (sym->stack < 0) {
4681 emitcode("subi","r24,<(%d)",-sym->stack);
4682 emitcode("sbci","r25,>(%d)",-sym->stack);
4684 emitcode("subi","r24,<(-%d)",sym->stack);
4685 emitcode("sbci","r25,>(-%d)",sym->stack);
4689 aopPut(AOP(IC_RESULT(ic)),"r24",0);
4690 aopPut(AOP(IC_RESULT(ic)),"r25",1);
4694 aopPut(AOP(IC_RESULT(ic)),"r28",0);
4695 aopPut(AOP(IC_RESULT(ic)),"r29",1);
4697 /* fill the result with zero */
4698 size = AOP_SIZE (IC_RESULT (ic)) - 2;
4701 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
4707 /* object not on stack then we need the name */
4708 size = AOP_SIZE (IC_RESULT (ic));
4712 char s[SDCC_NAME_MAX];
4714 sprintf (s, ">(%s)", sym->rname);
4716 sprintf (s, "<(%s)", sym->rname);
4717 aopPut (AOP (IC_RESULT (ic)), s, offset++);
4721 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4725 /*-----------------------------------------------------------------*/
4726 /* genFarFarAssign - assignment when both are in far space */
4727 /*-----------------------------------------------------------------*/
4729 genFarFarAssign (operand * result, operand * right, iCode * ic)
4731 int size = AOP_SIZE (right);
4734 /* first push the right side on to the stack */
4736 l = aopGet (AOP (right), offset++);
4738 emitcode ("push", "acc");
4741 freeAsmop (right, NULL, ic, FALSE);
4742 /* now assign DPTR to result */
4743 aopOp (result, ic, FALSE);
4744 size = AOP_SIZE (result);
4746 emitcode ("pop", "acc");
4747 aopPut (AOP (result), "a", --offset);
4749 freeAsmop (result, NULL, ic, FALSE);
4753 /*-----------------------------------------------------------------*/
4754 /* genAssign - generate code for assignment */
4755 /*-----------------------------------------------------------------*/
4757 genAssign (iCode * ic)
4759 operand *result, *right;
4761 unsigned long lit = 0L;
4763 result = IC_RESULT (ic);
4764 right = IC_RIGHT (ic);
4766 /* if they are the same */
4767 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4770 aopOp (right, ic, FALSE);
4772 /* special case both in far space */
4773 if (AOP_TYPE (right) == AOP_DPTR &&
4774 IS_TRUE_SYMOP (result) && isOperandInFarSpace (result)) {
4776 genFarFarAssign (result, right, ic);
4780 aopOp (result, ic, TRUE);
4782 /* if they are the same registers */
4783 if (sameRegs (AOP (right), AOP (result)))
4786 /* if the result is a bit */
4787 if (AOP_TYPE (result) == AOP_CRY) {
4789 /* if the right size is a literal then
4790 we know what the value is */
4791 if (AOP_TYPE (right) == AOP_LIT) {
4792 if (((int) operandLitValue (right)))
4793 aopPut (AOP (result), one, 0);
4795 aopPut (AOP (result), zero, 0);
4799 /* the right is also a bit variable */
4800 if (AOP_TYPE (right) == AOP_CRY) {
4801 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4802 aopPut (AOP (result), "c", 0);
4807 toBoolean (right, "", 0);
4808 aopPut (AOP (result), "a", 0);
4812 /* bit variables done */
4814 size = AOP_SIZE (result);
4816 if (AOP_TYPE (right) == AOP_LIT)
4818 (unsigned long) floatFromVal (AOP (right)->aopu.
4820 if ((size > 1) && (AOP_TYPE (result) != AOP_REG)
4821 && (AOP_TYPE (right) == AOP_LIT)
4822 && !IS_FLOAT (operandType (right)) && (lit < 256L)) {
4823 emitcode ("clr", "a");
4825 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) ==
4826 0) aopPut (AOP (result), "a", size);
4828 aopPut (AOP (result),
4829 aopGet (AOP (right), size), size);
4834 aopPut (AOP (result),
4835 aopGet (AOP (right), offset), offset);
4841 freeAsmop (right, NULL, ic, FALSE);
4842 freeAsmop (result, NULL, ic, TRUE);
4845 /*-----------------------------------------------------------------*/
4846 /* genJumpTab - genrates code for jump table */
4847 /*-----------------------------------------------------------------*/
4849 genJumpTab (iCode * ic)
4854 aopOp (IC_JTCOND (ic), ic, FALSE);
4855 /* get the condition into accumulator */
4856 l = aopGet (AOP (IC_JTCOND (ic)), 0);
4858 /* multiply by three */
4859 emitcode ("add", "a,acc");
4860 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0));
4861 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
4863 jtab = newiTempLabel (NULL);
4864 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
4865 emitcode ("jmp", "@a+dptr");
4866 emitcode ("", "%05d$:", jtab->key + 100);
4867 /* now generate the jump labels */
4868 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
4869 jtab = setNextItem (IC_JTLABELS (ic)))
4870 emitcode ("ljmp", "%05d$", jtab->key + 100);
4874 /*-----------------------------------------------------------------*/
4875 /* genCast - gen code for casting */
4876 /*-----------------------------------------------------------------*/
4878 genCast (iCode * ic)
4880 operand *result = IC_RESULT (ic);
4881 sym_link *ctype = operandType (IC_LEFT (ic));
4882 sym_link *rtype = operandType (IC_RIGHT (ic));
4883 operand *right = IC_RIGHT (ic);
4886 /* if they are equivalent then do nothing */
4887 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4890 aopOp (right, ic, FALSE);
4891 aopOp (result, ic, FALSE);
4893 /* if the result is a bit */
4894 if (AOP_TYPE (result) == AOP_CRY) {
4895 /* if the right size is a literal then
4896 we know what the value is */
4897 if (AOP_TYPE (right) == AOP_LIT) {
4898 if (((int) operandLitValue (right)))
4899 aopPut (AOP (result), one, 0);
4901 aopPut (AOP (result), zero, 0);
4906 /* the right is also a bit variable */
4907 if (AOP_TYPE (right) == AOP_CRY) {
4908 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4909 aopPut (AOP (result), "c", 0);
4914 toBoolean (right, "", 0);
4915 aopPut (AOP (result), "a", 0);
4919 /* if they are the same size : or less */
4920 if (AOP_SIZE (result) <= AOP_SIZE (right)) {
4922 /* if they are in the same place */
4923 if (sameRegs (AOP (right), AOP (result)))
4926 /* if they in different places then copy */
4927 size = AOP_SIZE (result);
4930 aopPut (AOP (result),
4931 aopGet (AOP (right), offset), offset);
4938 /* if the result is of type pointer */
4939 if (IS_PTR (ctype)) {
4942 sym_link *type = operandType (right);
4943 sym_link *etype = getSpec (type);
4945 /* pointer to generic pointer */
4946 if (IS_GENPTR (ctype)) {
4948 p_type = DCL_TYPE (type);
4950 /* we have to go by the storage class */
4951 p_type = PTR_TYPE (SPEC_OCLS (etype));
4954 /* the first two bytes are known */
4955 size = GPTRSIZE - 1;
4958 aopPut (AOP (result),
4959 aopGet (AOP (right), offset), offset);
4963 /* the last byte depending on type */
4965 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
4970 // pointerTypeToGPByte will have bitched.
4974 sprintf(gpValStr, "#0x%d", gpVal);
4975 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
4980 /* just copy the pointers */
4981 size = AOP_SIZE (result);
4984 aopPut (AOP (result),
4985 aopGet (AOP (right), offset), offset);
4991 /* so we now know that the size of destination is greater
4992 than the size of the source */
4993 /* we move to result for the size of source */
4994 size = AOP_SIZE (right);
4997 aopPut (AOP (result), aopGet (AOP (right), offset), offset);
5001 /* now depending on the sign of the source && destination */
5002 size = AOP_SIZE (result) - AOP_SIZE (right);
5003 /* if unsigned or not an integral type */
5004 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype)) {
5006 aopPut (AOP (result), zero, offset++);
5009 /* we need to extend the sign :{ */
5010 // PENDING: Does nothing on avr
5012 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1);
5015 emitcode ("rlc", "a");
5016 emitcode ("subb", "a,acc");
5018 aopPut (AOP (result), "a", offset++);
5021 /* we are done hurray !!!! */
5024 freeAsmop (right, NULL, ic, TRUE);
5025 freeAsmop (result, NULL, ic, TRUE);
5029 /*-----------------------------------------------------------------*/
5030 /* genDjnz - generate decrement & jump if not zero instrucion */
5031 /*-----------------------------------------------------------------*/
5033 genDjnz (iCode * ic, iCode * ifx)
5039 /* if the if condition has a false label
5040 then we cannot save */
5044 /* if the minus is not of the form
5046 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
5047 !IS_OP_LITERAL (IC_RIGHT (ic)))
5050 if (operandLitValue (IC_RIGHT (ic)) != 1)
5053 /* if the size of this greater than one then no
5055 if (getSize (operandType (IC_RESULT (ic))) > 1)
5058 /* otherwise we can save BIG */
5059 lbl = newiTempLabel (NULL);
5060 lbl1 = newiTempLabel (NULL);
5062 aopOp (IC_RESULT (ic), ic, FALSE);
5064 if (IS_AOP_PREG (IC_RESULT (ic))) {
5065 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0));
5066 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0));
5067 emitcode ("jnz", "%05d$", lbl->key + 100);
5070 emitcode ("djnz", "%s,%05d$",
5071 aopGet (AOP (IC_RESULT (ic)), 0), lbl->key + 100);
5073 emitcode ("sjmp", "%05d$", lbl1->key + 100);
5074 emitcode ("", "%05d$:", lbl->key + 100);
5075 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5076 emitcode ("", "%05d$:", lbl1->key + 100);
5078 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5083 static char *recvregs[8] = {
5084 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23"
5087 static int recvCnt = 0;
5089 /*-----------------------------------------------------------------*/
5090 /* genReceive - generate code for a receive iCode */
5091 /*-----------------------------------------------------------------*/
5093 genReceive (iCode * ic)
5095 int size, offset = 0;
5096 aopOp (IC_RESULT (ic), ic, FALSE);
5097 size = AOP_SIZE (IC_RESULT (ic));
5099 aopPut (AOP (IC_RESULT (ic)), recvregs[recvCnt++], offset);
5102 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5105 /*-----------------------------------------------------------------*/
5106 /* genDummyRead - generate code for dummy read of volatiles */
5107 /*-----------------------------------------------------------------*/
5109 genDummyRead (iCode * ic)
5111 emitcode ("; genDummyRead","");
5112 emitcode ("; not implemented","");
5117 /*-----------------------------------------------------------------*/
5118 /* gen51Code - generate code for 8051 based controllers */
5119 /*-----------------------------------------------------------------*/
5121 genAVRCode (iCode * lic)
5126 lineHead = lineCurr = NULL;
5128 /* print the allocation information */
5130 printAllocInfo (currFunc, codeOutFile);
5131 /* if debug information required */
5132 if (options.debug && currFunc) {
5133 debugFile->writeFunction (currFunc, lic);
5135 /* stack pointer name */
5139 for (ic = lic; ic; ic = ic->next) {
5141 if (cln != ic->lineno) {
5142 if (options.debug) {
5143 debugFile->writeCLine (ic);
5145 emitcode (";", "%s %d", ic->filename, ic->lineno);
5148 /* if the result is marked as
5149 spilt and rematerializable or code for
5150 this has already been generated then
5152 if (resultRemat (ic) || ic->generated)
5155 /* depending on the operation */
5174 /* IPOP happens only when trying to restore a
5175 spilt live range, if there is an ifx statement
5176 following this pop then the if statement might
5177 be using some of the registers being popped which
5178 would destory the contents of the register so
5179 we need to check for this condition and handle it */
5181 ic->next->op == IFX &&
5182 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
5183 genIfx (ic->next, ic);
5201 genEndFunction (ic);
5221 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
5238 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
5242 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
5246 genCmpLe (ic, ifxForOp (IC_RESULT (ic), ic));
5250 genCmpGe (ic, ifxForOp (IC_RESULT (ic), ic));
5254 genCmpNe (ic, ifxForOp (IC_RESULT (ic), ic));
5258 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
5270 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
5274 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
5278 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
5305 case GET_VALUE_AT_ADDRESS:
5306 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
5310 if (POINTER_SET (ic))
5311 genPointerSet (ic, hasInc(IC_RESULT(ic),ic));
5337 addSet (&_G.sendSet, ic);
5340 case DUMMY_READ_VOLATILE:
5350 /* now we are ready to call the
5351 peep hole optimizer */
5352 if (!options.nopeep)
5353 peepHole (&lineHead);
5355 /* now do the actual printing */
5356 printLine (lineHead, codeOutFile);