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 struct dbuf_s *codeOutBuf;
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 ((unsigned char)*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 asmop *oldAsmOp = NULL;
763 /* rematerialize it NOW */
765 sym->aop = op->aop = aop = aopForRemat (sym);
766 aop->size = getSize (sym->type);
771 assert ("ACC_USE cannot happen in AVR\n");
776 aop = op->aop = sym->aop = newAsmop (AOP_STR);
777 aop->size = getSize (sym->type);
778 for (i = 0; i < (int) fAVRReturnSize; i++)
779 aop->aopu.aop_str[i] = fAVRReturn[i];
783 /* else spill location */
784 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
785 /* force a new aop if sizes differ */
786 oldAsmOp = sym->usl.spillLoc->aop;
787 sym->usl.spillLoc->aop = NULL;
789 sym->aop = op->aop = aop =
790 aopForSym (ic, sym->usl.spillLoc, result);
791 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
792 /* Don't reuse the new aop, go with the last one */
793 sym->usl.spillLoc->aop = oldAsmOp;
795 aop->size = getSize (sym->type);
799 /* must be in a register */
800 sym->aop = op->aop = aop = newAsmop (AOP_REG);
801 aop->size = sym->nRegs;
802 for (i = 0; i < sym->nRegs; i++)
803 aop->aopu.aop_reg[i] = sym->regs[i];
806 /*-----------------------------------------------------------------*/
807 /* freeAsmop - free up the asmop given to an operand */
808 /*----------------------------------------------------------------*/
810 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
827 /* depending on the asmop type only three cases need work AOP_RO
828 , AOP_R1 && AOP_STK */
833 emitcode ("pop", "r26");
834 emitcode ("pop", "r27");
838 bitVectUnSetBit (ic->rUsed, X_IDX);
844 emitcode ("pop", "r30");
845 emitcode ("pop", "r31");
849 bitVectUnSetBit (ic->rUsed, Z_IDX);
855 int stk = aop->aopu.aop_stk + aop->size;
856 bitVectUnSetBit (ic->rUsed, X_IDX);
857 bitVectUnSetBit (ic->rUsed, Z_IDX);
859 getFreePtr (ic, &aop, FALSE, 0);
861 emitcode ("movw", "%s,r28");
863 if (stk <= 63 && stk > 0) {
864 emitcode ("adiw", "%s,0x%02x",
865 aop->aopu.aop_ptr->name,
869 emitcode ("subi", "%s,<(%d)",
870 aop->aopu.aop_ptr->name,
872 emitcode ("sbci", "%s,>(%d)",
879 emitcode ("pop", "r24");
880 emitcode ("st", "-%s,r24",
881 aop->type == AOP_X ? "X" : "Z");
886 freeAsmop (op, NULL, ic, TRUE);
888 emitcode ("pop", "r26");
889 emitcode ("pop", "r27");
894 emitcode ("pop", "r30");
895 emitcode ("pop", "r31");
902 /* all other cases just dealloc */
906 OP_SYMBOL (op)->aop = NULL;
907 /* if the symbol has a spill */
909 SPIL_LOC (op)->aop = NULL;
914 /*-----------------------------------------------------------------*/
915 /* aopGet - for fetching value of the aop */
916 /*-----------------------------------------------------------------*/
918 aopGet (asmop * aop, int offset)
923 /* offset is greater than
925 if (offset > (aop->size - 1) && aop->type != AOP_LIT)
928 /* depending on type */
932 if (offset > aop->coff) {
933 emitcode ("adiw", "%s,%d", aop->aopu.aop_ptr->name,
937 if (offset < aop->coff) {
938 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name,
943 emitcode ("ld", "%s,x",
944 (rs = ((offset & 1) ? "r25" : "r24")));
949 if (offset > aop->coff) {
950 emitcode ("adiw", "r30,%d",
954 emitcode ("sbiw", "r30,%d",
957 emitcode ("lpm", "%s,z",
958 (rs = ((offset & 1) ? "r25" : "r24")));
962 if (offset > aop->coff) {
963 emitcode ("ldd", "%s,z+%d",
965 ((offset & 1) ? "r25" : "r24")),
969 emitcode ("sbiw", "%s,%d",
970 aop->aopu.aop_ptr->name,
973 emitcode ("ld", "%s,z",
975 ((offset & 1) ? "r25" : "r24")));
982 emitcode ("lds", "%s,(%s)+%d",
983 (rs = ((offset & 1) ? "r25" : "r24")),
984 aop->aopu.aop_immd, offset);
988 emitcode ("lds", "%s,(%s)+%d",
989 (rs = ((offset & 1) ? "r25" : "r24")),
990 aop->aopu.aop_dir, offset);
994 return aop->aopu.aop_reg[offset]->name;
997 assert ("cannot be in bit space AOP_CRY\n");
1001 s = aopLiteral (aop->aopu.aop_lit, offset);
1002 emitcode ("ldi", "%s,<(%s)",
1003 (rs = ((offset & 1) ? "r24" : "r25")), s);
1008 return aop->aopu.aop_str[offset];
1011 emitcode ("ldd", "%s,Y+%d",
1012 (rs = ((offset & 1) ? "r25" : "r24")),
1013 aop->aopu.aop_stk + offset);
1017 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1018 "aopget got unsupported aop->type");
1022 /*-----------------------------------------------------------------*/
1023 /* aopPut - puts a string for a aop */
1024 /*-----------------------------------------------------------------*/
1026 aopPut (asmop * aop, char *s, int offset)
1030 if (aop->size && offset > (aop->size - 1)) {
1031 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1032 "aopPut got offset > aop->size");
1036 /* will assign value to value */
1037 /* depending on where it is ofcourse */
1038 switch (aop->type) {
1041 sprintf (d, "(%s)+%d", aop->aopu.aop_dir, offset);
1044 sprintf (d, "%s", aop->aopu.aop_dir);
1047 emitcode ("sts", "%s,%s", d, s);
1051 if (toupper ((unsigned char)*s) != 'R') {
1053 emitcode ("clr", "%s",
1054 aop->aopu.aop_reg[offset]->name);
1057 emitcode ("ldi", "r25,%s", s);
1058 emitcode ("mov", "%s,r35",
1059 aop->aopu.aop_reg[offset]->name);
1063 if (strcmp (aop->aopu.aop_reg[offset]->name, s)) {
1064 emitcode ("mov", "%s,%s",
1065 aop->aopu.aop_reg[offset]->name, s);
1071 if (offset > aop->coff) {
1072 emitcode ("adiw", "%s,%d", aop->aopu.aop_ptr->name,
1073 offset - aop->coff);
1076 if (offset < aop->coff) {
1077 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name,
1078 aop->coff - offset);
1082 emitcode ("st", "x,%s", s);
1087 if (offset > aop->coff) {
1088 emitcode ("adiw", "r30,%d",
1089 offset - aop->coff);
1092 emitcode ("sbiw", "r30,%d",
1093 aop->coff - offset);
1095 emitcode ("lpm", "%s,z", s);
1098 /* we can use lds */
1099 if (offset > aop->coff) {
1100 emitcode ("sdd", "z+%d,%s",
1101 offset - aop->coff, s);
1104 emitcode ("sbiw", "%s,%d",
1105 aop->aopu.aop_ptr->name,
1106 aop->coff - offset);
1108 emitcode ("ld", "%s,z", s);
1114 emitcode ("push", "%s", s);
1118 /* if used only for a condition code check */
1119 assert (toupper ((unsigned char)*s) == 'R');
1121 emitcode ("xrl", "r0,r0");
1122 emitcode ("cpi", "%s,0", s);
1125 emitcode ("cpc", "r0,%s", s);
1131 if (strcmp (aop->aopu.aop_str[offset], s))
1132 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset],
1137 emitcode ("std", "y+%d,%s", offset, s);
1141 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1142 "aopPut got unsupported aop->type");
1148 #define AOP(op) op->aop
1149 #define AOP_TYPE(op) AOP(op)->type
1150 #define AOP_SIZE(op) AOP(op)->size
1151 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_X || \
1152 AOP_TYPE(x) == AOP_Z))
1153 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1154 ((x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R27_IDX)) || \
1155 (x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R31_IDX)) )))
1156 #define AOP_ISX(x) (x && (x->type == AOP_REG && \
1157 ((x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R27_IDX)))))
1158 #define AOP_ISZ(x) (x && (x->type == AOP_REG && \
1159 ((x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R31_IDX)))))
1161 /*-----------------------------------------------------------------*/
1162 /* genNotFloat - generates not for float operations */
1163 /*-----------------------------------------------------------------*/
1165 genNotFloat (operand * op, operand * res)
1171 /* we will put 127 in the first byte of
1173 aopPut (AOP (res), "127", 0);
1174 size = AOP_SIZE (op) - 1;
1177 l = aopGet (op->aop, offset++);
1181 emitcode ("or", "R0,%s", aopGet (op->aop, offset++));
1183 tlbl = newiTempLabel (NULL);
1185 tlbl = newiTempLabel (NULL);
1186 aopPut (res->aop, zero, 1);
1187 emitcode ("cpi", "r0,0");
1188 emitcode ("breq", "L%05d", tlbl->key);
1189 aopPut (res->aop, one, 1);
1190 emitcode ("", "L%05d:", tlbl->key);
1192 size = res->aop->size - 2;
1194 /* put zeros in the rest */
1196 aopPut (res->aop, zero, offset++);
1199 /*-----------------------------------------------------------------*/
1200 /* opIsGptr: returns non-zero if the passed operand is */
1201 /* a generic pointer type. */
1202 /*-----------------------------------------------------------------*/
1204 opIsGptr (operand * op)
1206 sym_link *type = operandType (op);
1208 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type)) {
1214 /*-----------------------------------------------------------------*/
1215 /* getDataSize - get the operand data size */
1216 /*-----------------------------------------------------------------*/
1218 getDataSize (operand * op)
1221 size = AOP_SIZE (op);
1222 if (size == GPTRSIZE) {
1223 sym_link *type = operandType (op);
1224 if (IS_GENPTR (type)) {
1225 /* generic pointer; arithmetic operations
1226 * should ignore the high byte (pointer type).
1234 /*-----------------------------------------------------------------*/
1235 /* toBoolean - emit code for orl a,operator(sizeop) */
1236 /*-----------------------------------------------------------------*/
1238 toBoolean (operand * oper, char *r, bool clr)
1240 int size = AOP_SIZE (oper);
1243 emitcode ("clr", "%s", r);
1245 emitcode ("or", "%s,%s", r, aopGet (AOP (oper), offset++));
1248 emitcode("mov","%s,%s",r,aopGet (AOP (oper), offset++));
1249 if (size) while (size--) emitcode ("or", "%s,%s", r, aopGet (AOP (oper), offset++));
1254 /*-----------------------------------------------------------------*/
1255 /* genNot - generate code for ! operation */
1256 /*-----------------------------------------------------------------*/
1261 sym_link *optype = operandType (IC_LEFT (ic));
1262 int size, offset = 1;
1264 /* assign asmOps to operand & result */
1265 aopOp (IC_LEFT (ic), ic, FALSE);
1266 aopOp (IC_RESULT (ic), ic, TRUE);
1268 /* if type float then do float */
1269 if (IS_FLOAT (optype)) {
1270 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1273 emitcode ("clr", "r24");
1274 tlbl = newiTempLabel (NULL);
1275 size = AOP_SIZE (IC_LEFT (ic));
1278 emitcode ("cpse", "%s,r24", aopGet (AOP (IC_LEFT (ic)), 0));
1283 emitcode ("cpc", "%s,r24",
1284 aopGet (AOP (IC_LEFT (ic)),
1287 emitcode ("cpi", "%s,0",
1288 aopGet (AOP (IC_LEFT (ic)),
1292 emitcode ("bne", "L%05d", tlbl->key);
1294 emitcode ("ldi", "r24,1");
1295 emitcode ("", "L%05d:", tlbl->key);
1296 aopPut (AOP (IC_RESULT (ic)), "r24", 0);
1297 size = AOP_SIZE (IC_RESULT (ic)) - 1;
1300 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
1304 /* release the aops */
1305 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1306 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1310 /*-----------------------------------------------------------------*/
1311 /* genCpl - generate code for complement */
1312 /*-----------------------------------------------------------------*/
1320 /* assign asmOps to operand & result */
1321 aopOp (IC_LEFT (ic), ic, FALSE);
1322 aopOp (IC_RESULT (ic), ic, TRUE);
1323 samer = sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)));
1324 size = AOP_SIZE (IC_RESULT (ic));
1326 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
1328 emitcode ("com", "%s", l);
1331 aopPut (AOP (IC_RESULT (ic)), l, offset);
1332 emitcode ("com", "%s",
1333 aopGet (AOP (IC_RESULT (ic)), offset));
1338 /* release the aops */
1339 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1340 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1343 /*-----------------------------------------------------------------*/
1344 /* genUminusFloat - unary minus for floating points */
1345 /*-----------------------------------------------------------------*/
1347 genUminusFloat (operand * op, operand * result)
1349 int size, offset = 0;
1351 /* for this we just need to flip the
1352 first it then copy the rest in place */
1353 size = AOP_SIZE (op) - 1;
1354 l = aopGet (AOP (op), 3);
1356 emitcode ("ldi", "r24,0x80");
1357 if (sameRegs (AOP (op), AOP (result))) {
1358 emitcode ("eor", "%s,r24", l);
1361 aopPut (AOP (result), l, 3);
1362 emitcode ("eor", "%s,r24", aopGet (AOP (result), 3));
1365 aopPut (AOP (result), aopGet (AOP (op), offset), offset);
1370 /*-----------------------------------------------------------------*/
1371 /* genUminus - unary minus code generation */
1372 /*-----------------------------------------------------------------*/
1374 genUminus (iCode * ic)
1377 sym_link *optype, *rtype;
1381 aopOp (IC_LEFT (ic), ic, FALSE);
1382 aopOp (IC_RESULT (ic), ic, TRUE);
1384 optype = operandType (IC_LEFT (ic));
1385 rtype = operandType (IC_RESULT (ic));
1387 /* if float then do float stuff */
1388 if (IS_FLOAT (optype)) {
1389 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1393 /* otherwise subtract from zero */
1394 size = AOP_SIZE (IC_LEFT (ic));
1396 samer = sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)));
1399 emitcode ("neg", "%s",
1400 aopGet (AOP (IC_LEFT (ic)), 0));
1403 aopPut (AOP (IC_RESULT (ic)),
1404 aopGet (AOP (IC_LEFT (ic)), 0), 0);
1405 emitcode ("neg", "%s",
1406 aopGet (AOP (IC_RESULT (ic)), 0));
1412 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
1414 aopPut (AOP (IC_RESULT (ic)), l, offset);
1415 l = aopGet (AOP (IC_RESULT (ic)), offset);
1418 emitcode ("com", "%s", l);
1420 emitcode ("neg", "%s", l);
1423 size = AOP_SIZE (IC_LEFT (ic)) - 1;
1426 emitcode ("sbci", "%s,0xff",
1427 aopGet (AOP (IC_RESULT (ic)), offset++));
1431 /* if any remaining bytes in the result */
1432 /* we just need to propagate the sign */
1433 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic))))) {
1434 symbol *tlbl = newiTempLabel (NULL);
1435 emitcode ("clr", "r0");
1436 emitcode ("brcc", "L%05d", tlbl->key);
1437 emitcode ("com", "r0");
1438 emitcode ("", "L%05d:", tlbl->key);
1440 aopPut (AOP (IC_RESULT (ic)), "r0", offset++);
1444 /* release the aops */
1445 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1446 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1449 /*-----------------------------------------------------------------*/
1450 /* assignResultValue - */
1451 /*-----------------------------------------------------------------*/
1453 assignResultValue (operand * oper)
1456 int size = AOP_SIZE (oper);
1458 aopPut (AOP (oper), fAVRReturn[offset], offset);
1463 /*-----------------------------------------------------------------*/
1464 /* saveZreg - if indirect call then save z-pointer register */
1465 /*-----------------------------------------------------------------*/
1467 saveZreg (iCode * ic)
1469 /* only if live accross this call */
1470 if (ic->regsSaved == 0 &&
1471 (bitVectBitValue (ic->rMask, R30_IDX) ||
1472 bitVectBitValue (ic->rMask, R31_IDX))) {
1474 emitcode ("push", "r30");
1475 emitcode ("push", "r31");
1479 /*-----------------------------------------------------------------*/
1480 /* popZreg - restore values of zreg */
1481 /*-----------------------------------------------------------------*/
1483 popZreg (iCode * ic)
1485 if (ic->regsSaved) {
1486 emitcode ("pop", "r31");
1487 emitcode ("pop", "r30");
1491 /*-----------------------------------------------------------------*/
1492 /* genIpush - genrate code for pushing this gets a little complex */
1493 /*-----------------------------------------------------------------*/
1495 genIpush (iCode * ic)
1497 int size, offset = 0;
1501 if (!ic->parmPush) {
1502 /* and the item is spilt then do nothing */
1503 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1508 for (lic = ic->next; lic; lic = lic->next)
1509 if (lic->op == PCALL)
1515 /* this is a paramter push */
1516 aopOp (IC_LEFT (ic), ic, FALSE);
1517 size = AOP_SIZE (IC_LEFT (ic));
1519 l = aopGet (AOP (IC_LEFT (ic)), offset++);
1520 emitcode ("push", "%s", l);
1523 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1526 /*-----------------------------------------------------------------*/
1527 /* genIpop - recover the registers: can happen only for spilling */
1528 /*-----------------------------------------------------------------*/
1530 genIpop (iCode * ic)
1535 /* if the temp was not pushed then */
1536 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1539 aopOp (IC_LEFT (ic), ic, FALSE);
1540 size = AOP_SIZE (IC_LEFT (ic));
1541 offset = (size - 1);
1543 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--));
1545 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1548 /*-----------------------------------------------------------------*/
1549 /* genCall - generates a call statement */
1550 /*-----------------------------------------------------------------*/
1552 genCall (iCode * ic)
1555 /* if send set is not empty then assign */
1559 for (sic = setFirstItem (_G.sendSet); sic;
1560 sic = setNextItem (_G.sendSet)) {
1561 int size, offset = 0;
1562 aopOp (IC_LEFT (sic), sic, FALSE);
1563 size = AOP_SIZE (IC_LEFT (sic));
1566 aopGet (AOP (IC_LEFT (sic)), offset);
1568 sprintf (buffer, "r%d", rnum++);
1570 emitcode ("mov", "%s,%s", b, l);
1573 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1578 emitcode ("call", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1579 OP_SYMBOL (IC_LEFT (ic))->rname :
1580 OP_SYMBOL (IC_LEFT (ic))->name));
1582 /* if we need assign a result value */
1583 if ((IS_ITEMP (IC_RESULT (ic)) &&
1584 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1585 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1586 IS_TRUE_SYMOP (IC_RESULT (ic))) {
1588 aopOp (IC_RESULT (ic), ic, FALSE);
1589 assignResultValue (IC_RESULT (ic));
1590 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1593 /* adjust the stack for parameters if required */
1594 if (ic->parmBytes) {
1595 if (ic->parmBytes > 63) {
1596 emitcode ("sbiw", "r28,%d", ic->parmBytes);
1599 emitcode ("subi", "r28,<(%d)",
1601 emitcode ("sbci", "r29,>(%d)",
1608 /*-----------------------------------------------------------------*/
1609 /* genPcall - generates a call by pointer statement */
1610 /*-----------------------------------------------------------------*/
1612 genPcall (iCode * ic)
1618 aopOp (IC_LEFT (ic), ic, FALSE);
1619 emitcode ("mov", "r30", aopGet (AOP (IC_LEFT (ic)), 0));
1620 emitcode ("mov", "r31", aopGet (AOP (IC_RIGHT (ic)), 0));
1621 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1623 /* if send set is not empty the assign */
1627 for (sic = setFirstItem (_G.sendSet); sic;
1628 sic = setNextItem (_G.sendSet)) {
1629 int size, offset = 0;
1630 aopOp (IC_LEFT (sic), sic, FALSE);
1631 size = AOP_SIZE (IC_LEFT (sic));
1634 aopGet (AOP (IC_LEFT (sic)), offset);
1636 sprintf (b, "r%d", rnum++);
1638 emitcode ("mov", "%s,%s", b, l);
1641 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1646 emitcode ("icall", "");
1648 /* if we need assign a result value */
1649 if ((IS_ITEMP (IC_RESULT (ic)) &&
1650 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1651 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1652 IS_TRUE_SYMOP (IC_RESULT (ic))) {
1654 aopOp (IC_RESULT (ic), ic, FALSE);
1656 assignResultValue (IC_RESULT (ic));
1657 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1660 /* adjust the stack for parameters if
1662 if (ic->parmBytes) {
1664 if (ic->parmBytes > 3) {
1665 emitcode ("mov", "a,%s", spname);
1666 emitcode ("add", "a,#0x%02x",
1667 (-ic->parmBytes) & 0xff);
1668 emitcode ("mov", "%s,a", spname);
1671 for (i = 0; i < ic->parmBytes; i++)
1672 emitcode ("dec", "%s", spname);
1676 /* adjust the stack for parameters if required */
1677 if (ic->parmBytes) {
1678 if (ic->parmBytes > 63) {
1679 emitcode ("sbiw", "r28,%d", ic->parmBytes);
1682 emitcode ("subi", "r28,<(%d)",
1684 emitcode ("sbci", "r29,>(%d)",
1692 /*-----------------------------------------------------------------*/
1693 /* resultRemat - result is rematerializable */
1694 /*-----------------------------------------------------------------*/
1696 resultRemat (iCode * ic)
1698 if (SKIP_IC (ic) || ic->op == IFX)
1701 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic))) {
1702 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
1703 if (sym->remat && !POINTER_SET (ic))
1710 /*-----------------------------------------------------------------*/
1711 /* genFunction - generated code for function entry */
1712 /*-----------------------------------------------------------------*/
1714 genFunction (iCode * ic)
1721 /* create the function header */
1722 emitcode (";", "-----------------------------------------");
1723 emitcode (";", " function %s",
1724 (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
1725 emitcode (";", "-----------------------------------------");
1727 emitcode ("", "%s:", sym->rname);
1728 ftype = operandType (IC_LEFT (ic));
1730 /* if critical function then turn interrupts off */
1731 if (IFFUNC_ISCRITICAL (ftype))
1732 emitcode ("cli", "");
1734 if (IFFUNC_ISISR (sym->type)) {
1737 /* save the preserved registers that are used in this function */
1738 for (i = R2_IDX; i <= R15_IDX; i++) {
1739 if (bitVectBitValue (sym->regsUsed, i)) {
1741 emitcode ("push", "%s", avr_regWithIdx (i)->name);
1744 /* now for the pointer registers */
1745 if (bitVectBitValue (sym->regsUsed, R26_IDX)) {
1747 emitcode ("push", "r26");
1749 if (bitVectBitValue (sym->regsUsed, R27_IDX)) {
1751 emitcode ("push", "r27");
1753 if (bitVectBitValue (sym->regsUsed, R30_IDX)) {
1755 emitcode ("push", "r30");
1757 if (bitVectBitValue (sym->regsUsed, R31_IDX)) {
1759 emitcode ("push", "r31");
1761 /* adjust the stack for the function */
1763 emitcode ("push", "r28");
1764 emitcode ("push", "r29");
1765 emitcode ("in", "r28,__SP_L__");
1766 emitcode ("in", "r29,__SP_H__");
1767 if (sym->stack <= 63) {
1768 emitcode ("sbiw", "r28,%d", sym->stack);
1771 emitcode ("subi", "r28,<(%d)", sym->stack);
1772 emitcode ("sbci", "r29,>(%d)", sym->stack);
1774 emitcode ("out", "__SP_L__,r28");
1775 emitcode ("out", "__SP_H__,r29");
1779 /*-----------------------------------------------------------------*/
1780 /* genEndFunction - generates epilogue for functions */
1781 /*-----------------------------------------------------------------*/
1783 genEndFunction (iCode * ic)
1785 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
1788 /* restore stack pointer */
1790 if (sym->stack <= 63) {
1791 emitcode ("adiw", "r28,%d", sym->stack);
1794 emitcode ("subi", "r28,<(-%d)", sym->stack);
1795 emitcode ("sbci", "r29,>(-%d)", sym->stack);
1797 emitcode ("out", "__SP_L__,r28");
1798 emitcode ("out", "__SP_H__,r29");
1800 /* pop frame pointer */
1801 emitcode ("pop", "r29");
1802 emitcode ("pop", "r28");
1804 /* restore preserved registers */
1805 if (bitVectBitValue (sym->regsUsed, R31_IDX)) {
1807 emitcode ("pop", "r31");
1809 if (bitVectBitValue (sym->regsUsed, R30_IDX)) {
1811 emitcode ("pop", "r30");
1813 if (bitVectBitValue (sym->regsUsed, R27_IDX)) {
1815 emitcode ("pop", "r27");
1817 if (bitVectBitValue (sym->regsUsed, R26_IDX)) {
1819 emitcode ("pop", "r26");
1821 for (i = R15_IDX; i >= R2_IDX; i--) {
1822 if (bitVectBitValue (sym->regsUsed, i)) {
1824 emitcode ("pop", "%s", avr_regWithIdx (i)->name);
1828 if (IFFUNC_ISCRITICAL (sym->type))
1829 emitcode ("sti", "");
1831 if (options.debug && currFunc) {
1832 debugFile->writeEndFunction (currFunc, ic, 1);
1835 if (IFFUNC_ISISR (sym->type)) {
1836 emitcode ("rti", "");
1839 emitcode ("ret", "");
1844 /*-----------------------------------------------------------------*/
1845 /* genRet - generate code for return statement */
1846 /*-----------------------------------------------------------------*/
1850 int size, offset = 0;
1852 /* if we have no return value then
1853 just generate the "ret" */
1857 /* we have something to return then
1858 move the return value into place */
1859 aopOp (IC_LEFT (ic), ic, FALSE);
1860 size = AOP_SIZE (IC_LEFT (ic));
1863 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) {
1864 emitcode ("ldi", "%s,%s(%d)", fAVRReturn[offset],
1866 (int) floatFromVal (AOP (IC_LEFT (ic))->
1867 aopu.aop_lit), offset);
1871 l = aopGet (AOP (IC_LEFT (ic)), offset);
1872 if (strcmp (fAVRReturn[offset], l))
1873 emitcode ("mov", "%s,%s", fAVRReturn[offset],
1879 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1882 /* generate a jump to the return label
1883 if the next is not the return statement */
1884 if (!(ic->next && ic->next->op == LABEL &&
1885 IC_LABEL (ic->next) == returnLabel))
1887 emitcode ("rjmp", "L%05d", returnLabel->key);
1891 /*-----------------------------------------------------------------*/
1892 /* genLabel - generates a label */
1893 /*-----------------------------------------------------------------*/
1895 genLabel (iCode * ic)
1897 /* special case never generate */
1898 if (IC_LABEL (ic) == entryLabel)
1901 emitcode ("", "L%05d:", IC_LABEL (ic)->key);
1904 /*-----------------------------------------------------------------*/
1905 /* genGoto - generates a ljmp */
1906 /*-----------------------------------------------------------------*/
1908 genGoto (iCode * ic)
1910 emitcode ("rjmp", "L%05d", (IC_LABEL (ic)->key));
1913 /*-----------------------------------------------------------------*/
1914 /* genPlusIncr :- does addition with increment if possible */
1915 /*-----------------------------------------------------------------*/
1917 genPlusIncr (iCode * ic)
1919 unsigned int icount;
1922 /* will try to generate an increment */
1923 /* if the right side is not a literal
1925 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
1928 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.
1931 /* if the sizes are greater than 2 or they are not the same regs
1933 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1936 /* so we know LEFT & RESULT in the same registers and add
1938 /* for short & char types */
1939 if (AOP_SIZE (IC_RESULT (ic)) < 2) {
1941 emitcode ("inc", "%s",
1942 aopGet (AOP (IC_LEFT (ic)), 0));
1945 if (AOP_ISHIGHREG( AOP (IC_LEFT (ic)),0)) {
1946 emitcode ("subi", "%s,<(%d)",
1947 aopGet (AOP (IC_LEFT (ic)), 0), 0-icount);
1952 for (offset = 0 ; offset < AOP_SIZE(IC_RESULT(ic)) ; offset++) {
1953 if (!(AOP_ISHIGHREG(AOP(IC_RESULT(ic)),offset))) return FALSE;
1956 if (AOP_SIZE (IC_RESULT (ic)) <= 3) {
1957 /* if register pair and starts with 26/30 then adiw */
1958 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0
1960 && (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX) ||
1961 IS_REGIDX (AOP (IC_RESULT (ic)), R24_IDX) ||
1962 IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX))) {
1963 emitcode ("adiw", "%s,%d",
1964 aopGet (AOP (IC_RESULT (ic)), 0), icount);
1969 emitcode ("subi", "%s,<(%d)",
1970 aopGet (AOP (IC_RESULT (ic)), 0), 0-icount);
1971 emitcode ("sbci", "%s,>(%d)",
1972 aopGet (AOP (IC_RESULT (ic)), 1), 0-icount);
1976 /* for 32 bit longs */
1977 emitcode ("subi", "%s,<(%d)", aopGet (AOP (IC_RESULT (ic)), 0),
1979 emitcode ("sbci", "%s,>(%d)", aopGet (AOP (IC_RESULT (ic)), 1),
1981 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2),
1983 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3),
1989 /* This is the pure and virtuous version of this code.
1990 * I'm pretty certain it's right, but not enough to toss the old
1994 adjustArithmeticResult (iCode * ic)
1996 if (opIsGptr (IC_RESULT (ic)) &&
1997 opIsGptr (IC_LEFT (ic)) &&
1998 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)))) {
1999 aopPut (AOP (IC_RESULT (ic)),
2000 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1),
2004 if (opIsGptr (IC_RESULT (ic)) &&
2005 opIsGptr (IC_RIGHT (ic)) &&
2006 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)))) {
2007 aopPut (AOP (IC_RESULT (ic)),
2008 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1),
2012 if (opIsGptr (IC_RESULT (ic)) &&
2013 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2014 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2015 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2016 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)))) {
2018 sprintf (buffer, "%d",
2019 pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2020 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2024 /*-----------------------------------------------------------------*/
2025 /* genPlus - generates code for addition */
2026 /*-----------------------------------------------------------------*/
2028 genPlus (iCode * ic)
2030 int size, offset = 0;
2034 /* special cases :- */
2036 aopOp (IC_LEFT (ic), ic, FALSE);
2037 aopOp (IC_RIGHT (ic), ic, FALSE);
2038 aopOp (IC_RESULT (ic), ic, TRUE);
2040 /* if I can do an increment instead
2041 of add then GOOD for ME */
2042 if (genPlusIncr (ic) == TRUE)
2045 size = getDataSize (IC_RESULT (ic));
2046 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2050 aopPut (AOP (IC_RESULT (ic)),
2051 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2053 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
2060 emitcode (l, "%s,%s",
2061 aopGet (AOP (IC_RESULT (ic)), offset),
2062 aopGet (AOP (IC_RIGHT (ic)), offset));
2065 if (AOP_ISHIGHREG( AOP( IC_RESULT(ic)),offset)) {
2071 emitcode (l, "%s,%s(-%d)",
2072 aopGet (AOP (IC_RESULT (ic)), offset),
2074 (int) floatFromVal (AOP (IC_RIGHT (ic))->
2082 emitcode (l, "%s,%s",
2083 aopGet (AOP (IC_RESULT (ic)), offset),
2084 aopGet (AOP (IC_RIGHT (ic)), offset));
2090 adjustArithmeticResult (ic);
2093 freeAsmop (IC_LEFT (ic), NULL, ic,
2094 (RESULTONSTACK (ic) ? FALSE : TRUE));
2095 freeAsmop (IC_RIGHT (ic), NULL, ic,
2096 (RESULTONSTACK (ic) ? FALSE : TRUE));
2097 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2100 /*-----------------------------------------------------------------*/
2101 /* genMinusDec :- does subtraction with deccrement if possible */
2102 /*-----------------------------------------------------------------*/
2104 genMinusDec (iCode * ic)
2106 unsigned int icount;
2109 /* will try to generate an increment */
2110 /* if the right side is not a literal
2112 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2116 (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.
2119 /* if the sizes are greater than 2 or they are not the same regs
2121 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2124 /* so we know LEFT & RESULT in the same registers and add
2126 /* for short & char types */
2127 if (AOP_SIZE (IC_RESULT (ic)) < 2) {
2129 emitcode ("dec", "%s",
2130 aopGet (AOP (IC_LEFT (ic)), 0));
2133 if (AOP_ISHIGHREG( AOP ( IC_LEFT(ic)),0)) {
2134 emitcode ("subi", "%s,<(%d)",
2135 aopGet (AOP (IC_LEFT (ic)), 0), icount);
2140 for (offset = 0 ; offset < AOP_SIZE(IC_RESULT(ic)) ; offset++) {
2141 if (!(AOP_ISHIGHREG(AOP(IC_RESULT(ic)),offset))) return FALSE;
2144 if (AOP_SIZE (IC_RESULT (ic)) <= 3) {
2145 /* if register pair and starts with 26/30 then adiw */
2146 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0
2148 && (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX) ||
2149 IS_REGIDX (AOP (IC_RESULT (ic)), R24_IDX) ||
2150 IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX))) {
2151 emitcode ("sbiw", "%s,%d",
2152 aopGet (AOP (IC_RESULT (ic)), 0), icount);
2157 emitcode ("subi", "%s,<(%d)",
2158 aopGet (AOP (IC_RESULT (ic)), 0), icount);
2159 emitcode ("sbci", "%s,>(%d)",
2160 aopGet (AOP (IC_RESULT (ic)), 1), icount);
2163 /* for 32 bit longs */
2164 emitcode ("subi", "%s,<(%d)", aopGet (AOP (IC_RESULT (ic)), 0),
2166 emitcode ("sbci", "%s,>(%d)", aopGet (AOP (IC_RESULT (ic)), 1),
2168 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2),
2170 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3),
2176 /*-----------------------------------------------------------------*/
2177 /* genMinus - generates code for subtraction */
2178 /*-----------------------------------------------------------------*/
2180 genMinus (iCode * ic)
2182 int size, offset = 0, samer;
2185 aopOp (IC_LEFT (ic), ic, FALSE);
2186 aopOp (IC_RIGHT (ic), ic, FALSE);
2187 aopOp (IC_RESULT (ic), ic, TRUE);
2189 /* if I can do an decrement instead
2190 of subtract then GOOD for ME */
2191 if (genMinusDec (ic) == TRUE)
2194 size = getDataSize (IC_RESULT (ic));
2195 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2198 aopPut (AOP (IC_RESULT (ic)),
2199 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2201 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
2208 emitcode (l, "%s,%s",
2209 aopGet (AOP (IC_RESULT (ic)), offset),
2210 aopGet (AOP (IC_RIGHT (ic)), offset));
2213 if (AOP_ISHIGHREG(AOP (IC_RESULT (ic)),offset)) {
2219 emitcode (l, "%s,%s(%d)",
2220 aopGet (AOP (IC_RESULT (ic)), offset),
2222 (int) floatFromVal (AOP (IC_RIGHT (ic))->
2230 emitcode (l, "%s,%s",
2231 aopGet (AOP (IC_RESULT (ic)), offset),
2232 aopGet (AOP (IC_RIGHT (ic)), offset));
2238 adjustArithmeticResult (ic);
2241 freeAsmop (IC_LEFT (ic), NULL, ic,
2242 (RESULTONSTACK (ic) ? FALSE : TRUE));
2243 freeAsmop (IC_RIGHT (ic), NULL, ic,
2244 (RESULTONSTACK (ic) ? FALSE : TRUE));
2245 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2248 /*-----------------------------------------------------------------*/
2249 /* genMultOneByte : 8 bit multiplication & division */
2250 /*-----------------------------------------------------------------*/
2252 genMultOneByte (operand * left, operand * right, operand * result)
2254 sym_link *opetype = operandType (result);
2258 /* (if two literals, the value is computed before) */
2259 /* if one literal, literal on the right */
2260 if (AOP_TYPE (left) == AOP_LIT) {
2266 size = AOP_SIZE (result);
2268 if (SPEC_USIGN (opetype)) {
2269 emitcode ("mul", "%s,%s", aopGet (AOP (left), 0),
2270 aopGet (AOP (right), 0));
2273 emitcode ("muls", "%s,%s", aopGet (AOP (left), 0),
2274 aopGet (AOP (right), 0));
2276 aopPut (AOP (result), "r0", 0);
2278 aopPut (AOP (result), "r1", 1);
2281 if (SPEC_USIGN (opetype)) {
2283 aopPut (AOP (result), zero, offset++);
2288 lbl = newiTempLabel (NULL);
2289 emitcode ("ldi", "r24,0");
2290 emitcode ("brcc", "L%05d", lbl->key);
2291 emitcode ("ldi", "r24,0xff)");
2292 emitcode ("", "L%05d:", lbl->key);
2294 aopPut (AOP (result), "r24",
2302 /*-----------------------------------------------------------------*/
2303 /* genMult - generates code for multiplication */
2304 /*-----------------------------------------------------------------*/
2306 genMult (iCode * ic)
2308 operand *left = IC_LEFT (ic);
2309 operand *right = IC_RIGHT (ic);
2310 operand *result = IC_RESULT (ic);
2312 /* assign the amsops */
2313 aopOp (left, ic, FALSE);
2314 aopOp (right, ic, FALSE);
2315 aopOp (result, ic, TRUE);
2317 /* if both are of size == 1 */
2318 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1) {
2319 genMultOneByte (left, right, result);
2323 /* should have been converted to function call */
2327 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2328 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2329 freeAsmop (result, NULL, ic, TRUE);
2332 /*-----------------------------------------------------------------*/
2333 /* genDiv - generates code for division */
2334 /*-----------------------------------------------------------------*/
2338 /* should have been converted to function call */
2342 /*-----------------------------------------------------------------*/
2343 /* genMod - generates code for division */
2344 /*-----------------------------------------------------------------*/
2348 /* should have been converted to function call */
2360 /*-----------------------------------------------------------------*/
2361 /* revavrcnd - reverse a conditional for avr */
2362 /*-----------------------------------------------------------------*/
2364 revavrcnd (int type)
2376 for (i = 0; i < (sizeof (rar) / sizeof (rar[0])); i++) {
2377 if (rar[i].type == type)
2378 return rar[i].rtype;
2379 if (rar[i].rtype == type)
2382 assert (0); /* cannot happen */
2383 return 0; /* makes the compiler happy */
2386 static char *br_name[4] = { "breq", "brne", "brlt", "brge" };
2387 static char *br_uname[4] = { "breq", "brne", "brlo", "brcc" };
2389 /*-----------------------------------------------------------------*/
2390 /* genBranch - generate the branch instruction */
2391 /*-----------------------------------------------------------------*/
2393 genBranch (iCode * ifx, int br_type, int sign)
2395 int tj = (IC_TRUE (ifx) ? 1 : 0);
2397 if (tj) { /* if true jump */
2398 char *nm = (sign ? br_name[br_type] : br_uname[br_type]);
2399 emitcode (nm, "L%05d", IC_TRUE (ifx)->key);
2401 else { /* if false jump */
2402 int rtype = revavrcnd (br_type);
2403 char *nm = (sign ? br_name[rtype] : br_uname[rtype]);
2404 emitcode (nm, "L%05d", IC_FALSE (ifx)->key);
2409 /*-----------------------------------------------------------------*/
2410 /* genCmp - compare & jump */
2411 /*-----------------------------------------------------------------*/
2413 genCmp (iCode * ic, iCode * ifx, int br_type)
2415 operand *left, *right, *result;
2416 sym_link *letype, *retype;
2418 int sign, size, offset = 0;
2420 left = IC_LEFT (ic);
2421 right = IC_RIGHT (ic);
2422 result = IC_RESULT (ic);
2424 letype = getSpec (operandType (left));
2425 retype = getSpec (operandType (right));
2426 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
2428 /* assign the amsops */
2429 aopOp (left, ic, FALSE);
2430 aopOp (right, ic, FALSE);
2431 aopOp (result, ic, TRUE);
2432 size = AOP_SIZE (left);
2436 if (AOP_TYPE (right) == AOP_LIT) {
2437 emitcode ("cpi", "%s,<(%d)",
2438 aopGet (AOP (left), 0),
2440 floatFromVal (AOP (IC_RIGHT (ic))->
2442 genBranch (ifx, br_type, sign);
2444 else { /* right != literal */
2445 emitcode ("cp", "%s,%s",
2446 aopGet (AOP (left), 0),
2447 aopGet (AOP (right), 0));
2448 genBranch (ifx, br_type, sign);
2451 else { /* size != 1 */
2454 emitcode ("cp", "%s,%s",
2455 aopGet (AOP (left), 0),
2456 aopGet (AOP (right), 0));
2458 emitcode ("cpc", "%s,%s",
2459 aopGet (AOP (left), offset),
2460 aopGet (AOP (right),
2464 genBranch (ifx, br_type, sign);
2468 emitcode ("clr", "r0");
2471 emitcode ("cp", "%s,%s",
2472 aopGet (AOP (left), 0),
2473 aopGet (AOP (right), 0));
2475 emitcode ("cpc", "%s,%s",
2476 aopGet (AOP (left), offset),
2477 aopGet (AOP (right), offset));
2480 lbl = newiTempLabel (NULL);
2481 br_type = revavrcnd (br_type);
2483 emitcode (br_uname[br_type], "L%05d", lbl->key);
2485 emitcode (br_name[br_type], "L%05d", lbl->key);
2486 emitcode ("inc", "r0");
2487 emitcode ("", "L%05d:", lbl->key);
2488 aopPut (AOP (result), "r0", 0);
2489 size = AOP_SIZE (result) - 1;
2492 aopPut (AOP (result), zero, offset++);
2495 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2496 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2497 freeAsmop (result, NULL, ic, TRUE);
2500 /*-----------------------------------------------------------------*/
2501 /* genCmpGt :- greater than comparison */
2502 /*-----------------------------------------------------------------*/
2504 genCmpGt (iCode * ic, iCode * ifx)
2506 /* should have transformed by the parser */
2510 /*-----------------------------------------------------------------*/
2511 /* genCmpLt - less than comparisons */
2512 /*-----------------------------------------------------------------*/
2514 genCmpLt (iCode * ic, iCode * ifx)
2516 genCmp (ic, ifx, AVR_LT);
2519 /*-----------------------------------------------------------------*/
2520 /* genCmpEq - generates code for equal to */
2521 /*-----------------------------------------------------------------*/
2523 genCmpEq (iCode * ic, iCode * ifx)
2525 genCmp (ic, ifx, AVR_EQ);
2528 /*-----------------------------------------------------------------*/
2529 /* genCmpNe - generates code for not equal to */
2530 /*-----------------------------------------------------------------*/
2532 genCmpNe (iCode * ic, iCode * ifx)
2534 genCmp (ic, ifx, AVR_NE);
2537 /*-----------------------------------------------------------------*/
2538 /* genCmpGe - generates code for greater than equal to */
2539 /*-----------------------------------------------------------------*/
2541 genCmpGe (iCode * ic, iCode * ifx)
2543 genCmp (ic, ifx, AVR_GE);
2546 /*-----------------------------------------------------------------*/
2547 /* genCmpLe - generates code for less than equal to */
2548 /*-----------------------------------------------------------------*/
2550 genCmpLe (iCode * ic, iCode * ifx)
2552 operand *left = IC_LEFT (ic);
2553 operand *right = IC_RIGHT (ic);
2555 IC_RIGHT (ic) = left;
2556 IC_LEFT (ic) = right;
2557 genCmp (ic, ifx, AVR_GE);
2560 /*-----------------------------------------------------------------*/
2561 /* ifxForOp - returns the icode containing the ifx for operand */
2562 /*-----------------------------------------------------------------*/
2564 ifxForOp (operand * op, iCode * ic)
2566 /* if true symbol then needs to be assigned */
2567 if (IS_TRUE_SYMOP (op))
2570 /* if this has register type condition and
2571 the next instruction is ifx with the same operand
2572 and live to of the operand is upto the ifx only then */
2574 ic->next->op == IFX &&
2575 IC_COND (ic->next)->key == op->key &&
2576 OP_SYMBOL (op)->liveTo <= ic->next->seq) return ic->next;
2581 /*-----------------------------------------------------------------*/
2582 /* genAndOp - for && operation */
2583 /*-----------------------------------------------------------------*/
2585 genAndOp (iCode * ic)
2587 operand *left, *right, *result;
2591 /* note here that && operations that are in an
2592 if statement are taken away by backPatchLabels
2593 only those used in arthmetic operations remain */
2594 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2595 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2596 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
2598 tlbl = newiTempLabel (NULL);
2599 toBoolean (left, "r0", TRUE);
2600 toBoolean (right, "r1", TRUE);
2601 emitcode ("and", "r0,r1");
2602 emitcode ("ldi", "r24,1");
2603 emitcode ("breq", "L%05d", tlbl->key);
2604 emitcode ("dec", "r24");
2605 emitcode ("", "L%05d:", tlbl->key);
2606 aopPut (AOP (result), "r24", 0);
2607 size = AOP_SIZE (result) - 1;
2610 aopPut (AOP (result), zero, offset++);
2612 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2613 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2614 freeAsmop (result, NULL, ic, TRUE);
2618 /*-----------------------------------------------------------------*/
2619 /* genOrOp - for || operation */
2620 /*-----------------------------------------------------------------*/
2622 genOrOp (iCode * ic)
2624 operand *left, *right, *result;
2628 /* note here that || operations that are in an
2629 if statement are taken away by backPatchLabels
2630 only those used in arthmetic operations remain */
2631 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2632 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2633 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
2635 tlbl = newiTempLabel (NULL);
2636 toBoolean (left, "r0", TRUE);
2637 toBoolean (right, "r0", FALSE);
2638 emitcode ("ldi", "r24,1");
2639 emitcode ("breq", "L%05d", tlbl->key);
2640 emitcode ("dec", "r24");
2641 emitcode ("", "L%05d:", tlbl->key);
2642 aopPut (AOP (result), "r24", 0);
2643 size = AOP_SIZE (result) - 1;
2646 aopPut (AOP (result), zero, offset++);
2648 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2649 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2650 freeAsmop (result, NULL, ic, TRUE);
2654 AVR_AND = 0, AVR_OR, AVR_XOR
2656 static char *bopnames_lit[] = { "andi", "ori" };
2657 static char *bopnames[] = { "and", "or", "eor" };
2658 /*-----------------------------------------------------------------*/
2659 /* genBitWise - generate bitwise operations */
2660 /*-----------------------------------------------------------------*/
2662 genBitWise (iCode * ic, iCode * ifx, int bitop)
2664 operand *left, *right, *result;
2665 int size, offset = 0;
2670 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2671 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2672 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
2674 size = AOP_SIZE (left);
2676 if (ifx) { /* used only for jumps */
2677 if (AOP_TYPE (right) == AOP_LIT &&
2678 (bitop == AVR_AND || bitop == AVR_OR)) {
2680 (int) floatFromVal (AOP (right)->aopu.
2682 int p2 = powof2 (lit);
2683 if (bitop == AVR_AND && (p2 >= 0)) { /* right side is a power of 2 */
2684 l = aopGet (AOP (left), p2 / 8);
2685 if (IC_TRUE (ifx)) {
2686 emitcode ("sbrc", "%s,%d", l,
2688 emitcode ("rjmp", "L%05d",
2689 IC_TRUE (ifx)->key);
2692 emitcode ("sbrs", "%s,%d", l,
2694 emitcode ("rjmp", "L%05d",
2695 IC_FALSE (ifx)->key);
2698 else { /* right not power of two */
2699 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2701 if (eh && AOP_ISHIGHREG(AOP(IC_LEFT(ic)),0)) {
2702 emitcode (bopnames_lit[bitop],
2704 aopGet (AOP (IC_LEFT (ic)), 0), lit);
2707 MOVR24 (aopGet (AOP (IC_LEFT (ic)), 0));
2708 emitcode (bopnames_lit[bitop], "r24,<(%d)", lit);
2710 lbl = newiTempLabel (NULL);
2711 if (IC_TRUE (ifx)) {
2712 emitcode ("breq", "L%05d", lbl->key);
2713 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2716 emitcode ("brne", "L%05d", lbl->key);
2717 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)-> key);
2719 emitcode ("", "L%05d:", lbl->key);
2721 else if (size == 2) {
2722 emitcode ("mov", "r24,%s", aopGet (AOP (IC_LEFT (ic)), 0));
2723 emitcode ("mov", "r25,%s", aopGet (AOP (IC_LEFT (ic)), 1));
2724 emitcode (bopnames_lit[bitop], "r24,<(%d)", lit);
2725 emitcode (bopnames_lit[bitop], "r25,>(%d)", lit);
2726 emitcode ("sbiw", "r24,0");
2727 lbl = newiTempLabel (NULL);
2728 if (IC_TRUE (ifx)) {
2729 emitcode ("breq", "L%05d", lbl->key);
2730 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2733 emitcode ("brne", "L%05d", lbl->key);
2734 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2736 emitcode ("", "L%05d:", lbl->key);
2739 lbl = newiTempLabel (NULL);
2740 lbl1 = newiTempLabel (NULL);
2742 if (eh && AOP_ISHIGHREG(AOP(IC_LEFT(ic)),offset)) {
2743 emitcode (bopnames_lit [bitop], "%s,<(%d)",
2744 aopGet (AOP (IC_LEFT (ic)), offset),
2748 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
2750 emitcode ("andi", "r24,<(%d)", lit);
2752 emitcode ("brne", "L%05d", lbl->key);
2757 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)-> key);
2759 emitcode ("rjmp", "L%05d", lbl1->key);
2760 emitcode ("", "L%05d:", lbl->key);
2763 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2764 emitcode ("", "L%05d:", lbl1->key);
2769 else { /* right is not a literal */
2770 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2771 int reh = OP_SYMBOL (right)->liveTo <= ic->seq;
2774 emitcode (bopnames[bitop], "%s,%s", aopGet (AOP (IC_LEFT (ic)), 0),
2775 aopGet (AOP (IC_RIGHT (ic)), 0));
2778 emitcode (bopnames[bitop], "%s,%s",
2779 aopGet (AOP (IC_RIGHT (ic)), 0),
2780 aopGet (AOP (IC_LEFT (ic)), 0));
2783 MOVR0 (aopGet (AOP (IC_LEFT (ic)), 0));
2784 emitcode (bopnames[bitop], "r0,%s",
2785 aopGet (AOP (IC_RIGHT (ic)), 0));
2787 lbl = newiTempLabel (NULL);
2788 if (IC_TRUE (ifx)) {
2789 emitcode ("breq", "L%05d", lbl->key);
2790 emitcode ("rjmp", "L%05d",
2791 IC_TRUE (ifx)->key);
2794 emitcode ("brne", "L%05d", lbl->key);
2795 emitcode ("rjmp", "L%05d",
2796 IC_FALSE (ifx)->key);
2798 emitcode ("", "L%05d:", lbl->key);
2800 else if (size == 2) {
2801 emitcode ("mov", "r24,%s",
2802 aopGet (AOP (IC_LEFT (ic)), 0));
2803 emitcode ("mov", "r25,%s",
2804 aopGet (AOP (IC_LEFT (ic)), 1));
2805 emitcode (bopnames[bitop], "r24,%s",
2806 aopGet (AOP (IC_RIGHT (ic)), 0));
2807 emitcode (bopnames[bitop], "r25,%s",
2808 aopGet (AOP (IC_RIGHT (ic)), 1));
2809 emitcode ("sbiw", "r24,0");
2810 lbl = newiTempLabel (NULL);
2811 if (IC_TRUE (ifx)) {
2812 emitcode ("breq", "L%05d", lbl->key);
2813 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2816 emitcode ("brne", "L%05d", lbl->key);
2817 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2819 emitcode ("", "L%05d:", lbl->key);
2822 lbl = newiTempLabel (NULL);
2823 lbl1 = newiTempLabel (NULL);
2826 emitcode (bopnames[bitop], "%s,%s",
2827 aopGet (AOP (IC_LEFT (ic)), offset),
2828 aopGet (AOP (IC_RIGHT (ic)), offset));
2831 emitcode (bopnames[bitop], "%s,%s",
2832 aopGet (AOP (IC_RIGHT (ic)), offset),
2833 aopGet (AOP (IC_LEFT (ic)), offset));
2836 MOVR0 (aopGet (AOP (IC_LEFT (ic)), offset));
2837 emitcode (bopnames[bitop], "r0,%s",
2838 aopGet (AOP (IC_RIGHT (ic)), offset));
2840 emitcode ("brne", "L%05d", lbl->key);
2845 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2847 emitcode ("rjmp", "L%05d", lbl1->key);
2848 emitcode ("", "L%05d:", lbl->key);
2851 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2852 emitcode ("", "L%05d:", lbl1->key);
2859 /* result needs to go a register */
2860 samerl = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2861 samerr = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)));
2863 if (AOP_TYPE (right) == AOP_LIT) {
2865 (int) floatFromVal (AOP (right)->aopu.
2867 if (((lit >> (8 * offset)) & 0xff) == 0) {
2868 if (bitop == AVR_AND) {
2869 aopPut (AOP (result), zero, offset++);
2872 else if (bitop == AVR_OR) {
2874 aopPut (AOP (result),
2884 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT &&
2885 AOP_ISHIGHREG(AOP(IC_LEFT(ic)),offset) &&
2886 (bitop == AVR_AND || bitop == AVR_OR)) {
2887 emitcode (bopnames_lit[bitop], "%s,%s(%d)",
2888 aopGet (AOP (IC_LEFT (ic)), offset),
2890 (int) floatFromVal (AOP (right)-> aopu.aop_lit));
2893 emitcode (bopnames[bitop], "%s,%s",
2894 aopGet (AOP (IC_LEFT (ic)), offset),
2895 aopGet (AOP (IC_RIGHT (ic)), offset));
2899 emitcode (bopnames[bitop], "%s,%s",
2900 aopGet (AOP (IC_RIGHT (ic)), offset),
2901 aopGet (AOP (IC_LEFT (ic)), offset));
2904 aopPut (AOP (IC_RESULT (ic)),
2905 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2906 emitcode (bopnames[bitop],
2907 aopGet (AOP (IC_RESULT (ic)), offset),
2908 aopGet (AOP (IC_RIGHT (ic)), offset));
2913 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2914 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2915 freeAsmop (result, NULL, ic, TRUE);
2918 /*-----------------------------------------------------------------*/
2919 /* genAnd - code for and */
2920 /*-----------------------------------------------------------------*/
2922 genAnd (iCode * ic, iCode * ifx)
2924 genBitWise (ic, ifx, AVR_AND);
2927 /*-----------------------------------------------------------------*/
2928 /* genOr - code for or */
2929 /*-----------------------------------------------------------------*/
2931 genOr (iCode * ic, iCode * ifx)
2933 genBitWise (ic, ifx, AVR_OR);
2936 /*-----------------------------------------------------------------*/
2937 /* genXor - code for xclusive or */
2938 /*-----------------------------------------------------------------*/
2940 genXor (iCode * ic, iCode * ifx)
2942 genBitWise (ic, ifx, AVR_XOR);
2945 /*-----------------------------------------------------------------*/
2946 /* genInline - write the inline code out */
2947 /*-----------------------------------------------------------------*/
2949 genInline (iCode * ic)
2951 char *buffer, *bp, *bp1;
2953 _G.inLine += (!options.asmpeep);
2955 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
2956 strcpy (buffer, IC_INLINE (ic));
2958 /* emit each line as a code */
2979 /* emitcode("",buffer); */
2980 _G.inLine -= (!options.asmpeep);
2983 /*-----------------------------------------------------------------*/
2984 /* genRotC - rotate right/left with carry , lr = 1 rotate right */
2985 /*-----------------------------------------------------------------*/
2987 genRotC (iCode * ic, int lr)
2989 operand *left, *result;
2990 int size, offset = 0;
2992 /* rotate right with carry */
2993 left = IC_LEFT (ic);
2994 result = IC_RESULT (ic);
2995 aopOp (left, ic, FALSE);
2996 aopOp (result, ic, FALSE);
2998 /* move it to the result */
2999 size = AOP_SIZE (result);
3000 if (!sameRegs (AOP (left), AOP (result))) {
3003 aopPut (AOP (result),
3004 aopGet (AOP (left), offset), offset);
3007 size = AOP_SIZE (result);
3015 emitcode ("sbrc", "%s,%d", aopGet (AOP (result), offset),
3017 emitcode ("sec", "");
3020 emitcode ((lr ? "ror" : "rol"), "%s",
3021 aopGet (AOP (result), offset));
3027 freeAsmop (left, NULL, ic, TRUE);
3028 freeAsmop (result, NULL, ic, TRUE);
3031 /*-----------------------------------------------------------------*/
3032 /* genRRC - rotate right with carry */
3033 /*-----------------------------------------------------------------*/
3040 /*-----------------------------------------------------------------*/
3041 /* genRLC - generate code for rotate left with carry */
3042 /*-----------------------------------------------------------------*/
3049 /*-----------------------------------------------------------------*/
3050 /* genGetHbit - generates code get highest order bit */
3051 /*-----------------------------------------------------------------*/
3053 genGetHbit (iCode * ic)
3055 operand *left, *result;
3058 left = IC_LEFT (ic);
3059 result = IC_RESULT (ic);
3060 aopOp (left, ic, FALSE);
3061 aopOp (result, ic, FALSE);
3063 size = AOP_SIZE (result);
3064 if (!sameRegs (AOP (left), AOP (result))) {
3065 emitcode ("clr", "%s", aopGet (AOP (result), size - 1));
3066 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3067 emitcode ("subi", "%s,<(-1)",
3068 aopGet (AOP (result), size - 1));
3071 emitcode ("clr", "r0");
3072 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3073 emitcode ("subi", "r0,<(-1)");
3074 aopPut (AOP (result), "r0", 0);
3079 emitcode ("clr", aopGet (AOP (result), offset++));
3081 freeAsmop (left, NULL, ic, TRUE);
3082 freeAsmop (result, NULL, ic, TRUE);
3085 /*-----------------------------------------------------------------*/
3086 /* genShiftLeftLit - shift left by a known amount */
3087 /*-----------------------------------------------------------------*/
3089 genShiftLeftLit (iCode * ic)
3091 operand *left, *right, *result;
3092 int size, shCount, offset = 0;
3095 right = IC_RIGHT (ic);
3096 left = IC_LEFT (ic);
3097 result = IC_RESULT (ic);
3099 aopOp (left, ic, FALSE);
3100 aopOp (result, ic, FALSE);
3101 size = AOP_SIZE (result);
3102 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3104 if (shCount > (size * 8 - 1)) {
3106 aopPut (AOP (result), zero, offset++);
3111 if (!sameRegs (AOP (left), AOP (result)))
3112 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3114 if (AOP_ISHIGHREG(AOP(result),0)) {
3115 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3116 emitcode ("andi", "%s,0xf0");
3118 emitcode ("ldi","r24,0xf0");
3119 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3120 emitcode ("and", "%s,r24");
3125 emitcode ("add", "%s,%s", aopGet (AOP (result), 0),
3126 aopGet (AOP (result), 0));
3130 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3133 if (shCount >= 12) {
3134 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3135 aopPut (AOP (result), zero, 0);
3136 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3137 if (AOP_ISHIGHREG(AOP(result),1)) {
3138 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3140 emitcode ("ldi","r24,0xf0");
3141 emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
3147 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3148 aopPut (AOP (result), zero, 0);
3154 if (!sameRegs (AOP (left), AOP (result))) {
3155 aopPut (AOP (result), aopGet (AOP (left), 0),
3157 aopPut (AOP (result), aopGet (AOP (left), 1),
3160 emitcode ("mov", "r24,%s", aopGet (AOP (result), 0));
3161 emitcode ("andi", "r24,0x0f");
3162 if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
3163 emitcode("ldi","r25,0xf0");
3165 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3166 if (AOP_ISHIGHREG(AOP(result),0)) {
3167 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 0));
3169 emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
3171 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3172 if (AOP_ISHIGHREG(AOP(result),1)) {
3173 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3175 emitcode ("and", "%s,r25", aopGet (AOP (result), 1));
3177 emitcode ("or", "%s,r24", aopGet (AOP (result), 1));
3179 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3180 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3183 if (!lByteZ && !sameRegs (AOP (result), AOP (left))
3187 aopPut (AOP (result),
3188 aopGet (AOP (left), offset), offset);
3194 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3197 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3198 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3203 assert ("shifting generic pointer ?\n");
3206 /* 32 bits we do only byte boundaries */
3207 if (shCount >= 24) {
3208 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3209 aopPut (AOP (result), zero, 2);
3210 aopPut (AOP (result), zero, 1);
3211 aopPut (AOP (result), zero, 0);
3215 if (shCount >= 16) {
3216 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3217 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3218 aopPut (AOP (result), zero, 1);
3219 aopPut (AOP (result), zero, 0);
3224 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3225 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3226 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3227 aopPut (AOP (result), zero, 0);
3231 if (!lByteZ && !sameRegs (AOP (left), AOP (right))) {
3234 aopPut (AOP (result),
3235 aopGet (AOP (left), offset), offset);
3239 size = AOP_SIZE (result);
3245 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3246 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3247 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3248 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3253 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3254 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3255 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3260 emitcode ("lsl", "%s", aopGet (AOP (result), 2));
3261 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3266 emitcode ("lsl", "%s", aopGet (AOP (result), 3));
3274 freeAsmop (left, NULL, ic, TRUE);
3275 freeAsmop (right, NULL, ic, TRUE);
3276 freeAsmop (result, NULL, ic, TRUE);
3279 /*-----------------------------------------------------------------*/
3280 /* genLeftShift - generates code for left shifting */
3281 /*-----------------------------------------------------------------*/
3283 genLeftShift (iCode * ic)
3285 operand *left, *right, *result;
3289 right = IC_RIGHT (ic);
3290 left = IC_LEFT (ic);
3291 result = IC_RESULT (ic);
3293 aopOp (right, ic, FALSE);
3295 if (AOP_TYPE (right) == AOP_LIT) {
3296 genShiftLeftLit (ic);
3301 aopOp (left, ic, FALSE);
3302 aopOp (result, ic, FALSE);
3303 size = AOP_SIZE (result);
3305 if (AOP_SIZE (right) > 1) {
3306 if (isRegPair (AOP (right))) {
3307 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3310 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3311 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3315 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3317 if (!sameRegs (AOP (left), AOP (result))) {
3319 aopPut (AOP (result), aopGet (AOP (left), offset),
3323 size = AOP_SIZE (result);
3325 tlbl = newiTempLabel (NULL);
3326 emitcode ("", "L%05d:", tlbl->key);
3330 emitcode ("rol", "%s", aopGet (AOP (result), offset));
3332 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3335 if (AOP_SIZE (right) > 1)
3336 emitcode ("sbiw", "r24,1");
3338 emitcode ("dec", "r24");
3339 emitcode ("brne", "L%05d", tlbl->key);
3341 freeAsmop (left, NULL, ic, TRUE);
3342 freeAsmop (right, NULL, ic, TRUE);
3343 freeAsmop (result, NULL, ic, TRUE);
3346 /*-----------------------------------------------------------------*/
3347 /* genShiftRightLit - generate for right shift with known count */
3348 /*-----------------------------------------------------------------*/
3350 genShiftRightLit (iCode * ic)
3352 operand *left = IC_LEFT (ic)
3353 , *right = IC_RIGHT (ic)
3354 , *result = IC_RESULT (ic);
3355 int size, shCount, offset = 0;
3357 sym_link *letype = getSpec (operandType (left));
3358 int sign = !SPEC_USIGN (letype);
3360 right = IC_RIGHT (ic);
3361 left = IC_LEFT (ic);
3362 result = IC_RESULT (ic);
3364 aopOp (left, ic, FALSE);
3365 aopOp (result, ic, FALSE);
3366 size = AOP_SIZE (result);
3367 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3369 /* if signed then give up and use a loop to shift */
3372 if (!sameRegs (AOP (left), AOP (result))) {
3374 aopPut (AOP (result),
3375 aopGet (AOP (left), offset), offset);
3378 size = AOP_SIZE (result);
3381 /* be as economical as possible */
3384 size = AOP_SIZE (result);
3387 /* highest order byte */
3388 if (offset == (AOP_SIZE(result)-1))
3389 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3391 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3397 emitcode ("ldi", "r24,<(%d)", shCount);
3398 tlbl = newiTempLabel (NULL);
3399 emitcode ("", "L%05d:", tlbl->key);
3402 if (offset == (AOP_SIZE(result) - 1))
3403 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3405 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3408 emitcode ("dec", "r24");
3409 emitcode ("brne", "L%05d", tlbl->key);
3413 if (shCount > (size * 8 - 1)) {
3415 aopPut (AOP (result), zero, offset++);
3418 /* for unsigned we can much more efficient */
3421 if (!sameRegs (AOP (left), AOP (result)))
3422 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3424 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3425 if (AOP_ISHIGHREG(AOP(result),0)) {
3426 emitcode ("andi", "%s,0x0f",aopGet(AOP(result),0));
3428 emitcode ("ldi","r24,0x0f");
3429 emitcode ("and", "%s,r24",aopGet(AOP(result),0));
3434 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3437 if (shCount >= 12) {
3438 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3439 aopPut (AOP (result), zero, 1);
3440 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3441 if (AOP_ISHIGHREG(AOP(result),0)) {
3442 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3444 emitcode ("ldi","r24,0x0f");
3445 emitcode ("and", "%s,r24",aopGet(AOP(result),0));
3451 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3452 aopPut (AOP (result), zero, 1);
3458 if (!sameRegs (AOP (left), AOP (result))) {
3459 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3460 aopPut (AOP (result), aopGet (AOP (left), 1), 1);
3462 if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
3463 emitcode("ldi","r25,0x0f");
3465 emitcode ("mov", "r24,%s", aopGet (AOP (result), 1));
3466 emitcode ("andi", "r24,0xf0");
3467 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3468 if (AOP_ISHIGHREG(AOP(result),0)) {
3469 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3471 emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
3473 emitcode ("or", "%s,r24", aopGet (AOP (result), 0));
3474 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3475 if (AOP_ISHIGHREG(AOP(result),1)) {
3476 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 1));
3478 emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
3481 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3482 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3486 if (!hByteZ && !sameRegs (AOP (result), AOP (left))
3490 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3496 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3499 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3500 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3506 assert ("shifting generic pointer ?\n");
3509 /* 32 bits we do only byte boundaries */
3510 if (shCount >= 24) {
3511 aopPut (AOP (result), aopGet (AOP (left), 3), 0);
3512 aopPut (AOP (result), zero, 1);
3513 aopPut (AOP (result), zero, 2);
3514 aopPut (AOP (result), zero, 3);
3518 if (shCount >= 16) {
3519 aopPut (AOP (result), aopGet (AOP (left), 3), 1);
3520 aopPut (AOP (result), aopGet (AOP (left), 2), 0);
3521 aopPut (AOP (result), zero, 2);
3522 aopPut (AOP (result), zero, 3);
3527 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3528 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3529 aopPut (AOP (result), aopGet (AOP (left), 3), 2);
3530 aopPut (AOP (result), zero, 3);
3534 if (!hByteZ && !sameRegs (AOP (left), AOP (right))) {
3537 aopPut (AOP (result),
3538 aopGet (AOP (left), offset), offset);
3542 size = AOP_SIZE (result);
3548 emitcode ("lsr", "%s", aopGet (AOP (result), 3));
3549 emitcode ("ror", "%s", aopGet (AOP (result), 2));
3550 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3551 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3556 emitcode ("lsr", "%s", aopGet (AOP (result), 2));
3557 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3558 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3563 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3564 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3569 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3576 freeAsmop (left, NULL, ic, TRUE);
3577 freeAsmop (right, NULL, ic, TRUE);
3578 freeAsmop (result, NULL, ic, TRUE);
3581 /*-----------------------------------------------------------------*/
3582 /* genRightShift - generate code for right shifting */
3583 /*-----------------------------------------------------------------*/
3585 genRightShift (iCode * ic)
3587 operand *right, *left, *result;
3590 int sign = 0, first = 1;
3593 aopOp (right = IC_RIGHT (ic), ic, FALSE);
3595 if (AOP_TYPE (right) == AOP_LIT) {
3596 genShiftRightLit (ic);
3600 if (AOP_SIZE (right) > 1) {
3601 if (isRegPair (AOP (right))) {
3602 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3605 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3606 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3610 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3612 aopOp (left = IC_LEFT (ic), ic, FALSE);
3613 aopOp (result = IC_RESULT (ic), ic, FALSE);
3614 size = AOP_SIZE (result);
3615 tlbl = newiTempLabel (NULL);
3616 emitcode ("", "L%05d:", tlbl->key);
3618 letype = getSpec (operandType (left));
3619 sign = !SPEC_USIGN (letype);
3620 if (!sameRegs (AOP (left), AOP (result))) {
3622 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3625 size = AOP_SIZE (result);
3627 size = AOP_SIZE (result);
3631 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3633 emitcode ("lsr", "%s", aopGet (AOP (result), offset));
3637 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3640 if (AOP_SIZE (right) > 1)
3641 emitcode ("sbiw", "r24,1");
3643 emitcode ("dec", "r24");
3644 emitcode ("brne", "L%05d", tlbl->key);
3646 freeAsmop (left, NULL, ic, TRUE);
3647 freeAsmop (result, NULL, ic, TRUE);
3650 /*-----------------------------------------------------------------*/
3651 /* RRsh - shift right rn by known count */
3652 /*-----------------------------------------------------------------*/
3654 RRsh (int shCount,int reg)
3656 shCount &= 0x0007; // shCount : 0..7
3662 emitcode ("lsr", "r%d",reg);
3665 emitcode ("lsr", "r%d",reg);
3666 emitcode ("lsr", "r%d",reg);
3669 emitcode ("swap", "r%d",reg);
3670 emitcode ("lsl", "r%d",reg);
3673 emitcode ("swap", "r%d",reg);
3676 emitcode ("swap", "r%d",reg);
3677 emitcode ("lsr", "r%d",reg);
3680 emitcode ("swap","r%d",reg);
3681 emitcode ("lsr", "r%d",reg);
3682 emitcode ("lsr", "r%d",reg);
3685 emitcode ("swap","r%d",reg);
3686 emitcode ("lsr", "r%d",reg);
3687 emitcode ("lsr", "r%d",reg);
3688 emitcode ("lsr", "r%d",reg);
3693 /*-----------------------------------------------------------------*/
3694 /* RLsh - shift left rn by known count */
3695 /*-----------------------------------------------------------------*/
3697 RLsh (int shCount, int reg)
3699 shCount &= 0x0007; // shCount : 0..7
3705 emitcode ("lsl", "r%d",reg);
3708 emitcode ("lsl", "r%d",reg);
3709 emitcode ("lsl", "r%d",reg);
3712 emitcode ("swap","r%d",reg);
3713 emitcode ("lsr", "r%d",reg);
3716 emitcode ("swap", "r%d",reg);
3719 emitcode ("swap","r%d",reg);
3720 emitcode ("lsl", "r%d",reg);
3723 emitcode ("swap","r%d",reg);
3724 emitcode ("lsl", "r%d",reg);
3725 emitcode ("lsl", "r%d",reg);
3728 emitcode ("swap","r%d",reg);
3729 emitcode ("lsl", "r%d",reg);
3730 emitcode ("lsl", "r%d",reg);
3731 emitcode ("lsl", "r%d",reg);
3736 /*-----------------------------------------------------------------*/
3737 /* genUnpackBits - generates code for unpacking bits */
3738 /*-----------------------------------------------------------------*/
3740 genUnpackBits (operand * result, char *rname, int ptype)
3748 etype = getSpec (operandType (result));
3749 rsize = getSize (operandType (result));
3750 /* read the first byte */
3757 emitcode ("ld", "r24,%s+", rname);
3761 emitcode ("lpm", "r24,%s+", rname);
3765 emitcode ("call","__gptrget_pi");
3766 emitcode ("mov","r24,r0");
3770 rlen = SPEC_BLEN (etype);
3772 /* if we have bitdisplacement then it fits */
3773 /* into this byte completely or if length is */
3774 /* less than a byte */
3775 if ((shCnt = SPEC_BSTR (etype)) || (SPEC_BLEN (etype) <= 8)) {
3777 /* shift right acc */
3780 emitcode ("andi", "r24,lo(0x%x)",
3781 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
3782 aopPut (AOP (result), "r24", offset++);
3786 /* bit field did not fit in a byte */
3787 aopPut (AOP (result), "r24", offset++);
3797 emitcode ("ld", "r24,%s+");
3801 emitcode ("lpm", "r24,%s+");
3805 emitcode ("call", "__gptrget_pi");
3810 /* if we are done */
3814 aopPut (AOP (result), "r24", offset++);
3819 aopPut (AOP (result), "r24", offset++);
3823 if (offset < rsize) {
3826 aopPut (AOP (result), zero, offset++);
3831 /*-----------------------------------------------------------------*/
3832 /* genDataPointerGet - generates code when ptr offset is known */
3833 /*-----------------------------------------------------------------*/
3835 genDataPointerGet (operand * left, operand * result, iCode * ic)
3839 int size, offset = 0;
3840 aopOp (result, ic, TRUE);
3842 /* get the string representation of the name */
3843 l = aopGet (AOP (left), 0);
3844 size = AOP_SIZE (result);
3847 sprintf (buffer, "(%s + %d)", l, offset);
3849 sprintf (buffer, "%s", l);
3850 emitcode ("lds", "%s,%s", aopGet (AOP (result), offset++),
3854 freeAsmop (left, NULL, ic, TRUE);
3855 freeAsmop (result, NULL, ic, TRUE);
3858 /*-----------------------------------------------------------------*/
3859 /* genNearPointerGet - emitcode for near pointer fetch */
3860 /*-----------------------------------------------------------------*/
3862 genMemPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
3867 char *rname, *frname = NULL;
3868 sym_link *rtype, *retype;
3869 sym_link *ltype = operandType (left);
3871 rtype = operandType (result);
3872 retype = getSpec (rtype);
3874 aopOp (left, ic, FALSE);
3876 /* if left is rematerialisable and
3877 result is not bit variable type and
3878 the left is pointer to data space i.e
3879 lower 128 bytes of space */
3880 if (AOP_TYPE (left) == AOP_IMMD &&
3881 !IS_BITVAR (retype) && DCL_TYPE (ltype) == POINTER) {
3882 genDataPointerGet (left, result, ic);
3886 /* if the value is already in a pointer register
3887 then don't need anything more */
3888 if (!AOP_INPREG (AOP (left))) {
3889 /* otherwise get a free pointer register */
3891 preg = getFreePtr (ic, &aop, FALSE, 0);
3892 if (isRegPair (AOP (left) )) {
3893 emitcode ("movw", "%s,%s",
3894 aop->aopu.aop_ptr->name,
3895 aopGet(AOP(left),0));
3897 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
3898 aopGet (AOP (left), 0));
3899 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
3900 aopGet (AOP (left), 1));
3906 frname = aopGet(aop,0);
3910 } else if (AOP_ISZ(aop)) {
3913 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
3914 "pointer not in correct register");
3918 aopOp (result, ic, FALSE);
3920 /* if bitfield then unpack the bits */
3921 if (IS_BITVAR (retype))
3922 genUnpackBits (result, rname, POINTER);
3924 /* we have can just get the values */
3925 int size = AOP_SIZE (result);
3930 emitcode ("ld","%s,%s+",aopGet(AOP(result),offset), rname);
3932 emitcode ("ld","%s,%s",aopGet(AOP(result),offset), rname);
3937 /* now some housekeeping stuff */
3939 /* we had to allocate for this iCode */
3941 if (isRegPair (AOP (left) )) {
3942 emitcode ("movw", "%s,%s",
3943 aopGet (AOP(left),0),
3944 aop->aopu.aop_ptr->name);
3946 emitcode ("mov", "%s,%s",
3947 aopGet (AOP (left), 0),
3948 aop->aopu.aop_ptr->name);
3949 emitcode ("mov", "%s,%s",
3950 aopGet (AOP (left), 1),
3951 aop->aop_ptr2->name);
3954 freeAsmop (NULL, aop, ic, TRUE);
3957 /* we did not allocate which means left
3958 already in a pointer register, then
3959 if size > 0 && this could be used again
3960 we have to point it back to where it
3962 if ((AOP_SIZE (result) > 1 &&
3963 !OP_SYMBOL (left)->remat &&
3964 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) && !pi) {
3965 int size = AOP_SIZE (result) - 1;
3966 emitcode ("sbiw", "%s,%d",frname,size);
3971 if (pi) pi->generated = 1;
3972 freeAsmop (left, NULL, ic, TRUE);
3973 freeAsmop (result, NULL, ic, TRUE);
3977 /*-----------------------------------------------------------------*/
3978 /* genCodePointerGet - gget value from code space */
3979 /*-----------------------------------------------------------------*/
3981 genCodePointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
3984 sym_link *retype = getSpec (operandType (result));
3988 aopOp (left, ic, FALSE);
3990 /* if the operand is already in Z register
3991 then we do nothing else we move the value to Z register */
3992 if (AOP_ISZ(AOP(left))) {
3996 getFreePtr(ic,&aop,FALSE,TRUE);
3997 if (isRegPair(AOP (left))) {
3998 emitcode ("movw","r30,%s",aopGet (AOP (left), 0));
4000 emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
4001 emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
4006 aopOp (result, ic, FALSE);
4008 /* if bit then unpack */
4009 if (IS_BITVAR (retype))
4010 genUnpackBits (result, "Z", CPOINTER);
4012 size = AOP_SIZE (result);
4017 emitcode ("lpm","%s,Z+",aopGet(AOP(result),offset++));
4019 emitcode ("lpm","%s,Z",aopGet(AOP(result),offset++));
4024 /* now some housekeeping stuff */
4026 /* we had to allocate for this iCode */
4028 if (isRegPair(AOP (left))) {
4029 emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
4031 emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
4032 emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
4035 freeAsmop (NULL, aop, ic, TRUE);
4038 /* we did not allocate which means left
4039 already in a pointer register, then
4040 if size > 0 && this could be used again
4041 we have to point it back to where it
4043 if ((AOP_SIZE (result) > 1 &&
4044 !OP_SYMBOL (left)->remat &&
4045 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) &&
4047 int size = AOP_SIZE (result) - 1;
4048 emitcode ("sbiw", "r30,%d",size);
4053 if (pi) pi->generated=1;
4054 freeAsmop (left, NULL, ic, TRUE);
4055 freeAsmop (result, NULL, ic, TRUE);
4059 /*-----------------------------------------------------------------*/
4060 /* genGenPointerGet - gget value from generic pointer space */
4061 /*-----------------------------------------------------------------*/
4063 genGenPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
4067 sym_link *retype = getSpec (operandType (result));
4070 aopOp (left, ic, FALSE);
4072 /* if the operand is already in dptr
4073 then we do nothing else we move the value to dptr */
4074 if (AOP_ISZ(AOP(left))) {
4078 getFreePtr(ic,&aop,FALSE,TRUE);
4079 if (isRegPair(AOP(left))) {
4080 emitcode ("movw", "r30,%s", aopGet (AOP (left), 0));
4082 emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
4083 emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
4085 emitcode ("mov", "r24,%s", aopGet (AOP (left), 2));
4089 /* so Z register now contains the address */
4091 aopOp (result, ic, FALSE);
4093 /* if bit then unpack */
4094 if (IS_BITVAR (retype))
4095 genUnpackBits (result, "Z", GPOINTER);
4097 size = AOP_SIZE (result);
4102 emitcode ("call", "__gptrget_pi");
4104 emitcode ("call", "__gptrget");
4105 aopPut (AOP (result), "r0", offset++);
4110 /* now some housekeeping stuff */
4112 /* we had to allocate for this iCode */
4114 if (isRegPair(AOP (left))) {
4115 emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
4117 emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
4118 emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
4121 freeAsmop (NULL, aop, ic, TRUE);
4124 /* we did not allocate which means left
4125 already in a pointer register, then
4126 if size > 0 && this could be used again
4127 we have to point it back to where it
4129 if ((AOP_SIZE (result) > 1 &&
4130 !OP_SYMBOL (left)->remat &&
4131 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) &&
4133 int size = AOP_SIZE (result) - 1;
4134 emitcode ("sbiw", "r30,%d",size);
4137 if (pi) pi->generated=1;
4138 freeAsmop (left, NULL, ic, TRUE);
4139 freeAsmop (result, NULL, ic, TRUE);
4142 /*-----------------------------------------------------------------*/
4143 /* genPointerGet - generate code for pointer get */
4144 /*-----------------------------------------------------------------*/
4146 genPointerGet (iCode * ic, iCode *pi)
4148 operand *left, *result;
4149 sym_link *type, *etype;
4152 left = IC_LEFT (ic);
4153 result = IC_RESULT (ic);
4155 /* depending on the type of pointer we need to
4156 move it to the correct pointer register */
4157 type = operandType (left);
4158 etype = getSpec (type);
4159 /* if left is of type of pointer then it is simple */
4160 if (IS_PTR (type) && !IS_FUNC (type->next))
4161 p_type = DCL_TYPE (type);
4163 /* we have to go by the storage class */
4164 p_type = PTR_TYPE (SPEC_OCLS (etype));
4169 /* now that we have the pointer type we assign
4170 the pointer values */
4177 genMemPointerGet (left, result, ic, pi);
4181 genCodePointerGet (left, result, ic, pi);
4185 genGenPointerGet (left, result, ic, pi);
4191 /*-----------------------------------------------------------------*/
4192 /* genPackBits - generates code for packed bit storage */
4193 /*-----------------------------------------------------------------*/
4195 genPackBits (sym_link * etype,
4197 char *rname, int p_type)
4205 blen = SPEC_BLEN (etype);
4206 bstr = SPEC_BSTR (etype);
4208 l = aopGet (AOP (right), offset++);
4211 /* if the bit lenth is less than or */
4212 /* it exactly fits a byte then */
4213 if (SPEC_BLEN (etype) <= 8) {
4214 shCount = SPEC_BSTR (etype);
4216 /* shift left acc */
4219 if (SPEC_BLEN (etype) < 8) { /* if smaller than a byte */
4226 emitcode ("ld", "r1,%s",rname);
4230 emitcode ("push", "r1");
4231 emitcode ("push", "r24");
4232 emitcode ("call", "__gptrget");
4233 emitcode ("pop", "r1");
4234 emitcode ("mov","r24,r0");
4238 emitcode ("andi", "r24,#0x%02x", (unsigned char)
4239 ((unsigned char) (0xFF << (blen + bstr)) |
4240 (unsigned char) (0xFF >> (8 - bstr))));
4241 emitcode ("or", "r24,r1");
4242 if (p_type == GPOINTER)
4243 emitcode ("pop", "r1");
4252 emitcode("st","%s+,r24");
4256 emitcode("mov","r0,r24");
4257 emitcode ("call", "__gptrput_pi");
4262 if (SPEC_BLEN (etype) <= 8)
4265 rLen = SPEC_BLEN (etype);
4267 /* now generate for lengths greater than one byte */
4270 l = aopGet (AOP (right), offset++);
4281 emitcode ("st", "%s+,%s",rname,l);
4286 emitcode ("lcall", "__gptrput_pi");
4293 /* last last was not complete */
4295 /* save the byte & read byte */
4301 emitcode ("st","%s+,r24",rname);
4304 emitcode ("push", "r1");
4305 emitcode ("push", "r24");
4306 emitcode ("lcall", "__gptrget");
4307 emitcode ("mov","r24,r0");
4308 emitcode ("pop", "r1");
4312 emitcode ("andi", "r24,0x%02x", (((unsigned char) -1 << rLen) & 0xff));
4313 emitcode ("or", "r24,r1");
4316 if (p_type == GPOINTER)
4317 emitcode ("pop", "r1");
4325 emitcode ("st", "%s,r24", rname);
4329 emitcode ("mov","r0,r24");
4330 emitcode ("call", "__gptrput");
4335 /*-----------------------------------------------------------------*/
4336 /* genDataPointerSet - remat pointer to data space */
4337 /*-----------------------------------------------------------------*/
4339 genDataPointerSet (operand * right, operand * result, iCode * ic)
4341 int size, offset = 0;
4342 char *l, buffer[256];
4344 aopOp (right, ic, FALSE);
4346 l = aopGet (AOP (result), 0);
4347 size = AOP_SIZE (right);
4350 sprintf (buffer, "(%s + %d)", l, offset);
4352 sprintf (buffer, "%s", l);
4353 emitcode ("sts", "%s,%s", buffer,
4354 aopGet (AOP (right), offset++));
4357 freeAsmop (right, NULL, ic, TRUE);
4358 freeAsmop (result, NULL, ic, TRUE);
4361 /*-----------------------------------------------------------------*/
4362 /* genNearPointerSet - emitcode for near pointer put */
4363 /*-----------------------------------------------------------------*/
4365 genMemPointerSet (operand * right, operand * result, iCode * ic, iCode *pi)
4368 char *frname = NULL, *rname, *l;
4371 sym_link *ptype = operandType (result);
4373 retype = getSpec (operandType (right));
4375 aopOp (result, ic, FALSE);
4377 /* if the result is rematerializable &
4378 in data space & not a bit variable */
4379 if (AOP_TYPE (result) == AOP_IMMD &&
4380 DCL_TYPE (ptype) == POINTER && !IS_BITVAR (retype)) {
4381 genDataPointerSet (right, result, ic);
4384 if (!AOP_INPREG(AOP(result))) {
4385 /* otherwise get a free pointer register */
4387 getFreePtr (ic, &aop, FALSE, 0);
4388 if (isRegPair (AOP (result) )) {
4389 emitcode ("movw", "%s,%s",aop->aopu.aop_ptr->name,
4390 aopGet(AOP (result), 0));
4392 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
4393 aopGet (AOP (result), 0));
4394 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
4395 aopGet (AOP (result), 1));
4400 frname = aopGet(aop,0);
4403 aopOp (right, ic, FALSE);
4406 } else if (AOP_ISZ(aop)) {
4409 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4410 "pointer not in correct register");
4413 /* if bitfield then unpack the bits */
4414 if (IS_BITVAR (retype))
4415 genPackBits (retype, right, rname, POINTER);
4417 /* we have can just get the values */
4418 int size = AOP_SIZE (right);
4422 l = aopGet (AOP (right), offset);
4424 emitcode ("st", "%s+,%s", rname,l);
4426 emitcode ("st", "%s,%s", rname,l);
4431 /* now some housekeeping stuff */
4433 /* we had to allocate for this iCode */
4435 if (isRegPair (AOP (result) )) {
4436 emitcode ("movw", "%s,%s",
4437 aopGet(AOP(result),0),
4438 aop->aopu.aop_ptr->name);
4440 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
4441 aopGet (AOP (result), 0));
4442 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
4443 aopGet (AOP (result), 1));
4446 freeAsmop (NULL, aop, ic, TRUE);
4449 /* we did not allocate which means left
4450 already in a pointer register, then
4451 if size > 0 && this could be used again
4452 we have to point it back to where it
4454 if ((AOP_SIZE (right) > 1 &&
4455 !OP_SYMBOL (result)->remat &&
4456 (OP_SYMBOL (right)->liveTo > ic->seq || ic->depth)) && !pi) {
4457 int size = AOP_SIZE (right) - 1;
4458 emitcode ("sbiw", "%s,%d",frname,size);
4463 if (pi) pi->generated = 1;
4464 freeAsmop (result, NULL, ic, TRUE);
4465 freeAsmop (right, NULL, ic, TRUE);
4468 /*-----------------------------------------------------------------*/
4469 /* genGenPointerSet - set value from generic pointer space */
4470 /*-----------------------------------------------------------------*/
4472 genGenPointerSet (operand * right, operand * result, iCode * ic, iCode *pi)
4476 sym_link *retype = getSpec (operandType (right));
4479 aopOp (result, ic, FALSE);
4481 /* if the operand is already in dptr
4482 then we do nothing else we move the value to dptr */
4483 if (AOP_ISZ(AOP(result))) {
4487 getFreePtr(ic,&aop,FALSE,TRUE);
4488 if (isRegPair(AOP(result))) {
4489 emitcode ("movw", "r30,%s", aopGet (AOP (result), 0));
4491 emitcode ("mov", "r30,%s", aopGet (AOP (result), 0));
4492 emitcode ("mov", "r31,%s", aopGet (AOP (result), 1));
4494 emitcode ("mov", "r24,%s", aopGet (AOP (result), 2));
4498 /* so Z register now contains the address */
4499 aopOp (right, ic, FALSE);
4501 /* if bit then unpack */
4502 if (IS_BITVAR (retype))
4503 genUnpackBits (result, "Z", GPOINTER);
4505 size = AOP_SIZE (right);
4509 char *l = aopGet(AOP (right), offset++);
4513 emitcode ("call", "__gptrput_pi");
4515 emitcode ("call", "__gptrput");
4519 /* now some housekeeping stuff */
4521 /* we had to allocate for this iCode */
4523 if (isRegPair(AOP(result))) {
4524 emitcode ("movw", "%s,r30", aopGet (AOP (result), 0));
4526 emitcode ("mov", "%s,r30", aopGet (AOP (result), 0));
4527 emitcode ("mov", "%s,r31", aopGet (AOP (result), 1));
4530 freeAsmop (NULL, aop, ic, TRUE);
4533 /* we did not allocate which means left
4534 already in a pointer register, then
4535 if size > 0 && this could be used again
4536 we have to point it back to where it
4538 if ((AOP_SIZE (right) > 1 &&
4539 !OP_SYMBOL (result)->remat &&
4540 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) && !pi) {
4541 int size = AOP_SIZE (right) - 1;
4542 emitcode ("sbiw", "r30,%d",size);
4545 if (pi) pi->generated = 1;
4546 freeAsmop (right, NULL, ic, TRUE);
4547 freeAsmop (result, NULL, ic, TRUE);
4550 /*-----------------------------------------------------------------*/
4551 /* genPointerSet - stores the value into a pointer location */
4552 /*-----------------------------------------------------------------*/
4554 genPointerSet (iCode * ic, iCode *pi)
4556 operand *right, *result;
4557 sym_link *type, *etype;
4560 right = IC_RIGHT (ic);
4561 result = IC_RESULT (ic);
4563 /* depending on the type of pointer we need to
4564 move it to the correct pointer register */
4565 type = operandType (result);
4566 etype = getSpec (type);
4567 /* if left is of type of pointer then it is simple */
4568 if (IS_PTR (type) && !IS_FUNC (type->next)) {
4569 p_type = DCL_TYPE (type);
4572 /* we have to go by the storage class */
4573 p_type = PTR_TYPE (SPEC_OCLS (etype));
4577 /* now that we have the pointer type we assign
4578 the pointer values */
4585 genMemPointerSet (right, result, ic, pi);
4589 genGenPointerSet (right, result, ic, pi);
4593 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4594 "genPointerSet: illegal pointer type");
4599 /*-----------------------------------------------------------------*/
4600 /* genIfx - generate code for Ifx statement */
4601 /*-----------------------------------------------------------------*/
4603 genIfx (iCode * ic, iCode * popIc)
4605 operand *cond = IC_COND (ic);
4610 aopOp (cond, ic, FALSE);
4612 /* get the value into acc */
4613 if (AOP_SIZE(cond) == 1 && AOP_ISHIGHREG(AOP(cond),0)) {
4614 cname = aopGet(AOP(cond),0);
4616 toBoolean (cond, "r24", 0);
4620 /* the result is now in the accumulator */
4621 freeAsmop (cond, NULL, ic, TRUE);
4623 /* if there was something to be popped then do it */
4626 emitcode("cpi","%s,0",cname);
4627 } else if (!tob) emitcode("cpi","%s,0",cname);
4629 lbl = newiTempLabel(NULL);
4631 emitcode ("breq","L%05d",lbl->key);
4632 emitcode ("jmp","L%05d",IC_TRUE(ic)->key);
4633 emitcode ("","L%05d:",lbl->key);
4635 emitcode ("brne","L%05d",lbl->key);
4636 emitcode ("jmp","L%05d",IC_FALSE(ic)->key);
4637 emitcode ("","L%05d:",lbl->key);
4642 /*-----------------------------------------------------------------*/
4643 /* genAddrOf - generates code for address of */
4644 /*-----------------------------------------------------------------*/
4646 genAddrOf (iCode * ic)
4648 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
4651 aopOp (IC_RESULT (ic), ic, FALSE);
4652 assert(AOP_SIZE(IC_RESULT(ic)) >= 2);
4653 /* if the operand is on the stack then we
4654 need to get the stack offset of this
4657 /* if it has an offset then we need to compute it */
4659 if (allHigh(AOP(IC_RESULT(ic)))) {
4660 if (isRegPair (AOP(IC_RESULT(ic)))) {
4661 emitcode ("movw","%s,r28",aopGet(AOP(IC_RESULT(ic)),0));
4663 emitcode ("mov","%s,r28",aopGet(AOP(IC_RESULT(ic)),0));
4664 emitcode ("mov","%s,r29",aopGet(AOP(IC_RESULT(ic)),1));
4666 if (sym->stack < 0) {
4667 emitcode("subi","%s,<(%d)",aopGet(AOP(IC_RESULT(ic)),0),-sym->stack);
4668 emitcode("sbci","%s,>(%d)",aopGet(AOP(IC_RESULT(ic)),1),-sym->stack);
4670 emitcode("subi","%s,<(-%d)",aopGet(AOP(IC_RESULT(ic)),0),sym->stack);
4671 emitcode("sbci","%s,>(-%d)",aopGet(AOP(IC_RESULT(ic)),1),sym->stack);
4674 emitcode("movw","r24,r28");
4675 if (sym->stack > -63 && sym->stack < 63) {
4677 emitcode("sbiw","r24,%d",-sym->stack);
4679 emitcode("sbiw","r24,%d",sym->stack);
4681 if (sym->stack < 0) {
4682 emitcode("subi","r24,<(%d)",-sym->stack);
4683 emitcode("sbci","r25,>(%d)",-sym->stack);
4685 emitcode("subi","r24,<(-%d)",sym->stack);
4686 emitcode("sbci","r25,>(-%d)",sym->stack);
4690 aopPut(AOP(IC_RESULT(ic)),"r24",0);
4691 aopPut(AOP(IC_RESULT(ic)),"r25",1);
4695 aopPut(AOP(IC_RESULT(ic)),"r28",0);
4696 aopPut(AOP(IC_RESULT(ic)),"r29",1);
4698 /* fill the result with zero */
4699 size = AOP_SIZE (IC_RESULT (ic)) - 2;
4702 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
4708 /* object not on stack then we need the name */
4709 size = AOP_SIZE (IC_RESULT (ic));
4713 char s[SDCC_NAME_MAX];
4715 sprintf (s, ">(%s)", sym->rname);
4717 sprintf (s, "<(%s)", sym->rname);
4718 aopPut (AOP (IC_RESULT (ic)), s, offset++);
4722 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4726 /*-----------------------------------------------------------------*/
4727 /* genFarFarAssign - assignment when both are in far space */
4728 /*-----------------------------------------------------------------*/
4730 genFarFarAssign (operand * result, operand * right, iCode * ic)
4732 int size = AOP_SIZE (right);
4735 /* first push the right side on to the stack */
4737 l = aopGet (AOP (right), offset++);
4739 emitcode ("push", "acc");
4742 freeAsmop (right, NULL, ic, FALSE);
4743 /* now assign DPTR to result */
4744 aopOp (result, ic, FALSE);
4745 size = AOP_SIZE (result);
4747 emitcode ("pop", "acc");
4748 aopPut (AOP (result), "a", --offset);
4750 freeAsmop (result, NULL, ic, FALSE);
4754 /*-----------------------------------------------------------------*/
4755 /* genAssign - generate code for assignment */
4756 /*-----------------------------------------------------------------*/
4758 genAssign (iCode * ic)
4760 operand *result, *right;
4762 unsigned long lit = 0L;
4764 result = IC_RESULT (ic);
4765 right = IC_RIGHT (ic);
4767 /* if they are the same */
4768 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4771 aopOp (right, ic, FALSE);
4773 /* special case both in far space */
4774 if (AOP_TYPE (right) == AOP_DPTR &&
4775 IS_TRUE_SYMOP (result) && isOperandInFarSpace (result)) {
4777 genFarFarAssign (result, right, ic);
4781 aopOp (result, ic, TRUE);
4783 /* if they are the same registers */
4784 if (sameRegs (AOP (right), AOP (result)))
4787 /* if the result is a bit */
4788 if (AOP_TYPE (result) == AOP_CRY) {
4790 /* if the right size is a literal then
4791 we know what the value is */
4792 if (AOP_TYPE (right) == AOP_LIT) {
4793 if (((int) operandLitValue (right)))
4794 aopPut (AOP (result), one, 0);
4796 aopPut (AOP (result), zero, 0);
4800 /* the right is also a bit variable */
4801 if (AOP_TYPE (right) == AOP_CRY) {
4802 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4803 aopPut (AOP (result), "c", 0);
4808 toBoolean (right, "", 0);
4809 aopPut (AOP (result), "a", 0);
4813 /* bit variables done */
4815 size = AOP_SIZE (result);
4817 if (AOP_TYPE (right) == AOP_LIT)
4819 (unsigned long) floatFromVal (AOP (right)->aopu.
4821 if ((size > 1) && (AOP_TYPE (result) != AOP_REG)
4822 && (AOP_TYPE (right) == AOP_LIT)
4823 && !IS_FLOAT (operandType (right)) && (lit < 256L)) {
4824 emitcode ("clr", "a");
4826 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) ==
4827 0) aopPut (AOP (result), "a", size);
4829 aopPut (AOP (result),
4830 aopGet (AOP (right), size), size);
4835 aopPut (AOP (result),
4836 aopGet (AOP (right), offset), offset);
4842 freeAsmop (right, NULL, ic, FALSE);
4843 freeAsmop (result, NULL, ic, TRUE);
4846 /*-----------------------------------------------------------------*/
4847 /* genJumpTab - genrates code for jump table */
4848 /*-----------------------------------------------------------------*/
4850 genJumpTab (iCode * ic)
4855 aopOp (IC_JTCOND (ic), ic, FALSE);
4856 /* get the condition into accumulator */
4857 l = aopGet (AOP (IC_JTCOND (ic)), 0);
4859 /* multiply by three */
4860 emitcode ("add", "a,acc");
4861 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0));
4862 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
4864 jtab = newiTempLabel (NULL);
4865 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
4866 emitcode ("jmp", "@a+dptr");
4867 emitcode ("", "%05d$:", jtab->key + 100);
4868 /* now generate the jump labels */
4869 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
4870 jtab = setNextItem (IC_JTLABELS (ic)))
4871 emitcode ("ljmp", "%05d$", jtab->key + 100);
4875 /*-----------------------------------------------------------------*/
4876 /* genCast - gen code for casting */
4877 /*-----------------------------------------------------------------*/
4879 genCast (iCode * ic)
4881 operand *result = IC_RESULT (ic);
4882 sym_link *ctype = operandType (IC_LEFT (ic));
4883 sym_link *rtype = operandType (IC_RIGHT (ic));
4884 operand *right = IC_RIGHT (ic);
4887 /* if they are equivalent then do nothing */
4888 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4891 aopOp (right, ic, FALSE);
4892 aopOp (result, ic, FALSE);
4894 /* if the result is a bit */
4895 if (AOP_TYPE (result) == AOP_CRY) {
4896 /* if the right size is a literal then
4897 we know what the value is */
4898 if (AOP_TYPE (right) == AOP_LIT) {
4899 if (((int) operandLitValue (right)))
4900 aopPut (AOP (result), one, 0);
4902 aopPut (AOP (result), zero, 0);
4907 /* the right is also a bit variable */
4908 if (AOP_TYPE (right) == AOP_CRY) {
4909 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4910 aopPut (AOP (result), "c", 0);
4915 toBoolean (right, "", 0);
4916 aopPut (AOP (result), "a", 0);
4920 /* if they are the same size : or less */
4921 if (AOP_SIZE (result) <= AOP_SIZE (right)) {
4923 /* if they are in the same place */
4924 if (sameRegs (AOP (right), AOP (result)))
4927 /* if they in different places then copy */
4928 size = AOP_SIZE (result);
4931 aopPut (AOP (result),
4932 aopGet (AOP (right), offset), offset);
4939 /* if the result is of type pointer */
4940 if (IS_PTR (ctype)) {
4943 sym_link *type = operandType (right);
4944 sym_link *etype = getSpec (type);
4946 /* pointer to generic pointer */
4947 if (IS_GENPTR (ctype)) {
4949 p_type = DCL_TYPE (type);
4951 /* we have to go by the storage class */
4952 p_type = PTR_TYPE (SPEC_OCLS (etype));
4955 /* the first two bytes are known */
4956 size = GPTRSIZE - 1;
4959 aopPut (AOP (result),
4960 aopGet (AOP (right), offset), offset);
4964 /* the last byte depending on type */
4966 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
4971 // pointerTypeToGPByte will have bitched.
4975 sprintf(gpValStr, "#0x%x", gpVal);
4976 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
4981 /* just copy the pointers */
4982 size = AOP_SIZE (result);
4985 aopPut (AOP (result),
4986 aopGet (AOP (right), offset), offset);
4992 /* so we now know that the size of destination is greater
4993 than the size of the source */
4994 /* we move to result for the size of source */
4995 size = AOP_SIZE (right);
4998 aopPut (AOP (result), aopGet (AOP (right), offset), offset);
5002 /* now depending on the sign of the source && destination */
5003 size = AOP_SIZE (result) - AOP_SIZE (right);
5004 /* if unsigned or not an integral type */
5005 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype)) {
5007 aopPut (AOP (result), zero, offset++);
5010 /* we need to extend the sign :{ */
5011 // PENDING: Does nothing on avr
5013 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1);
5016 emitcode ("rlc", "a");
5017 emitcode ("subb", "a,acc");
5019 aopPut (AOP (result), "a", offset++);
5022 /* we are done hurray !!!! */
5025 freeAsmop (right, NULL, ic, TRUE);
5026 freeAsmop (result, NULL, ic, TRUE);
5030 /*-----------------------------------------------------------------*/
5031 /* genDjnz - generate decrement & jump if not zero instrucion */
5032 /*-----------------------------------------------------------------*/
5034 genDjnz (iCode * ic, iCode * ifx)
5040 /* if the if condition has a false label
5041 then we cannot save */
5045 /* if the minus is not of the form
5047 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
5048 !IS_OP_LITERAL (IC_RIGHT (ic)))
5051 if (operandLitValue (IC_RIGHT (ic)) != 1)
5054 /* if the size of this greater than one then no
5056 if (getSize (operandType (IC_RESULT (ic))) > 1)
5059 /* otherwise we can save BIG */
5060 lbl = newiTempLabel (NULL);
5061 lbl1 = newiTempLabel (NULL);
5063 aopOp (IC_RESULT (ic), ic, FALSE);
5065 if (IS_AOP_PREG (IC_RESULT (ic))) {
5066 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0));
5067 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0));
5068 emitcode ("jnz", "%05d$", lbl->key + 100);
5071 emitcode ("djnz", "%s,%05d$",
5072 aopGet (AOP (IC_RESULT (ic)), 0), lbl->key + 100);
5074 emitcode ("sjmp", "%05d$", lbl1->key + 100);
5075 emitcode ("", "%05d$:", lbl->key + 100);
5076 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5077 emitcode ("", "%05d$:", lbl1->key + 100);
5079 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5084 static char *recvregs[8] = {
5085 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23"
5088 static int recvCnt = 0;
5090 /*-----------------------------------------------------------------*/
5091 /* genReceive - generate code for a receive iCode */
5092 /*-----------------------------------------------------------------*/
5094 genReceive (iCode * ic)
5096 int size, offset = 0;
5097 aopOp (IC_RESULT (ic), ic, FALSE);
5098 size = AOP_SIZE (IC_RESULT (ic));
5100 aopPut (AOP (IC_RESULT (ic)), recvregs[recvCnt++], offset);
5103 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5106 /*-----------------------------------------------------------------*/
5107 /* genDummyRead - generate code for dummy read of volatiles */
5108 /*-----------------------------------------------------------------*/
5110 genDummyRead (iCode * ic)
5112 emitcode ("; genDummyRead","");
5113 emitcode ("; not implemented","");
5118 /*-----------------------------------------------------------------*/
5119 /* gen51Code - generate code for 8051 based controllers */
5120 /*-----------------------------------------------------------------*/
5122 genAVRCode (iCode * lic)
5127 lineHead = lineCurr = NULL;
5129 /* print the allocation information */
5131 printAllocInfo (currFunc, codeOutBuf);
5132 /* if debug information required */
5133 if (options.debug && currFunc) {
5134 debugFile->writeFunction (currFunc, lic);
5136 /* stack pointer name */
5140 for (ic = lic; ic; ic = ic->next) {
5142 if (cln != ic->lineno) {
5143 if (options.debug) {
5144 debugFile->writeCLine (ic);
5146 emitcode (";", "%s %d", ic->filename, ic->lineno);
5149 /* if the result is marked as
5150 spilt and rematerializable or code for
5151 this has already been generated then
5153 if (resultRemat (ic) || ic->generated)
5156 /* depending on the operation */
5175 /* IPOP happens only when trying to restore a
5176 spilt live range, if there is an ifx statement
5177 following this pop then the if statement might
5178 be using some of the registers being popped which
5179 would destory the contents of the register so
5180 we need to check for this condition and handle it */
5182 ic->next->op == IFX &&
5183 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
5184 genIfx (ic->next, ic);
5202 genEndFunction (ic);
5222 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
5239 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
5243 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
5247 genCmpLe (ic, ifxForOp (IC_RESULT (ic), ic));
5251 genCmpGe (ic, ifxForOp (IC_RESULT (ic), ic));
5255 genCmpNe (ic, ifxForOp (IC_RESULT (ic), ic));
5259 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
5271 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
5275 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
5279 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
5306 case GET_VALUE_AT_ADDRESS:
5307 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
5311 if (POINTER_SET (ic))
5312 genPointerSet (ic, hasInc(IC_RESULT(ic),ic));
5338 addSet (&_G.sendSet, ic);
5341 case DUMMY_READ_VOLATILE:
5351 /* now we are ready to call the
5352 peep hole optimizer */
5353 if (!options.nopeep)
5354 peepHole (&lineHead);
5356 /* now do the actual printing */
5357 printLine (lineHead, codeOutBuf);