1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for ATMEL AVR
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (2000)
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding!
25 -------------------------------------------------------------------------*/
31 #include "SDCCglobl.h"
35 #include "SDCCpeeph.h"
39 char *aopLiteral (value * val, int offset);
42 /* this is the down and dirty file with all kinds of
43 kludgy & hacky stuff. This is what it is all about
44 CODE GENERATION for a specific MCU . some of the
45 routines may be reusable, will have to see */
47 static char *zero = "0x00";
48 static char *one = "0x01";
51 char *fReturnAVR[] = { "r16", "r17", "r18", "r19" };
52 unsigned fAVRReturnSize = 4; /* shared with ralloc.c */
53 char **fAVRReturn = fReturnAVR;
54 static char *larray[4] = { ">", "<", "hlo8", "hhi8" };
66 extern int avr_ptrRegReq;
68 extern FILE *codeOutFile;
69 #define RESULTONSTACK(x) \
70 (IC_RESULT(x) && IC_RESULT(x)->aop && \
71 IC_RESULT(x)->aop->type == AOP_STK )
73 #define MOVR0(x) if (strcmp(x,"r0")) emitcode("mov","r0,%s",x);
74 #define MOVR24(x) if (strcmp(x,"r24")) emitcode("mov","r24,%s",x);
75 #define AOP_ISHIGHREG(a,n) (a->type == AOP_REG && a->aopu.aop_reg[n] && a->aopu.aop_reg[n]->rIdx >= R16_IDX)
76 #define CLRC emitcode("clc","")
77 #define SETC emitcode("stc","")
79 #define IS_REGIDX(a,r) (a->type == AOP_REG && a->aopu.aop_reg[0]->rIdx == r)
81 static lineNode *lineHead = NULL;
82 static lineNode *lineCurr = NULL;
91 /*-----------------------------------------------------------------*/
92 /* reAdjustPreg - points a register back to where it should */
93 /*-----------------------------------------------------------------*/
95 reAdjustPreg (asmop * aop)
100 if ((size = aop->size) <= 1)
106 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name, size);
112 /*-----------------------------------------------------------------*/
113 /* outBitC - output a bit C */
114 /*-----------------------------------------------------------------*/
116 outBitC (operand * result)
118 emitcode ("clr", "r0");
119 emitcode ("rol", "r0");
123 /*-----------------------------------------------------------------*/
124 /* inExcludeList - return 1 if the string is in exclude Reg list */
125 /*-----------------------------------------------------------------*/
127 inExcludeList (char *s)
131 if (options.excludeRegs[i] &&
132 STRCASECMP (options.excludeRegs[i], "none") == 0)
135 for (i = 0; options.excludeRegs[i]; i++) {
136 if (options.excludeRegs[i] &&
137 STRCASECMP (s, options.excludeRegs[i]) == 0)
143 /*-----------------------------------------------------------------*/
144 /* findLabelBackwards: walks back through the iCode chain looking */
145 /* for the given label. Returns number of iCode instructions */
146 /* between that label and given ic. */
147 /* Returns zero if label not found. */
148 /*-----------------------------------------------------------------*/
150 findLabelBackwards (iCode * ic, int key)
158 if (ic->op == LABEL && IC_LABEL (ic)->key == key) {
159 /* printf("findLabelBackwards = %d\n", count); */
167 /*-----------------------------------------------------------------*/
168 /* addSign - complete with sign */
169 /*-----------------------------------------------------------------*/
171 addSign (operand * result, int offset, int sign)
173 int size = (getDataSize (result) - offset);
176 emitcode ("rlc", "a");
177 emitcode ("subb", "a,acc");
179 aopPut (AOP (result), "a", offset++);
183 aopPut (AOP (result), zero, offset++);
187 /*-----------------------------------------------------------------*/
188 /* isLiteralBit - test if lit == 2^n */
189 /*-----------------------------------------------------------------*/
191 isLiteralBit (unsigned long lit)
193 unsigned long pw[32] = { 1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
194 0x100L, 0x200L, 0x400L, 0x800L,
195 0x1000L, 0x2000L, 0x4000L, 0x8000L,
196 0x10000L, 0x20000L, 0x40000L, 0x80000L,
197 0x100000L, 0x200000L, 0x400000L, 0x800000L,
198 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
199 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L
203 for (idx = 0; idx < 32; idx++)
209 /*-----------------------------------------------------------------*/
210 /* outAcc - output Acc */
211 /*-----------------------------------------------------------------*/
213 outAcc (operand * result)
216 size = getDataSize (result);
218 aopPut (AOP (result), "r0", 0);
221 /* unsigned or positive */
223 aopPut (AOP (result), zero, offset++);
228 #endif // End Unused code section
230 /*-----------------------------------------------------------------*/
231 /* emitcode - writes the code into a file : for now it is simple */
232 /*-----------------------------------------------------------------*/
234 emitcode (char *inst, char *fmt, ...)
237 char lb[INITIAL_INLINEASM];
244 sprintf (lb, "%s\t", inst);
246 sprintf (lb, "%s", inst);
247 vsprintf (lb + (strlen (lb)), fmt, ap);
250 vsprintf (lb, fmt, ap);
252 while (isspace ((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 #if defined(__BORLANDC__) || defined(_MSC_VER)
1711 #define STRCASECMP stricmp
1713 #define STRCASECMP strcasecmp
1716 /*-----------------------------------------------------------------*/
1717 /* genFunction - generated code for function entry */
1718 /*-----------------------------------------------------------------*/
1720 genFunction (iCode * ic)
1727 /* create the function header */
1728 emitcode (";", "-----------------------------------------");
1729 emitcode (";", " function %s",
1730 (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
1731 emitcode (";", "-----------------------------------------");
1733 emitcode ("", "%s:", sym->rname);
1734 ftype = operandType (IC_LEFT (ic));
1736 /* if critical function then turn interrupts off */
1737 if (IFFUNC_ISCRITICAL (ftype))
1738 emitcode ("cli", "");
1740 if (IFFUNC_ISISR (sym->type)) {
1743 /* save the preserved registers that are used in this function */
1744 for (i = R2_IDX; i <= R15_IDX; i++) {
1745 if (bitVectBitValue (sym->regsUsed, i)) {
1747 emitcode ("push", "%s", avr_regWithIdx (i)->name);
1750 /* now for the pointer registers */
1751 if (bitVectBitValue (sym->regsUsed, R26_IDX)) {
1753 emitcode ("push", "r26");
1755 if (bitVectBitValue (sym->regsUsed, R27_IDX)) {
1757 emitcode ("push", "r27");
1759 if (bitVectBitValue (sym->regsUsed, R30_IDX)) {
1761 emitcode ("push", "r30");
1763 if (bitVectBitValue (sym->regsUsed, R31_IDX)) {
1765 emitcode ("push", "r31");
1767 /* adjust the stack for the function */
1769 emitcode ("push", "r28");
1770 emitcode ("push", "r29");
1771 emitcode ("in", "r28,__SP_L__");
1772 emitcode ("in", "r29,__SP_H__");
1773 if (sym->stack <= 63) {
1774 emitcode ("sbiw", "r28,%d", sym->stack);
1777 emitcode ("subi", "r28,<(%d)", sym->stack);
1778 emitcode ("sbci", "r29,>(%d)", sym->stack);
1780 emitcode ("out", "__SP_L__,r28");
1781 emitcode ("out", "__SP_H__,r29");
1785 /*-----------------------------------------------------------------*/
1786 /* genEndFunction - generates epilogue for functions */
1787 /*-----------------------------------------------------------------*/
1789 genEndFunction (iCode * ic)
1791 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
1794 /* restore stack pointer */
1796 if (sym->stack <= 63) {
1797 emitcode ("adiw", "r28,%d", sym->stack);
1800 emitcode ("subi", "r28,<(-%d)", sym->stack);
1801 emitcode ("sbci", "r29,>(-%d)", sym->stack);
1803 emitcode ("out", "__SP_L__,r28");
1804 emitcode ("out", "__SP_H__,r29");
1806 /* pop frame pointer */
1807 emitcode ("pop", "r29");
1808 emitcode ("pop", "r28");
1810 /* restore preserved registers */
1811 if (bitVectBitValue (sym->regsUsed, R31_IDX)) {
1813 emitcode ("pop", "r31");
1815 if (bitVectBitValue (sym->regsUsed, R30_IDX)) {
1817 emitcode ("pop", "r30");
1819 if (bitVectBitValue (sym->regsUsed, R27_IDX)) {
1821 emitcode ("pop", "r27");
1823 if (bitVectBitValue (sym->regsUsed, R26_IDX)) {
1825 emitcode ("pop", "r26");
1827 for (i = R15_IDX; i >= R2_IDX; i--) {
1828 if (bitVectBitValue (sym->regsUsed, i)) {
1830 emitcode ("pop", "%s", avr_regWithIdx (i)->name);
1834 if (IFFUNC_ISCRITICAL (sym->type))
1835 emitcode ("sti", "");
1837 if (options.debug && currFunc) {
1838 debugFile->writeEndFunction (currFunc, ic, 1);
1841 if (IFFUNC_ISISR (sym->type)) {
1842 emitcode ("rti", "");
1845 emitcode ("ret", "");
1850 /*-----------------------------------------------------------------*/
1851 /* genRet - generate code for return statement */
1852 /*-----------------------------------------------------------------*/
1856 int size, offset = 0;
1858 /* if we have no return value then
1859 just generate the "ret" */
1863 /* we have something to return then
1864 move the return value into place */
1865 aopOp (IC_LEFT (ic), ic, FALSE);
1866 size = AOP_SIZE (IC_LEFT (ic));
1869 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) {
1870 emitcode ("ldi", "%s,%s(%d)", fAVRReturn[offset],
1872 (int) floatFromVal (AOP (IC_LEFT (ic))->
1873 aopu.aop_lit), offset);
1877 l = aopGet (AOP (IC_LEFT (ic)), offset);
1878 if (strcmp (fAVRReturn[offset], l))
1879 emitcode ("mov", "%s,%s", fAVRReturn[offset],
1885 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1888 /* generate a jump to the return label
1889 if the next is not the return statement */
1890 if (!(ic->next && ic->next->op == LABEL &&
1891 IC_LABEL (ic->next) == returnLabel))
1893 emitcode ("rjmp", "L%05d", returnLabel->key);
1897 /*-----------------------------------------------------------------*/
1898 /* genLabel - generates a label */
1899 /*-----------------------------------------------------------------*/
1901 genLabel (iCode * ic)
1903 /* special case never generate */
1904 if (IC_LABEL (ic) == entryLabel)
1907 emitcode ("", "L%05d:", IC_LABEL (ic)->key);
1910 /*-----------------------------------------------------------------*/
1911 /* genGoto - generates a ljmp */
1912 /*-----------------------------------------------------------------*/
1914 genGoto (iCode * ic)
1916 emitcode ("rjmp", "L%05d", (IC_LABEL (ic)->key));
1919 /*-----------------------------------------------------------------*/
1920 /* genPlusIncr :- does addition with increment if possible */
1921 /*-----------------------------------------------------------------*/
1923 genPlusIncr (iCode * ic)
1925 unsigned int icount;
1928 /* will try to generate an increment */
1929 /* if the right side is not a literal
1931 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
1934 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.
1937 /* if the sizes are greater than 2 or they are not the same regs
1939 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1942 /* so we know LEFT & RESULT in the same registers and add
1944 /* for short & char types */
1945 if (AOP_SIZE (IC_RESULT (ic)) < 2) {
1947 emitcode ("inc", "%s",
1948 aopGet (AOP (IC_LEFT (ic)), 0));
1951 if (AOP_ISHIGHREG( AOP (IC_LEFT (ic)),0)) {
1952 emitcode ("subi", "%s,<(%d)",
1953 aopGet (AOP (IC_LEFT (ic)), 0), 0-icount);
1958 for (offset = 0 ; offset < AOP_SIZE(IC_RESULT(ic)) ; offset++) {
1959 if (!(AOP_ISHIGHREG(AOP(IC_RESULT(ic)),offset))) return FALSE;
1962 if (AOP_SIZE (IC_RESULT (ic)) <= 3) {
1963 /* if register pair and starts with 26/30 then adiw */
1964 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0
1966 && (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX) ||
1967 IS_REGIDX (AOP (IC_RESULT (ic)), R24_IDX) ||
1968 IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX))) {
1969 emitcode ("adiw", "%s,%d",
1970 aopGet (AOP (IC_RESULT (ic)), 0), icount);
1975 emitcode ("subi", "%s,<(%d)",
1976 aopGet (AOP (IC_RESULT (ic)), 0), 0-icount);
1977 emitcode ("sbci", "%s,>(%d)",
1978 aopGet (AOP (IC_RESULT (ic)), 1), 0-icount);
1982 /* for 32 bit longs */
1983 emitcode ("subi", "%s,<(%d)", aopGet (AOP (IC_RESULT (ic)), 0),
1985 emitcode ("sbci", "%s,>(%d)", aopGet (AOP (IC_RESULT (ic)), 1),
1987 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2),
1989 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3),
1995 /* This is the pure and virtuous version of this code.
1996 * I'm pretty certain it's right, but not enough to toss the old
2000 adjustArithmeticResult (iCode * ic)
2002 if (opIsGptr (IC_RESULT (ic)) &&
2003 opIsGptr (IC_LEFT (ic)) &&
2004 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)))) {
2005 aopPut (AOP (IC_RESULT (ic)),
2006 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1),
2010 if (opIsGptr (IC_RESULT (ic)) &&
2011 opIsGptr (IC_RIGHT (ic)) &&
2012 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)))) {
2013 aopPut (AOP (IC_RESULT (ic)),
2014 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1),
2018 if (opIsGptr (IC_RESULT (ic)) &&
2019 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2020 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2021 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2022 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)))) {
2024 sprintf (buffer, "%d",
2025 pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2026 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2030 /*-----------------------------------------------------------------*/
2031 /* genPlus - generates code for addition */
2032 /*-----------------------------------------------------------------*/
2034 genPlus (iCode * ic)
2036 int size, offset = 0;
2040 /* special cases :- */
2042 aopOp (IC_LEFT (ic), ic, FALSE);
2043 aopOp (IC_RIGHT (ic), ic, FALSE);
2044 aopOp (IC_RESULT (ic), ic, TRUE);
2046 /* if I can do an increment instead
2047 of add then GOOD for ME */
2048 if (genPlusIncr (ic) == TRUE)
2051 size = getDataSize (IC_RESULT (ic));
2052 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2056 aopPut (AOP (IC_RESULT (ic)),
2057 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2059 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
2066 emitcode (l, "%s,%s",
2067 aopGet (AOP (IC_RESULT (ic)), offset),
2068 aopGet (AOP (IC_RIGHT (ic)), offset));
2071 if (AOP_ISHIGHREG( AOP( IC_RESULT(ic)),offset)) {
2077 emitcode (l, "%s,%s(-%d)",
2078 aopGet (AOP (IC_RESULT (ic)), offset),
2080 (int) floatFromVal (AOP (IC_RIGHT (ic))->
2088 emitcode (l, "%s,%s",
2089 aopGet (AOP (IC_RESULT (ic)), offset),
2090 aopGet (AOP (IC_RIGHT (ic)), offset));
2096 adjustArithmeticResult (ic);
2099 freeAsmop (IC_LEFT (ic), NULL, ic,
2100 (RESULTONSTACK (ic) ? FALSE : TRUE));
2101 freeAsmop (IC_RIGHT (ic), NULL, ic,
2102 (RESULTONSTACK (ic) ? FALSE : TRUE));
2103 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2106 /*-----------------------------------------------------------------*/
2107 /* genMinusDec :- does subtraction with deccrement if possible */
2108 /*-----------------------------------------------------------------*/
2110 genMinusDec (iCode * ic)
2112 unsigned int icount;
2115 /* will try to generate an increment */
2116 /* if the right side is not a literal
2118 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2122 (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.
2125 /* if the sizes are greater than 2 or they are not the same regs
2127 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2130 /* so we know LEFT & RESULT in the same registers and add
2132 /* for short & char types */
2133 if (AOP_SIZE (IC_RESULT (ic)) < 2) {
2135 emitcode ("dec", "%s",
2136 aopGet (AOP (IC_LEFT (ic)), 0));
2139 if (AOP_ISHIGHREG( AOP ( IC_LEFT(ic)),0)) {
2140 emitcode ("subi", "%s,<(%d)",
2141 aopGet (AOP (IC_LEFT (ic)), 0), icount);
2146 for (offset = 0 ; offset < AOP_SIZE(IC_RESULT(ic)) ; offset++) {
2147 if (!(AOP_ISHIGHREG(AOP(IC_RESULT(ic)),offset))) return FALSE;
2150 if (AOP_SIZE (IC_RESULT (ic)) <= 3) {
2151 /* if register pair and starts with 26/30 then adiw */
2152 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0
2154 && (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX) ||
2155 IS_REGIDX (AOP (IC_RESULT (ic)), R24_IDX) ||
2156 IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX))) {
2157 emitcode ("sbiw", "%s,%d",
2158 aopGet (AOP (IC_RESULT (ic)), 0), icount);
2163 emitcode ("subi", "%s,<(%d)",
2164 aopGet (AOP (IC_RESULT (ic)), 0), icount);
2165 emitcode ("sbci", "%s,>(%d)",
2166 aopGet (AOP (IC_RESULT (ic)), 1), icount);
2169 /* for 32 bit longs */
2170 emitcode ("subi", "%s,<(%d)", aopGet (AOP (IC_RESULT (ic)), 0),
2172 emitcode ("sbci", "%s,>(%d)", aopGet (AOP (IC_RESULT (ic)), 1),
2174 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2),
2176 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3),
2182 /*-----------------------------------------------------------------*/
2183 /* genMinus - generates code for subtraction */
2184 /*-----------------------------------------------------------------*/
2186 genMinus (iCode * ic)
2188 int size, offset = 0, samer;
2191 aopOp (IC_LEFT (ic), ic, FALSE);
2192 aopOp (IC_RIGHT (ic), ic, FALSE);
2193 aopOp (IC_RESULT (ic), ic, TRUE);
2195 /* if I can do an decrement instead
2196 of subtract then GOOD for ME */
2197 if (genMinusDec (ic) == TRUE)
2200 size = getDataSize (IC_RESULT (ic));
2201 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2204 aopPut (AOP (IC_RESULT (ic)),
2205 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2207 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
2214 emitcode (l, "%s,%s",
2215 aopGet (AOP (IC_RESULT (ic)), offset),
2216 aopGet (AOP (IC_RIGHT (ic)), offset));
2219 if (AOP_ISHIGHREG(AOP (IC_RESULT (ic)),offset)) {
2225 emitcode (l, "%s,%s(%d)",
2226 aopGet (AOP (IC_RESULT (ic)), offset),
2228 (int) floatFromVal (AOP (IC_RIGHT (ic))->
2236 emitcode (l, "%s,%s",
2237 aopGet (AOP (IC_RESULT (ic)), offset),
2238 aopGet (AOP (IC_RIGHT (ic)), offset));
2244 adjustArithmeticResult (ic);
2247 freeAsmop (IC_LEFT (ic), NULL, ic,
2248 (RESULTONSTACK (ic) ? FALSE : TRUE));
2249 freeAsmop (IC_RIGHT (ic), NULL, ic,
2250 (RESULTONSTACK (ic) ? FALSE : TRUE));
2251 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2254 /*-----------------------------------------------------------------*/
2255 /* genMultOneByte : 8 bit multiplication & division */
2256 /*-----------------------------------------------------------------*/
2258 genMultOneByte (operand * left, operand * right, operand * result)
2260 sym_link *opetype = operandType (result);
2264 /* (if two literals, the value is computed before) */
2265 /* if one literal, literal on the right */
2266 if (AOP_TYPE (left) == AOP_LIT) {
2272 size = AOP_SIZE (result);
2274 if (SPEC_USIGN (opetype)) {
2275 emitcode ("mul", "%s,%s", aopGet (AOP (left), 0),
2276 aopGet (AOP (right), 0));
2279 emitcode ("muls", "%s,%s", aopGet (AOP (left), 0),
2280 aopGet (AOP (right), 0));
2282 aopPut (AOP (result), "r0", 0);
2284 aopPut (AOP (result), "r1", 1);
2287 if (SPEC_USIGN (opetype)) {
2289 aopPut (AOP (result), zero, offset++);
2294 lbl = newiTempLabel (NULL);
2295 emitcode ("ldi", "r24,0");
2296 emitcode ("brcc", "L%05d", lbl->key);
2297 emitcode ("ldi", "r24,0xff)");
2298 emitcode ("", "L%05d:", lbl->key);
2300 aopPut (AOP (result), "r24",
2308 /*-----------------------------------------------------------------*/
2309 /* genMult - generates code for multiplication */
2310 /*-----------------------------------------------------------------*/
2312 genMult (iCode * ic)
2314 operand *left = IC_LEFT (ic);
2315 operand *right = IC_RIGHT (ic);
2316 operand *result = IC_RESULT (ic);
2318 /* assign the amsops */
2319 aopOp (left, ic, FALSE);
2320 aopOp (right, ic, FALSE);
2321 aopOp (result, ic, TRUE);
2323 /* if both are of size == 1 */
2324 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1) {
2325 genMultOneByte (left, right, result);
2329 /* should have been converted to function call */
2333 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2334 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2335 freeAsmop (result, NULL, ic, TRUE);
2338 /*-----------------------------------------------------------------*/
2339 /* genDiv - generates code for division */
2340 /*-----------------------------------------------------------------*/
2344 /* should have been converted to function call */
2348 /*-----------------------------------------------------------------*/
2349 /* genMod - generates code for division */
2350 /*-----------------------------------------------------------------*/
2354 /* should have been converted to function call */
2366 /*-----------------------------------------------------------------*/
2367 /* revavrcnd - reverse a conditional for avr */
2368 /*-----------------------------------------------------------------*/
2370 revavrcnd (int type)
2382 for (i = 0; i < (sizeof (rar) / sizeof (rar[0])); i++) {
2383 if (rar[i].type == type)
2384 return rar[i].rtype;
2385 if (rar[i].rtype == type)
2388 assert (0); /* cannot happen */
2389 return 0; /* makes the compiler happy */
2392 static char *br_name[4] = { "breq", "brne", "brlt", "brge" };
2393 static char *br_uname[4] = { "breq", "brne", "brlo", "brcc" };
2395 /*-----------------------------------------------------------------*/
2396 /* genBranch - generate the branch instruction */
2397 /*-----------------------------------------------------------------*/
2399 genBranch (iCode * ifx, int br_type, int sign)
2401 int tj = (IC_TRUE (ifx) ? 1 : 0);
2403 if (tj) { /* if true jump */
2404 char *nm = (sign ? br_name[br_type] : br_uname[br_type]);
2405 emitcode (nm, "L%05d", IC_TRUE (ifx)->key);
2407 else { /* if false jump */
2408 int rtype = revavrcnd (br_type);
2409 char *nm = (sign ? br_name[rtype] : br_uname[rtype]);
2410 emitcode (nm, "L%05d", IC_FALSE (ifx)->key);
2415 /*-----------------------------------------------------------------*/
2416 /* genCmp - compare & jump */
2417 /*-----------------------------------------------------------------*/
2419 genCmp (iCode * ic, iCode * ifx, int br_type)
2421 operand *left, *right, *result;
2422 sym_link *letype, *retype;
2424 int sign, size, offset = 0;
2426 left = IC_LEFT (ic);
2427 right = IC_RIGHT (ic);
2428 result = IC_RESULT (ic);
2430 letype = getSpec (operandType (left));
2431 retype = getSpec (operandType (right));
2432 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
2434 /* assign the amsops */
2435 aopOp (left, ic, FALSE);
2436 aopOp (right, ic, FALSE);
2437 aopOp (result, ic, TRUE);
2438 size = AOP_SIZE (left);
2442 if (AOP_TYPE (right) == AOP_LIT) {
2443 emitcode ("cpi", "%s,<(%d)",
2444 aopGet (AOP (left), 0),
2446 floatFromVal (AOP (IC_RIGHT (ic))->
2448 genBranch (ifx, br_type, sign);
2450 else { /* right != literal */
2451 emitcode ("cp", "%s,%s",
2452 aopGet (AOP (left), 0),
2453 aopGet (AOP (right), 0));
2454 genBranch (ifx, br_type, sign);
2457 else { /* size != 1 */
2460 emitcode ("cp", "%s,%s",
2461 aopGet (AOP (left), 0),
2462 aopGet (AOP (right), 0));
2464 emitcode ("cpc", "%s,%s",
2465 aopGet (AOP (left), offset),
2466 aopGet (AOP (right),
2470 genBranch (ifx, br_type, sign);
2474 emitcode ("clr", "r0");
2477 emitcode ("cp", "%s,%s",
2478 aopGet (AOP (left), 0),
2479 aopGet (AOP (right), 0));
2481 emitcode ("cpc", "%s,%s",
2482 aopGet (AOP (left), offset),
2483 aopGet (AOP (right), offset));
2486 lbl = newiTempLabel (NULL);
2487 br_type = revavrcnd (br_type);
2489 emitcode (br_uname[br_type], "L%05d", lbl->key);
2491 emitcode (br_name[br_type], "L%05d", lbl->key);
2492 emitcode ("inc", "r0");
2493 emitcode ("", "L%05d:", lbl->key);
2494 aopPut (AOP (result), "r0", 0);
2495 size = AOP_SIZE (result) - 1;
2498 aopPut (AOP (result), zero, offset++);
2501 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2502 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2503 freeAsmop (result, NULL, ic, TRUE);
2506 /*-----------------------------------------------------------------*/
2507 /* genCmpGt :- greater than comparison */
2508 /*-----------------------------------------------------------------*/
2510 genCmpGt (iCode * ic, iCode * ifx)
2512 /* should have transformed by the parser */
2516 /*-----------------------------------------------------------------*/
2517 /* genCmpLt - less than comparisons */
2518 /*-----------------------------------------------------------------*/
2520 genCmpLt (iCode * ic, iCode * ifx)
2522 genCmp (ic, ifx, AVR_LT);
2525 /*-----------------------------------------------------------------*/
2526 /* genCmpEq - generates code for equal to */
2527 /*-----------------------------------------------------------------*/
2529 genCmpEq (iCode * ic, iCode * ifx)
2531 genCmp (ic, ifx, AVR_EQ);
2534 /*-----------------------------------------------------------------*/
2535 /* genCmpNe - generates code for not equal to */
2536 /*-----------------------------------------------------------------*/
2538 genCmpNe (iCode * ic, iCode * ifx)
2540 genCmp (ic, ifx, AVR_NE);
2543 /*-----------------------------------------------------------------*/
2544 /* genCmpGe - generates code for greater than equal to */
2545 /*-----------------------------------------------------------------*/
2547 genCmpGe (iCode * ic, iCode * ifx)
2549 genCmp (ic, ifx, AVR_GE);
2552 /*-----------------------------------------------------------------*/
2553 /* genCmpLe - generates code for less than equal to */
2554 /*-----------------------------------------------------------------*/
2556 genCmpLe (iCode * ic, iCode * ifx)
2558 operand *left = IC_LEFT (ic);
2559 operand *right = IC_RIGHT (ic);
2561 IC_RIGHT (ic) = left;
2562 IC_LEFT (ic) = right;
2563 genCmp (ic, ifx, AVR_GE);
2566 /*-----------------------------------------------------------------*/
2567 /* ifxForOp - returns the icode containing the ifx for operand */
2568 /*-----------------------------------------------------------------*/
2570 ifxForOp (operand * op, iCode * ic)
2572 /* if true symbol then needs to be assigned */
2573 if (IS_TRUE_SYMOP (op))
2576 /* if this has register type condition and
2577 the next instruction is ifx with the same operand
2578 and live to of the operand is upto the ifx only then */
2580 ic->next->op == IFX &&
2581 IC_COND (ic->next)->key == op->key &&
2582 OP_SYMBOL (op)->liveTo <= ic->next->seq) return ic->next;
2587 /*-----------------------------------------------------------------*/
2588 /* genAndOp - for && operation */
2589 /*-----------------------------------------------------------------*/
2591 genAndOp (iCode * ic)
2593 operand *left, *right, *result;
2597 /* note here that && operations that are in an
2598 if statement are taken away by backPatchLabels
2599 only those used in arthmetic operations remain */
2600 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2601 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2602 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
2604 tlbl = newiTempLabel (NULL);
2605 toBoolean (left, "r0", TRUE);
2606 toBoolean (right, "r1", TRUE);
2607 emitcode ("and", "r0,r1");
2608 emitcode ("ldi", "r24,1");
2609 emitcode ("breq", "L%05d", tlbl->key);
2610 emitcode ("dec", "r24");
2611 emitcode ("", "L%05d:", tlbl->key);
2612 aopPut (AOP (result), "r24", 0);
2613 size = AOP_SIZE (result) - 1;
2616 aopPut (AOP (result), zero, offset++);
2618 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2619 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2620 freeAsmop (result, NULL, ic, TRUE);
2624 /*-----------------------------------------------------------------*/
2625 /* genOrOp - for || operation */
2626 /*-----------------------------------------------------------------*/
2628 genOrOp (iCode * ic)
2630 operand *left, *right, *result;
2634 /* note here that || operations that are in an
2635 if statement are taken away by backPatchLabels
2636 only those used in arthmetic operations remain */
2637 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2638 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2639 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
2641 tlbl = newiTempLabel (NULL);
2642 toBoolean (left, "r0", TRUE);
2643 toBoolean (right, "r0", FALSE);
2644 emitcode ("ldi", "r24,1");
2645 emitcode ("breq", "L%05d", tlbl->key);
2646 emitcode ("dec", "r24");
2647 emitcode ("", "L%05d:", tlbl->key);
2648 aopPut (AOP (result), "r24", 0);
2649 size = AOP_SIZE (result) - 1;
2652 aopPut (AOP (result), zero, offset++);
2654 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2655 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2656 freeAsmop (result, NULL, ic, TRUE);
2660 AVR_AND = 0, AVR_OR, AVR_XOR
2662 static char *bopnames_lit[] = { "andi", "ori" };
2663 static char *bopnames[] = { "and", "or", "eor" };
2664 /*-----------------------------------------------------------------*/
2665 /* genBitWise - generate bitwise operations */
2666 /*-----------------------------------------------------------------*/
2668 genBitWise (iCode * ic, iCode * ifx, int bitop)
2670 operand *left, *right, *result;
2671 int size, offset = 0;
2676 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2677 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2678 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
2680 size = AOP_SIZE (left);
2682 if (ifx) { /* used only for jumps */
2683 if (AOP_TYPE (right) == AOP_LIT &&
2684 (bitop == AVR_AND || bitop == AVR_OR)) {
2686 (int) floatFromVal (AOP (right)->aopu.
2688 int p2 = powof2 (lit);
2689 if (bitop == AVR_AND && (p2 >= 0)) { /* right side is a power of 2 */
2690 l = aopGet (AOP (left), p2 / 8);
2691 if (IC_TRUE (ifx)) {
2692 emitcode ("sbrc", "%s,%d", l,
2694 emitcode ("rjmp", "L%05d",
2695 IC_TRUE (ifx)->key);
2698 emitcode ("sbrs", "%s,%d", l,
2700 emitcode ("rjmp", "L%05d",
2701 IC_FALSE (ifx)->key);
2704 else { /* right not power of two */
2705 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2707 if (eh && AOP_ISHIGHREG(AOP(IC_LEFT(ic)),0)) {
2708 emitcode (bopnames_lit[bitop],
2710 aopGet (AOP (IC_LEFT (ic)), 0), lit);
2713 MOVR24 (aopGet (AOP (IC_LEFT (ic)), 0));
2714 emitcode (bopnames_lit[bitop], "r24,<(%d)", lit);
2716 lbl = newiTempLabel (NULL);
2717 if (IC_TRUE (ifx)) {
2718 emitcode ("breq", "L%05d", lbl->key);
2719 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2722 emitcode ("brne", "L%05d", lbl->key);
2723 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)-> key);
2725 emitcode ("", "L%05d:", lbl->key);
2727 else if (size == 2) {
2728 emitcode ("mov", "r24,%s", aopGet (AOP (IC_LEFT (ic)), 0));
2729 emitcode ("mov", "r25,%s", aopGet (AOP (IC_LEFT (ic)), 1));
2730 emitcode (bopnames_lit[bitop], "r24,<(%d)", lit);
2731 emitcode (bopnames_lit[bitop], "r25,>(%d)", lit);
2732 emitcode ("sbiw", "r24,0");
2733 lbl = newiTempLabel (NULL);
2734 if (IC_TRUE (ifx)) {
2735 emitcode ("breq", "L%05d", lbl->key);
2736 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2739 emitcode ("brne", "L%05d", lbl->key);
2740 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2742 emitcode ("", "L%05d:", lbl->key);
2745 lbl = newiTempLabel (NULL);
2746 lbl1 = newiTempLabel (NULL);
2748 if (eh && AOP_ISHIGHREG(AOP(IC_LEFT(ic)),offset)) {
2749 emitcode (bopnames_lit [bitop], "%s,<(%d)",
2750 aopGet (AOP (IC_LEFT (ic)), offset),
2754 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
2756 emitcode ("andi", "r24,<(%d)", lit);
2758 emitcode ("brne", "L%05d", lbl->key);
2763 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)-> key);
2765 emitcode ("rjmp", "L%05d", lbl1->key);
2766 emitcode ("", "L%05d:", lbl->key);
2769 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2770 emitcode ("", "L%05d:", lbl1->key);
2775 else { /* right is not a literal */
2776 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2777 int reh = OP_SYMBOL (right)->liveTo <= ic->seq;
2780 emitcode (bopnames[bitop], "%s,%s", aopGet (AOP (IC_LEFT (ic)), 0),
2781 aopGet (AOP (IC_RIGHT (ic)), 0));
2784 emitcode (bopnames[bitop], "%s,%s",
2785 aopGet (AOP (IC_RIGHT (ic)), 0),
2786 aopGet (AOP (IC_LEFT (ic)), 0));
2789 MOVR0 (aopGet (AOP (IC_LEFT (ic)), 0));
2790 emitcode (bopnames[bitop], "r0,%s",
2791 aopGet (AOP (IC_RIGHT (ic)), 0));
2793 lbl = newiTempLabel (NULL);
2794 if (IC_TRUE (ifx)) {
2795 emitcode ("breq", "L%05d", lbl->key);
2796 emitcode ("rjmp", "L%05d",
2797 IC_TRUE (ifx)->key);
2800 emitcode ("brne", "L%05d", lbl->key);
2801 emitcode ("rjmp", "L%05d",
2802 IC_FALSE (ifx)->key);
2804 emitcode ("", "L%05d:", lbl->key);
2806 else if (size == 2) {
2807 emitcode ("mov", "r24,%s",
2808 aopGet (AOP (IC_LEFT (ic)), 0));
2809 emitcode ("mov", "r25,%s",
2810 aopGet (AOP (IC_LEFT (ic)), 1));
2811 emitcode (bopnames[bitop], "r24,%s",
2812 aopGet (AOP (IC_RIGHT (ic)), 0));
2813 emitcode (bopnames[bitop], "r25,%s",
2814 aopGet (AOP (IC_RIGHT (ic)), 1));
2815 emitcode ("sbiw", "r24,0");
2816 lbl = newiTempLabel (NULL);
2817 if (IC_TRUE (ifx)) {
2818 emitcode ("breq", "L%05d", lbl->key);
2819 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2822 emitcode ("brne", "L%05d", lbl->key);
2823 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2825 emitcode ("", "L%05d:", lbl->key);
2828 lbl = newiTempLabel (NULL);
2829 lbl1 = newiTempLabel (NULL);
2832 emitcode (bopnames[bitop], "%s,%s",
2833 aopGet (AOP (IC_LEFT (ic)), offset),
2834 aopGet (AOP (IC_RIGHT (ic)), offset));
2837 emitcode (bopnames[bitop], "%s,%s",
2838 aopGet (AOP (IC_RIGHT (ic)), offset),
2839 aopGet (AOP (IC_LEFT (ic)), offset));
2842 MOVR0 (aopGet (AOP (IC_LEFT (ic)), offset));
2843 emitcode (bopnames[bitop], "r0,%s",
2844 aopGet (AOP (IC_RIGHT (ic)), offset));
2846 emitcode ("brne", "L%05d", lbl->key);
2851 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2853 emitcode ("rjmp", "L%05d", lbl1->key);
2854 emitcode ("", "L%05d:", lbl->key);
2857 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2858 emitcode ("", "L%05d:", lbl1->key);
2865 /* result needs to go a register */
2866 samerl = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2867 samerr = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)));
2869 if (AOP_TYPE (right) == AOP_LIT) {
2871 (int) floatFromVal (AOP (right)->aopu.
2873 if (((lit >> (8 * offset)) & 0xff) == 0) {
2874 if (bitop == AVR_AND) {
2875 aopPut (AOP (result), zero, offset++);
2878 else if (bitop == AVR_OR) {
2880 aopPut (AOP (result),
2890 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT &&
2891 AOP_ISHIGHREG(AOP(IC_LEFT(ic)),offset) &&
2892 (bitop == AVR_AND || bitop == AVR_OR)) {
2893 emitcode (bopnames_lit[bitop], "%s,%s(%d)",
2894 aopGet (AOP (IC_LEFT (ic)), offset),
2896 (int) floatFromVal (AOP (right)-> aopu.aop_lit));
2899 emitcode (bopnames[bitop], "%s,%s",
2900 aopGet (AOP (IC_LEFT (ic)), offset),
2901 aopGet (AOP (IC_RIGHT (ic)), offset));
2905 emitcode (bopnames[bitop], "%s,%s",
2906 aopGet (AOP (IC_RIGHT (ic)), offset),
2907 aopGet (AOP (IC_LEFT (ic)), offset));
2910 aopPut (AOP (IC_RESULT (ic)),
2911 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2912 emitcode (bopnames[bitop],
2913 aopGet (AOP (IC_RESULT (ic)), offset),
2914 aopGet (AOP (IC_RIGHT (ic)), offset));
2919 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2920 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2921 freeAsmop (result, NULL, ic, TRUE);
2924 /*-----------------------------------------------------------------*/
2925 /* genAnd - code for and */
2926 /*-----------------------------------------------------------------*/
2928 genAnd (iCode * ic, iCode * ifx)
2930 genBitWise (ic, ifx, AVR_AND);
2933 /*-----------------------------------------------------------------*/
2934 /* genOr - code for or */
2935 /*-----------------------------------------------------------------*/
2937 genOr (iCode * ic, iCode * ifx)
2939 genBitWise (ic, ifx, AVR_OR);
2942 /*-----------------------------------------------------------------*/
2943 /* genXor - code for xclusive or */
2944 /*-----------------------------------------------------------------*/
2946 genXor (iCode * ic, iCode * ifx)
2948 genBitWise (ic, ifx, AVR_XOR);
2951 /*-----------------------------------------------------------------*/
2952 /* genInline - write the inline code out */
2953 /*-----------------------------------------------------------------*/
2955 genInline (iCode * ic)
2957 char *buffer, *bp, *bp1;
2959 _G.inLine += (!options.asmpeep);
2961 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
2962 strcpy (buffer, IC_INLINE (ic));
2964 /* emit each line as a code */
2985 /* emitcode("",buffer); */
2986 _G.inLine -= (!options.asmpeep);
2989 /*-----------------------------------------------------------------*/
2990 /* genRotC - rotate right/left with carry , lr = 1 rotate right */
2991 /*-----------------------------------------------------------------*/
2993 genRotC (iCode * ic, int lr)
2995 operand *left, *result;
2996 int size, offset = 0;
2998 /* rotate right with carry */
2999 left = IC_LEFT (ic);
3000 result = IC_RESULT (ic);
3001 aopOp (left, ic, FALSE);
3002 aopOp (result, ic, FALSE);
3004 /* move it to the result */
3005 size = AOP_SIZE (result);
3006 if (!sameRegs (AOP (left), AOP (result))) {
3009 aopPut (AOP (result),
3010 aopGet (AOP (left), offset), offset);
3013 size = AOP_SIZE (result);
3021 emitcode ("sbrc", "%s,%d", aopGet (AOP (result), offset),
3023 emitcode ("sec", "");
3026 emitcode ((lr ? "ror" : "rol"), "%s",
3027 aopGet (AOP (result), offset));
3033 freeAsmop (left, NULL, ic, TRUE);
3034 freeAsmop (result, NULL, ic, TRUE);
3037 /*-----------------------------------------------------------------*/
3038 /* genRRC - rotate right with carry */
3039 /*-----------------------------------------------------------------*/
3046 /*-----------------------------------------------------------------*/
3047 /* genRLC - generate code for rotate left with carry */
3048 /*-----------------------------------------------------------------*/
3055 /*-----------------------------------------------------------------*/
3056 /* genGetHbit - generates code get highest order bit */
3057 /*-----------------------------------------------------------------*/
3059 genGetHbit (iCode * ic)
3061 operand *left, *result;
3064 left = IC_LEFT (ic);
3065 result = IC_RESULT (ic);
3066 aopOp (left, ic, FALSE);
3067 aopOp (result, ic, FALSE);
3069 size = AOP_SIZE (result);
3070 if (!sameRegs (AOP (left), AOP (result))) {
3071 emitcode ("clr", "%s", aopGet (AOP (result), size - 1));
3072 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3073 emitcode ("subi", "%s,<(-1)",
3074 aopGet (AOP (result), size - 1));
3077 emitcode ("clr", "r0");
3078 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3079 emitcode ("subi", "r0,<(-1)");
3080 aopPut (AOP (result), "r0", 0);
3085 emitcode ("clr", aopGet (AOP (result), offset++));
3087 freeAsmop (left, NULL, ic, TRUE);
3088 freeAsmop (result, NULL, ic, TRUE);
3091 /*-----------------------------------------------------------------*/
3092 /* genShiftLeftLit - shift left by a known amount */
3093 /*-----------------------------------------------------------------*/
3095 genShiftLeftLit (iCode * ic)
3097 operand *left, *right, *result;
3098 int size, shCount, offset = 0;
3101 right = IC_RIGHT (ic);
3102 left = IC_LEFT (ic);
3103 result = IC_RESULT (ic);
3105 aopOp (left, ic, FALSE);
3106 aopOp (result, ic, FALSE);
3107 size = AOP_SIZE (result);
3108 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3110 if (shCount > (size * 8 - 1)) {
3112 aopPut (AOP (result), zero, offset++);
3117 if (!sameRegs (AOP (left), AOP (result)))
3118 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3120 if (AOP_ISHIGHREG(AOP(result),0)) {
3121 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3122 emitcode ("andi", "%s,0xf0");
3124 emitcode ("ldi","r24,0xf0");
3125 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3126 emitcode ("and", "%s,r24");
3131 emitcode ("add", "%s,%s", aopGet (AOP (result), 0),
3132 aopGet (AOP (result), 0));
3136 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3139 if (shCount >= 12) {
3140 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3141 aopPut (AOP (result), zero, 0);
3142 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3143 if (AOP_ISHIGHREG(AOP(result),1)) {
3144 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3146 emitcode ("ldi","r24,0xf0");
3147 emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
3153 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3154 aopPut (AOP (result), zero, 0);
3160 if (!sameRegs (AOP (left), AOP (result))) {
3161 aopPut (AOP (result), aopGet (AOP (left), 0),
3163 aopPut (AOP (result), aopGet (AOP (left), 1),
3166 emitcode ("mov", "r24,%s", aopGet (AOP (result), 0));
3167 emitcode ("andi", "r24,0x0f");
3168 if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
3169 emitcode("ldi","r25,0xf0");
3171 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3172 if (AOP_ISHIGHREG(AOP(result),0)) {
3173 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 0));
3175 emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
3177 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3178 if (AOP_ISHIGHREG(AOP(result),1)) {
3179 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3181 emitcode ("and", "%s,r25", aopGet (AOP (result), 1));
3183 emitcode ("or", "%s,r24", aopGet (AOP (result), 1));
3185 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3186 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3189 if (!lByteZ && !sameRegs (AOP (result), AOP (left))
3193 aopPut (AOP (result),
3194 aopGet (AOP (left), offset), offset);
3200 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3203 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3204 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3209 assert ("shifting generic pointer ?\n");
3212 /* 32 bits we do only byte boundaries */
3213 if (shCount >= 24) {
3214 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3215 aopPut (AOP (result), zero, 2);
3216 aopPut (AOP (result), zero, 1);
3217 aopPut (AOP (result), zero, 0);
3221 if (shCount >= 16) {
3222 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3223 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3224 aopPut (AOP (result), zero, 1);
3225 aopPut (AOP (result), zero, 0);
3230 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3231 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3232 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3233 aopPut (AOP (result), zero, 0);
3237 if (!lByteZ && !sameRegs (AOP (left), AOP (right))) {
3240 aopPut (AOP (result),
3241 aopGet (AOP (left), offset), offset);
3245 size = AOP_SIZE (result);
3251 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3252 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3253 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3254 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3259 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3260 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3261 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3266 emitcode ("lsl", "%s", aopGet (AOP (result), 2));
3267 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3272 emitcode ("lsl", "%s", aopGet (AOP (result), 3));
3280 freeAsmop (left, NULL, ic, TRUE);
3281 freeAsmop (right, NULL, ic, TRUE);
3282 freeAsmop (result, NULL, ic, TRUE);
3285 /*-----------------------------------------------------------------*/
3286 /* genLeftShift - generates code for left shifting */
3287 /*-----------------------------------------------------------------*/
3289 genLeftShift (iCode * ic)
3291 operand *left, *right, *result;
3295 right = IC_RIGHT (ic);
3296 left = IC_LEFT (ic);
3297 result = IC_RESULT (ic);
3299 aopOp (right, ic, FALSE);
3301 if (AOP_TYPE (right) == AOP_LIT) {
3302 genShiftLeftLit (ic);
3307 aopOp (left, ic, FALSE);
3308 aopOp (result, ic, FALSE);
3309 size = AOP_SIZE (result);
3311 if (AOP_SIZE (right) > 1) {
3312 if (isRegPair (AOP (right))) {
3313 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3316 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3317 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3321 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3323 if (!sameRegs (AOP (left), AOP (result))) {
3325 aopPut (AOP (result), aopGet (AOP (left), offset),
3329 size = AOP_SIZE (result);
3331 tlbl = newiTempLabel (NULL);
3332 emitcode ("", "L%05d:", tlbl->key);
3336 emitcode ("rol", "%s", aopGet (AOP (result), offset));
3338 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3341 if (AOP_SIZE (right) > 1)
3342 emitcode ("sbiw", "r24,1");
3344 emitcode ("dec", "r24");
3345 emitcode ("brne", "L%05d", tlbl->key);
3347 freeAsmop (left, NULL, ic, TRUE);
3348 freeAsmop (right, NULL, ic, TRUE);
3349 freeAsmop (result, NULL, ic, TRUE);
3352 /*-----------------------------------------------------------------*/
3353 /* genShiftRightLit - generate for right shift with known count */
3354 /*-----------------------------------------------------------------*/
3356 genShiftRightLit (iCode * ic)
3358 operand *left = IC_LEFT (ic)
3359 , *right = IC_RIGHT (ic)
3360 , *result = IC_RESULT (ic);
3361 int size, shCount, offset = 0;
3363 sym_link *letype = getSpec (operandType (left));
3364 int sign = !SPEC_USIGN (letype);
3366 right = IC_RIGHT (ic);
3367 left = IC_LEFT (ic);
3368 result = IC_RESULT (ic);
3370 aopOp (left, ic, FALSE);
3371 aopOp (result, ic, FALSE);
3372 size = AOP_SIZE (result);
3373 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3375 /* if signed then give up and use a loop to shift */
3378 if (!sameRegs (AOP (left), AOP (result))) {
3380 aopPut (AOP (result),
3381 aopGet (AOP (left), offset), offset);
3384 size = AOP_SIZE (result);
3387 /* be as economical as possible */
3390 size = AOP_SIZE (result);
3393 /* highest order byte */
3394 if (offset == (AOP_SIZE(result)-1))
3395 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3397 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3403 emitcode ("ldi", "r24,<(%d)", shCount);
3404 tlbl = newiTempLabel (NULL);
3405 emitcode ("", "L%05d:", tlbl->key);
3408 if (offset == (AOP_SIZE(result) - 1))
3409 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3411 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3414 emitcode ("dec", "r24");
3415 emitcode ("brne", "L%05d", tlbl->key);
3419 if (shCount > (size * 8 - 1)) {
3421 aopPut (AOP (result), zero, offset++);
3424 /* for unsigned we can much more efficient */
3427 if (!sameRegs (AOP (left), AOP (result)))
3428 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3430 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3431 if (AOP_ISHIGHREG(AOP(result),0)) {
3432 emitcode ("andi", "%s,0x0f",aopGet(AOP(result),0));
3434 emitcode ("ldi","r24,0x0f");
3435 emitcode ("and", "%s,r24",aopGet(AOP(result),0));
3440 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3443 if (shCount >= 12) {
3444 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3445 aopPut (AOP (result), zero, 1);
3446 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3447 if (AOP_ISHIGHREG(AOP(result),0)) {
3448 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3450 emitcode ("ldi","r24,0x0f");
3451 emitcode ("and", "%s,r24",aopGet(AOP(result),0));
3457 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3458 aopPut (AOP (result), zero, 1);
3464 if (!sameRegs (AOP (left), AOP (result))) {
3465 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3466 aopPut (AOP (result), aopGet (AOP (left), 1), 1);
3468 if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
3469 emitcode("ldi","r25,0x0f");
3471 emitcode ("mov", "r24,%s", aopGet (AOP (result), 1));
3472 emitcode ("andi", "r24,0xf0");
3473 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3474 if (AOP_ISHIGHREG(AOP(result),0)) {
3475 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3477 emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
3479 emitcode ("or", "%s,r24", aopGet (AOP (result), 0));
3480 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3481 if (AOP_ISHIGHREG(AOP(result),1)) {
3482 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 1));
3484 emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
3487 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3488 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3492 if (!hByteZ && !sameRegs (AOP (result), AOP (left))
3496 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3502 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3505 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3506 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3512 assert ("shifting generic pointer ?\n");
3515 /* 32 bits we do only byte boundaries */
3516 if (shCount >= 24) {
3517 aopPut (AOP (result), aopGet (AOP (left), 3), 0);
3518 aopPut (AOP (result), zero, 1);
3519 aopPut (AOP (result), zero, 2);
3520 aopPut (AOP (result), zero, 3);
3524 if (shCount >= 16) {
3525 aopPut (AOP (result), aopGet (AOP (left), 3), 1);
3526 aopPut (AOP (result), aopGet (AOP (left), 2), 0);
3527 aopPut (AOP (result), zero, 2);
3528 aopPut (AOP (result), zero, 3);
3533 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3534 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3535 aopPut (AOP (result), aopGet (AOP (left), 3), 2);
3536 aopPut (AOP (result), zero, 3);
3540 if (!hByteZ && !sameRegs (AOP (left), AOP (right))) {
3543 aopPut (AOP (result),
3544 aopGet (AOP (left), offset), offset);
3548 size = AOP_SIZE (result);
3554 emitcode ("lsr", "%s", aopGet (AOP (result), 3));
3555 emitcode ("ror", "%s", aopGet (AOP (result), 2));
3556 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3557 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3562 emitcode ("lsr", "%s", aopGet (AOP (result), 2));
3563 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3564 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3569 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3570 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3575 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3582 freeAsmop (left, NULL, ic, TRUE);
3583 freeAsmop (right, NULL, ic, TRUE);
3584 freeAsmop (result, NULL, ic, TRUE);
3587 /*-----------------------------------------------------------------*/
3588 /* genRightShift - generate code for right shifting */
3589 /*-----------------------------------------------------------------*/
3591 genRightShift (iCode * ic)
3593 operand *right, *left, *result;
3596 int sign = 0, first = 1;
3599 aopOp (right = IC_RIGHT (ic), ic, FALSE);
3601 if (AOP_TYPE (right) == AOP_LIT) {
3602 genShiftRightLit (ic);
3606 if (AOP_SIZE (right) > 1) {
3607 if (isRegPair (AOP (right))) {
3608 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3611 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3612 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3616 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3618 aopOp (left = IC_LEFT (ic), ic, FALSE);
3619 aopOp (result = IC_RESULT (ic), ic, FALSE);
3620 size = AOP_SIZE (result);
3621 tlbl = newiTempLabel (NULL);
3622 emitcode ("", "L%05d:", tlbl->key);
3624 letype = getSpec (operandType (left));
3625 sign = !SPEC_USIGN (letype);
3626 if (!sameRegs (AOP (left), AOP (result))) {
3628 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3631 size = AOP_SIZE (result);
3633 size = AOP_SIZE (result);
3637 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3639 emitcode ("lsr", "%s", aopGet (AOP (result), offset));
3643 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3646 if (AOP_SIZE (right) > 1)
3647 emitcode ("sbiw", "r24,1");
3649 emitcode ("dec", "r24");
3650 emitcode ("brne", "L%05d", tlbl->key);
3652 freeAsmop (left, NULL, ic, TRUE);
3653 freeAsmop (result, NULL, ic, TRUE);
3656 /*-----------------------------------------------------------------*/
3657 /* RRsh - shift right rn by known count */
3658 /*-----------------------------------------------------------------*/
3660 RRsh (int shCount,int reg)
3662 shCount &= 0x0007; // shCount : 0..7
3668 emitcode ("lsr", "r%d",reg);
3671 emitcode ("lsr", "r%d",reg);
3672 emitcode ("lsr", "r%d",reg);
3675 emitcode ("swap", "r%d",reg);
3676 emitcode ("lsl", "r%d",reg);
3679 emitcode ("swap", "r%d",reg);
3682 emitcode ("swap", "r%d",reg);
3683 emitcode ("lsr", "r%d",reg);
3686 emitcode ("swap","r%d",reg);
3687 emitcode ("lsr", "r%d",reg);
3688 emitcode ("lsr", "r%d",reg);
3691 emitcode ("swap","r%d",reg);
3692 emitcode ("lsr", "r%d",reg);
3693 emitcode ("lsr", "r%d",reg);
3694 emitcode ("lsr", "r%d",reg);
3699 /*-----------------------------------------------------------------*/
3700 /* RLsh - shift left rn by known count */
3701 /*-----------------------------------------------------------------*/
3703 RLsh (int shCount, int reg)
3705 shCount &= 0x0007; // shCount : 0..7
3711 emitcode ("lsl", "r%d",reg);
3714 emitcode ("lsl", "r%d",reg);
3715 emitcode ("lsl", "r%d",reg);
3718 emitcode ("swap","r%d",reg);
3719 emitcode ("lsr", "r%d",reg);
3722 emitcode ("swap", "r%d",reg);
3725 emitcode ("swap","r%d",reg);
3726 emitcode ("lsl", "r%d",reg);
3729 emitcode ("swap","r%d",reg);
3730 emitcode ("lsl", "r%d",reg);
3731 emitcode ("lsl", "r%d",reg);
3734 emitcode ("swap","r%d",reg);
3735 emitcode ("lsl", "r%d",reg);
3736 emitcode ("lsl", "r%d",reg);
3737 emitcode ("lsl", "r%d",reg);
3742 /*-----------------------------------------------------------------*/
3743 /* genUnpackBits - generates code for unpacking bits */
3744 /*-----------------------------------------------------------------*/
3746 genUnpackBits (operand * result, char *rname, int ptype)
3754 etype = getSpec (operandType (result));
3755 rsize = getSize (operandType (result));
3756 /* read the first byte */
3763 emitcode ("ld", "r24,%s+", rname);
3767 emitcode ("lpm", "r24,%s+", rname);
3771 emitcode ("call","__gptrget_pi");
3772 emitcode ("mov","r24,r0");
3776 rlen = SPEC_BLEN (etype);
3778 /* if we have bitdisplacement then it fits */
3779 /* into this byte completely or if length is */
3780 /* less than a byte */
3781 if ((shCnt = SPEC_BSTR (etype)) || (SPEC_BLEN (etype) <= 8)) {
3783 /* shift right acc */
3786 emitcode ("andi", "r24,lo(0x%x)",
3787 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
3788 aopPut (AOP (result), "r24", offset++);
3792 /* bit field did not fit in a byte */
3793 aopPut (AOP (result), "r24", offset++);
3803 emitcode ("ld", "r24,%s+");
3807 emitcode ("lpm", "r24,%s+");
3811 emitcode ("call", "__gptrget_pi");
3816 /* if we are done */
3820 aopPut (AOP (result), "r24", offset++);
3825 aopPut (AOP (result), "r24", offset++);
3829 if (offset < rsize) {
3832 aopPut (AOP (result), zero, offset++);
3837 /*-----------------------------------------------------------------*/
3838 /* genDataPointerGet - generates code when ptr offset is known */
3839 /*-----------------------------------------------------------------*/
3841 genDataPointerGet (operand * left, operand * result, iCode * ic)
3845 int size, offset = 0;
3846 aopOp (result, ic, TRUE);
3848 /* get the string representation of the name */
3849 l = aopGet (AOP (left), 0);
3850 size = AOP_SIZE (result);
3853 sprintf (buffer, "(%s + %d)", l, offset);
3855 sprintf (buffer, "%s", l);
3856 emitcode ("lds", "%s,%s", aopGet (AOP (result), offset++),
3860 freeAsmop (left, NULL, ic, TRUE);
3861 freeAsmop (result, NULL, ic, TRUE);
3864 /*-----------------------------------------------------------------*/
3865 /* genNearPointerGet - emitcode for near pointer fetch */
3866 /*-----------------------------------------------------------------*/
3868 genMemPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
3873 char *rname, *frname = NULL;
3874 sym_link *rtype, *retype;
3875 sym_link *ltype = operandType (left);
3877 rtype = operandType (result);
3878 retype = getSpec (rtype);
3880 aopOp (left, ic, FALSE);
3882 /* if left is rematerialisable and
3883 result is not bit variable type and
3884 the left is pointer to data space i.e
3885 lower 128 bytes of space */
3886 if (AOP_TYPE (left) == AOP_IMMD &&
3887 !IS_BITVAR (retype) && DCL_TYPE (ltype) == POINTER) {
3888 genDataPointerGet (left, result, ic);
3892 /* if the value is already in a pointer register
3893 then don't need anything more */
3894 if (!AOP_INPREG (AOP (left))) {
3895 /* otherwise get a free pointer register */
3897 preg = getFreePtr (ic, &aop, FALSE, 0);
3898 if (isRegPair (AOP (left) )) {
3899 emitcode ("movw", "%s,%s",
3900 aop->aopu.aop_ptr->name,
3901 aopGet(AOP(left),0));
3903 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
3904 aopGet (AOP (left), 0));
3905 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
3906 aopGet (AOP (left), 1));
3912 frname = aopGet(aop,0);
3916 } else if (AOP_ISZ(aop)) {
3919 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
3920 "pointer not in correct register");
3924 aopOp (result, ic, FALSE);
3926 /* if bitfield then unpack the bits */
3927 if (IS_BITVAR (retype))
3928 genUnpackBits (result, rname, POINTER);
3930 /* we have can just get the values */
3931 int size = AOP_SIZE (result);
3936 emitcode ("ld","%s,%s+",aopGet(AOP(result),offset), rname);
3938 emitcode ("ld","%s,%s",aopGet(AOP(result),offset), rname);
3943 /* now some housekeeping stuff */
3945 /* we had to allocate for this iCode */
3947 if (isRegPair (AOP (left) )) {
3948 emitcode ("movw", "%s,%s",
3949 aopGet (AOP(left),0),
3950 aop->aopu.aop_ptr->name);
3952 emitcode ("mov", "%s,%s",
3953 aopGet (AOP (left), 0),
3954 aop->aopu.aop_ptr->name);
3955 emitcode ("mov", "%s,%s",
3956 aopGet (AOP (left), 1),
3957 aop->aop_ptr2->name);
3960 freeAsmop (NULL, aop, ic, TRUE);
3963 /* we did not allocate which means left
3964 already in a pointer register, then
3965 if size > 0 && this could be used again
3966 we have to point it back to where it
3968 if ((AOP_SIZE (result) > 1 &&
3969 !OP_SYMBOL (left)->remat &&
3970 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) && !pi) {
3971 int size = AOP_SIZE (result) - 1;
3972 emitcode ("sbiw", "%s,%d",frname,size);
3977 if (pi) pi->generated = 1;
3978 freeAsmop (left, NULL, ic, TRUE);
3979 freeAsmop (result, NULL, ic, TRUE);
3983 /*-----------------------------------------------------------------*/
3984 /* genCodePointerGet - gget value from code space */
3985 /*-----------------------------------------------------------------*/
3987 genCodePointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
3990 sym_link *retype = getSpec (operandType (result));
3994 aopOp (left, ic, FALSE);
3996 /* if the operand is already in Z register
3997 then we do nothing else we move the value to Z register */
3998 if (AOP_ISZ(AOP(left))) {
4002 getFreePtr(ic,&aop,FALSE,TRUE);
4003 if (isRegPair(AOP (left))) {
4004 emitcode ("movw","r30,%s",aopGet (AOP (left), 0));
4006 emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
4007 emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
4012 aopOp (result, ic, FALSE);
4014 /* if bit then unpack */
4015 if (IS_BITVAR (retype))
4016 genUnpackBits (result, "Z", CPOINTER);
4018 size = AOP_SIZE (result);
4023 emitcode ("lpm","%s,Z+",aopGet(AOP(result),offset++));
4025 emitcode ("lpm","%s,Z",aopGet(AOP(result),offset++));
4030 /* now some housekeeping stuff */
4032 /* we had to allocate for this iCode */
4034 if (isRegPair(AOP (left))) {
4035 emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
4037 emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
4038 emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
4041 freeAsmop (NULL, aop, ic, TRUE);
4044 /* we did not allocate which means left
4045 already in a pointer register, then
4046 if size > 0 && this could be used again
4047 we have to point it back to where it
4049 if ((AOP_SIZE (result) > 1 &&
4050 !OP_SYMBOL (left)->remat &&
4051 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) &&
4053 int size = AOP_SIZE (result) - 1;
4054 emitcode ("sbiw", "r30,%d",size);
4059 if (pi) pi->generated=1;
4060 freeAsmop (left, NULL, ic, TRUE);
4061 freeAsmop (result, NULL, ic, TRUE);
4065 /*-----------------------------------------------------------------*/
4066 /* genGenPointerGet - gget value from generic pointer space */
4067 /*-----------------------------------------------------------------*/
4069 genGenPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
4073 sym_link *retype = getSpec (operandType (result));
4076 aopOp (left, ic, FALSE);
4078 /* if the operand is already in dptr
4079 then we do nothing else we move the value to dptr */
4080 if (AOP_ISZ(AOP(left))) {
4084 getFreePtr(ic,&aop,FALSE,TRUE);
4085 if (isRegPair(AOP(left))) {
4086 emitcode ("movw", "r30,%s", aopGet (AOP (left), 0));
4088 emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
4089 emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
4091 emitcode ("mov", "r24,%s", aopGet (AOP (left), 2));
4095 /* so Z register now contains the address */
4097 aopOp (result, ic, FALSE);
4099 /* if bit then unpack */
4100 if (IS_BITVAR (retype))
4101 genUnpackBits (result, "Z", GPOINTER);
4103 size = AOP_SIZE (result);
4108 emitcode ("call", "__gptrget_pi");
4110 emitcode ("call", "__gptrget");
4111 aopPut (AOP (result), "r0", offset++);
4116 /* now some housekeeping stuff */
4118 /* we had to allocate for this iCode */
4120 if (isRegPair(AOP (left))) {
4121 emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
4123 emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
4124 emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
4127 freeAsmop (NULL, aop, ic, TRUE);
4130 /* we did not allocate which means left
4131 already in a pointer register, then
4132 if size > 0 && this could be used again
4133 we have to point it back to where it
4135 if ((AOP_SIZE (result) > 1 &&
4136 !OP_SYMBOL (left)->remat &&
4137 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) &&
4139 int size = AOP_SIZE (result) - 1;
4140 emitcode ("sbiw", "r30,%d",size);
4143 if (pi) pi->generated=1;
4144 freeAsmop (left, NULL, ic, TRUE);
4145 freeAsmop (result, NULL, ic, TRUE);
4148 /*-----------------------------------------------------------------*/
4149 /* genPointerGet - generate code for pointer get */
4150 /*-----------------------------------------------------------------*/
4152 genPointerGet (iCode * ic, iCode *pi)
4154 operand *left, *result;
4155 sym_link *type, *etype;
4158 left = IC_LEFT (ic);
4159 result = IC_RESULT (ic);
4161 /* depending on the type of pointer we need to
4162 move it to the correct pointer register */
4163 type = operandType (left);
4164 etype = getSpec (type);
4165 /* if left is of type of pointer then it is simple */
4166 if (IS_PTR (type) && !IS_FUNC (type->next))
4167 p_type = DCL_TYPE (type);
4169 /* we have to go by the storage class */
4170 p_type = PTR_TYPE (SPEC_OCLS (etype));
4175 /* now that we have the pointer type we assign
4176 the pointer values */
4183 genMemPointerGet (left, result, ic, pi);
4187 genCodePointerGet (left, result, ic, pi);
4191 genGenPointerGet (left, result, ic, pi);
4197 /*-----------------------------------------------------------------*/
4198 /* genPackBits - generates code for packed bit storage */
4199 /*-----------------------------------------------------------------*/
4201 genPackBits (sym_link * etype,
4203 char *rname, int p_type)
4211 blen = SPEC_BLEN (etype);
4212 bstr = SPEC_BSTR (etype);
4214 l = aopGet (AOP (right), offset++);
4217 /* if the bit lenth is less than or */
4218 /* it exactly fits a byte then */
4219 if (SPEC_BLEN (etype) <= 8) {
4220 shCount = SPEC_BSTR (etype);
4222 /* shift left acc */
4225 if (SPEC_BLEN (etype) < 8) { /* if smaller than a byte */
4232 emitcode ("ld", "r1,%s",rname);
4236 emitcode ("push", "r1");
4237 emitcode ("push", "r24");
4238 emitcode ("call", "__gptrget");
4239 emitcode ("pop", "r1");
4240 emitcode ("mov","r24,r0");
4244 emitcode ("andi", "r24,#0x%02x", (unsigned char)
4245 ((unsigned char) (0xFF << (blen + bstr)) |
4246 (unsigned char) (0xFF >> (8 - bstr))));
4247 emitcode ("or", "r24,r1");
4248 if (p_type == GPOINTER)
4249 emitcode ("pop", "r1");
4258 emitcode("st","%s+,r24");
4262 emitcode("mov","r0,r24");
4263 emitcode ("call", "__gptrput_pi");
4268 if (SPEC_BLEN (etype) <= 8)
4271 rLen = SPEC_BLEN (etype);
4273 /* now generate for lengths greater than one byte */
4276 l = aopGet (AOP (right), offset++);
4287 emitcode ("st", "%s+,%s",rname,l);
4292 emitcode ("lcall", "__gptrput_pi");
4299 /* last last was not complete */
4301 /* save the byte & read byte */
4307 emitcode ("st","%s+,r24",rname);
4310 emitcode ("push", "r1");
4311 emitcode ("push", "r24");
4312 emitcode ("lcall", "__gptrget");
4313 emitcode ("mov","r24,r0");
4314 emitcode ("pop", "r1");
4318 emitcode ("andi", "r24,0x%02x", (((unsigned char) -1 << rLen) & 0xff));
4319 emitcode ("or", "r24,r1");
4322 if (p_type == GPOINTER)
4323 emitcode ("pop", "r1");
4331 emitcode ("st", "%s,r24", rname);
4335 emitcode ("mov","r0,r24");
4336 emitcode ("call", "__gptrput");
4341 /*-----------------------------------------------------------------*/
4342 /* genDataPointerSet - remat pointer to data space */
4343 /*-----------------------------------------------------------------*/
4345 genDataPointerSet (operand * right, operand * result, iCode * ic)
4347 int size, offset = 0;
4348 char *l, buffer[256];
4350 aopOp (right, ic, FALSE);
4352 l = aopGet (AOP (result), 0);
4353 size = AOP_SIZE (right);
4356 sprintf (buffer, "(%s + %d)", l, offset);
4358 sprintf (buffer, "%s", l);
4359 emitcode ("sts", "%s,%s", buffer,
4360 aopGet (AOP (right), offset++));
4363 freeAsmop (right, NULL, ic, TRUE);
4364 freeAsmop (result, NULL, ic, TRUE);
4367 /*-----------------------------------------------------------------*/
4368 /* genNearPointerSet - emitcode for near pointer put */
4369 /*-----------------------------------------------------------------*/
4371 genMemPointerSet (operand * right, operand * result, iCode * ic, iCode *pi)
4374 char *frname = NULL, *rname, *l;
4377 sym_link *ptype = operandType (result);
4379 retype = getSpec (operandType (right));
4381 aopOp (result, ic, FALSE);
4383 /* if the result is rematerializable &
4384 in data space & not a bit variable */
4385 if (AOP_TYPE (result) == AOP_IMMD &&
4386 DCL_TYPE (ptype) == POINTER && !IS_BITVAR (retype)) {
4387 genDataPointerSet (right, result, ic);
4390 if (!AOP_INPREG(AOP(result))) {
4391 /* otherwise get a free pointer register */
4393 getFreePtr (ic, &aop, FALSE, 0);
4394 if (isRegPair (AOP (result) )) {
4395 emitcode ("movw", "%s,%s",aop->aopu.aop_ptr->name,
4396 aopGet(AOP (result), 0));
4398 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
4399 aopGet (AOP (result), 0));
4400 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
4401 aopGet (AOP (result), 1));
4406 frname = aopGet(aop,0);
4409 aopOp (right, ic, FALSE);
4412 } else if (AOP_ISZ(aop)) {
4415 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4416 "pointer not in correct register");
4419 /* if bitfield then unpack the bits */
4420 if (IS_BITVAR (retype))
4421 genPackBits (retype, right, rname, POINTER);
4423 /* we have can just get the values */
4424 int size = AOP_SIZE (right);
4428 l = aopGet (AOP (right), offset);
4430 emitcode ("st", "%s+,%s", rname,l);
4432 emitcode ("st", "%s,%s", rname,l);
4437 /* now some housekeeping stuff */
4439 /* we had to allocate for this iCode */
4441 if (isRegPair (AOP (result) )) {
4442 emitcode ("movw", "%s,%s",
4443 aopGet(AOP(result),0),
4444 aop->aopu.aop_ptr->name);
4446 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
4447 aopGet (AOP (result), 0));
4448 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
4449 aopGet (AOP (result), 1));
4452 freeAsmop (NULL, aop, ic, TRUE);
4455 /* we did not allocate which means left
4456 already in a pointer register, then
4457 if size > 0 && this could be used again
4458 we have to point it back to where it
4460 if ((AOP_SIZE (right) > 1 &&
4461 !OP_SYMBOL (result)->remat &&
4462 (OP_SYMBOL (right)->liveTo > ic->seq || ic->depth)) && !pi) {
4463 int size = AOP_SIZE (right) - 1;
4464 emitcode ("sbiw", "%s,%d",frname,size);
4469 if (pi) pi->generated = 1;
4470 freeAsmop (result, NULL, ic, TRUE);
4471 freeAsmop (right, NULL, ic, TRUE);
4474 /*-----------------------------------------------------------------*/
4475 /* genGenPointerSet - set value from generic pointer space */
4476 /*-----------------------------------------------------------------*/
4478 genGenPointerSet (operand * right, operand * result, iCode * ic, iCode *pi)
4482 sym_link *retype = getSpec (operandType (right));
4485 aopOp (result, ic, FALSE);
4487 /* if the operand is already in dptr
4488 then we do nothing else we move the value to dptr */
4489 if (AOP_ISZ(AOP(result))) {
4493 getFreePtr(ic,&aop,FALSE,TRUE);
4494 if (isRegPair(AOP(result))) {
4495 emitcode ("movw", "r30,%s", aopGet (AOP (result), 0));
4497 emitcode ("mov", "r30,%s", aopGet (AOP (result), 0));
4498 emitcode ("mov", "r31,%s", aopGet (AOP (result), 1));
4500 emitcode ("mov", "r24,%s", aopGet (AOP (result), 2));
4504 /* so Z register now contains the address */
4505 aopOp (right, ic, FALSE);
4507 /* if bit then unpack */
4508 if (IS_BITVAR (retype))
4509 genUnpackBits (result, "Z", GPOINTER);
4511 size = AOP_SIZE (right);
4515 char *l = aopGet(AOP (right), offset++);
4519 emitcode ("call", "__gptrput_pi");
4521 emitcode ("call", "__gptrput");
4525 /* now some housekeeping stuff */
4527 /* we had to allocate for this iCode */
4529 if (isRegPair(AOP(result))) {
4530 emitcode ("movw", "%s,r30", aopGet (AOP (result), 0));
4532 emitcode ("mov", "%s,r30", aopGet (AOP (result), 0));
4533 emitcode ("mov", "%s,r31", aopGet (AOP (result), 1));
4536 freeAsmop (NULL, aop, ic, TRUE);
4539 /* we did not allocate which means left
4540 already in a pointer register, then
4541 if size > 0 && this could be used again
4542 we have to point it back to where it
4544 if ((AOP_SIZE (right) > 1 &&
4545 !OP_SYMBOL (result)->remat &&
4546 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) && !pi) {
4547 int size = AOP_SIZE (right) - 1;
4548 emitcode ("sbiw", "r30,%d",size);
4551 if (pi) pi->generated = 1;
4552 freeAsmop (right, NULL, ic, TRUE);
4553 freeAsmop (result, NULL, ic, TRUE);
4556 /*-----------------------------------------------------------------*/
4557 /* genPointerSet - stores the value into a pointer location */
4558 /*-----------------------------------------------------------------*/
4560 genPointerSet (iCode * ic, iCode *pi)
4562 operand *right, *result;
4563 sym_link *type, *etype;
4566 right = IC_RIGHT (ic);
4567 result = IC_RESULT (ic);
4569 /* depending on the type of pointer we need to
4570 move it to the correct pointer register */
4571 type = operandType (result);
4572 etype = getSpec (type);
4573 /* if left is of type of pointer then it is simple */
4574 if (IS_PTR (type) && !IS_FUNC (type->next)) {
4575 p_type = DCL_TYPE (type);
4578 /* we have to go by the storage class */
4579 p_type = PTR_TYPE (SPEC_OCLS (etype));
4583 /* now that we have the pointer type we assign
4584 the pointer values */
4591 genMemPointerSet (right, result, ic, pi);
4595 genGenPointerSet (right, result, ic, pi);
4599 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4600 "genPointerSet: illegal pointer type");
4605 /*-----------------------------------------------------------------*/
4606 /* genIfx - generate code for Ifx statement */
4607 /*-----------------------------------------------------------------*/
4609 genIfx (iCode * ic, iCode * popIc)
4611 operand *cond = IC_COND (ic);
4616 aopOp (cond, ic, FALSE);
4618 /* get the value into acc */
4619 if (AOP_SIZE(cond) == 1 && AOP_ISHIGHREG(AOP(cond),0)) {
4620 cname = aopGet(AOP(cond),0);
4622 toBoolean (cond, "r24", 0);
4626 /* the result is now in the accumulator */
4627 freeAsmop (cond, NULL, ic, TRUE);
4629 /* if there was something to be popped then do it */
4632 emitcode("cpi","%s,0",cname);
4633 } else if (!tob) emitcode("cpi","%s,0",cname);
4635 lbl = newiTempLabel(NULL);
4637 emitcode ("breq","L%05d",lbl->key);
4638 emitcode ("jmp","L%05d",IC_TRUE(ic)->key);
4639 emitcode ("","L%05d:",lbl->key);
4641 emitcode ("brne","L%05d",lbl->key);
4642 emitcode ("jmp","L%05d",IC_FALSE(ic)->key);
4643 emitcode ("","L%05d:",lbl->key);
4648 /*-----------------------------------------------------------------*/
4649 /* genAddrOf - generates code for address of */
4650 /*-----------------------------------------------------------------*/
4652 genAddrOf (iCode * ic)
4654 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
4657 aopOp (IC_RESULT (ic), ic, FALSE);
4658 assert(AOP_SIZE(IC_RESULT(ic)) >= 2);
4659 /* if the operand is on the stack then we
4660 need to get the stack offset of this
4663 /* if it has an offset then we need to compute it */
4665 if (allHigh(AOP(IC_RESULT(ic)))) {
4666 if (isRegPair (AOP(IC_RESULT(ic)))) {
4667 emitcode ("movw","%s,r28",aopGet(AOP(IC_RESULT(ic)),0));
4669 emitcode ("mov","%s,r28",aopGet(AOP(IC_RESULT(ic)),0));
4670 emitcode ("mov","%s,r29",aopGet(AOP(IC_RESULT(ic)),1));
4672 if (sym->stack < 0) {
4673 emitcode("subi","%s,<(%d)",aopGet(AOP(IC_RESULT(ic)),0),-sym->stack);
4674 emitcode("sbci","%s,>(%d)",aopGet(AOP(IC_RESULT(ic)),1),-sym->stack);
4676 emitcode("subi","%s,<(-%d)",aopGet(AOP(IC_RESULT(ic)),0),sym->stack);
4677 emitcode("sbci","%s,>(-%d)",aopGet(AOP(IC_RESULT(ic)),1),sym->stack);
4680 emitcode("movw","r24,r28");
4681 if (sym->stack > -63 && sym->stack < 63) {
4683 emitcode("sbiw","r24,%d",-sym->stack);
4685 emitcode("sbiw","r24,%d",sym->stack);
4687 if (sym->stack < 0) {
4688 emitcode("subi","r24,<(%d)",-sym->stack);
4689 emitcode("sbci","r25,>(%d)",-sym->stack);
4691 emitcode("subi","r24,<(-%d)",sym->stack);
4692 emitcode("sbci","r25,>(-%d)",sym->stack);
4696 aopPut(AOP(IC_RESULT(ic)),"r24",0);
4697 aopPut(AOP(IC_RESULT(ic)),"r25",1);
4701 aopPut(AOP(IC_RESULT(ic)),"r28",0);
4702 aopPut(AOP(IC_RESULT(ic)),"r29",1);
4704 /* fill the result with zero */
4705 size = AOP_SIZE (IC_RESULT (ic)) - 2;
4708 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
4714 /* object not on stack then we need the name */
4715 size = AOP_SIZE (IC_RESULT (ic));
4719 char s[SDCC_NAME_MAX];
4721 sprintf (s, ">(%s)", sym->rname);
4723 sprintf (s, "<(%s)", sym->rname);
4724 aopPut (AOP (IC_RESULT (ic)), s, offset++);
4728 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4732 /*-----------------------------------------------------------------*/
4733 /* genFarFarAssign - assignment when both are in far space */
4734 /*-----------------------------------------------------------------*/
4736 genFarFarAssign (operand * result, operand * right, iCode * ic)
4738 int size = AOP_SIZE (right);
4741 /* first push the right side on to the stack */
4743 l = aopGet (AOP (right), offset++);
4745 emitcode ("push", "acc");
4748 freeAsmop (right, NULL, ic, FALSE);
4749 /* now assign DPTR to result */
4750 aopOp (result, ic, FALSE);
4751 size = AOP_SIZE (result);
4753 emitcode ("pop", "acc");
4754 aopPut (AOP (result), "a", --offset);
4756 freeAsmop (result, NULL, ic, FALSE);
4760 /*-----------------------------------------------------------------*/
4761 /* genAssign - generate code for assignment */
4762 /*-----------------------------------------------------------------*/
4764 genAssign (iCode * ic)
4766 operand *result, *right;
4768 unsigned long lit = 0L;
4770 result = IC_RESULT (ic);
4771 right = IC_RIGHT (ic);
4773 /* if they are the same */
4774 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4777 aopOp (right, ic, FALSE);
4779 /* special case both in far space */
4780 if (AOP_TYPE (right) == AOP_DPTR &&
4781 IS_TRUE_SYMOP (result) && isOperandInFarSpace (result)) {
4783 genFarFarAssign (result, right, ic);
4787 aopOp (result, ic, TRUE);
4789 /* if they are the same registers */
4790 if (sameRegs (AOP (right), AOP (result)))
4793 /* if the result is a bit */
4794 if (AOP_TYPE (result) == AOP_CRY) {
4796 /* if the right size is a literal then
4797 we know what the value is */
4798 if (AOP_TYPE (right) == AOP_LIT) {
4799 if (((int) operandLitValue (right)))
4800 aopPut (AOP (result), one, 0);
4802 aopPut (AOP (result), zero, 0);
4806 /* the right is also a bit variable */
4807 if (AOP_TYPE (right) == AOP_CRY) {
4808 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4809 aopPut (AOP (result), "c", 0);
4814 toBoolean (right, "", 0);
4815 aopPut (AOP (result), "a", 0);
4819 /* bit variables done */
4821 size = AOP_SIZE (result);
4823 if (AOP_TYPE (right) == AOP_LIT)
4825 (unsigned long) floatFromVal (AOP (right)->aopu.
4827 if ((size > 1) && (AOP_TYPE (result) != AOP_REG)
4828 && (AOP_TYPE (right) == AOP_LIT)
4829 && !IS_FLOAT (operandType (right)) && (lit < 256L)) {
4830 emitcode ("clr", "a");
4832 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) ==
4833 0) aopPut (AOP (result), "a", size);
4835 aopPut (AOP (result),
4836 aopGet (AOP (right), size), size);
4841 aopPut (AOP (result),
4842 aopGet (AOP (right), offset), offset);
4848 freeAsmop (right, NULL, ic, FALSE);
4849 freeAsmop (result, NULL, ic, TRUE);
4852 /*-----------------------------------------------------------------*/
4853 /* genJumpTab - genrates code for jump table */
4854 /*-----------------------------------------------------------------*/
4856 genJumpTab (iCode * ic)
4861 aopOp (IC_JTCOND (ic), ic, FALSE);
4862 /* get the condition into accumulator */
4863 l = aopGet (AOP (IC_JTCOND (ic)), 0);
4865 /* multiply by three */
4866 emitcode ("add", "a,acc");
4867 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0));
4868 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
4870 jtab = newiTempLabel (NULL);
4871 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
4872 emitcode ("jmp", "@a+dptr");
4873 emitcode ("", "%05d$:", jtab->key + 100);
4874 /* now generate the jump labels */
4875 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
4876 jtab = setNextItem (IC_JTLABELS (ic)))
4877 emitcode ("ljmp", "%05d$", jtab->key + 100);
4881 /*-----------------------------------------------------------------*/
4882 /* genCast - gen code for casting */
4883 /*-----------------------------------------------------------------*/
4885 genCast (iCode * ic)
4887 operand *result = IC_RESULT (ic);
4888 sym_link *ctype = operandType (IC_LEFT (ic));
4889 sym_link *rtype = operandType (IC_RIGHT (ic));
4890 operand *right = IC_RIGHT (ic);
4893 /* if they are equivalent then do nothing */
4894 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4897 aopOp (right, ic, FALSE);
4898 aopOp (result, ic, FALSE);
4900 /* if the result is a bit */
4901 if (AOP_TYPE (result) == AOP_CRY) {
4902 /* if the right size is a literal then
4903 we know what the value is */
4904 if (AOP_TYPE (right) == AOP_LIT) {
4905 if (((int) operandLitValue (right)))
4906 aopPut (AOP (result), one, 0);
4908 aopPut (AOP (result), zero, 0);
4913 /* the right is also a bit variable */
4914 if (AOP_TYPE (right) == AOP_CRY) {
4915 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4916 aopPut (AOP (result), "c", 0);
4921 toBoolean (right, "", 0);
4922 aopPut (AOP (result), "a", 0);
4926 /* if they are the same size : or less */
4927 if (AOP_SIZE (result) <= AOP_SIZE (right)) {
4929 /* if they are in the same place */
4930 if (sameRegs (AOP (right), AOP (result)))
4933 /* if they in different places then copy */
4934 size = AOP_SIZE (result);
4937 aopPut (AOP (result),
4938 aopGet (AOP (right), offset), offset);
4945 /* if the result is of type pointer */
4946 if (IS_PTR (ctype)) {
4949 sym_link *type = operandType (right);
4950 sym_link *etype = getSpec (type);
4952 /* pointer to generic pointer */
4953 if (IS_GENPTR (ctype)) {
4955 p_type = DCL_TYPE (type);
4957 /* we have to go by the storage class */
4958 p_type = PTR_TYPE (SPEC_OCLS (etype));
4961 /* the first two bytes are known */
4962 size = GPTRSIZE - 1;
4965 aopPut (AOP (result),
4966 aopGet (AOP (right), offset), offset);
4970 /* the last byte depending on type */
4972 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
4977 // pointerTypeToGPByte will have bitched.
4981 sprintf(gpValStr, "#0x%x", gpVal);
4982 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
4987 /* just copy the pointers */
4988 size = AOP_SIZE (result);
4991 aopPut (AOP (result),
4992 aopGet (AOP (right), offset), offset);
4998 /* so we now know that the size of destination is greater
4999 than the size of the source */
5000 /* we move to result for the size of source */
5001 size = AOP_SIZE (right);
5004 aopPut (AOP (result), aopGet (AOP (right), offset), offset);
5008 /* now depending on the sign of the source && destination */
5009 size = AOP_SIZE (result) - AOP_SIZE (right);
5010 /* if unsigned or not an integral type */
5011 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype)) {
5013 aopPut (AOP (result), zero, offset++);
5016 /* we need to extend the sign :{ */
5017 // PENDING: Does nothing on avr
5019 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1);
5022 emitcode ("rlc", "a");
5023 emitcode ("subb", "a,acc");
5025 aopPut (AOP (result), "a", offset++);
5028 /* we are done hurray !!!! */
5031 freeAsmop (right, NULL, ic, TRUE);
5032 freeAsmop (result, NULL, ic, TRUE);
5036 /*-----------------------------------------------------------------*/
5037 /* genDjnz - generate decrement & jump if not zero instrucion */
5038 /*-----------------------------------------------------------------*/
5040 genDjnz (iCode * ic, iCode * ifx)
5046 /* if the if condition has a false label
5047 then we cannot save */
5051 /* if the minus is not of the form
5053 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
5054 !IS_OP_LITERAL (IC_RIGHT (ic)))
5057 if (operandLitValue (IC_RIGHT (ic)) != 1)
5060 /* if the size of this greater than one then no
5062 if (getSize (operandType (IC_RESULT (ic))) > 1)
5065 /* otherwise we can save BIG */
5066 lbl = newiTempLabel (NULL);
5067 lbl1 = newiTempLabel (NULL);
5069 aopOp (IC_RESULT (ic), ic, FALSE);
5071 if (IS_AOP_PREG (IC_RESULT (ic))) {
5072 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0));
5073 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0));
5074 emitcode ("jnz", "%05d$", lbl->key + 100);
5077 emitcode ("djnz", "%s,%05d$",
5078 aopGet (AOP (IC_RESULT (ic)), 0), lbl->key + 100);
5080 emitcode ("sjmp", "%05d$", lbl1->key + 100);
5081 emitcode ("", "%05d$:", lbl->key + 100);
5082 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5083 emitcode ("", "%05d$:", lbl1->key + 100);
5085 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5090 static char *recvregs[8] = {
5091 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23"
5094 static int recvCnt = 0;
5096 /*-----------------------------------------------------------------*/
5097 /* genReceive - generate code for a receive iCode */
5098 /*-----------------------------------------------------------------*/
5100 genReceive (iCode * ic)
5102 int size, offset = 0;
5103 aopOp (IC_RESULT (ic), ic, FALSE);
5104 size = AOP_SIZE (IC_RESULT (ic));
5106 aopPut (AOP (IC_RESULT (ic)), recvregs[recvCnt++], offset);
5109 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5112 /*-----------------------------------------------------------------*/
5113 /* genDummyRead - generate code for dummy read of volatiles */
5114 /*-----------------------------------------------------------------*/
5116 genDummyRead (iCode * ic)
5118 emitcode ("; genDummyRead","");
5119 emitcode ("; not implemented","");
5124 /*-----------------------------------------------------------------*/
5125 /* gen51Code - generate code for 8051 based controllers */
5126 /*-----------------------------------------------------------------*/
5128 genAVRCode (iCode * lic)
5133 lineHead = lineCurr = NULL;
5135 /* print the allocation information */
5137 printAllocInfo (currFunc, codeOutFile);
5138 /* if debug information required */
5139 if (options.debug && currFunc) {
5140 debugFile->writeFunction (currFunc, lic);
5142 /* stack pointer name */
5146 for (ic = lic; ic; ic = ic->next) {
5148 if (cln != ic->lineno) {
5149 if (options.debug) {
5150 debugFile->writeCLine (ic);
5152 emitcode (";", "%s %d", ic->filename, ic->lineno);
5155 /* if the result is marked as
5156 spilt and rematerializable or code for
5157 this has already been generated then
5159 if (resultRemat (ic) || ic->generated)
5162 /* depending on the operation */
5181 /* IPOP happens only when trying to restore a
5182 spilt live range, if there is an ifx statement
5183 following this pop then the if statement might
5184 be using some of the registers being popped which
5185 would destory the contents of the register so
5186 we need to check for this condition and handle it */
5188 ic->next->op == IFX &&
5189 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
5190 genIfx (ic->next, ic);
5208 genEndFunction (ic);
5228 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
5245 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
5249 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
5253 genCmpLe (ic, ifxForOp (IC_RESULT (ic), ic));
5257 genCmpGe (ic, ifxForOp (IC_RESULT (ic), ic));
5261 genCmpNe (ic, ifxForOp (IC_RESULT (ic), ic));
5265 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
5277 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
5281 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
5285 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
5312 case GET_VALUE_AT_ADDRESS:
5313 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
5317 if (POINTER_SET (ic))
5318 genPointerSet (ic, hasInc(IC_RESULT(ic),ic));
5344 addSet (&_G.sendSet, ic);
5347 case DUMMY_READ_VOLATILE:
5357 /* now we are ready to call the
5358 peep hole optimizer */
5359 if (!options.nopeep)
5360 peepHole (&lineHead);
5362 /* now do the actual printing */
5363 printLine (lineHead, codeOutFile);