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;
2952 bool inComment = FALSE;
2954 _G.inLine += (!options.asmpeep);
2956 buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
2958 /* emit each line as a code */
2976 /* Add \n for labels, not dirs such as c:\mydir */
2977 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
2995 _G.inLine -= (!options.asmpeep);
2998 /*-----------------------------------------------------------------*/
2999 /* genRotC - rotate right/left with carry , lr = 1 rotate right */
3000 /*-----------------------------------------------------------------*/
3002 genRotC (iCode * ic, int lr)
3004 operand *left, *result;
3005 int size, offset = 0;
3007 /* rotate right with carry */
3008 left = IC_LEFT (ic);
3009 result = IC_RESULT (ic);
3010 aopOp (left, ic, FALSE);
3011 aopOp (result, ic, FALSE);
3013 /* move it to the result */
3014 size = AOP_SIZE (result);
3015 if (!sameRegs (AOP (left), AOP (result))) {
3018 aopPut (AOP (result),
3019 aopGet (AOP (left), offset), offset);
3022 size = AOP_SIZE (result);
3030 emitcode ("sbrc", "%s,%d", aopGet (AOP (result), offset),
3032 emitcode ("sec", "");
3035 emitcode ((lr ? "ror" : "rol"), "%s",
3036 aopGet (AOP (result), offset));
3042 freeAsmop (left, NULL, ic, TRUE);
3043 freeAsmop (result, NULL, ic, TRUE);
3046 /*-----------------------------------------------------------------*/
3047 /* genRRC - rotate right with carry */
3048 /*-----------------------------------------------------------------*/
3055 /*-----------------------------------------------------------------*/
3056 /* genRLC - generate code for rotate left with carry */
3057 /*-----------------------------------------------------------------*/
3064 /*-----------------------------------------------------------------*/
3065 /* genGetHbit - generates code get highest order bit */
3066 /*-----------------------------------------------------------------*/
3068 genGetHbit (iCode * ic)
3070 operand *left, *result;
3073 left = IC_LEFT (ic);
3074 result = IC_RESULT (ic);
3075 aopOp (left, ic, FALSE);
3076 aopOp (result, ic, FALSE);
3078 size = AOP_SIZE (result);
3079 if (!sameRegs (AOP (left), AOP (result))) {
3080 emitcode ("clr", "%s", aopGet (AOP (result), size - 1));
3081 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3082 emitcode ("subi", "%s,<(-1)",
3083 aopGet (AOP (result), size - 1));
3086 emitcode ("clr", "r0");
3087 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3088 emitcode ("subi", "r0,<(-1)");
3089 aopPut (AOP (result), "r0", 0);
3094 emitcode ("clr", aopGet (AOP (result), offset++));
3096 freeAsmop (left, NULL, ic, TRUE);
3097 freeAsmop (result, NULL, ic, TRUE);
3100 /*-----------------------------------------------------------------*/
3101 /* genShiftLeftLit - shift left by a known amount */
3102 /*-----------------------------------------------------------------*/
3104 genShiftLeftLit (iCode * ic)
3106 operand *left, *right, *result;
3107 int size, shCount, offset = 0;
3110 right = IC_RIGHT (ic);
3111 left = IC_LEFT (ic);
3112 result = IC_RESULT (ic);
3114 aopOp (left, ic, FALSE);
3115 aopOp (result, ic, FALSE);
3116 size = AOP_SIZE (result);
3117 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3119 if (shCount > (size * 8 - 1)) {
3121 aopPut (AOP (result), zero, offset++);
3126 if (!sameRegs (AOP (left), AOP (result)))
3127 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3129 if (AOP_ISHIGHREG(AOP(result),0)) {
3130 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3131 emitcode ("andi", "%s,0xf0");
3133 emitcode ("ldi","r24,0xf0");
3134 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3135 emitcode ("and", "%s,r24");
3140 emitcode ("add", "%s,%s", aopGet (AOP (result), 0),
3141 aopGet (AOP (result), 0));
3145 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3148 if (shCount >= 12) {
3149 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3150 aopPut (AOP (result), zero, 0);
3151 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3152 if (AOP_ISHIGHREG(AOP(result),1)) {
3153 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3155 emitcode ("ldi","r24,0xf0");
3156 emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
3162 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3163 aopPut (AOP (result), zero, 0);
3169 if (!sameRegs (AOP (left), AOP (result))) {
3170 aopPut (AOP (result), aopGet (AOP (left), 0),
3172 aopPut (AOP (result), aopGet (AOP (left), 1),
3175 emitcode ("mov", "r24,%s", aopGet (AOP (result), 0));
3176 emitcode ("andi", "r24,0x0f");
3177 if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
3178 emitcode("ldi","r25,0xf0");
3180 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3181 if (AOP_ISHIGHREG(AOP(result),0)) {
3182 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 0));
3184 emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
3186 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3187 if (AOP_ISHIGHREG(AOP(result),1)) {
3188 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3190 emitcode ("and", "%s,r25", aopGet (AOP (result), 1));
3192 emitcode ("or", "%s,r24", aopGet (AOP (result), 1));
3194 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3195 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3198 if (!lByteZ && !sameRegs (AOP (result), AOP (left))
3202 aopPut (AOP (result),
3203 aopGet (AOP (left), offset), offset);
3209 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3212 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3213 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3218 assert ("shifting generic pointer ?\n");
3221 /* 32 bits we do only byte boundaries */
3222 if (shCount >= 24) {
3223 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3224 aopPut (AOP (result), zero, 2);
3225 aopPut (AOP (result), zero, 1);
3226 aopPut (AOP (result), zero, 0);
3230 if (shCount >= 16) {
3231 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3232 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3233 aopPut (AOP (result), zero, 1);
3234 aopPut (AOP (result), zero, 0);
3239 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3240 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3241 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3242 aopPut (AOP (result), zero, 0);
3246 if (!lByteZ && !sameRegs (AOP (left), AOP (right))) {
3249 aopPut (AOP (result),
3250 aopGet (AOP (left), offset), offset);
3254 size = AOP_SIZE (result);
3260 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3261 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3262 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3263 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3268 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3269 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3270 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3275 emitcode ("lsl", "%s", aopGet (AOP (result), 2));
3276 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3281 emitcode ("lsl", "%s", aopGet (AOP (result), 3));
3289 freeAsmop (left, NULL, ic, TRUE);
3290 freeAsmop (right, NULL, ic, TRUE);
3291 freeAsmop (result, NULL, ic, TRUE);
3294 /*-----------------------------------------------------------------*/
3295 /* genLeftShift - generates code for left shifting */
3296 /*-----------------------------------------------------------------*/
3298 genLeftShift (iCode * ic)
3300 operand *left, *right, *result;
3304 right = IC_RIGHT (ic);
3305 left = IC_LEFT (ic);
3306 result = IC_RESULT (ic);
3308 aopOp (right, ic, FALSE);
3310 if (AOP_TYPE (right) == AOP_LIT) {
3311 genShiftLeftLit (ic);
3316 aopOp (left, ic, FALSE);
3317 aopOp (result, ic, FALSE);
3318 size = AOP_SIZE (result);
3320 if (AOP_SIZE (right) > 1) {
3321 if (isRegPair (AOP (right))) {
3322 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3325 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3326 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3330 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3332 if (!sameRegs (AOP (left), AOP (result))) {
3334 aopPut (AOP (result), aopGet (AOP (left), offset),
3338 size = AOP_SIZE (result);
3340 tlbl = newiTempLabel (NULL);
3341 emitcode ("", "L%05d:", tlbl->key);
3345 emitcode ("rol", "%s", aopGet (AOP (result), offset));
3347 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3350 if (AOP_SIZE (right) > 1)
3351 emitcode ("sbiw", "r24,1");
3353 emitcode ("dec", "r24");
3354 emitcode ("brne", "L%05d", tlbl->key);
3356 freeAsmop (left, NULL, ic, TRUE);
3357 freeAsmop (right, NULL, ic, TRUE);
3358 freeAsmop (result, NULL, ic, TRUE);
3361 /*-----------------------------------------------------------------*/
3362 /* genShiftRightLit - generate for right shift with known count */
3363 /*-----------------------------------------------------------------*/
3365 genShiftRightLit (iCode * ic)
3367 operand *left = IC_LEFT (ic)
3368 , *right = IC_RIGHT (ic)
3369 , *result = IC_RESULT (ic);
3370 int size, shCount, offset = 0;
3372 sym_link *letype = getSpec (operandType (left));
3373 int sign = !SPEC_USIGN (letype);
3375 right = IC_RIGHT (ic);
3376 left = IC_LEFT (ic);
3377 result = IC_RESULT (ic);
3379 aopOp (left, ic, FALSE);
3380 aopOp (result, ic, FALSE);
3381 size = AOP_SIZE (result);
3382 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3384 /* if signed then give up and use a loop to shift */
3387 if (!sameRegs (AOP (left), AOP (result))) {
3389 aopPut (AOP (result),
3390 aopGet (AOP (left), offset), offset);
3393 size = AOP_SIZE (result);
3396 /* be as economical as possible */
3399 size = AOP_SIZE (result);
3402 /* highest order byte */
3403 if (offset == (AOP_SIZE(result)-1))
3404 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3406 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3412 emitcode ("ldi", "r24,<(%d)", shCount);
3413 tlbl = newiTempLabel (NULL);
3414 emitcode ("", "L%05d:", tlbl->key);
3417 if (offset == (AOP_SIZE(result) - 1))
3418 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3420 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3423 emitcode ("dec", "r24");
3424 emitcode ("brne", "L%05d", tlbl->key);
3428 if (shCount > (size * 8 - 1)) {
3430 aopPut (AOP (result), zero, offset++);
3433 /* for unsigned we can much more efficient */
3436 if (!sameRegs (AOP (left), AOP (result)))
3437 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3439 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3440 if (AOP_ISHIGHREG(AOP(result),0)) {
3441 emitcode ("andi", "%s,0x0f",aopGet(AOP(result),0));
3443 emitcode ("ldi","r24,0x0f");
3444 emitcode ("and", "%s,r24",aopGet(AOP(result),0));
3449 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3452 if (shCount >= 12) {
3453 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3454 aopPut (AOP (result), zero, 1);
3455 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3456 if (AOP_ISHIGHREG(AOP(result),0)) {
3457 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3459 emitcode ("ldi","r24,0x0f");
3460 emitcode ("and", "%s,r24",aopGet(AOP(result),0));
3466 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3467 aopPut (AOP (result), zero, 1);
3473 if (!sameRegs (AOP (left), AOP (result))) {
3474 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3475 aopPut (AOP (result), aopGet (AOP (left), 1), 1);
3477 if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
3478 emitcode("ldi","r25,0x0f");
3480 emitcode ("mov", "r24,%s", aopGet (AOP (result), 1));
3481 emitcode ("andi", "r24,0xf0");
3482 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3483 if (AOP_ISHIGHREG(AOP(result),0)) {
3484 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3486 emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
3488 emitcode ("or", "%s,r24", aopGet (AOP (result), 0));
3489 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3490 if (AOP_ISHIGHREG(AOP(result),1)) {
3491 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 1));
3493 emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
3496 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3497 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3501 if (!hByteZ && !sameRegs (AOP (result), AOP (left))
3505 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3511 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3514 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3515 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3521 assert ("shifting generic pointer ?\n");
3524 /* 32 bits we do only byte boundaries */
3525 if (shCount >= 24) {
3526 aopPut (AOP (result), aopGet (AOP (left), 3), 0);
3527 aopPut (AOP (result), zero, 1);
3528 aopPut (AOP (result), zero, 2);
3529 aopPut (AOP (result), zero, 3);
3533 if (shCount >= 16) {
3534 aopPut (AOP (result), aopGet (AOP (left), 3), 1);
3535 aopPut (AOP (result), aopGet (AOP (left), 2), 0);
3536 aopPut (AOP (result), zero, 2);
3537 aopPut (AOP (result), zero, 3);
3542 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3543 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3544 aopPut (AOP (result), aopGet (AOP (left), 3), 2);
3545 aopPut (AOP (result), zero, 3);
3549 if (!hByteZ && !sameRegs (AOP (left), AOP (right))) {
3552 aopPut (AOP (result),
3553 aopGet (AOP (left), offset), offset);
3557 size = AOP_SIZE (result);
3563 emitcode ("lsr", "%s", aopGet (AOP (result), 3));
3564 emitcode ("ror", "%s", aopGet (AOP (result), 2));
3565 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3566 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3571 emitcode ("lsr", "%s", aopGet (AOP (result), 2));
3572 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3573 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3578 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3579 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3584 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3591 freeAsmop (left, NULL, ic, TRUE);
3592 freeAsmop (right, NULL, ic, TRUE);
3593 freeAsmop (result, NULL, ic, TRUE);
3596 /*-----------------------------------------------------------------*/
3597 /* genRightShift - generate code for right shifting */
3598 /*-----------------------------------------------------------------*/
3600 genRightShift (iCode * ic)
3602 operand *right, *left, *result;
3605 int sign = 0, first = 1;
3608 aopOp (right = IC_RIGHT (ic), ic, FALSE);
3610 if (AOP_TYPE (right) == AOP_LIT) {
3611 genShiftRightLit (ic);
3615 if (AOP_SIZE (right) > 1) {
3616 if (isRegPair (AOP (right))) {
3617 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3620 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3621 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3625 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3627 aopOp (left = IC_LEFT (ic), ic, FALSE);
3628 aopOp (result = IC_RESULT (ic), ic, FALSE);
3629 size = AOP_SIZE (result);
3630 tlbl = newiTempLabel (NULL);
3631 emitcode ("", "L%05d:", tlbl->key);
3633 letype = getSpec (operandType (left));
3634 sign = !SPEC_USIGN (letype);
3635 if (!sameRegs (AOP (left), AOP (result))) {
3637 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3640 size = AOP_SIZE (result);
3642 size = AOP_SIZE (result);
3646 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3648 emitcode ("lsr", "%s", aopGet (AOP (result), offset));
3652 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3655 if (AOP_SIZE (right) > 1)
3656 emitcode ("sbiw", "r24,1");
3658 emitcode ("dec", "r24");
3659 emitcode ("brne", "L%05d", tlbl->key);
3661 freeAsmop (left, NULL, ic, TRUE);
3662 freeAsmop (result, NULL, ic, TRUE);
3665 /*-----------------------------------------------------------------*/
3666 /* RRsh - shift right rn by known count */
3667 /*-----------------------------------------------------------------*/
3669 RRsh (int shCount,int reg)
3671 shCount &= 0x0007; // shCount : 0..7
3677 emitcode ("lsr", "r%d",reg);
3680 emitcode ("lsr", "r%d",reg);
3681 emitcode ("lsr", "r%d",reg);
3684 emitcode ("swap", "r%d",reg);
3685 emitcode ("lsl", "r%d",reg);
3688 emitcode ("swap", "r%d",reg);
3691 emitcode ("swap", "r%d",reg);
3692 emitcode ("lsr", "r%d",reg);
3695 emitcode ("swap","r%d",reg);
3696 emitcode ("lsr", "r%d",reg);
3697 emitcode ("lsr", "r%d",reg);
3700 emitcode ("swap","r%d",reg);
3701 emitcode ("lsr", "r%d",reg);
3702 emitcode ("lsr", "r%d",reg);
3703 emitcode ("lsr", "r%d",reg);
3708 /*-----------------------------------------------------------------*/
3709 /* RLsh - shift left rn by known count */
3710 /*-----------------------------------------------------------------*/
3712 RLsh (int shCount, int reg)
3714 shCount &= 0x0007; // shCount : 0..7
3720 emitcode ("lsl", "r%d",reg);
3723 emitcode ("lsl", "r%d",reg);
3724 emitcode ("lsl", "r%d",reg);
3727 emitcode ("swap","r%d",reg);
3728 emitcode ("lsr", "r%d",reg);
3731 emitcode ("swap", "r%d",reg);
3734 emitcode ("swap","r%d",reg);
3735 emitcode ("lsl", "r%d",reg);
3738 emitcode ("swap","r%d",reg);
3739 emitcode ("lsl", "r%d",reg);
3740 emitcode ("lsl", "r%d",reg);
3743 emitcode ("swap","r%d",reg);
3744 emitcode ("lsl", "r%d",reg);
3745 emitcode ("lsl", "r%d",reg);
3746 emitcode ("lsl", "r%d",reg);
3751 /*-----------------------------------------------------------------*/
3752 /* genUnpackBits - generates code for unpacking bits */
3753 /*-----------------------------------------------------------------*/
3755 genUnpackBits (operand * result, char *rname, int ptype)
3763 etype = getSpec (operandType (result));
3764 rsize = getSize (operandType (result));
3765 /* read the first byte */
3772 emitcode ("ld", "r24,%s+", rname);
3776 emitcode ("lpm", "r24,%s+", rname);
3780 emitcode ("call","__gptrget_pi");
3781 emitcode ("mov","r24,r0");
3785 rlen = SPEC_BLEN (etype);
3787 /* if we have bitdisplacement then it fits */
3788 /* into this byte completely or if length is */
3789 /* less than a byte */
3790 if ((shCnt = SPEC_BSTR (etype)) || (SPEC_BLEN (etype) <= 8)) {
3792 /* shift right acc */
3795 emitcode ("andi", "r24,lo(0x%x)",
3796 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
3797 aopPut (AOP (result), "r24", offset++);
3801 /* bit field did not fit in a byte */
3802 aopPut (AOP (result), "r24", offset++);
3812 emitcode ("ld", "r24,%s+");
3816 emitcode ("lpm", "r24,%s+");
3820 emitcode ("call", "__gptrget_pi");
3825 /* if we are done */
3829 aopPut (AOP (result), "r24", offset++);
3834 aopPut (AOP (result), "r24", offset++);
3838 if (offset < rsize) {
3841 aopPut (AOP (result), zero, offset++);
3846 /*-----------------------------------------------------------------*/
3847 /* genDataPointerGet - generates code when ptr offset is known */
3848 /*-----------------------------------------------------------------*/
3850 genDataPointerGet (operand * left, operand * result, iCode * ic)
3854 int size, offset = 0;
3855 aopOp (result, ic, TRUE);
3857 /* get the string representation of the name */
3858 l = aopGet (AOP (left), 0);
3859 size = AOP_SIZE (result);
3862 sprintf (buffer, "(%s + %d)", l, offset);
3864 sprintf (buffer, "%s", l);
3865 emitcode ("lds", "%s,%s", aopGet (AOP (result), offset++),
3869 freeAsmop (left, NULL, ic, TRUE);
3870 freeAsmop (result, NULL, ic, TRUE);
3873 /*-----------------------------------------------------------------*/
3874 /* genNearPointerGet - emitcode for near pointer fetch */
3875 /*-----------------------------------------------------------------*/
3877 genMemPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
3882 char *rname, *frname = NULL;
3883 sym_link *rtype, *retype;
3884 sym_link *ltype = operandType (left);
3886 rtype = operandType (result);
3887 retype = getSpec (rtype);
3889 aopOp (left, ic, FALSE);
3891 /* if left is rematerialisable and
3892 result is not bit variable type and
3893 the left is pointer to data space i.e
3894 lower 128 bytes of space */
3895 if (AOP_TYPE (left) == AOP_IMMD &&
3896 !IS_BITVAR (retype) && DCL_TYPE (ltype) == POINTER) {
3897 genDataPointerGet (left, result, ic);
3901 /* if the value is already in a pointer register
3902 then don't need anything more */
3903 if (!AOP_INPREG (AOP (left))) {
3904 /* otherwise get a free pointer register */
3906 preg = getFreePtr (ic, &aop, FALSE, 0);
3907 if (isRegPair (AOP (left) )) {
3908 emitcode ("movw", "%s,%s",
3909 aop->aopu.aop_ptr->name,
3910 aopGet(AOP(left),0));
3912 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
3913 aopGet (AOP (left), 0));
3914 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
3915 aopGet (AOP (left), 1));
3921 frname = aopGet(aop,0);
3925 } else if (AOP_ISZ(aop)) {
3928 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
3929 "pointer not in correct register");
3933 aopOp (result, ic, FALSE);
3935 /* if bitfield then unpack the bits */
3936 if (IS_BITVAR (retype))
3937 genUnpackBits (result, rname, POINTER);
3939 /* we have can just get the values */
3940 int size = AOP_SIZE (result);
3945 emitcode ("ld","%s,%s+",aopGet(AOP(result),offset), rname);
3947 emitcode ("ld","%s,%s",aopGet(AOP(result),offset), rname);
3952 /* now some housekeeping stuff */
3954 /* we had to allocate for this iCode */
3956 if (isRegPair (AOP (left) )) {
3957 emitcode ("movw", "%s,%s",
3958 aopGet (AOP(left),0),
3959 aop->aopu.aop_ptr->name);
3961 emitcode ("mov", "%s,%s",
3962 aopGet (AOP (left), 0),
3963 aop->aopu.aop_ptr->name);
3964 emitcode ("mov", "%s,%s",
3965 aopGet (AOP (left), 1),
3966 aop->aop_ptr2->name);
3969 freeAsmop (NULL, aop, ic, TRUE);
3972 /* we did not allocate which means left
3973 already in a pointer register, then
3974 if size > 0 && this could be used again
3975 we have to point it back to where it
3977 if ((AOP_SIZE (result) > 1 &&
3978 !OP_SYMBOL (left)->remat &&
3979 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) && !pi) {
3980 int size = AOP_SIZE (result) - 1;
3981 emitcode ("sbiw", "%s,%d",frname,size);
3986 if (pi) pi->generated = 1;
3987 freeAsmop (left, NULL, ic, TRUE);
3988 freeAsmop (result, NULL, ic, TRUE);
3992 /*-----------------------------------------------------------------*/
3993 /* genCodePointerGet - gget value from code space */
3994 /*-----------------------------------------------------------------*/
3996 genCodePointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
3999 sym_link *retype = getSpec (operandType (result));
4003 aopOp (left, ic, FALSE);
4005 /* if the operand is already in Z register
4006 then we do nothing else we move the value to Z register */
4007 if (AOP_ISZ(AOP(left))) {
4011 getFreePtr(ic,&aop,FALSE,TRUE);
4012 if (isRegPair(AOP (left))) {
4013 emitcode ("movw","r30,%s",aopGet (AOP (left), 0));
4015 emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
4016 emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
4021 aopOp (result, ic, FALSE);
4023 /* if bit then unpack */
4024 if (IS_BITVAR (retype))
4025 genUnpackBits (result, "Z", CPOINTER);
4027 size = AOP_SIZE (result);
4032 emitcode ("lpm","%s,Z+",aopGet(AOP(result),offset++));
4034 emitcode ("lpm","%s,Z",aopGet(AOP(result),offset++));
4039 /* now some housekeeping stuff */
4041 /* we had to allocate for this iCode */
4043 if (isRegPair(AOP (left))) {
4044 emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
4046 emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
4047 emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
4050 freeAsmop (NULL, aop, ic, TRUE);
4053 /* we did not allocate which means left
4054 already in a pointer register, then
4055 if size > 0 && this could be used again
4056 we have to point it back to where it
4058 if ((AOP_SIZE (result) > 1 &&
4059 !OP_SYMBOL (left)->remat &&
4060 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) &&
4062 int size = AOP_SIZE (result) - 1;
4063 emitcode ("sbiw", "r30,%d",size);
4068 if (pi) pi->generated=1;
4069 freeAsmop (left, NULL, ic, TRUE);
4070 freeAsmop (result, NULL, ic, TRUE);
4074 /*-----------------------------------------------------------------*/
4075 /* genGenPointerGet - gget value from generic pointer space */
4076 /*-----------------------------------------------------------------*/
4078 genGenPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
4082 sym_link *retype = getSpec (operandType (result));
4085 aopOp (left, ic, FALSE);
4087 /* if the operand is already in dptr
4088 then we do nothing else we move the value to dptr */
4089 if (AOP_ISZ(AOP(left))) {
4093 getFreePtr(ic,&aop,FALSE,TRUE);
4094 if (isRegPair(AOP(left))) {
4095 emitcode ("movw", "r30,%s", aopGet (AOP (left), 0));
4097 emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
4098 emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
4100 emitcode ("mov", "r24,%s", aopGet (AOP (left), 2));
4104 /* so Z register now contains the address */
4106 aopOp (result, ic, FALSE);
4108 /* if bit then unpack */
4109 if (IS_BITVAR (retype))
4110 genUnpackBits (result, "Z", GPOINTER);
4112 size = AOP_SIZE (result);
4117 emitcode ("call", "__gptrget_pi");
4119 emitcode ("call", "__gptrget");
4120 aopPut (AOP (result), "r0", offset++);
4125 /* now some housekeeping stuff */
4127 /* we had to allocate for this iCode */
4129 if (isRegPair(AOP (left))) {
4130 emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
4132 emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
4133 emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
4136 freeAsmop (NULL, aop, ic, TRUE);
4139 /* we did not allocate which means left
4140 already in a pointer register, then
4141 if size > 0 && this could be used again
4142 we have to point it back to where it
4144 if ((AOP_SIZE (result) > 1 &&
4145 !OP_SYMBOL (left)->remat &&
4146 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) &&
4148 int size = AOP_SIZE (result) - 1;
4149 emitcode ("sbiw", "r30,%d",size);
4152 if (pi) pi->generated=1;
4153 freeAsmop (left, NULL, ic, TRUE);
4154 freeAsmop (result, NULL, ic, TRUE);
4157 /*-----------------------------------------------------------------*/
4158 /* genPointerGet - generate code for pointer get */
4159 /*-----------------------------------------------------------------*/
4161 genPointerGet (iCode * ic, iCode *pi)
4163 operand *left, *result;
4164 sym_link *type, *etype;
4167 left = IC_LEFT (ic);
4168 result = IC_RESULT (ic);
4170 /* depending on the type of pointer we need to
4171 move it to the correct pointer register */
4172 type = operandType (left);
4173 etype = getSpec (type);
4174 /* if left is of type of pointer then it is simple */
4175 if (IS_PTR (type) && !IS_FUNC (type->next))
4176 p_type = DCL_TYPE (type);
4178 /* we have to go by the storage class */
4179 p_type = PTR_TYPE (SPEC_OCLS (etype));
4184 /* now that we have the pointer type we assign
4185 the pointer values */
4192 genMemPointerGet (left, result, ic, pi);
4196 genCodePointerGet (left, result, ic, pi);
4200 genGenPointerGet (left, result, ic, pi);
4206 /*-----------------------------------------------------------------*/
4207 /* genPackBits - generates code for packed bit storage */
4208 /*-----------------------------------------------------------------*/
4210 genPackBits (sym_link * etype,
4212 char *rname, int p_type)
4220 blen = SPEC_BLEN (etype);
4221 bstr = SPEC_BSTR (etype);
4223 l = aopGet (AOP (right), offset++);
4226 /* if the bit lenth is less than or */
4227 /* it exactly fits a byte then */
4228 if (SPEC_BLEN (etype) <= 8) {
4229 shCount = SPEC_BSTR (etype);
4231 /* shift left acc */
4234 if (SPEC_BLEN (etype) < 8) { /* if smaller than a byte */
4241 emitcode ("ld", "r1,%s",rname);
4245 emitcode ("push", "r1");
4246 emitcode ("push", "r24");
4247 emitcode ("call", "__gptrget");
4248 emitcode ("pop", "r1");
4249 emitcode ("mov","r24,r0");
4253 emitcode ("andi", "r24,#0x%02x", (unsigned char)
4254 ((unsigned char) (0xFF << (blen + bstr)) |
4255 (unsigned char) (0xFF >> (8 - bstr))));
4256 emitcode ("or", "r24,r1");
4257 if (p_type == GPOINTER)
4258 emitcode ("pop", "r1");
4267 emitcode("st","%s+,r24");
4271 emitcode("mov","r0,r24");
4272 emitcode ("call", "__gptrput_pi");
4277 if (SPEC_BLEN (etype) <= 8)
4280 rLen = SPEC_BLEN (etype);
4282 /* now generate for lengths greater than one byte */
4285 l = aopGet (AOP (right), offset++);
4296 emitcode ("st", "%s+,%s",rname,l);
4301 emitcode ("lcall", "__gptrput_pi");
4308 /* last last was not complete */
4310 /* save the byte & read byte */
4316 emitcode ("st","%s+,r24",rname);
4319 emitcode ("push", "r1");
4320 emitcode ("push", "r24");
4321 emitcode ("lcall", "__gptrget");
4322 emitcode ("mov","r24,r0");
4323 emitcode ("pop", "r1");
4327 emitcode ("andi", "r24,0x%02x", (((unsigned char) -1 << rLen) & 0xff));
4328 emitcode ("or", "r24,r1");
4331 if (p_type == GPOINTER)
4332 emitcode ("pop", "r1");
4340 emitcode ("st", "%s,r24", rname);
4344 emitcode ("mov","r0,r24");
4345 emitcode ("call", "__gptrput");
4350 /*-----------------------------------------------------------------*/
4351 /* genDataPointerSet - remat pointer to data space */
4352 /*-----------------------------------------------------------------*/
4354 genDataPointerSet (operand * right, operand * result, iCode * ic)
4356 int size, offset = 0;
4357 char *l, buffer[256];
4359 aopOp (right, ic, FALSE);
4361 l = aopGet (AOP (result), 0);
4362 size = AOP_SIZE (right);
4365 sprintf (buffer, "(%s + %d)", l, offset);
4367 sprintf (buffer, "%s", l);
4368 emitcode ("sts", "%s,%s", buffer,
4369 aopGet (AOP (right), offset++));
4372 freeAsmop (right, NULL, ic, TRUE);
4373 freeAsmop (result, NULL, ic, TRUE);
4376 /*-----------------------------------------------------------------*/
4377 /* genNearPointerSet - emitcode for near pointer put */
4378 /*-----------------------------------------------------------------*/
4380 genMemPointerSet (operand * right, operand * result, iCode * ic, iCode *pi)
4383 char *frname = NULL, *rname, *l;
4386 sym_link *ptype = operandType (result);
4388 retype = getSpec (operandType (right));
4390 aopOp (result, ic, FALSE);
4392 /* if the result is rematerializable &
4393 in data space & not a bit variable */
4394 if (AOP_TYPE (result) == AOP_IMMD &&
4395 DCL_TYPE (ptype) == POINTER && !IS_BITVAR (retype)) {
4396 genDataPointerSet (right, result, ic);
4399 if (!AOP_INPREG(AOP(result))) {
4400 /* otherwise get a free pointer register */
4402 getFreePtr (ic, &aop, FALSE, 0);
4403 if (isRegPair (AOP (result) )) {
4404 emitcode ("movw", "%s,%s",aop->aopu.aop_ptr->name,
4405 aopGet(AOP (result), 0));
4407 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
4408 aopGet (AOP (result), 0));
4409 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
4410 aopGet (AOP (result), 1));
4415 frname = aopGet(aop,0);
4418 aopOp (right, ic, FALSE);
4421 } else if (AOP_ISZ(aop)) {
4424 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4425 "pointer not in correct register");
4428 /* if bitfield then unpack the bits */
4429 if (IS_BITVAR (retype))
4430 genPackBits (retype, right, rname, POINTER);
4432 /* we have can just get the values */
4433 int size = AOP_SIZE (right);
4437 l = aopGet (AOP (right), offset);
4439 emitcode ("st", "%s+,%s", rname,l);
4441 emitcode ("st", "%s,%s", rname,l);
4446 /* now some housekeeping stuff */
4448 /* we had to allocate for this iCode */
4450 if (isRegPair (AOP (result) )) {
4451 emitcode ("movw", "%s,%s",
4452 aopGet(AOP(result),0),
4453 aop->aopu.aop_ptr->name);
4455 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
4456 aopGet (AOP (result), 0));
4457 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
4458 aopGet (AOP (result), 1));
4461 freeAsmop (NULL, aop, ic, TRUE);
4464 /* we did not allocate which means left
4465 already in a pointer register, then
4466 if size > 0 && this could be used again
4467 we have to point it back to where it
4469 if ((AOP_SIZE (right) > 1 &&
4470 !OP_SYMBOL (result)->remat &&
4471 (OP_SYMBOL (right)->liveTo > ic->seq || ic->depth)) && !pi) {
4472 int size = AOP_SIZE (right) - 1;
4473 emitcode ("sbiw", "%s,%d",frname,size);
4478 if (pi) pi->generated = 1;
4479 freeAsmop (result, NULL, ic, TRUE);
4480 freeAsmop (right, NULL, ic, TRUE);
4483 /*-----------------------------------------------------------------*/
4484 /* genGenPointerSet - set value from generic pointer space */
4485 /*-----------------------------------------------------------------*/
4487 genGenPointerSet (operand * right, operand * result, iCode * ic, iCode *pi)
4491 sym_link *retype = getSpec (operandType (right));
4494 aopOp (result, ic, FALSE);
4496 /* if the operand is already in dptr
4497 then we do nothing else we move the value to dptr */
4498 if (AOP_ISZ(AOP(result))) {
4502 getFreePtr(ic,&aop,FALSE,TRUE);
4503 if (isRegPair(AOP(result))) {
4504 emitcode ("movw", "r30,%s", aopGet (AOP (result), 0));
4506 emitcode ("mov", "r30,%s", aopGet (AOP (result), 0));
4507 emitcode ("mov", "r31,%s", aopGet (AOP (result), 1));
4509 emitcode ("mov", "r24,%s", aopGet (AOP (result), 2));
4513 /* so Z register now contains the address */
4514 aopOp (right, ic, FALSE);
4516 /* if bit then unpack */
4517 if (IS_BITVAR (retype))
4518 genUnpackBits (result, "Z", GPOINTER);
4520 size = AOP_SIZE (right);
4524 char *l = aopGet(AOP (right), offset++);
4528 emitcode ("call", "__gptrput_pi");
4530 emitcode ("call", "__gptrput");
4534 /* now some housekeeping stuff */
4536 /* we had to allocate for this iCode */
4538 if (isRegPair(AOP(result))) {
4539 emitcode ("movw", "%s,r30", aopGet (AOP (result), 0));
4541 emitcode ("mov", "%s,r30", aopGet (AOP (result), 0));
4542 emitcode ("mov", "%s,r31", aopGet (AOP (result), 1));
4545 freeAsmop (NULL, aop, ic, TRUE);
4548 /* we did not allocate which means left
4549 already in a pointer register, then
4550 if size > 0 && this could be used again
4551 we have to point it back to where it
4553 if ((AOP_SIZE (right) > 1 &&
4554 !OP_SYMBOL (result)->remat &&
4555 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) && !pi) {
4556 int size = AOP_SIZE (right) - 1;
4557 emitcode ("sbiw", "r30,%d",size);
4560 if (pi) pi->generated = 1;
4561 freeAsmop (right, NULL, ic, TRUE);
4562 freeAsmop (result, NULL, ic, TRUE);
4565 /*-----------------------------------------------------------------*/
4566 /* genPointerSet - stores the value into a pointer location */
4567 /*-----------------------------------------------------------------*/
4569 genPointerSet (iCode * ic, iCode *pi)
4571 operand *right, *result;
4572 sym_link *type, *etype;
4575 right = IC_RIGHT (ic);
4576 result = IC_RESULT (ic);
4578 /* depending on the type of pointer we need to
4579 move it to the correct pointer register */
4580 type = operandType (result);
4581 etype = getSpec (type);
4582 /* if left is of type of pointer then it is simple */
4583 if (IS_PTR (type) && !IS_FUNC (type->next)) {
4584 p_type = DCL_TYPE (type);
4587 /* we have to go by the storage class */
4588 p_type = PTR_TYPE (SPEC_OCLS (etype));
4592 /* now that we have the pointer type we assign
4593 the pointer values */
4600 genMemPointerSet (right, result, ic, pi);
4604 genGenPointerSet (right, result, ic, pi);
4608 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4609 "genPointerSet: illegal pointer type");
4614 /*-----------------------------------------------------------------*/
4615 /* genIfx - generate code for Ifx statement */
4616 /*-----------------------------------------------------------------*/
4618 genIfx (iCode * ic, iCode * popIc)
4620 operand *cond = IC_COND (ic);
4625 aopOp (cond, ic, FALSE);
4627 /* get the value into acc */
4628 if (AOP_SIZE(cond) == 1 && AOP_ISHIGHREG(AOP(cond),0)) {
4629 cname = aopGet(AOP(cond),0);
4631 toBoolean (cond, "r24", 0);
4635 /* the result is now in the accumulator */
4636 freeAsmop (cond, NULL, ic, TRUE);
4638 /* if there was something to be popped then do it */
4641 emitcode("cpi","%s,0",cname);
4642 } else if (!tob) emitcode("cpi","%s,0",cname);
4644 lbl = newiTempLabel(NULL);
4646 emitcode ("breq","L%05d",lbl->key);
4647 emitcode ("jmp","L%05d",IC_TRUE(ic)->key);
4648 emitcode ("","L%05d:",lbl->key);
4650 emitcode ("brne","L%05d",lbl->key);
4651 emitcode ("jmp","L%05d",IC_FALSE(ic)->key);
4652 emitcode ("","L%05d:",lbl->key);
4657 /*-----------------------------------------------------------------*/
4658 /* genAddrOf - generates code for address of */
4659 /*-----------------------------------------------------------------*/
4661 genAddrOf (iCode * ic)
4663 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
4666 aopOp (IC_RESULT (ic), ic, FALSE);
4667 assert(AOP_SIZE(IC_RESULT(ic)) >= 2);
4668 /* if the operand is on the stack then we
4669 need to get the stack offset of this
4672 /* if it has an offset then we need to compute it */
4674 if (allHigh(AOP(IC_RESULT(ic)))) {
4675 if (isRegPair (AOP(IC_RESULT(ic)))) {
4676 emitcode ("movw","%s,r28",aopGet(AOP(IC_RESULT(ic)),0));
4678 emitcode ("mov","%s,r28",aopGet(AOP(IC_RESULT(ic)),0));
4679 emitcode ("mov","%s,r29",aopGet(AOP(IC_RESULT(ic)),1));
4681 if (sym->stack < 0) {
4682 emitcode("subi","%s,<(%d)",aopGet(AOP(IC_RESULT(ic)),0),-sym->stack);
4683 emitcode("sbci","%s,>(%d)",aopGet(AOP(IC_RESULT(ic)),1),-sym->stack);
4685 emitcode("subi","%s,<(-%d)",aopGet(AOP(IC_RESULT(ic)),0),sym->stack);
4686 emitcode("sbci","%s,>(-%d)",aopGet(AOP(IC_RESULT(ic)),1),sym->stack);
4689 emitcode("movw","r24,r28");
4690 if (sym->stack > -63 && sym->stack < 63) {
4692 emitcode("sbiw","r24,%d",-sym->stack);
4694 emitcode("sbiw","r24,%d",sym->stack);
4696 if (sym->stack < 0) {
4697 emitcode("subi","r24,<(%d)",-sym->stack);
4698 emitcode("sbci","r25,>(%d)",-sym->stack);
4700 emitcode("subi","r24,<(-%d)",sym->stack);
4701 emitcode("sbci","r25,>(-%d)",sym->stack);
4705 aopPut(AOP(IC_RESULT(ic)),"r24",0);
4706 aopPut(AOP(IC_RESULT(ic)),"r25",1);
4710 aopPut(AOP(IC_RESULT(ic)),"r28",0);
4711 aopPut(AOP(IC_RESULT(ic)),"r29",1);
4713 /* fill the result with zero */
4714 size = AOP_SIZE (IC_RESULT (ic)) - 2;
4717 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
4723 /* object not on stack then we need the name */
4724 size = AOP_SIZE (IC_RESULT (ic));
4728 char s[SDCC_NAME_MAX];
4730 sprintf (s, ">(%s)", sym->rname);
4732 sprintf (s, "<(%s)", sym->rname);
4733 aopPut (AOP (IC_RESULT (ic)), s, offset++);
4737 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4741 /*-----------------------------------------------------------------*/
4742 /* genFarFarAssign - assignment when both are in far space */
4743 /*-----------------------------------------------------------------*/
4745 genFarFarAssign (operand * result, operand * right, iCode * ic)
4747 int size = AOP_SIZE (right);
4750 /* first push the right side on to the stack */
4752 l = aopGet (AOP (right), offset++);
4754 emitcode ("push", "acc");
4757 freeAsmop (right, NULL, ic, FALSE);
4758 /* now assign DPTR to result */
4759 aopOp (result, ic, FALSE);
4760 size = AOP_SIZE (result);
4762 emitcode ("pop", "acc");
4763 aopPut (AOP (result), "a", --offset);
4765 freeAsmop (result, NULL, ic, FALSE);
4769 /*-----------------------------------------------------------------*/
4770 /* genAssign - generate code for assignment */
4771 /*-----------------------------------------------------------------*/
4773 genAssign (iCode * ic)
4775 operand *result, *right;
4777 unsigned long lit = 0L;
4779 result = IC_RESULT (ic);
4780 right = IC_RIGHT (ic);
4782 /* if they are the same */
4783 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4786 aopOp (right, ic, FALSE);
4788 /* special case both in far space */
4789 if (AOP_TYPE (right) == AOP_DPTR &&
4790 IS_TRUE_SYMOP (result) && isOperandInFarSpace (result)) {
4792 genFarFarAssign (result, right, ic);
4796 aopOp (result, ic, TRUE);
4798 /* if they are the same registers */
4799 if (sameRegs (AOP (right), AOP (result)))
4802 /* if the result is a bit */
4803 if (AOP_TYPE (result) == AOP_CRY) {
4805 /* if the right size is a literal then
4806 we know what the value is */
4807 if (AOP_TYPE (right) == AOP_LIT) {
4808 if (((int) operandLitValue (right)))
4809 aopPut (AOP (result), one, 0);
4811 aopPut (AOP (result), zero, 0);
4815 /* the right is also a bit variable */
4816 if (AOP_TYPE (right) == AOP_CRY) {
4817 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4818 aopPut (AOP (result), "c", 0);
4823 toBoolean (right, "", 0);
4824 aopPut (AOP (result), "a", 0);
4828 /* bit variables done */
4830 size = AOP_SIZE (result);
4832 if (AOP_TYPE (right) == AOP_LIT)
4834 (unsigned long) floatFromVal (AOP (right)->aopu.
4836 if ((size > 1) && (AOP_TYPE (result) != AOP_REG)
4837 && (AOP_TYPE (right) == AOP_LIT)
4838 && !IS_FLOAT (operandType (right)) && (lit < 256L)) {
4839 emitcode ("clr", "a");
4841 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) ==
4842 0) aopPut (AOP (result), "a", size);
4844 aopPut (AOP (result),
4845 aopGet (AOP (right), size), size);
4850 aopPut (AOP (result),
4851 aopGet (AOP (right), offset), offset);
4857 freeAsmop (right, NULL, ic, FALSE);
4858 freeAsmop (result, NULL, ic, TRUE);
4861 /*-----------------------------------------------------------------*/
4862 /* genJumpTab - genrates code for jump table */
4863 /*-----------------------------------------------------------------*/
4865 genJumpTab (iCode * ic)
4870 aopOp (IC_JTCOND (ic), ic, FALSE);
4871 /* get the condition into accumulator */
4872 l = aopGet (AOP (IC_JTCOND (ic)), 0);
4874 /* multiply by three */
4875 emitcode ("add", "a,acc");
4876 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0));
4877 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
4879 jtab = newiTempLabel (NULL);
4880 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
4881 emitcode ("jmp", "@a+dptr");
4882 emitcode ("", "%05d$:", jtab->key + 100);
4883 /* now generate the jump labels */
4884 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
4885 jtab = setNextItem (IC_JTLABELS (ic)))
4886 emitcode ("ljmp", "%05d$", jtab->key + 100);
4890 /*-----------------------------------------------------------------*/
4891 /* genCast - gen code for casting */
4892 /*-----------------------------------------------------------------*/
4894 genCast (iCode * ic)
4896 operand *result = IC_RESULT (ic);
4897 sym_link *ctype = operandType (IC_LEFT (ic));
4898 sym_link *rtype = operandType (IC_RIGHT (ic));
4899 operand *right = IC_RIGHT (ic);
4902 /* if they are equivalent then do nothing */
4903 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4906 aopOp (right, ic, FALSE);
4907 aopOp (result, ic, FALSE);
4909 /* if the result is a bit */
4910 if (AOP_TYPE (result) == AOP_CRY) {
4911 /* if the right size is a literal then
4912 we know what the value is */
4913 if (AOP_TYPE (right) == AOP_LIT) {
4914 if (((int) operandLitValue (right)))
4915 aopPut (AOP (result), one, 0);
4917 aopPut (AOP (result), zero, 0);
4922 /* the right is also a bit variable */
4923 if (AOP_TYPE (right) == AOP_CRY) {
4924 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4925 aopPut (AOP (result), "c", 0);
4930 toBoolean (right, "", 0);
4931 aopPut (AOP (result), "a", 0);
4935 /* if they are the same size : or less */
4936 if (AOP_SIZE (result) <= AOP_SIZE (right)) {
4938 /* if they are in the same place */
4939 if (sameRegs (AOP (right), AOP (result)))
4942 /* if they in different places then copy */
4943 size = AOP_SIZE (result);
4946 aopPut (AOP (result),
4947 aopGet (AOP (right), offset), offset);
4954 /* if the result is of type pointer */
4955 if (IS_PTR (ctype)) {
4958 sym_link *type = operandType (right);
4959 sym_link *etype = getSpec (type);
4961 /* pointer to generic pointer */
4962 if (IS_GENPTR (ctype)) {
4964 p_type = DCL_TYPE (type);
4966 /* we have to go by the storage class */
4967 p_type = PTR_TYPE (SPEC_OCLS (etype));
4970 /* the first two bytes are known */
4971 size = GPTRSIZE - 1;
4974 aopPut (AOP (result),
4975 aopGet (AOP (right), offset), offset);
4979 /* the last byte depending on type */
4981 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
4986 // pointerTypeToGPByte will have bitched.
4990 sprintf(gpValStr, "#0x%x", gpVal);
4991 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
4996 /* just copy the pointers */
4997 size = AOP_SIZE (result);
5000 aopPut (AOP (result),
5001 aopGet (AOP (right), offset), offset);
5007 /* so we now know that the size of destination is greater
5008 than the size of the source */
5009 /* we move to result for the size of source */
5010 size = AOP_SIZE (right);
5013 aopPut (AOP (result), aopGet (AOP (right), offset), offset);
5017 /* now depending on the sign of the source && destination */
5018 size = AOP_SIZE (result) - AOP_SIZE (right);
5019 /* if unsigned or not an integral type */
5020 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype)) {
5022 aopPut (AOP (result), zero, offset++);
5025 /* we need to extend the sign :{ */
5026 // PENDING: Does nothing on avr
5028 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1);
5031 emitcode ("rlc", "a");
5032 emitcode ("subb", "a,acc");
5034 aopPut (AOP (result), "a", offset++);
5037 /* we are done hurray !!!! */
5040 freeAsmop (right, NULL, ic, TRUE);
5041 freeAsmop (result, NULL, ic, TRUE);
5045 /*-----------------------------------------------------------------*/
5046 /* genDjnz - generate decrement & jump if not zero instrucion */
5047 /*-----------------------------------------------------------------*/
5049 genDjnz (iCode * ic, iCode * ifx)
5055 /* if the if condition has a false label
5056 then we cannot save */
5060 /* if the minus is not of the form
5062 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
5063 !IS_OP_LITERAL (IC_RIGHT (ic)))
5066 if (operandLitValue (IC_RIGHT (ic)) != 1)
5069 /* if the size of this greater than one then no
5071 if (getSize (operandType (IC_RESULT (ic))) > 1)
5074 /* otherwise we can save BIG */
5075 lbl = newiTempLabel (NULL);
5076 lbl1 = newiTempLabel (NULL);
5078 aopOp (IC_RESULT (ic), ic, FALSE);
5080 if (IS_AOP_PREG (IC_RESULT (ic))) {
5081 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0));
5082 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0));
5083 emitcode ("jnz", "%05d$", lbl->key + 100);
5086 emitcode ("djnz", "%s,%05d$",
5087 aopGet (AOP (IC_RESULT (ic)), 0), lbl->key + 100);
5089 emitcode ("sjmp", "%05d$", lbl1->key + 100);
5090 emitcode ("", "%05d$:", lbl->key + 100);
5091 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5092 emitcode ("", "%05d$:", lbl1->key + 100);
5094 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5099 static char *recvregs[8] = {
5100 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23"
5103 static int recvCnt = 0;
5105 /*-----------------------------------------------------------------*/
5106 /* genReceive - generate code for a receive iCode */
5107 /*-----------------------------------------------------------------*/
5109 genReceive (iCode * ic)
5111 int size, offset = 0;
5112 aopOp (IC_RESULT (ic), ic, FALSE);
5113 size = AOP_SIZE (IC_RESULT (ic));
5115 aopPut (AOP (IC_RESULT (ic)), recvregs[recvCnt++], offset);
5118 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5121 /*-----------------------------------------------------------------*/
5122 /* genDummyRead - generate code for dummy read of volatiles */
5123 /*-----------------------------------------------------------------*/
5125 genDummyRead (iCode * ic)
5127 emitcode ("; genDummyRead","");
5128 emitcode ("; not implemented","");
5133 /*-----------------------------------------------------------------*/
5134 /* gen51Code - generate code for 8051 based controllers */
5135 /*-----------------------------------------------------------------*/
5137 genAVRCode (iCode * lic)
5142 lineHead = lineCurr = NULL;
5144 /* print the allocation information */
5146 printAllocInfo (currFunc, codeOutBuf);
5147 /* if debug information required */
5148 if (options.debug && currFunc) {
5149 debugFile->writeFunction (currFunc, lic);
5151 /* stack pointer name */
5155 for (ic = lic; ic; ic = ic->next) {
5157 if (cln != ic->lineno) {
5158 if (options.debug) {
5159 debugFile->writeCLine (ic);
5161 emitcode (";", "%s %d", ic->filename, ic->lineno);
5164 /* if the result is marked as
5165 spilt and rematerializable or code for
5166 this has already been generated then
5168 if (resultRemat (ic) || ic->generated)
5171 /* depending on the operation */
5190 /* IPOP happens only when trying to restore a
5191 spilt live range, if there is an ifx statement
5192 following this pop then the if statement might
5193 be using some of the registers being popped which
5194 would destory the contents of the register so
5195 we need to check for this condition and handle it */
5197 ic->next->op == IFX &&
5198 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
5199 genIfx (ic->next, ic);
5217 genEndFunction (ic);
5237 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
5254 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
5258 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
5262 genCmpLe (ic, ifxForOp (IC_RESULT (ic), ic));
5266 genCmpGe (ic, ifxForOp (IC_RESULT (ic), ic));
5270 genCmpNe (ic, ifxForOp (IC_RESULT (ic), ic));
5274 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
5286 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
5290 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
5294 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
5321 case GET_VALUE_AT_ADDRESS:
5322 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
5326 if (POINTER_SET (ic))
5327 genPointerSet (ic, hasInc(IC_RESULT(ic),ic));
5353 addSet (&_G.sendSet, ic);
5356 case DUMMY_READ_VOLATILE:
5366 /* now we are ready to call the
5367 peep hole optimizer */
5368 if (!options.nopeep)
5369 peepHole (&lineHead);
5371 /* now do the actual printing */
5372 printLine (lineHead, codeOutBuf);