1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for ATMEL AVR
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (2000)
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding!
25 -------------------------------------------------------------------------*/
31 #include "SDCCglobl.h"
35 #include "SDCCpeeph.h"
39 char *aopLiteral (value * val, int offset);
42 /* this is the down and dirty file with all kinds of
43 kludgy & hacky stuff. This is what it is all about
44 CODE GENERATION for a specific MCU . some of the
45 routines may be reusable, will have to see */
47 static char *zero = "0x00";
48 static char *one = "0x01";
51 char *fReturnAVR[] = { "r16", "r17", "r18", "r19" };
52 unsigned fAVRReturnSize = 4; /* shared with ralloc.c */
53 char **fAVRReturn = fReturnAVR;
54 static char *larray[4] = { ">", "<", "hlo8", "hhi8" };
66 extern int avr_ptrRegReq;
68 extern struct dbuf_s *codeOutBuf;
69 #define RESULTONSTACK(x) \
70 (IC_RESULT(x) && IC_RESULT(x)->aop && \
71 IC_RESULT(x)->aop->type == AOP_STK )
73 #define MOVR0(x) if (strcmp(x,"r0")) emitcode("mov","r0,%s",x);
74 #define MOVR24(x) if (strcmp(x,"r24")) emitcode("mov","r24,%s",x);
75 #define AOP_ISHIGHREG(a,n) (a->type == AOP_REG && a->aopu.aop_reg[n] && a->aopu.aop_reg[n]->rIdx >= R16_IDX)
76 #define CLRC emitcode("clc","")
77 #define SETC emitcode("stc","")
79 #define IS_REGIDX(a,r) (a->type == AOP_REG && a->aopu.aop_reg[0]->rIdx == r)
81 static lineNode *lineHead = NULL;
82 static lineNode *lineCurr = NULL;
91 /*-----------------------------------------------------------------*/
92 /* reAdjustPreg - points a register back to where it should */
93 /*-----------------------------------------------------------------*/
95 reAdjustPreg (asmop * aop)
100 if ((size = aop->size) <= 1)
106 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name, size);
112 /*-----------------------------------------------------------------*/
113 /* outBitC - output a bit C */
114 /*-----------------------------------------------------------------*/
116 outBitC (operand * result)
118 emitcode ("clr", "r0");
119 emitcode ("rol", "r0");
123 /*-----------------------------------------------------------------*/
124 /* inExcludeList - return 1 if the string is in exclude Reg list */
125 /*-----------------------------------------------------------------*/
127 inExcludeList (char *s)
131 if (options.excludeRegs[i] &&
132 STRCASECMP (options.excludeRegs[i], "none") == 0)
135 for (i = 0; options.excludeRegs[i]; i++) {
136 if (options.excludeRegs[i] &&
137 STRCASECMP (s, options.excludeRegs[i]) == 0)
143 /*-----------------------------------------------------------------*/
144 /* findLabelBackwards: walks back through the iCode chain looking */
145 /* for the given label. Returns number of iCode instructions */
146 /* between that label and given ic. */
147 /* Returns zero if label not found. */
148 /*-----------------------------------------------------------------*/
150 findLabelBackwards (iCode * ic, int key)
158 if (ic->op == LABEL && IC_LABEL (ic)->key == key) {
159 /* printf("findLabelBackwards = %d\n", count); */
167 /*-----------------------------------------------------------------*/
168 /* addSign - complete with sign */
169 /*-----------------------------------------------------------------*/
171 addSign (operand * result, int offset, int sign)
173 int size = (getDataSize (result) - offset);
176 emitcode ("rlc", "a");
177 emitcode ("subb", "a,acc");
179 aopPut (AOP (result), "a", offset++);
183 aopPut (AOP (result), zero, offset++);
187 /*-----------------------------------------------------------------*/
188 /* isLiteralBit - test if lit == 2^n */
189 /*-----------------------------------------------------------------*/
191 isLiteralBit (unsigned long lit)
193 unsigned long pw[32] = { 1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
194 0x100L, 0x200L, 0x400L, 0x800L,
195 0x1000L, 0x2000L, 0x4000L, 0x8000L,
196 0x10000L, 0x20000L, 0x40000L, 0x80000L,
197 0x100000L, 0x200000L, 0x400000L, 0x800000L,
198 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
199 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L
203 for (idx = 0; idx < 32; idx++)
209 /*-----------------------------------------------------------------*/
210 /* outAcc - output Acc */
211 /*-----------------------------------------------------------------*/
213 outAcc (operand * result)
216 size = getDataSize (result);
218 aopPut (AOP (result), "r0", 0);
221 /* unsigned or positive */
223 aopPut (AOP (result), zero, offset++);
228 #endif // End Unused code section
230 /*-----------------------------------------------------------------*/
231 /* emitcode - writes the code into a file : for now it is simple */
232 /*-----------------------------------------------------------------*/
234 emitcode (char *inst, char *fmt, ...)
237 char lb[INITIAL_INLINEASM];
244 sprintf (lb, "%s\t", inst);
246 sprintf (lb, "%s", inst);
247 vsprintf (lb + (strlen (lb)), fmt, ap);
250 vsprintf (lb, fmt, ap);
252 while (isspace ((unsigned char)*lbp))
256 lineCurr = (lineCurr ?
257 connectLine (lineCurr, newLineNode (lb)) :
258 (lineHead = newLineNode (lb)));
259 lineCurr->isInline = _G.inLine;
260 lineCurr->isDebug = _G.debugLine;
264 /*-----------------------------------------------------------------*/
265 /* avr_emitDebuggerSymbol - associate the current code location */
266 /* with a debugger symbol */
267 /*-----------------------------------------------------------------*/
269 avr_emitDebuggerSymbol (char * debugSym)
272 emitcode ("", "%s ==.", debugSym);
276 /*-----------------------------------------------------------------*/
277 /* hasInc - operand is incremented before any other use */
278 /*-----------------------------------------------------------------*/
280 hasInc (operand *op, iCode *ic)
282 sym_link *type = operandType(op);
283 sym_link *retype = getSpec (type);
284 iCode *lic = ic->next;
287 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
288 if (IS_AGGREGATE(type->next)) return NULL;
289 isize = getSize(type->next);
291 /* if operand of the form op = op + <sizeof *op> */
292 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
293 isOperandEqual(IC_RESULT(lic),op) &&
294 isOperandLiteral(IC_RIGHT(lic)) &&
295 operandLitValue(IC_RIGHT(lic)) == isize) {
298 /* if the operand used or deffed */
299 if (bitVectBitValue(OP_USES(op),lic->key) || (lic->defKey == op->key)) {
307 /*-----------------------------------------------------------------*/
308 /* getFreePtr - returns X or Z whichever is free or can be pushed */
309 /*-----------------------------------------------------------------*/
311 getFreePtr (iCode * ic, asmop ** aopp, bool result, bool zonly)
313 bool xiu = FALSE, ziu = FALSE;
314 bool xou = FALSE, zou = FALSE;
316 /* the logic: if x & z used in the instruction
317 then we are in trouble otherwise */
319 /* first check if x & z are used by this
320 instruction, in which case we are in trouble */
321 if ((xiu = bitVectBitValue (ic->rUsed, X_IDX)) &&
322 (ziu = bitVectBitValue (ic->rUsed, Z_IDX))) {
326 xou = bitVectBitValue (ic->rMask, X_IDX);
327 zou = bitVectBitValue (ic->rMask, Z_IDX);
329 /* if no usage of Z then return it */
331 ic->rUsed = bitVectSetBit (ic->rUsed, Z_IDX);
332 (*aopp)->type = AOP_Z;
334 (*aopp)->aop_ptr2 = avr_regWithIdx (R31_IDX);
335 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R30_IDX);
338 /* if no usage of X then return it */
339 if (!xiu && !xou && !zonly) {
340 ic->rUsed = bitVectSetBit (ic->rUsed, X_IDX);
341 (*aopp)->type = AOP_X;
343 (*aopp)->aop_ptr2 = avr_regWithIdx (R27_IDX);
344 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R26_IDX);
347 /* if z not used then */
350 /* push it if not already pushed */
352 emitcode ("push", "%s",
353 avr_regWithIdx (R30_IDX)->dname);
354 emitcode ("push", "%s",
355 avr_regWithIdx (R31_IDX)->dname);
359 ic->rUsed = bitVectSetBit (ic->rUsed, Z_IDX);
360 (*aopp)->type = AOP_Z;
361 (*aopp)->aop_ptr2 = avr_regWithIdx (R31_IDX);
362 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R30_IDX);
365 /* now we know they both have usage */
366 /* if x not used in this instruction */
367 if (!xiu && !zonly) {
368 /* push it if not already pushed */
370 emitcode ("push", "%s",
371 avr_regWithIdx (R26_IDX)->dname);
372 emitcode ("push", "%s",
373 avr_regWithIdx (R27_IDX)->dname);
377 ic->rUsed = bitVectSetBit (ic->rUsed, X_IDX);
378 (*aopp)->type = AOP_X;
380 (*aopp)->aop_ptr2 = avr_regWithIdx (R27_IDX);
381 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R26_IDX);
386 /* I said end of world but not quite end of world yet */
387 /* if this is a result then we can push it on the stack */
389 (*aopp)->type = AOP_STK;
393 /* other wise this is true end of the world */
394 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
395 "getFreePtr should never reach here");
399 /*-----------------------------------------------------------------*/
400 /* newAsmop - creates a new asmOp */
401 /*-----------------------------------------------------------------*/
403 newAsmop (short type)
407 aop = Safe_calloc (1, sizeof (asmop));
412 /*-----------------------------------------------------------------*/
413 /* pointerCode - returns the code for a pointer type */
414 /*-----------------------------------------------------------------*/
416 pointerCode (sym_link * etype)
419 return PTR_TYPE (SPEC_OCLS (etype));
423 /*-----------------------------------------------------------------*/
424 /* aopForSym - for a true symbol */
425 /*-----------------------------------------------------------------*/
427 aopForSym (iCode * ic, symbol * sym, bool result)
430 memmap *space = SPEC_OCLS (sym->etype);
432 /* if already has one */
436 /* assign depending on the storage class */
437 /* if it is on the stack */
439 sym->aop = aop = newAsmop (0);
440 aop->size = getSize (sym->type);
442 /* we can use std / ldd instruction */
444 && (sym->stack + getSize (sym->type) - 1) <= 63) {
445 aop->type = AOP_STK_D;
446 aop->aopu.aop_stk = sym->stack;
450 /* otherwise get a free pointer register X/Z */
451 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result, FALSE);
453 /* now assign the address of the variable to
454 the pointer register */
455 if (aop->type != AOP_STK) {
456 emitcode ("movw", "%s,r28", aop->aopu.aop_ptr->name);
457 if (sym->stack < 0) {
458 if ((sym->stack - _G.nRegsSaved) > -63) {
459 emitcode ("sbiw", "%s,0x%02x",
460 aop->aopu.aop_ptr->name,
465 emitcode ("subi", "%s,<(%d)",
466 aop->aopu.aop_ptr->name,
467 sym->stack - _G.nRegsSaved);
468 emitcode ("sbci", "%s,>(%d)",
470 sym->stack - _G.nRegsSaved);
474 if (sym->stack <= 63) {
475 emitcode ("adiw", "%s,0x%02x",
476 aop->aopu.aop_ptr->name,
480 emitcode ("subi", "%s,<(-%d)",
481 aop->aopu.aop_ptr->name,
483 emitcode ("sbci", "%s,>(-%d)",
492 /* if in bit space */
493 if (IN_BITSPACE (space)) {
494 sym->aop = aop = newAsmop (AOP_CRY);
495 aop->aopu.aop_dir = sym->rname;
496 aop->size = getSize (sym->type);
499 /* if it is in direct space */
500 if (IN_DIRSPACE (space)) {
501 sym->aop = aop = newAsmop (AOP_DIR);
502 aop->aopu.aop_dir = sym->rname;
503 aop->size = getSize (sym->type);
507 /* special case for a function */
508 if (IS_FUNC (sym->type)) {
509 sym->aop = aop = newAsmop (AOP_IMMD);
510 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
511 strcpy (aop->aopu.aop_immd, sym->rname);
512 aop->size = FPTRSIZE;
516 /* only remaining is code / eeprom which will need pointer reg */
517 /* if it is in code space */
519 sym->aop = aop = newAsmop (0);
521 if (IN_CODESPACE (space))
524 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result, aop->code);
525 aop->size = getSize (sym->type);
526 emitcode ("ldi", "%s,<(%s)", aop->aopu.aop_ptr->name, sym->rname);
527 emitcode ("ldi", "%s,>(%s)", aop->aop_ptr2);
532 /*-----------------------------------------------------------------*/
533 /* aopForRemat - rematerialzes an object */
534 /*-----------------------------------------------------------------*/
536 aopForRemat (symbol * sym)
538 iCode *ic = sym->rematiCode;
539 asmop *aop = newAsmop (AOP_IMMD);
544 val += (int) operandLitValue (IC_RIGHT (ic));
545 else if (ic->op == '-')
546 val -= (int) operandLitValue (IC_RIGHT (ic));
550 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
554 sprintf (buffer, "(%s %c 0x%04x)",
555 OP_SYMBOL (IC_LEFT (ic))->rname,
556 val >= 0 ? '+' : '-', abs (val) & 0xffff);
558 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
560 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
561 strcpy (aop->aopu.aop_immd, buffer);
565 /*-----------------------------------------------------------------*/
566 /* regsInCommon - two operands have some registers in common */
567 /*-----------------------------------------------------------------*/
569 regsInCommon (operand * op1, operand * op2)
574 /* if they have registers in common */
575 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
578 sym1 = OP_SYMBOL (op1);
579 sym2 = OP_SYMBOL (op2);
581 if (sym1->nRegs == 0 || sym2->nRegs == 0)
584 for (i = 0; i < sym1->nRegs; i++) {
589 for (j = 0; j < sym2->nRegs; j++) {
593 if (sym2->regs[j] == sym1->regs[i])
601 /*-----------------------------------------------------------------*/
602 /* operandsEqu - equivalent */
603 /*-----------------------------------------------------------------*/
605 operandsEqu (operand * op1, operand * op2)
609 /* if they not symbols */
610 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
613 sym1 = OP_SYMBOL (op1);
614 sym2 = OP_SYMBOL (op2);
616 /* if both are itemps & one is spilt
617 and the other is not then false */
618 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
619 sym1->isspilt != sym2->isspilt) return FALSE;
621 /* if they are the same */
625 if (strcmp (sym1->rname, sym2->rname) == 0)
629 /* if left is a tmp & right is not */
630 if (IS_ITEMP (op1) &&
631 !IS_ITEMP (op2) && sym1->isspilt && (sym1->usl.spillLoc == sym2))
634 if (IS_ITEMP (op2) &&
636 sym2->isspilt && sym1->level > 0 && (sym2->usl.spillLoc == sym1))
642 /*-----------------------------------------------------------------*/
643 /* sameRegs - two asmops have the same registers */
644 /*-----------------------------------------------------------------*/
646 sameRegs (asmop * aop1, asmop * aop2)
653 if (aop1->type != AOP_REG || aop2->type != AOP_REG)
656 if (aop1->size != aop2->size)
659 for (i = 0; i < aop1->size; i++)
660 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
666 /*-----------------------------------------------------------------*/
667 /* isRegPair - for size 2 if this operand has a register pair */
668 /*-----------------------------------------------------------------*/
670 isRegPair (asmop * aop)
672 if (!aop || aop->size < 2)
674 if (aop->type == AOP_X || aop->type == AOP_Z)
676 if (aop->type != AOP_REG)
678 if ( ((aop->aopu.aop_reg[1]->rIdx - aop->aopu.aop_reg[0]->rIdx) == 1) &&
679 (aop->aopu.aop_reg[0]->rIdx & 1) == 0)
685 /*-----------------------------------------------------------------*/
686 /* allHigh - all registers are high registers */
687 /*-----------------------------------------------------------------*/
688 static int allHigh (asmop * aop)
692 if (aop->type == AOP_X || aop->type == AOP_Z)
694 if (aop->type != AOP_REG)
696 for (i=0; i < aop->size ; i++ )
697 if (aop->aopu.aop_reg[i]->rIdx < R16_IDX) return 0;
701 /*-----------------------------------------------------------------*/
702 /* aopOp - allocates an asmop for an operand : */
703 /*-----------------------------------------------------------------*/
705 aopOp (operand * op, iCode * ic, bool result)
714 /* if this a literal */
715 if (IS_OP_LITERAL (op)) {
716 op->aop = aop = newAsmop (AOP_LIT);
717 aop->aopu.aop_lit = op->operand.valOperand;
718 aop->size = getSize (operandType (op));
722 /* if already has a asmop then continue */
726 /* if the underlying symbol has a aop */
727 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop) {
728 op->aop = OP_SYMBOL (op)->aop;
732 /* if this is a true symbol */
733 if (IS_TRUE_SYMOP (op)) {
734 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
738 /* this is a temporary : this has
744 e) can be a return use only */
746 sym = OP_SYMBOL (op);
749 /* if the type is a conditional */
750 if (sym->regType & REG_CND) {
751 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
756 /* if it is spilt then two situations
758 b) has a spill location */
759 if (sym->isspilt || sym->nRegs == 0) {
761 asmop *oldAsmOp = NULL;
763 /* rematerialize it NOW */
765 sym->aop = op->aop = aop = aopForRemat (sym);
766 aop->size = getSize (sym->type);
771 assert ("ACC_USE cannot happen in AVR\n");
776 aop = op->aop = sym->aop = newAsmop (AOP_STR);
777 aop->size = getSize (sym->type);
778 for (i = 0; i < (int) fAVRReturnSize; i++)
779 aop->aopu.aop_str[i] = fAVRReturn[i];
783 /* else spill location */
784 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
785 /* force a new aop if sizes differ */
786 oldAsmOp = sym->usl.spillLoc->aop;
787 sym->usl.spillLoc->aop = NULL;
789 sym->aop = op->aop = aop =
790 aopForSym (ic, sym->usl.spillLoc, result);
791 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
792 /* Don't reuse the new aop, go with the last one */
793 sym->usl.spillLoc->aop = oldAsmOp;
795 aop->size = getSize (sym->type);
799 /* must be in a register */
800 sym->aop = op->aop = aop = newAsmop (AOP_REG);
801 aop->size = sym->nRegs;
802 for (i = 0; i < sym->nRegs; i++)
803 aop->aopu.aop_reg[i] = sym->regs[i];
806 /*-----------------------------------------------------------------*/
807 /* freeAsmop - free up the asmop given to an operand */
808 /*----------------------------------------------------------------*/
810 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
827 /* depending on the asmop type only three cases need work AOP_RO
828 , AOP_R1 && AOP_STK */
833 emitcode ("pop", "r26");
834 emitcode ("pop", "r27");
838 bitVectUnSetBit (ic->rUsed, X_IDX);
844 emitcode ("pop", "r30");
845 emitcode ("pop", "r31");
849 bitVectUnSetBit (ic->rUsed, Z_IDX);
855 int stk = aop->aopu.aop_stk + aop->size;
856 bitVectUnSetBit (ic->rUsed, X_IDX);
857 bitVectUnSetBit (ic->rUsed, Z_IDX);
859 getFreePtr (ic, &aop, FALSE, 0);
861 emitcode ("movw", "%s,r28");
863 if (stk <= 63 && stk > 0) {
864 emitcode ("adiw", "%s,0x%02x",
865 aop->aopu.aop_ptr->name,
869 emitcode ("subi", "%s,<(%d)",
870 aop->aopu.aop_ptr->name,
872 emitcode ("sbci", "%s,>(%d)",
879 emitcode ("pop", "r24");
880 emitcode ("st", "-%s,r24",
881 aop->type == AOP_X ? "X" : "Z");
886 freeAsmop (op, NULL, ic, TRUE);
888 emitcode ("pop", "r26");
889 emitcode ("pop", "r27");
894 emitcode ("pop", "r30");
895 emitcode ("pop", "r31");
902 /* all other cases just dealloc */
906 OP_SYMBOL (op)->aop = NULL;
907 /* if the symbol has a spill */
909 SPIL_LOC (op)->aop = NULL;
914 /*-----------------------------------------------------------------*/
915 /* aopGet - for fetching value of the aop */
916 /*-----------------------------------------------------------------*/
918 aopGet (asmop * aop, int offset)
923 /* offset is greater than
925 if (offset > (aop->size - 1) && aop->type != AOP_LIT)
928 /* depending on type */
932 if (offset > aop->coff) {
933 emitcode ("adiw", "%s,%d", aop->aopu.aop_ptr->name,
937 if (offset < aop->coff) {
938 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name,
943 emitcode ("ld", "%s,x",
944 (rs = ((offset & 1) ? "r25" : "r24")));
949 if (offset > aop->coff) {
950 emitcode ("adiw", "r30,%d",
954 emitcode ("sbiw", "r30,%d",
957 emitcode ("lpm", "%s,z",
958 (rs = ((offset & 1) ? "r25" : "r24")));
962 if (offset > aop->coff) {
963 emitcode ("ldd", "%s,z+%d",
965 ((offset & 1) ? "r25" : "r24")),
969 emitcode ("sbiw", "%s,%d",
970 aop->aopu.aop_ptr->name,
973 emitcode ("ld", "%s,z",
975 ((offset & 1) ? "r25" : "r24")));
982 emitcode ("lds", "%s,(%s)+%d",
983 (rs = ((offset & 1) ? "r25" : "r24")),
984 aop->aopu.aop_immd, offset);
988 emitcode ("lds", "%s,(%s)+%d",
989 (rs = ((offset & 1) ? "r25" : "r24")),
990 aop->aopu.aop_dir, offset);
994 return aop->aopu.aop_reg[offset]->name;
997 assert ("cannot be in bit space AOP_CRY\n");
1001 s = aopLiteral (aop->aopu.aop_lit, offset);
1002 emitcode ("ldi", "%s,<(%s)",
1003 (rs = ((offset & 1) ? "r24" : "r25")), s);
1008 return aop->aopu.aop_str[offset];
1011 emitcode ("ldd", "%s,Y+%d",
1012 (rs = ((offset & 1) ? "r25" : "r24")),
1013 aop->aopu.aop_stk + offset);
1017 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1018 "aopget got unsupported aop->type");
1022 /*-----------------------------------------------------------------*/
1023 /* aopPut - puts a string for a aop */
1024 /*-----------------------------------------------------------------*/
1026 aopPut (asmop * aop, char *s, int offset)
1030 if (aop->size && offset > (aop->size - 1)) {
1031 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1032 "aopPut got offset > aop->size");
1036 /* will assign value to value */
1037 /* depending on where it is ofcourse */
1038 switch (aop->type) {
1041 sprintf (d, "(%s)+%d", aop->aopu.aop_dir, offset);
1044 sprintf (d, "%s", aop->aopu.aop_dir);
1047 emitcode ("sts", "%s,%s", d, s);
1051 if (toupper ((unsigned char)*s) != 'R') {
1053 emitcode ("clr", "%s",
1054 aop->aopu.aop_reg[offset]->name);
1057 emitcode ("ldi", "r25,%s", s);
1058 emitcode ("mov", "%s,r35",
1059 aop->aopu.aop_reg[offset]->name);
1063 if (strcmp (aop->aopu.aop_reg[offset]->name, s)) {
1064 emitcode ("mov", "%s,%s",
1065 aop->aopu.aop_reg[offset]->name, s);
1071 if (offset > aop->coff) {
1072 emitcode ("adiw", "%s,%d", aop->aopu.aop_ptr->name,
1073 offset - aop->coff);
1076 if (offset < aop->coff) {
1077 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name,
1078 aop->coff - offset);
1082 emitcode ("st", "x,%s", s);
1087 if (offset > aop->coff) {
1088 emitcode ("adiw", "r30,%d",
1089 offset - aop->coff);
1092 emitcode ("sbiw", "r30,%d",
1093 aop->coff - offset);
1095 emitcode ("lpm", "%s,z", s);
1098 /* we can use lds */
1099 if (offset > aop->coff) {
1100 emitcode ("sdd", "z+%d,%s",
1101 offset - aop->coff, s);
1104 emitcode ("sbiw", "%s,%d",
1105 aop->aopu.aop_ptr->name,
1106 aop->coff - offset);
1108 emitcode ("ld", "%s,z", s);
1114 emitcode ("push", "%s", s);
1118 /* if used only for a condition code check */
1119 assert (toupper ((unsigned char)*s) == 'R');
1121 emitcode ("xrl", "r0,r0");
1122 emitcode ("cpi", "%s,0", s);
1125 emitcode ("cpc", "r0,%s", s);
1131 if (strcmp (aop->aopu.aop_str[offset], s))
1132 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset],
1137 emitcode ("std", "y+%d,%s", offset, s);
1141 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1142 "aopPut got unsupported aop->type");
1148 #define AOP(op) op->aop
1149 #define AOP_TYPE(op) AOP(op)->type
1150 #define AOP_SIZE(op) AOP(op)->size
1151 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_X || \
1152 AOP_TYPE(x) == AOP_Z))
1153 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1154 ((x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R27_IDX)) || \
1155 (x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R31_IDX)) )))
1156 #define AOP_ISX(x) (x && (x->type == AOP_REG && \
1157 ((x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R27_IDX)))))
1158 #define AOP_ISZ(x) (x && (x->type == AOP_REG && \
1159 ((x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R31_IDX)))))
1161 /*-----------------------------------------------------------------*/
1162 /* genNotFloat - generates not for float operations */
1163 /*-----------------------------------------------------------------*/
1165 genNotFloat (operand * op, operand * res)
1171 /* we will put 127 in the first byte of
1173 aopPut (AOP (res), "127", 0);
1174 size = AOP_SIZE (op) - 1;
1177 l = aopGet (op->aop, offset++);
1181 emitcode ("or", "R0,%s", aopGet (op->aop, offset++));
1183 tlbl = newiTempLabel (NULL);
1185 tlbl = newiTempLabel (NULL);
1186 aopPut (res->aop, zero, 1);
1187 emitcode ("cpi", "r0,0");
1188 emitcode ("breq", "L%05d", tlbl->key);
1189 aopPut (res->aop, one, 1);
1190 emitcode ("", "L%05d:", tlbl->key);
1192 size = res->aop->size - 2;
1194 /* put zeros in the rest */
1196 aopPut (res->aop, zero, offset++);
1199 /*-----------------------------------------------------------------*/
1200 /* opIsGptr: returns non-zero if the passed operand is */
1201 /* a generic pointer type. */
1202 /*-----------------------------------------------------------------*/
1204 opIsGptr (operand * op)
1206 sym_link *type = operandType (op);
1208 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type)) {
1214 /*-----------------------------------------------------------------*/
1215 /* getDataSize - get the operand data size */
1216 /*-----------------------------------------------------------------*/
1218 getDataSize (operand * op)
1221 size = AOP_SIZE (op);
1222 if (size == GPTRSIZE) {
1223 sym_link *type = operandType (op);
1224 if (IS_GENPTR (type)) {
1225 /* generic pointer; arithmetic operations
1226 * should ignore the high byte (pointer type).
1234 /*-----------------------------------------------------------------*/
1235 /* toBoolean - emit code for orl a,operator(sizeop) */
1236 /*-----------------------------------------------------------------*/
1238 toBoolean (operand * oper, char *r, bool clr)
1240 int size = AOP_SIZE (oper);
1243 emitcode ("clr", "%s", r);
1245 emitcode ("or", "%s,%s", r, aopGet (AOP (oper), offset++));
1248 emitcode("mov","%s,%s",r,aopGet (AOP (oper), offset++));
1249 if (size) while (size--) emitcode ("or", "%s,%s", r, aopGet (AOP (oper), offset++));
1254 /*-----------------------------------------------------------------*/
1255 /* genNot - generate code for ! operation */
1256 /*-----------------------------------------------------------------*/
1261 sym_link *optype = operandType (IC_LEFT (ic));
1262 int size, offset = 1;
1264 /* assign asmOps to operand & result */
1265 aopOp (IC_LEFT (ic), ic, FALSE);
1266 aopOp (IC_RESULT (ic), ic, TRUE);
1268 /* if type float then do float */
1269 if (IS_FLOAT (optype)) {
1270 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1273 emitcode ("clr", "r24");
1274 tlbl = newiTempLabel (NULL);
1275 size = AOP_SIZE (IC_LEFT (ic));
1278 emitcode ("cpse", "%s,r24", aopGet (AOP (IC_LEFT (ic)), 0));
1283 emitcode ("cpc", "%s,r24",
1284 aopGet (AOP (IC_LEFT (ic)),
1287 emitcode ("cpi", "%s,0",
1288 aopGet (AOP (IC_LEFT (ic)),
1292 emitcode ("bne", "L%05d", tlbl->key);
1294 emitcode ("ldi", "r24,1");
1295 emitcode ("", "L%05d:", tlbl->key);
1296 aopPut (AOP (IC_RESULT (ic)), "r24", 0);
1297 size = AOP_SIZE (IC_RESULT (ic)) - 1;
1300 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
1304 /* release the aops */
1305 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1306 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1310 /*-----------------------------------------------------------------*/
1311 /* genCpl - generate code for complement */
1312 /*-----------------------------------------------------------------*/
1320 /* assign asmOps to operand & result */
1321 aopOp (IC_LEFT (ic), ic, FALSE);
1322 aopOp (IC_RESULT (ic), ic, TRUE);
1323 samer = sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)));
1324 size = AOP_SIZE (IC_RESULT (ic));
1326 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
1328 emitcode ("com", "%s", l);
1331 aopPut (AOP (IC_RESULT (ic)), l, offset);
1332 emitcode ("com", "%s",
1333 aopGet (AOP (IC_RESULT (ic)), offset));
1338 /* release the aops */
1339 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1340 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1343 /*-----------------------------------------------------------------*/
1344 /* genUminusFloat - unary minus for floating points */
1345 /*-----------------------------------------------------------------*/
1347 genUminusFloat (operand * op, operand * result)
1349 int size, offset = 0;
1351 /* for this we just need to flip the
1352 first it then copy the rest in place */
1353 size = AOP_SIZE (op) - 1;
1354 l = aopGet (AOP (op), 3);
1356 emitcode ("ldi", "r24,0x80");
1357 if (sameRegs (AOP (op), AOP (result))) {
1358 emitcode ("eor", "%s,r24", l);
1361 aopPut (AOP (result), l, 3);
1362 emitcode ("eor", "%s,r24", aopGet (AOP (result), 3));
1365 aopPut (AOP (result), aopGet (AOP (op), offset), offset);
1370 /*-----------------------------------------------------------------*/
1371 /* genUminus - unary minus code generation */
1372 /*-----------------------------------------------------------------*/
1374 genUminus (iCode * ic)
1377 sym_link *optype, *rtype;
1381 aopOp (IC_LEFT (ic), ic, FALSE);
1382 aopOp (IC_RESULT (ic), ic, TRUE);
1384 optype = operandType (IC_LEFT (ic));
1385 rtype = operandType (IC_RESULT (ic));
1387 /* if float then do float stuff */
1388 if (IS_FLOAT (optype)) {
1389 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1393 /* otherwise subtract from zero */
1394 size = AOP_SIZE (IC_LEFT (ic));
1396 samer = sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)));
1399 emitcode ("neg", "%s",
1400 aopGet (AOP (IC_LEFT (ic)), 0));
1403 aopPut (AOP (IC_RESULT (ic)),
1404 aopGet (AOP (IC_LEFT (ic)), 0), 0);
1405 emitcode ("neg", "%s",
1406 aopGet (AOP (IC_RESULT (ic)), 0));
1412 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
1414 aopPut (AOP (IC_RESULT (ic)), l, offset);
1415 l = aopGet (AOP (IC_RESULT (ic)), offset);
1418 emitcode ("com", "%s", l);
1420 emitcode ("neg", "%s", l);
1423 size = AOP_SIZE (IC_LEFT (ic)) - 1;
1426 emitcode ("sbci", "%s,0xff",
1427 aopGet (AOP (IC_RESULT (ic)), offset++));
1431 /* if any remaining bytes in the result */
1432 /* we just need to propagate the sign */
1433 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic))))) {
1434 symbol *tlbl = newiTempLabel (NULL);
1435 emitcode ("clr", "r0");
1436 emitcode ("brcc", "L%05d", tlbl->key);
1437 emitcode ("com", "r0");
1438 emitcode ("", "L%05d:", tlbl->key);
1440 aopPut (AOP (IC_RESULT (ic)), "r0", offset++);
1444 /* release the aops */
1445 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1446 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1449 /*-----------------------------------------------------------------*/
1450 /* assignResultValue - */
1451 /*-----------------------------------------------------------------*/
1453 assignResultValue (operand * oper)
1456 int size = AOP_SIZE (oper);
1458 aopPut (AOP (oper), fAVRReturn[offset], offset);
1463 /*-----------------------------------------------------------------*/
1464 /* saveZreg - if indirect call then save z-pointer register */
1465 /*-----------------------------------------------------------------*/
1467 saveZreg (iCode * ic)
1469 /* only if live accross this call */
1470 if (ic->regsSaved == 0 &&
1471 (bitVectBitValue (ic->rMask, R30_IDX) ||
1472 bitVectBitValue (ic->rMask, R31_IDX))) {
1474 emitcode ("push", "r30");
1475 emitcode ("push", "r31");
1479 /*-----------------------------------------------------------------*/
1480 /* popZreg - restore values of zreg */
1481 /*-----------------------------------------------------------------*/
1483 popZreg (iCode * ic)
1485 if (ic->regsSaved) {
1486 emitcode ("pop", "r31");
1487 emitcode ("pop", "r30");
1491 /*-----------------------------------------------------------------*/
1492 /* genIpush - genrate code for pushing this gets a little complex */
1493 /*-----------------------------------------------------------------*/
1495 genIpush (iCode * ic)
1497 int size, offset = 0;
1501 if (!ic->parmPush) {
1502 /* and the item is spilt then do nothing */
1503 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1508 for (lic = ic->next; lic; lic = lic->next)
1509 if (lic->op == PCALL)
1515 /* this is a paramter push */
1516 aopOp (IC_LEFT (ic), ic, FALSE);
1517 size = AOP_SIZE (IC_LEFT (ic));
1519 l = aopGet (AOP (IC_LEFT (ic)), offset++);
1520 emitcode ("push", "%s", l);
1523 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1526 /*-----------------------------------------------------------------*/
1527 /* genIpop - recover the registers: can happen only for spilling */
1528 /*-----------------------------------------------------------------*/
1530 genIpop (iCode * ic)
1535 /* if the temp was not pushed then */
1536 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1539 aopOp (IC_LEFT (ic), ic, FALSE);
1540 size = AOP_SIZE (IC_LEFT (ic));
1541 offset = (size - 1);
1543 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--));
1545 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1548 /*-----------------------------------------------------------------*/
1549 /* genCall - generates a call statement */
1550 /*-----------------------------------------------------------------*/
1552 genCall (iCode * ic)
1555 /* if send set is not empty then assign */
1559 for (sic = setFirstItem (_G.sendSet); sic;
1560 sic = setNextItem (_G.sendSet)) {
1561 int size, offset = 0;
1562 aopOp (IC_LEFT (sic), sic, FALSE);
1563 size = AOP_SIZE (IC_LEFT (sic));
1566 aopGet (AOP (IC_LEFT (sic)), offset);
1568 sprintf (buffer, "r%d", rnum++);
1570 emitcode ("mov", "%s,%s", b, l);
1573 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1578 emitcode ("call", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1579 OP_SYMBOL (IC_LEFT (ic))->rname :
1580 OP_SYMBOL (IC_LEFT (ic))->name));
1582 /* if we need assign a result value */
1583 if ((IS_ITEMP (IC_RESULT (ic)) &&
1584 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1585 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1586 IS_TRUE_SYMOP (IC_RESULT (ic))) {
1588 aopOp (IC_RESULT (ic), ic, FALSE);
1589 assignResultValue (IC_RESULT (ic));
1590 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1593 /* adjust the stack for parameters if required */
1594 if (ic->parmBytes) {
1595 if (ic->parmBytes > 63) {
1596 emitcode ("sbiw", "r28,%d", ic->parmBytes);
1599 emitcode ("subi", "r28,<(%d)",
1601 emitcode ("sbci", "r29,>(%d)",
1608 /*-----------------------------------------------------------------*/
1609 /* genPcall - generates a call by pointer statement */
1610 /*-----------------------------------------------------------------*/
1612 genPcall (iCode * ic)
1618 aopOp (IC_LEFT (ic), ic, FALSE);
1619 emitcode ("mov", "r30", aopGet (AOP (IC_LEFT (ic)), 0));
1620 emitcode ("mov", "r31", aopGet (AOP (IC_RIGHT (ic)), 0));
1621 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1623 /* if send set is not empty the assign */
1627 for (sic = setFirstItem (_G.sendSet); sic;
1628 sic = setNextItem (_G.sendSet)) {
1629 int size, offset = 0;
1630 aopOp (IC_LEFT (sic), sic, FALSE);
1631 size = AOP_SIZE (IC_LEFT (sic));
1634 aopGet (AOP (IC_LEFT (sic)), offset);
1636 sprintf (b, "r%d", rnum++);
1638 emitcode ("mov", "%s,%s", b, l);
1641 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1646 emitcode ("icall", "");
1648 /* if we need assign a result value */
1649 if ((IS_ITEMP (IC_RESULT (ic)) &&
1650 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1651 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1652 IS_TRUE_SYMOP (IC_RESULT (ic))) {
1654 aopOp (IC_RESULT (ic), ic, FALSE);
1656 assignResultValue (IC_RESULT (ic));
1657 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1660 /* adjust the stack for parameters if
1662 if (ic->parmBytes) {
1664 if (ic->parmBytes > 3) {
1665 emitcode ("mov", "a,%s", spname);
1666 emitcode ("add", "a,#0x%02x",
1667 (-ic->parmBytes) & 0xff);
1668 emitcode ("mov", "%s,a", spname);
1671 for (i = 0; i < ic->parmBytes; i++)
1672 emitcode ("dec", "%s", spname);
1676 /* adjust the stack for parameters if required */
1677 if (ic->parmBytes) {
1678 if (ic->parmBytes > 63) {
1679 emitcode ("sbiw", "r28,%d", ic->parmBytes);
1682 emitcode ("subi", "r28,<(%d)",
1684 emitcode ("sbci", "r29,>(%d)",
1692 /*-----------------------------------------------------------------*/
1693 /* resultRemat - result is rematerializable */
1694 /*-----------------------------------------------------------------*/
1696 resultRemat (iCode * ic)
1698 if (SKIP_IC (ic) || ic->op == IFX)
1701 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic))) {
1702 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
1703 if (sym->remat && !POINTER_SET (ic))
1710 /*-----------------------------------------------------------------*/
1711 /* genFunction - generated code for function entry */
1712 /*-----------------------------------------------------------------*/
1714 genFunction (iCode * ic)
1721 /* create the function header */
1722 emitcode (";", "-----------------------------------------");
1723 emitcode (";", " function %s",
1724 (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
1725 emitcode (";", "-----------------------------------------");
1727 emitcode ("", "%s:", sym->rname);
1728 ftype = operandType (IC_LEFT (ic));
1730 /* if critical function then turn interrupts off */
1731 if (IFFUNC_ISCRITICAL (ftype))
1732 emitcode ("cli", "");
1734 if (IFFUNC_ISISR (sym->type)) {
1737 /* save the preserved registers that are used in this function */
1738 for (i = R2_IDX; i <= R15_IDX; i++) {
1739 if (bitVectBitValue (sym->regsUsed, i)) {
1741 emitcode ("push", "%s", avr_regWithIdx (i)->name);
1744 /* now for the pointer registers */
1745 if (bitVectBitValue (sym->regsUsed, R26_IDX)) {
1747 emitcode ("push", "r26");
1749 if (bitVectBitValue (sym->regsUsed, R27_IDX)) {
1751 emitcode ("push", "r27");
1753 if (bitVectBitValue (sym->regsUsed, R30_IDX)) {
1755 emitcode ("push", "r30");
1757 if (bitVectBitValue (sym->regsUsed, R31_IDX)) {
1759 emitcode ("push", "r31");
1761 /* adjust the stack for the function */
1763 emitcode ("push", "r28");
1764 emitcode ("push", "r29");
1765 emitcode ("in", "r28,__SP_L__");
1766 emitcode ("in", "r29,__SP_H__");
1767 if (sym->stack <= 63) {
1768 emitcode ("sbiw", "r28,%d", sym->stack);
1771 emitcode ("subi", "r28,<(%d)", sym->stack);
1772 emitcode ("sbci", "r29,>(%d)", sym->stack);
1774 emitcode ("out", "__SP_L__,r28");
1775 emitcode ("out", "__SP_H__,r29");
1779 /*-----------------------------------------------------------------*/
1780 /* genEndFunction - generates epilogue for functions */
1781 /*-----------------------------------------------------------------*/
1783 genEndFunction (iCode * ic)
1785 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
1788 /* restore stack pointer */
1790 if (sym->stack <= 63) {
1791 emitcode ("adiw", "r28,%d", sym->stack);
1794 emitcode ("subi", "r28,<(-%d)", sym->stack);
1795 emitcode ("sbci", "r29,>(-%d)", sym->stack);
1797 emitcode ("out", "__SP_L__,r28");
1798 emitcode ("out", "__SP_H__,r29");
1800 /* pop frame pointer */
1801 emitcode ("pop", "r29");
1802 emitcode ("pop", "r28");
1804 /* restore preserved registers */
1805 if (bitVectBitValue (sym->regsUsed, R31_IDX)) {
1807 emitcode ("pop", "r31");
1809 if (bitVectBitValue (sym->regsUsed, R30_IDX)) {
1811 emitcode ("pop", "r30");
1813 if (bitVectBitValue (sym->regsUsed, R27_IDX)) {
1815 emitcode ("pop", "r27");
1817 if (bitVectBitValue (sym->regsUsed, R26_IDX)) {
1819 emitcode ("pop", "r26");
1821 for (i = R15_IDX; i >= R2_IDX; i--) {
1822 if (bitVectBitValue (sym->regsUsed, i)) {
1824 emitcode ("pop", "%s", avr_regWithIdx (i)->name);
1828 if (IFFUNC_ISCRITICAL (sym->type))
1829 emitcode ("sti", "");
1831 if (options.debug && currFunc) {
1832 debugFile->writeEndFunction (currFunc, ic, 1);
1835 if (IFFUNC_ISISR (sym->type)) {
1836 emitcode ("rti", "");
1839 emitcode ("ret", "");
1844 /*-----------------------------------------------------------------*/
1845 /* genRet - generate code for return statement */
1846 /*-----------------------------------------------------------------*/
1850 int size, offset = 0;
1852 /* if we have no return value then
1853 just generate the "ret" */
1857 /* we have something to return then
1858 move the return value into place */
1859 aopOp (IC_LEFT (ic), ic, FALSE);
1860 size = AOP_SIZE (IC_LEFT (ic));
1863 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) {
1864 emitcode ("ldi", "%s,%s(%d)", fAVRReturn[offset],
1866 (int) ulFromVal (AOP (IC_LEFT (ic))->
1867 aopu.aop_lit), offset);
1871 l = aopGet (AOP (IC_LEFT (ic)), offset);
1872 if (strcmp (fAVRReturn[offset], l))
1873 emitcode ("mov", "%s,%s", fAVRReturn[offset],
1879 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1882 /* generate a jump to the return label
1883 if the next is not the return statement */
1884 if (!(ic->next && ic->next->op == LABEL &&
1885 IC_LABEL (ic->next) == returnLabel))
1887 emitcode ("rjmp", "L%05d", returnLabel->key);
1891 /*-----------------------------------------------------------------*/
1892 /* genLabel - generates a label */
1893 /*-----------------------------------------------------------------*/
1895 genLabel (iCode * ic)
1897 /* special case never generate */
1898 if (IC_LABEL (ic) == entryLabel)
1901 emitcode ("", "L%05d:", IC_LABEL (ic)->key);
1904 /*-----------------------------------------------------------------*/
1905 /* genGoto - generates a ljmp */
1906 /*-----------------------------------------------------------------*/
1908 genGoto (iCode * ic)
1910 emitcode ("rjmp", "L%05d", (IC_LABEL (ic)->key));
1913 /*-----------------------------------------------------------------*/
1914 /* genPlusIncr :- does addition with increment if possible */
1915 /*-----------------------------------------------------------------*/
1917 genPlusIncr (iCode * ic)
1919 unsigned int icount;
1922 /* will try to generate an increment */
1923 /* if the right side is not a literal
1925 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
1928 icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.
1931 /* if the sizes are greater than 2 or they are not the same regs
1933 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1936 /* so we know LEFT & RESULT in the same registers and add
1938 /* for short & char types */
1939 if (AOP_SIZE (IC_RESULT (ic)) < 2) {
1941 emitcode ("inc", "%s",
1942 aopGet (AOP (IC_LEFT (ic)), 0));
1945 if (AOP_ISHIGHREG( AOP (IC_LEFT (ic)),0)) {
1946 emitcode ("subi", "%s,<(%d)",
1947 aopGet (AOP (IC_LEFT (ic)), 0), 0-icount);
1952 for (offset = 0 ; offset < AOP_SIZE(IC_RESULT(ic)) ; offset++) {
1953 if (!(AOP_ISHIGHREG(AOP(IC_RESULT(ic)),offset))) return FALSE;
1956 if (AOP_SIZE (IC_RESULT (ic)) <= 3) {
1957 /* if register pair and starts with 26/30 then adiw */
1958 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0
1960 && (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX) ||
1961 IS_REGIDX (AOP (IC_RESULT (ic)), R24_IDX) ||
1962 IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX))) {
1963 emitcode ("adiw", "%s,%d",
1964 aopGet (AOP (IC_RESULT (ic)), 0), icount);
1969 emitcode ("subi", "%s,<(%d)",
1970 aopGet (AOP (IC_RESULT (ic)), 0), 0-icount);
1971 emitcode ("sbci", "%s,>(%d)",
1972 aopGet (AOP (IC_RESULT (ic)), 1), 0-icount);
1976 /* for 32 bit longs */
1977 emitcode ("subi", "%s,<(%d)", aopGet (AOP (IC_RESULT (ic)), 0),
1979 emitcode ("sbci", "%s,>(%d)", aopGet (AOP (IC_RESULT (ic)), 1),
1981 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2),
1983 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3),
1989 /* This is the pure and virtuous version of this code.
1990 * I'm pretty certain it's right, but not enough to toss the old
1994 adjustArithmeticResult (iCode * ic)
1996 if (opIsGptr (IC_RESULT (ic)) &&
1997 opIsGptr (IC_LEFT (ic)) &&
1998 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)))) {
1999 aopPut (AOP (IC_RESULT (ic)),
2000 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1),
2004 if (opIsGptr (IC_RESULT (ic)) &&
2005 opIsGptr (IC_RIGHT (ic)) &&
2006 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)))) {
2007 aopPut (AOP (IC_RESULT (ic)),
2008 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1),
2012 if (opIsGptr (IC_RESULT (ic)) &&
2013 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2014 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2015 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2016 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)))) {
2018 sprintf (buffer, "%d",
2019 pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2020 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2024 /*-----------------------------------------------------------------*/
2025 /* genPlus - generates code for addition */
2026 /*-----------------------------------------------------------------*/
2028 genPlus (iCode * ic)
2030 int size, offset = 0;
2034 /* special cases :- */
2036 aopOp (IC_LEFT (ic), ic, FALSE);
2037 aopOp (IC_RIGHT (ic), ic, FALSE);
2038 aopOp (IC_RESULT (ic), ic, TRUE);
2040 /* if I can do an increment instead
2041 of add then GOOD for ME */
2042 if (genPlusIncr (ic) == TRUE)
2045 size = getDataSize (IC_RESULT (ic));
2046 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2050 aopPut (AOP (IC_RESULT (ic)),
2051 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2053 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
2060 emitcode (l, "%s,%s",
2061 aopGet (AOP (IC_RESULT (ic)), offset),
2062 aopGet (AOP (IC_RIGHT (ic)), offset));
2065 if (AOP_ISHIGHREG( AOP( IC_RESULT(ic)),offset)) {
2071 emitcode (l, "%s,%s(-%d)",
2072 aopGet (AOP (IC_RESULT (ic)), offset),
2074 (int) ulFromVal (AOP (IC_RIGHT (ic))->
2082 emitcode (l, "%s,%s",
2083 aopGet (AOP (IC_RESULT (ic)), offset),
2084 aopGet (AOP (IC_RIGHT (ic)), offset));
2090 adjustArithmeticResult (ic);
2093 freeAsmop (IC_LEFT (ic), NULL, ic,
2094 (RESULTONSTACK (ic) ? FALSE : TRUE));
2095 freeAsmop (IC_RIGHT (ic), NULL, ic,
2096 (RESULTONSTACK (ic) ? FALSE : TRUE));
2097 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2100 /*-----------------------------------------------------------------*/
2101 /* genMinusDec :- does subtraction with deccrement if possible */
2102 /*-----------------------------------------------------------------*/
2104 genMinusDec (iCode * ic)
2106 unsigned int icount;
2109 /* will try to generate an increment */
2110 /* if the right side is not a literal
2112 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2116 (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.
2119 /* if the sizes are greater than 2 or they are not the same regs
2121 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2124 /* so we know LEFT & RESULT in the same registers and add
2126 /* for short & char types */
2127 if (AOP_SIZE (IC_RESULT (ic)) < 2) {
2129 emitcode ("dec", "%s",
2130 aopGet (AOP (IC_LEFT (ic)), 0));
2133 if (AOP_ISHIGHREG( AOP ( IC_LEFT(ic)),0)) {
2134 emitcode ("subi", "%s,<(%d)",
2135 aopGet (AOP (IC_LEFT (ic)), 0), icount);
2140 for (offset = 0 ; offset < AOP_SIZE(IC_RESULT(ic)) ; offset++) {
2141 if (!(AOP_ISHIGHREG(AOP(IC_RESULT(ic)),offset))) return FALSE;
2144 if (AOP_SIZE (IC_RESULT (ic)) <= 3) {
2145 /* if register pair and starts with 26/30 then adiw */
2146 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0
2148 && (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX) ||
2149 IS_REGIDX (AOP (IC_RESULT (ic)), R24_IDX) ||
2150 IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX))) {
2151 emitcode ("sbiw", "%s,%d",
2152 aopGet (AOP (IC_RESULT (ic)), 0), icount);
2157 emitcode ("subi", "%s,<(%d)",
2158 aopGet (AOP (IC_RESULT (ic)), 0), icount);
2159 emitcode ("sbci", "%s,>(%d)",
2160 aopGet (AOP (IC_RESULT (ic)), 1), icount);
2163 /* for 32 bit longs */
2164 emitcode ("subi", "%s,<(%d)", aopGet (AOP (IC_RESULT (ic)), 0),
2166 emitcode ("sbci", "%s,>(%d)", aopGet (AOP (IC_RESULT (ic)), 1),
2168 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2),
2170 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3),
2176 /*-----------------------------------------------------------------*/
2177 /* genMinus - generates code for subtraction */
2178 /*-----------------------------------------------------------------*/
2180 genMinus (iCode * ic)
2182 int size, offset = 0, samer;
2185 aopOp (IC_LEFT (ic), ic, FALSE);
2186 aopOp (IC_RIGHT (ic), ic, FALSE);
2187 aopOp (IC_RESULT (ic), ic, TRUE);
2189 /* if I can do an decrement instead
2190 of subtract then GOOD for ME */
2191 if (genMinusDec (ic) == TRUE)
2194 size = getDataSize (IC_RESULT (ic));
2195 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2198 aopPut (AOP (IC_RESULT (ic)),
2199 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2201 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
2208 emitcode (l, "%s,%s",
2209 aopGet (AOP (IC_RESULT (ic)), offset),
2210 aopGet (AOP (IC_RIGHT (ic)), offset));
2213 if (AOP_ISHIGHREG(AOP (IC_RESULT (ic)),offset)) {
2219 emitcode (l, "%s,%s(%d)",
2220 aopGet (AOP (IC_RESULT (ic)), offset),
2222 (int) ulFromVal (AOP (IC_RIGHT (ic))->
2230 emitcode (l, "%s,%s",
2231 aopGet (AOP (IC_RESULT (ic)), offset),
2232 aopGet (AOP (IC_RIGHT (ic)), offset));
2238 adjustArithmeticResult (ic);
2241 freeAsmop (IC_LEFT (ic), NULL, ic,
2242 (RESULTONSTACK (ic) ? FALSE : TRUE));
2243 freeAsmop (IC_RIGHT (ic), NULL, ic,
2244 (RESULTONSTACK (ic) ? FALSE : TRUE));
2245 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2248 /*-----------------------------------------------------------------*/
2249 /* genMultOneByte : 8 bit multiplication & division */
2250 /*-----------------------------------------------------------------*/
2252 genMultOneByte (operand * left, operand * right, operand * result)
2254 sym_link *opetype = operandType (result);
2258 /* (if two literals, the value is computed before) */
2259 /* if one literal, literal on the right */
2260 if (AOP_TYPE (left) == AOP_LIT) {
2266 size = AOP_SIZE (result);
2268 if (SPEC_USIGN (opetype)) {
2269 emitcode ("mul", "%s,%s", aopGet (AOP (left), 0),
2270 aopGet (AOP (right), 0));
2273 emitcode ("muls", "%s,%s", aopGet (AOP (left), 0),
2274 aopGet (AOP (right), 0));
2276 aopPut (AOP (result), "r0", 0);
2278 aopPut (AOP (result), "r1", 1);
2281 if (SPEC_USIGN (opetype)) {
2283 aopPut (AOP (result), zero, offset++);
2288 lbl = newiTempLabel (NULL);
2289 emitcode ("ldi", "r24,0");
2290 emitcode ("brcc", "L%05d", lbl->key);
2291 emitcode ("ldi", "r24,0xff)");
2292 emitcode ("", "L%05d:", lbl->key);
2294 aopPut (AOP (result), "r24",
2302 /*-----------------------------------------------------------------*/
2303 /* genMult - generates code for multiplication */
2304 /*-----------------------------------------------------------------*/
2306 genMult (iCode * ic)
2308 operand *left = IC_LEFT (ic);
2309 operand *right = IC_RIGHT (ic);
2310 operand *result = IC_RESULT (ic);
2312 /* assign the amsops */
2313 aopOp (left, ic, FALSE);
2314 aopOp (right, ic, FALSE);
2315 aopOp (result, ic, TRUE);
2317 /* if both are of size == 1 */
2318 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1) {
2319 genMultOneByte (left, right, result);
2323 /* should have been converted to function call */
2327 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2328 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2329 freeAsmop (result, NULL, ic, TRUE);
2332 /*-----------------------------------------------------------------*/
2333 /* genDiv - generates code for division */
2334 /*-----------------------------------------------------------------*/
2338 /* should have been converted to function call */
2342 /*-----------------------------------------------------------------*/
2343 /* genMod - generates code for division */
2344 /*-----------------------------------------------------------------*/
2348 /* should have been converted to function call */
2360 /*-----------------------------------------------------------------*/
2361 /* revavrcnd - reverse a conditional for avr */
2362 /*-----------------------------------------------------------------*/
2364 revavrcnd (int type)
2376 for (i = 0; i < (sizeof (rar) / sizeof (rar[0])); i++) {
2377 if (rar[i].type == type)
2378 return rar[i].rtype;
2379 if (rar[i].rtype == type)
2382 assert (0); /* cannot happen */
2383 return 0; /* makes the compiler happy */
2386 static char *br_name[4] = { "breq", "brne", "brlt", "brge" };
2387 static char *br_uname[4] = { "breq", "brne", "brlo", "brcc" };
2389 /*-----------------------------------------------------------------*/
2390 /* genBranch - generate the branch instruction */
2391 /*-----------------------------------------------------------------*/
2393 genBranch (iCode * ifx, int br_type, int sign)
2395 int tj = (IC_TRUE (ifx) ? 1 : 0);
2397 if (tj) { /* if true jump */
2398 char *nm = (sign ? br_name[br_type] : br_uname[br_type]);
2399 emitcode (nm, "L%05d", IC_TRUE (ifx)->key);
2401 else { /* if false jump */
2402 int rtype = revavrcnd (br_type);
2403 char *nm = (sign ? br_name[rtype] : br_uname[rtype]);
2404 emitcode (nm, "L%05d", IC_FALSE (ifx)->key);
2409 /*-----------------------------------------------------------------*/
2410 /* genCmp - compare & jump */
2411 /*-----------------------------------------------------------------*/
2413 genCmp (iCode * ic, iCode * ifx, int br_type)
2415 operand *left, *right, *result;
2416 sym_link *letype, *retype;
2418 int sign, size, offset = 0;
2420 left = IC_LEFT (ic);
2421 right = IC_RIGHT (ic);
2422 result = IC_RESULT (ic);
2424 letype = getSpec (operandType (left));
2425 retype = getSpec (operandType (right));
2426 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
2428 /* assign the amsops */
2429 aopOp (left, ic, FALSE);
2430 aopOp (right, ic, FALSE);
2431 aopOp (result, ic, TRUE);
2432 size = AOP_SIZE (left);
2436 if (AOP_TYPE (right) == AOP_LIT) {
2437 emitcode ("cpi", "%s,<(%d)",
2438 aopGet (AOP (left), 0),
2439 (int) ulFromVal (AOP (IC_RIGHT (ic))->
2441 genBranch (ifx, br_type, sign);
2443 else { /* right != literal */
2444 emitcode ("cp", "%s,%s",
2445 aopGet (AOP (left), 0),
2446 aopGet (AOP (right), 0));
2447 genBranch (ifx, br_type, sign);
2450 else { /* size != 1 */
2453 emitcode ("cp", "%s,%s",
2454 aopGet (AOP (left), 0),
2455 aopGet (AOP (right), 0));
2457 emitcode ("cpc", "%s,%s",
2458 aopGet (AOP (left), offset),
2459 aopGet (AOP (right),
2463 genBranch (ifx, br_type, sign);
2467 emitcode ("clr", "r0");
2470 emitcode ("cp", "%s,%s",
2471 aopGet (AOP (left), 0),
2472 aopGet (AOP (right), 0));
2474 emitcode ("cpc", "%s,%s",
2475 aopGet (AOP (left), offset),
2476 aopGet (AOP (right), offset));
2479 lbl = newiTempLabel (NULL);
2480 br_type = revavrcnd (br_type);
2482 emitcode (br_uname[br_type], "L%05d", lbl->key);
2484 emitcode (br_name[br_type], "L%05d", lbl->key);
2485 emitcode ("inc", "r0");
2486 emitcode ("", "L%05d:", lbl->key);
2487 aopPut (AOP (result), "r0", 0);
2488 size = AOP_SIZE (result) - 1;
2491 aopPut (AOP (result), zero, offset++);
2494 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2495 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2496 freeAsmop (result, NULL, ic, TRUE);
2499 /*-----------------------------------------------------------------*/
2500 /* genCmpGt :- greater than comparison */
2501 /*-----------------------------------------------------------------*/
2503 genCmpGt (iCode * ic, iCode * ifx)
2505 /* should have transformed by the parser */
2509 /*-----------------------------------------------------------------*/
2510 /* genCmpLt - less than comparisons */
2511 /*-----------------------------------------------------------------*/
2513 genCmpLt (iCode * ic, iCode * ifx)
2515 genCmp (ic, ifx, AVR_LT);
2518 /*-----------------------------------------------------------------*/
2519 /* genCmpEq - generates code for equal to */
2520 /*-----------------------------------------------------------------*/
2522 genCmpEq (iCode * ic, iCode * ifx)
2524 genCmp (ic, ifx, AVR_EQ);
2527 /*-----------------------------------------------------------------*/
2528 /* genCmpNe - generates code for not equal to */
2529 /*-----------------------------------------------------------------*/
2531 genCmpNe (iCode * ic, iCode * ifx)
2533 genCmp (ic, ifx, AVR_NE);
2536 /*-----------------------------------------------------------------*/
2537 /* genCmpGe - generates code for greater than equal to */
2538 /*-----------------------------------------------------------------*/
2540 genCmpGe (iCode * ic, iCode * ifx)
2542 genCmp (ic, ifx, AVR_GE);
2545 /*-----------------------------------------------------------------*/
2546 /* genCmpLe - generates code for less than equal to */
2547 /*-----------------------------------------------------------------*/
2549 genCmpLe (iCode * ic, iCode * ifx)
2551 operand *left = IC_LEFT (ic);
2552 operand *right = IC_RIGHT (ic);
2554 IC_RIGHT (ic) = left;
2555 IC_LEFT (ic) = right;
2556 genCmp (ic, ifx, AVR_GE);
2559 /*-----------------------------------------------------------------*/
2560 /* ifxForOp - returns the icode containing the ifx for operand */
2561 /*-----------------------------------------------------------------*/
2563 ifxForOp (operand * op, iCode * ic)
2565 /* if true symbol then needs to be assigned */
2566 if (IS_TRUE_SYMOP (op))
2569 /* if this has register type condition and
2570 the next instruction is ifx with the same operand
2571 and live to of the operand is upto the ifx only then */
2573 ic->next->op == IFX &&
2574 IC_COND (ic->next)->key == op->key &&
2575 OP_SYMBOL (op)->liveTo <= ic->next->seq) return ic->next;
2580 /*-----------------------------------------------------------------*/
2581 /* genAndOp - for && operation */
2582 /*-----------------------------------------------------------------*/
2584 genAndOp (iCode * ic)
2586 operand *left, *right, *result;
2590 /* note here that && operations that are in an
2591 if statement are taken away by backPatchLabels
2592 only those used in arthmetic operations remain */
2593 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2594 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2595 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
2597 tlbl = newiTempLabel (NULL);
2598 toBoolean (left, "r0", TRUE);
2599 toBoolean (right, "r1", TRUE);
2600 emitcode ("and", "r0,r1");
2601 emitcode ("ldi", "r24,1");
2602 emitcode ("breq", "L%05d", tlbl->key);
2603 emitcode ("dec", "r24");
2604 emitcode ("", "L%05d:", tlbl->key);
2605 aopPut (AOP (result), "r24", 0);
2606 size = AOP_SIZE (result) - 1;
2609 aopPut (AOP (result), zero, offset++);
2611 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2612 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2613 freeAsmop (result, NULL, ic, TRUE);
2617 /*-----------------------------------------------------------------*/
2618 /* genOrOp - for || operation */
2619 /*-----------------------------------------------------------------*/
2621 genOrOp (iCode * ic)
2623 operand *left, *right, *result;
2627 /* note here that || operations that are in an
2628 if statement are taken away by backPatchLabels
2629 only those used in arthmetic operations remain */
2630 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2631 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2632 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
2634 tlbl = newiTempLabel (NULL);
2635 toBoolean (left, "r0", TRUE);
2636 toBoolean (right, "r0", FALSE);
2637 emitcode ("ldi", "r24,1");
2638 emitcode ("breq", "L%05d", tlbl->key);
2639 emitcode ("dec", "r24");
2640 emitcode ("", "L%05d:", tlbl->key);
2641 aopPut (AOP (result), "r24", 0);
2642 size = AOP_SIZE (result) - 1;
2645 aopPut (AOP (result), zero, offset++);
2647 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2648 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2649 freeAsmop (result, NULL, ic, TRUE);
2653 AVR_AND = 0, AVR_OR, AVR_XOR
2655 static char *bopnames_lit[] = { "andi", "ori" };
2656 static char *bopnames[] = { "and", "or", "eor" };
2657 /*-----------------------------------------------------------------*/
2658 /* genBitWise - generate bitwise operations */
2659 /*-----------------------------------------------------------------*/
2661 genBitWise (iCode * ic, iCode * ifx, int bitop)
2663 operand *left, *right, *result;
2664 int size, offset = 0;
2669 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2670 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2671 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
2673 size = AOP_SIZE (left);
2675 if (ifx) { /* used only for jumps */
2676 if (AOP_TYPE (right) == AOP_LIT &&
2677 (bitop == AVR_AND || bitop == AVR_OR)) {
2679 (int) ulFromVal (AOP (right)->aopu.
2681 int p2 = powof2 (lit);
2682 if (bitop == AVR_AND && (p2 >= 0)) { /* right side is a power of 2 */
2683 l = aopGet (AOP (left), p2 / 8);
2684 if (IC_TRUE (ifx)) {
2685 emitcode ("sbrc", "%s,%d", l,
2687 emitcode ("rjmp", "L%05d",
2688 IC_TRUE (ifx)->key);
2691 emitcode ("sbrs", "%s,%d", l,
2693 emitcode ("rjmp", "L%05d",
2694 IC_FALSE (ifx)->key);
2697 else { /* right not power of two */
2698 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2700 if (eh && AOP_ISHIGHREG(AOP(IC_LEFT(ic)),0)) {
2701 emitcode (bopnames_lit[bitop],
2703 aopGet (AOP (IC_LEFT (ic)), 0), lit);
2706 MOVR24 (aopGet (AOP (IC_LEFT (ic)), 0));
2707 emitcode (bopnames_lit[bitop], "r24,<(%d)", lit);
2709 lbl = newiTempLabel (NULL);
2710 if (IC_TRUE (ifx)) {
2711 emitcode ("breq", "L%05d", lbl->key);
2712 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2715 emitcode ("brne", "L%05d", lbl->key);
2716 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)-> key);
2718 emitcode ("", "L%05d:", lbl->key);
2720 else if (size == 2) {
2721 emitcode ("mov", "r24,%s", aopGet (AOP (IC_LEFT (ic)), 0));
2722 emitcode ("mov", "r25,%s", aopGet (AOP (IC_LEFT (ic)), 1));
2723 emitcode (bopnames_lit[bitop], "r24,<(%d)", lit);
2724 emitcode (bopnames_lit[bitop], "r25,>(%d)", lit);
2725 emitcode ("sbiw", "r24,0");
2726 lbl = newiTempLabel (NULL);
2727 if (IC_TRUE (ifx)) {
2728 emitcode ("breq", "L%05d", lbl->key);
2729 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2732 emitcode ("brne", "L%05d", lbl->key);
2733 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2735 emitcode ("", "L%05d:", lbl->key);
2738 lbl = newiTempLabel (NULL);
2739 lbl1 = newiTempLabel (NULL);
2741 if (eh && AOP_ISHIGHREG(AOP(IC_LEFT(ic)),offset)) {
2742 emitcode (bopnames_lit [bitop], "%s,<(%d)",
2743 aopGet (AOP (IC_LEFT (ic)), offset),
2747 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
2749 emitcode ("andi", "r24,<(%d)", lit);
2751 emitcode ("brne", "L%05d", lbl->key);
2756 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)-> key);
2758 emitcode ("rjmp", "L%05d", lbl1->key);
2759 emitcode ("", "L%05d:", lbl->key);
2762 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2763 emitcode ("", "L%05d:", lbl1->key);
2768 else { /* right is not a literal */
2769 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2770 int reh = OP_SYMBOL (right)->liveTo <= ic->seq;
2773 emitcode (bopnames[bitop], "%s,%s", aopGet (AOP (IC_LEFT (ic)), 0),
2774 aopGet (AOP (IC_RIGHT (ic)), 0));
2777 emitcode (bopnames[bitop], "%s,%s",
2778 aopGet (AOP (IC_RIGHT (ic)), 0),
2779 aopGet (AOP (IC_LEFT (ic)), 0));
2782 MOVR0 (aopGet (AOP (IC_LEFT (ic)), 0));
2783 emitcode (bopnames[bitop], "r0,%s",
2784 aopGet (AOP (IC_RIGHT (ic)), 0));
2786 lbl = newiTempLabel (NULL);
2787 if (IC_TRUE (ifx)) {
2788 emitcode ("breq", "L%05d", lbl->key);
2789 emitcode ("rjmp", "L%05d",
2790 IC_TRUE (ifx)->key);
2793 emitcode ("brne", "L%05d", lbl->key);
2794 emitcode ("rjmp", "L%05d",
2795 IC_FALSE (ifx)->key);
2797 emitcode ("", "L%05d:", lbl->key);
2799 else if (size == 2) {
2800 emitcode ("mov", "r24,%s",
2801 aopGet (AOP (IC_LEFT (ic)), 0));
2802 emitcode ("mov", "r25,%s",
2803 aopGet (AOP (IC_LEFT (ic)), 1));
2804 emitcode (bopnames[bitop], "r24,%s",
2805 aopGet (AOP (IC_RIGHT (ic)), 0));
2806 emitcode (bopnames[bitop], "r25,%s",
2807 aopGet (AOP (IC_RIGHT (ic)), 1));
2808 emitcode ("sbiw", "r24,0");
2809 lbl = newiTempLabel (NULL);
2810 if (IC_TRUE (ifx)) {
2811 emitcode ("breq", "L%05d", lbl->key);
2812 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2815 emitcode ("brne", "L%05d", lbl->key);
2816 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2818 emitcode ("", "L%05d:", lbl->key);
2821 lbl = newiTempLabel (NULL);
2822 lbl1 = newiTempLabel (NULL);
2825 emitcode (bopnames[bitop], "%s,%s",
2826 aopGet (AOP (IC_LEFT (ic)), offset),
2827 aopGet (AOP (IC_RIGHT (ic)), offset));
2830 emitcode (bopnames[bitop], "%s,%s",
2831 aopGet (AOP (IC_RIGHT (ic)), offset),
2832 aopGet (AOP (IC_LEFT (ic)), offset));
2835 MOVR0 (aopGet (AOP (IC_LEFT (ic)), offset));
2836 emitcode (bopnames[bitop], "r0,%s",
2837 aopGet (AOP (IC_RIGHT (ic)), offset));
2839 emitcode ("brne", "L%05d", lbl->key);
2844 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2846 emitcode ("rjmp", "L%05d", lbl1->key);
2847 emitcode ("", "L%05d:", lbl->key);
2850 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2851 emitcode ("", "L%05d:", lbl1->key);
2858 /* result needs to go a register */
2859 samerl = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2860 samerr = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)));
2862 if (AOP_TYPE (right) == AOP_LIT) {
2864 (int) ulFromVal (AOP (right)->aopu.
2866 if (((lit >> (8 * offset)) & 0xff) == 0) {
2867 if (bitop == AVR_AND) {
2868 aopPut (AOP (result), zero, offset++);
2871 else if (bitop == AVR_OR) {
2873 aopPut (AOP (result),
2883 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT &&
2884 AOP_ISHIGHREG(AOP(IC_LEFT(ic)),offset) &&
2885 (bitop == AVR_AND || bitop == AVR_OR)) {
2886 emitcode (bopnames_lit[bitop], "%s,%s(%d)",
2887 aopGet (AOP (IC_LEFT (ic)), offset),
2889 (int) ulFromVal (AOP (right)-> aopu.aop_lit));
2892 emitcode (bopnames[bitop], "%s,%s",
2893 aopGet (AOP (IC_LEFT (ic)), offset),
2894 aopGet (AOP (IC_RIGHT (ic)), offset));
2898 emitcode (bopnames[bitop], "%s,%s",
2899 aopGet (AOP (IC_RIGHT (ic)), offset),
2900 aopGet (AOP (IC_LEFT (ic)), offset));
2903 aopPut (AOP (IC_RESULT (ic)),
2904 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2905 emitcode (bopnames[bitop],
2906 aopGet (AOP (IC_RESULT (ic)), offset),
2907 aopGet (AOP (IC_RIGHT (ic)), offset));
2912 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2913 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2914 freeAsmop (result, NULL, ic, TRUE);
2917 /*-----------------------------------------------------------------*/
2918 /* genAnd - code for and */
2919 /*-----------------------------------------------------------------*/
2921 genAnd (iCode * ic, iCode * ifx)
2923 genBitWise (ic, ifx, AVR_AND);
2926 /*-----------------------------------------------------------------*/
2927 /* genOr - code for or */
2928 /*-----------------------------------------------------------------*/
2930 genOr (iCode * ic, iCode * ifx)
2932 genBitWise (ic, ifx, AVR_OR);
2935 /*-----------------------------------------------------------------*/
2936 /* genXor - code for xclusive or */
2937 /*-----------------------------------------------------------------*/
2939 genXor (iCode * ic, iCode * ifx)
2941 genBitWise (ic, ifx, AVR_XOR);
2944 /*-----------------------------------------------------------------*/
2945 /* genInline - write the inline code out */
2946 /*-----------------------------------------------------------------*/
2948 genInline (iCode * ic)
2950 char *buffer, *bp, *bp1;
2951 bool inComment = FALSE;
2953 _G.inLine += (!options.asmpeep);
2955 buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
2957 /* emit each line as a code */
2975 /* Add \n for labels, not dirs such as c:\mydir */
2976 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
2994 _G.inLine -= (!options.asmpeep);
2997 /*-----------------------------------------------------------------*/
2998 /* genRotC - rotate right/left with carry , lr = 1 rotate right */
2999 /*-----------------------------------------------------------------*/
3001 genRotC (iCode * ic, int lr)
3003 operand *left, *result;
3004 int size, offset = 0;
3006 /* rotate right with carry */
3007 left = IC_LEFT (ic);
3008 result = IC_RESULT (ic);
3009 aopOp (left, ic, FALSE);
3010 aopOp (result, ic, FALSE);
3012 /* move it to the result */
3013 size = AOP_SIZE (result);
3014 if (!sameRegs (AOP (left), AOP (result))) {
3017 aopPut (AOP (result),
3018 aopGet (AOP (left), offset), offset);
3021 size = AOP_SIZE (result);
3029 emitcode ("sbrc", "%s,%d", aopGet (AOP (result), offset),
3031 emitcode ("sec", "");
3034 emitcode ((lr ? "ror" : "rol"), "%s",
3035 aopGet (AOP (result), offset));
3041 freeAsmop (left, NULL, ic, TRUE);
3042 freeAsmop (result, NULL, ic, TRUE);
3045 /*-----------------------------------------------------------------*/
3046 /* genRRC - rotate right with carry */
3047 /*-----------------------------------------------------------------*/
3054 /*-----------------------------------------------------------------*/
3055 /* genRLC - generate code for rotate left with carry */
3056 /*-----------------------------------------------------------------*/
3063 /*-----------------------------------------------------------------*/
3064 /* genGetHbit - generates code get highest order bit */
3065 /*-----------------------------------------------------------------*/
3067 genGetHbit (iCode * ic)
3069 operand *left, *result;
3072 left = IC_LEFT (ic);
3073 result = IC_RESULT (ic);
3074 aopOp (left, ic, FALSE);
3075 aopOp (result, ic, FALSE);
3077 size = AOP_SIZE (result);
3078 if (!sameRegs (AOP (left), AOP (result))) {
3079 emitcode ("clr", "%s", aopGet (AOP (result), size - 1));
3080 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3081 emitcode ("subi", "%s,<(-1)",
3082 aopGet (AOP (result), size - 1));
3085 emitcode ("clr", "r0");
3086 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3087 emitcode ("subi", "r0,<(-1)");
3088 aopPut (AOP (result), "r0", 0);
3093 emitcode ("clr", aopGet (AOP (result), offset++));
3095 freeAsmop (left, NULL, ic, TRUE);
3096 freeAsmop (result, NULL, ic, TRUE);
3099 /*-----------------------------------------------------------------*/
3100 /* genShiftLeftLit - shift left by a known amount */
3101 /*-----------------------------------------------------------------*/
3103 genShiftLeftLit (iCode * ic)
3105 operand *left, *right, *result;
3106 int size, shCount, offset = 0;
3109 right = IC_RIGHT (ic);
3110 left = IC_LEFT (ic);
3111 result = IC_RESULT (ic);
3113 aopOp (left, ic, FALSE);
3114 aopOp (result, ic, FALSE);
3115 size = AOP_SIZE (result);
3116 shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
3118 if (shCount > (size * 8 - 1)) {
3120 aopPut (AOP (result), zero, offset++);
3125 if (!sameRegs (AOP (left), AOP (result)))
3126 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3128 if (AOP_ISHIGHREG(AOP(result),0)) {
3129 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3130 emitcode ("andi", "%s,0xf0");
3132 emitcode ("ldi","r24,0xf0");
3133 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3134 emitcode ("and", "%s,r24");
3139 emitcode ("add", "%s,%s", aopGet (AOP (result), 0),
3140 aopGet (AOP (result), 0));
3144 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3147 if (shCount >= 12) {
3148 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3149 aopPut (AOP (result), zero, 0);
3150 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3151 if (AOP_ISHIGHREG(AOP(result),1)) {
3152 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3154 emitcode ("ldi","r24,0xf0");
3155 emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
3161 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3162 aopPut (AOP (result), zero, 0);
3168 if (!sameRegs (AOP (left), AOP (result))) {
3169 aopPut (AOP (result), aopGet (AOP (left), 0),
3171 aopPut (AOP (result), aopGet (AOP (left), 1),
3174 emitcode ("mov", "r24,%s", aopGet (AOP (result), 0));
3175 emitcode ("andi", "r24,0x0f");
3176 if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
3177 emitcode("ldi","r25,0xf0");
3179 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3180 if (AOP_ISHIGHREG(AOP(result),0)) {
3181 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 0));
3183 emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
3185 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3186 if (AOP_ISHIGHREG(AOP(result),1)) {
3187 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3189 emitcode ("and", "%s,r25", aopGet (AOP (result), 1));
3191 emitcode ("or", "%s,r24", aopGet (AOP (result), 1));
3193 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3194 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3197 if (!lByteZ && !sameRegs (AOP (result), AOP (left))
3201 aopPut (AOP (result),
3202 aopGet (AOP (left), offset), offset);
3208 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3211 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3212 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3217 assert ("shifting generic pointer ?\n");
3220 /* 32 bits we do only byte boundaries */
3221 if (shCount >= 24) {
3222 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3223 aopPut (AOP (result), zero, 2);
3224 aopPut (AOP (result), zero, 1);
3225 aopPut (AOP (result), zero, 0);
3229 if (shCount >= 16) {
3230 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3231 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3232 aopPut (AOP (result), zero, 1);
3233 aopPut (AOP (result), zero, 0);
3238 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3239 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3240 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3241 aopPut (AOP (result), zero, 0);
3245 if (!lByteZ && !sameRegs (AOP (left), AOP (right))) {
3248 aopPut (AOP (result),
3249 aopGet (AOP (left), offset), offset);
3253 size = AOP_SIZE (result);
3259 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3260 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3261 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3262 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3267 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3268 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3269 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3274 emitcode ("lsl", "%s", aopGet (AOP (result), 2));
3275 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3280 emitcode ("lsl", "%s", aopGet (AOP (result), 3));
3288 freeAsmop (left, NULL, ic, TRUE);
3289 freeAsmop (right, NULL, ic, TRUE);
3290 freeAsmop (result, NULL, ic, TRUE);
3293 /*-----------------------------------------------------------------*/
3294 /* genLeftShift - generates code for left shifting */
3295 /*-----------------------------------------------------------------*/
3297 genLeftShift (iCode * ic)
3299 operand *left, *right, *result;
3303 right = IC_RIGHT (ic);
3304 left = IC_LEFT (ic);
3305 result = IC_RESULT (ic);
3307 aopOp (right, ic, FALSE);
3309 if (AOP_TYPE (right) == AOP_LIT) {
3310 genShiftLeftLit (ic);
3315 aopOp (left, ic, FALSE);
3316 aopOp (result, ic, FALSE);
3317 size = AOP_SIZE (result);
3319 if (AOP_SIZE (right) > 1) {
3320 if (isRegPair (AOP (right))) {
3321 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3324 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3325 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3329 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3331 if (!sameRegs (AOP (left), AOP (result))) {
3333 aopPut (AOP (result), aopGet (AOP (left), offset),
3337 size = AOP_SIZE (result);
3339 tlbl = newiTempLabel (NULL);
3340 emitcode ("", "L%05d:", tlbl->key);
3344 emitcode ("rol", "%s", aopGet (AOP (result), offset));
3346 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3349 if (AOP_SIZE (right) > 1)
3350 emitcode ("sbiw", "r24,1");
3352 emitcode ("dec", "r24");
3353 emitcode ("brne", "L%05d", tlbl->key);
3355 freeAsmop (left, NULL, ic, TRUE);
3356 freeAsmop (right, NULL, ic, TRUE);
3357 freeAsmop (result, NULL, ic, TRUE);
3360 /*-----------------------------------------------------------------*/
3361 /* genShiftRightLit - generate for right shift with known count */
3362 /*-----------------------------------------------------------------*/
3364 genShiftRightLit (iCode * ic)
3366 operand *left = IC_LEFT (ic)
3367 , *right = IC_RIGHT (ic)
3368 , *result = IC_RESULT (ic);
3369 int size, shCount, offset = 0;
3371 sym_link *letype = getSpec (operandType (left));
3372 int sign = !SPEC_USIGN (letype);
3374 right = IC_RIGHT (ic);
3375 left = IC_LEFT (ic);
3376 result = IC_RESULT (ic);
3378 aopOp (left, ic, FALSE);
3379 aopOp (result, ic, FALSE);
3380 size = AOP_SIZE (result);
3381 shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
3383 /* if signed then give up and use a loop to shift */
3386 if (!sameRegs (AOP (left), AOP (result))) {
3388 aopPut (AOP (result),
3389 aopGet (AOP (left), offset), offset);
3392 size = AOP_SIZE (result);
3395 /* be as economical as possible */
3398 size = AOP_SIZE (result);
3401 /* highest order byte */
3402 if (offset == (AOP_SIZE(result)-1))
3403 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3405 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3411 emitcode ("ldi", "r24,<(%d)", shCount);
3412 tlbl = newiTempLabel (NULL);
3413 emitcode ("", "L%05d:", tlbl->key);
3416 if (offset == (AOP_SIZE(result) - 1))
3417 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3419 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3422 emitcode ("dec", "r24");
3423 emitcode ("brne", "L%05d", tlbl->key);
3427 if (shCount > (size * 8 - 1)) {
3429 aopPut (AOP (result), zero, offset++);
3432 /* for unsigned we can much more efficient */
3435 if (!sameRegs (AOP (left), AOP (result)))
3436 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3438 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3439 if (AOP_ISHIGHREG(AOP(result),0)) {
3440 emitcode ("andi", "%s,0x0f",aopGet(AOP(result),0));
3442 emitcode ("ldi","r24,0x0f");
3443 emitcode ("and", "%s,r24",aopGet(AOP(result),0));
3448 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3451 if (shCount >= 12) {
3452 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3453 aopPut (AOP (result), zero, 1);
3454 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3455 if (AOP_ISHIGHREG(AOP(result),0)) {
3456 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3458 emitcode ("ldi","r24,0x0f");
3459 emitcode ("and", "%s,r24",aopGet(AOP(result),0));
3465 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3466 aopPut (AOP (result), zero, 1);
3472 if (!sameRegs (AOP (left), AOP (result))) {
3473 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3474 aopPut (AOP (result), aopGet (AOP (left), 1), 1);
3476 if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
3477 emitcode("ldi","r25,0x0f");
3479 emitcode ("mov", "r24,%s", aopGet (AOP (result), 1));
3480 emitcode ("andi", "r24,0xf0");
3481 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3482 if (AOP_ISHIGHREG(AOP(result),0)) {
3483 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3485 emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
3487 emitcode ("or", "%s,r24", aopGet (AOP (result), 0));
3488 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3489 if (AOP_ISHIGHREG(AOP(result),1)) {
3490 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 1));
3492 emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
3495 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3496 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3500 if (!hByteZ && !sameRegs (AOP (result), AOP (left))
3504 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3510 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3513 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3514 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3520 assert ("shifting generic pointer ?\n");
3523 /* 32 bits we do only byte boundaries */
3524 if (shCount >= 24) {
3525 aopPut (AOP (result), aopGet (AOP (left), 3), 0);
3526 aopPut (AOP (result), zero, 1);
3527 aopPut (AOP (result), zero, 2);
3528 aopPut (AOP (result), zero, 3);
3532 if (shCount >= 16) {
3533 aopPut (AOP (result), aopGet (AOP (left), 3), 1);
3534 aopPut (AOP (result), aopGet (AOP (left), 2), 0);
3535 aopPut (AOP (result), zero, 2);
3536 aopPut (AOP (result), zero, 3);
3541 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3542 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3543 aopPut (AOP (result), aopGet (AOP (left), 3), 2);
3544 aopPut (AOP (result), zero, 3);
3548 if (!hByteZ && !sameRegs (AOP (left), AOP (right))) {
3551 aopPut (AOP (result),
3552 aopGet (AOP (left), offset), offset);
3556 size = AOP_SIZE (result);
3562 emitcode ("lsr", "%s", aopGet (AOP (result), 3));
3563 emitcode ("ror", "%s", aopGet (AOP (result), 2));
3564 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3565 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3570 emitcode ("lsr", "%s", aopGet (AOP (result), 2));
3571 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3572 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3577 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3578 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3583 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3590 freeAsmop (left, NULL, ic, TRUE);
3591 freeAsmop (right, NULL, ic, TRUE);
3592 freeAsmop (result, NULL, ic, TRUE);
3595 /*-----------------------------------------------------------------*/
3596 /* genRightShift - generate code for right shifting */
3597 /*-----------------------------------------------------------------*/
3599 genRightShift (iCode * ic)
3601 operand *right, *left, *result;
3604 int sign = 0, first = 1;
3607 aopOp (right = IC_RIGHT (ic), ic, FALSE);
3609 if (AOP_TYPE (right) == AOP_LIT) {
3610 genShiftRightLit (ic);
3614 if (AOP_SIZE (right) > 1) {
3615 if (isRegPair (AOP (right))) {
3616 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3619 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3620 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3624 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3626 aopOp (left = IC_LEFT (ic), ic, FALSE);
3627 aopOp (result = IC_RESULT (ic), ic, FALSE);
3628 size = AOP_SIZE (result);
3629 tlbl = newiTempLabel (NULL);
3630 emitcode ("", "L%05d:", tlbl->key);
3632 letype = getSpec (operandType (left));
3633 sign = !SPEC_USIGN (letype);
3634 if (!sameRegs (AOP (left), AOP (result))) {
3636 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3639 size = AOP_SIZE (result);
3641 size = AOP_SIZE (result);
3645 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3647 emitcode ("lsr", "%s", aopGet (AOP (result), offset));
3651 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3654 if (AOP_SIZE (right) > 1)
3655 emitcode ("sbiw", "r24,1");
3657 emitcode ("dec", "r24");
3658 emitcode ("brne", "L%05d", tlbl->key);
3660 freeAsmop (left, NULL, ic, TRUE);
3661 freeAsmop (result, NULL, ic, TRUE);
3664 /*-----------------------------------------------------------------*/
3665 /* RRsh - shift right rn by known count */
3666 /*-----------------------------------------------------------------*/
3668 RRsh (int shCount,int reg)
3670 shCount &= 0x0007; // shCount : 0..7
3676 emitcode ("lsr", "r%d",reg);
3679 emitcode ("lsr", "r%d",reg);
3680 emitcode ("lsr", "r%d",reg);
3683 emitcode ("swap", "r%d",reg);
3684 emitcode ("lsl", "r%d",reg);
3687 emitcode ("swap", "r%d",reg);
3690 emitcode ("swap", "r%d",reg);
3691 emitcode ("lsr", "r%d",reg);
3694 emitcode ("swap","r%d",reg);
3695 emitcode ("lsr", "r%d",reg);
3696 emitcode ("lsr", "r%d",reg);
3699 emitcode ("swap","r%d",reg);
3700 emitcode ("lsr", "r%d",reg);
3701 emitcode ("lsr", "r%d",reg);
3702 emitcode ("lsr", "r%d",reg);
3707 /*-----------------------------------------------------------------*/
3708 /* RLsh - shift left rn by known count */
3709 /*-----------------------------------------------------------------*/
3711 RLsh (int shCount, int reg)
3713 shCount &= 0x0007; // shCount : 0..7
3719 emitcode ("lsl", "r%d",reg);
3722 emitcode ("lsl", "r%d",reg);
3723 emitcode ("lsl", "r%d",reg);
3726 emitcode ("swap","r%d",reg);
3727 emitcode ("lsr", "r%d",reg);
3730 emitcode ("swap", "r%d",reg);
3733 emitcode ("swap","r%d",reg);
3734 emitcode ("lsl", "r%d",reg);
3737 emitcode ("swap","r%d",reg);
3738 emitcode ("lsl", "r%d",reg);
3739 emitcode ("lsl", "r%d",reg);
3742 emitcode ("swap","r%d",reg);
3743 emitcode ("lsl", "r%d",reg);
3744 emitcode ("lsl", "r%d",reg);
3745 emitcode ("lsl", "r%d",reg);
3750 /*-----------------------------------------------------------------*/
3751 /* genUnpackBits - generates code for unpacking bits */
3752 /*-----------------------------------------------------------------*/
3754 genUnpackBits (operand * result, char *rname, int ptype)
3762 etype = getSpec (operandType (result));
3763 rsize = getSize (operandType (result));
3764 /* read the first byte */
3771 emitcode ("ld", "r24,%s+", rname);
3775 emitcode ("lpm", "r24,%s+", rname);
3779 emitcode ("call","__gptrget_pi");
3780 emitcode ("mov","r24,r0");
3784 rlen = SPEC_BLEN (etype);
3786 /* if we have bitdisplacement then it fits */
3787 /* into this byte completely or if length is */
3788 /* less than a byte */
3789 if ((shCnt = SPEC_BSTR (etype)) || (SPEC_BLEN (etype) <= 8)) {
3791 /* shift right acc */
3794 emitcode ("andi", "r24,lo(0x%x)",
3795 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
3796 aopPut (AOP (result), "r24", offset++);
3800 /* bit field did not fit in a byte */
3801 aopPut (AOP (result), "r24", offset++);
3811 emitcode ("ld", "r24,%s+");
3815 emitcode ("lpm", "r24,%s+");
3819 emitcode ("call", "__gptrget_pi");
3824 /* if we are done */
3828 aopPut (AOP (result), "r24", offset++);
3833 aopPut (AOP (result), "r24", offset++);
3837 if (offset < rsize) {
3840 aopPut (AOP (result), zero, offset++);
3845 /*-----------------------------------------------------------------*/
3846 /* genDataPointerGet - generates code when ptr offset is known */
3847 /*-----------------------------------------------------------------*/
3849 genDataPointerGet (operand * left, operand * result, iCode * ic)
3853 int size, offset = 0;
3854 aopOp (result, ic, TRUE);
3856 /* get the string representation of the name */
3857 l = aopGet (AOP (left), 0);
3858 size = AOP_SIZE (result);
3861 sprintf (buffer, "(%s + %d)", l, offset);
3863 sprintf (buffer, "%s", l);
3864 emitcode ("lds", "%s,%s", aopGet (AOP (result), offset++),
3868 freeAsmop (left, NULL, ic, TRUE);
3869 freeAsmop (result, NULL, ic, TRUE);
3872 /*-----------------------------------------------------------------*/
3873 /* genNearPointerGet - emitcode for near pointer fetch */
3874 /*-----------------------------------------------------------------*/
3876 genMemPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
3881 char *rname, *frname = NULL;
3882 sym_link *rtype, *retype;
3883 sym_link *ltype = operandType (left);
3885 rtype = operandType (result);
3886 retype = getSpec (rtype);
3888 aopOp (left, ic, FALSE);
3890 /* if left is rematerialisable and
3891 result is not bit variable type and
3892 the left is pointer to data space i.e
3893 lower 128 bytes of space */
3894 if (AOP_TYPE (left) == AOP_IMMD &&
3895 !IS_BITVAR (retype) && DCL_TYPE (ltype) == POINTER) {
3896 genDataPointerGet (left, result, ic);
3900 /* if the value is already in a pointer register
3901 then don't need anything more */
3902 if (!AOP_INPREG (AOP (left))) {
3903 /* otherwise get a free pointer register */
3905 preg = getFreePtr (ic, &aop, FALSE, 0);
3906 if (isRegPair (AOP (left) )) {
3907 emitcode ("movw", "%s,%s",
3908 aop->aopu.aop_ptr->name,
3909 aopGet(AOP(left),0));
3911 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
3912 aopGet (AOP (left), 0));
3913 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
3914 aopGet (AOP (left), 1));
3920 frname = aopGet(aop,0);
3924 } else if (AOP_ISZ(aop)) {
3927 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
3928 "pointer not in correct register");
3932 aopOp (result, ic, FALSE);
3934 /* if bitfield then unpack the bits */
3935 if (IS_BITVAR (retype))
3936 genUnpackBits (result, rname, POINTER);
3938 /* we have can just get the values */
3939 int size = AOP_SIZE (result);
3944 emitcode ("ld","%s,%s+",aopGet(AOP(result),offset), rname);
3946 emitcode ("ld","%s,%s",aopGet(AOP(result),offset), rname);
3951 /* now some housekeeping stuff */
3953 /* we had to allocate for this iCode */
3955 if (isRegPair (AOP (left) )) {
3956 emitcode ("movw", "%s,%s",
3957 aopGet (AOP(left),0),
3958 aop->aopu.aop_ptr->name);
3960 emitcode ("mov", "%s,%s",
3961 aopGet (AOP (left), 0),
3962 aop->aopu.aop_ptr->name);
3963 emitcode ("mov", "%s,%s",
3964 aopGet (AOP (left), 1),
3965 aop->aop_ptr2->name);
3968 freeAsmop (NULL, aop, ic, TRUE);
3971 /* we did not allocate which means left
3972 already in a pointer register, then
3973 if size > 0 && this could be used again
3974 we have to point it back to where it
3976 if ((AOP_SIZE (result) > 1 &&
3977 !OP_SYMBOL (left)->remat &&
3978 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) && !pi) {
3979 int size = AOP_SIZE (result) - 1;
3980 emitcode ("sbiw", "%s,%d",frname,size);
3985 if (pi) pi->generated = 1;
3986 freeAsmop (left, NULL, ic, TRUE);
3987 freeAsmop (result, NULL, ic, TRUE);
3991 /*-----------------------------------------------------------------*/
3992 /* genCodePointerGet - gget value from code space */
3993 /*-----------------------------------------------------------------*/
3995 genCodePointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
3998 sym_link *retype = getSpec (operandType (result));
4002 aopOp (left, ic, FALSE);
4004 /* if the operand is already in Z register
4005 then we do nothing else we move the value to Z register */
4006 if (AOP_ISZ(AOP(left))) {
4010 getFreePtr(ic,&aop,FALSE,TRUE);
4011 if (isRegPair(AOP (left))) {
4012 emitcode ("movw","r30,%s",aopGet (AOP (left), 0));
4014 emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
4015 emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
4020 aopOp (result, ic, FALSE);
4022 /* if bit then unpack */
4023 if (IS_BITVAR (retype))
4024 genUnpackBits (result, "Z", CPOINTER);
4026 size = AOP_SIZE (result);
4031 emitcode ("lpm","%s,Z+",aopGet(AOP(result),offset++));
4033 emitcode ("lpm","%s,Z",aopGet(AOP(result),offset++));
4038 /* now some housekeeping stuff */
4040 /* we had to allocate for this iCode */
4042 if (isRegPair(AOP (left))) {
4043 emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
4045 emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
4046 emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
4049 freeAsmop (NULL, aop, ic, TRUE);
4052 /* we did not allocate which means left
4053 already in a pointer register, then
4054 if size > 0 && this could be used again
4055 we have to point it back to where it
4057 if ((AOP_SIZE (result) > 1 &&
4058 !OP_SYMBOL (left)->remat &&
4059 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) &&
4061 int size = AOP_SIZE (result) - 1;
4062 emitcode ("sbiw", "r30,%d",size);
4067 if (pi) pi->generated=1;
4068 freeAsmop (left, NULL, ic, TRUE);
4069 freeAsmop (result, NULL, ic, TRUE);
4073 /*-----------------------------------------------------------------*/
4074 /* genGenPointerGet - gget value from generic pointer space */
4075 /*-----------------------------------------------------------------*/
4077 genGenPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
4081 sym_link *retype = getSpec (operandType (result));
4084 aopOp (left, ic, FALSE);
4086 /* if the operand is already in dptr
4087 then we do nothing else we move the value to dptr */
4088 if (AOP_ISZ(AOP(left))) {
4092 getFreePtr(ic,&aop,FALSE,TRUE);
4093 if (isRegPair(AOP(left))) {
4094 emitcode ("movw", "r30,%s", aopGet (AOP (left), 0));
4096 emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
4097 emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
4099 emitcode ("mov", "r24,%s", aopGet (AOP (left), 2));
4103 /* so Z register now contains the address */
4105 aopOp (result, ic, FALSE);
4107 /* if bit then unpack */
4108 if (IS_BITVAR (retype))
4109 genUnpackBits (result, "Z", GPOINTER);
4111 size = AOP_SIZE (result);
4116 emitcode ("call", "__gptrget_pi");
4118 emitcode ("call", "__gptrget");
4119 aopPut (AOP (result), "r0", offset++);
4124 /* now some housekeeping stuff */
4126 /* we had to allocate for this iCode */
4128 if (isRegPair(AOP (left))) {
4129 emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
4131 emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
4132 emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
4135 freeAsmop (NULL, aop, ic, TRUE);
4138 /* we did not allocate which means left
4139 already in a pointer register, then
4140 if size > 0 && this could be used again
4141 we have to point it back to where it
4143 if ((AOP_SIZE (result) > 1 &&
4144 !OP_SYMBOL (left)->remat &&
4145 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) &&
4147 int size = AOP_SIZE (result) - 1;
4148 emitcode ("sbiw", "r30,%d",size);
4151 if (pi) pi->generated=1;
4152 freeAsmop (left, NULL, ic, TRUE);
4153 freeAsmop (result, NULL, ic, TRUE);
4156 /*-----------------------------------------------------------------*/
4157 /* genPointerGet - generate code for pointer get */
4158 /*-----------------------------------------------------------------*/
4160 genPointerGet (iCode * ic, iCode *pi)
4162 operand *left, *result;
4163 sym_link *type, *etype;
4166 left = IC_LEFT (ic);
4167 result = IC_RESULT (ic);
4169 /* depending on the type of pointer we need to
4170 move it to the correct pointer register */
4171 type = operandType (left);
4172 etype = getSpec (type);
4173 /* if left is of type of pointer then it is simple */
4174 if (IS_PTR (type) && !IS_FUNC (type->next))
4175 p_type = DCL_TYPE (type);
4177 /* we have to go by the storage class */
4178 p_type = PTR_TYPE (SPEC_OCLS (etype));
4183 /* now that we have the pointer type we assign
4184 the pointer values */
4191 genMemPointerGet (left, result, ic, pi);
4195 genCodePointerGet (left, result, ic, pi);
4199 genGenPointerGet (left, result, ic, pi);
4205 /*-----------------------------------------------------------------*/
4206 /* genPackBits - generates code for packed bit storage */
4207 /*-----------------------------------------------------------------*/
4209 genPackBits (sym_link * etype,
4211 char *rname, int p_type)
4219 blen = SPEC_BLEN (etype);
4220 bstr = SPEC_BSTR (etype);
4222 l = aopGet (AOP (right), offset++);
4225 /* if the bit lenth is less than or */
4226 /* it exactly fits a byte then */
4227 if (SPEC_BLEN (etype) <= 8) {
4228 shCount = SPEC_BSTR (etype);
4230 /* shift left acc */
4233 if (SPEC_BLEN (etype) < 8) { /* if smaller than a byte */
4240 emitcode ("ld", "r1,%s",rname);
4244 emitcode ("push", "r1");
4245 emitcode ("push", "r24");
4246 emitcode ("call", "__gptrget");
4247 emitcode ("pop", "r1");
4248 emitcode ("mov","r24,r0");
4252 emitcode ("andi", "r24,#0x%02x", (unsigned char)
4253 ((unsigned char) (0xFF << (blen + bstr)) |
4254 (unsigned char) (0xFF >> (8 - bstr))));
4255 emitcode ("or", "r24,r1");
4256 if (p_type == GPOINTER)
4257 emitcode ("pop", "r1");
4266 emitcode("st","%s+,r24");
4270 emitcode("mov","r0,r24");
4271 emitcode ("call", "__gptrput_pi");
4276 if (SPEC_BLEN (etype) <= 8)
4279 rLen = SPEC_BLEN (etype);
4281 /* now generate for lengths greater than one byte */
4284 l = aopGet (AOP (right), offset++);
4295 emitcode ("st", "%s+,%s",rname,l);
4300 emitcode ("lcall", "__gptrput_pi");
4307 /* last last was not complete */
4309 /* save the byte & read byte */
4315 emitcode ("st","%s+,r24",rname);
4318 emitcode ("push", "r1");
4319 emitcode ("push", "r24");
4320 emitcode ("lcall", "__gptrget");
4321 emitcode ("mov","r24,r0");
4322 emitcode ("pop", "r1");
4326 emitcode ("andi", "r24,0x%02x", (((unsigned char) -1 << rLen) & 0xff));
4327 emitcode ("or", "r24,r1");
4330 if (p_type == GPOINTER)
4331 emitcode ("pop", "r1");
4339 emitcode ("st", "%s,r24", rname);
4343 emitcode ("mov","r0,r24");
4344 emitcode ("call", "__gptrput");
4349 /*-----------------------------------------------------------------*/
4350 /* genDataPointerSet - remat pointer to data space */
4351 /*-----------------------------------------------------------------*/
4353 genDataPointerSet (operand * right, operand * result, iCode * ic)
4355 int size, offset = 0;
4356 char *l, buffer[256];
4358 aopOp (right, ic, FALSE);
4360 l = aopGet (AOP (result), 0);
4361 size = AOP_SIZE (right);
4364 sprintf (buffer, "(%s + %d)", l, offset);
4366 sprintf (buffer, "%s", l);
4367 emitcode ("sts", "%s,%s", buffer,
4368 aopGet (AOP (right), offset++));
4371 freeAsmop (right, NULL, ic, TRUE);
4372 freeAsmop (result, NULL, ic, TRUE);
4375 /*-----------------------------------------------------------------*/
4376 /* genNearPointerSet - emitcode for near pointer put */
4377 /*-----------------------------------------------------------------*/
4379 genMemPointerSet (operand * right, operand * result, iCode * ic, iCode *pi)
4382 char *frname = NULL, *rname, *l;
4385 sym_link *ptype = operandType (result);
4387 retype = getSpec (operandType (right));
4389 aopOp (result, ic, FALSE);
4391 /* if the result is rematerializable &
4392 in data space & not a bit variable */
4393 if (AOP_TYPE (result) == AOP_IMMD &&
4394 DCL_TYPE (ptype) == POINTER && !IS_BITVAR (retype)) {
4395 genDataPointerSet (right, result, ic);
4398 if (!AOP_INPREG(AOP(result))) {
4399 /* otherwise get a free pointer register */
4401 getFreePtr (ic, &aop, FALSE, 0);
4402 if (isRegPair (AOP (result) )) {
4403 emitcode ("movw", "%s,%s",aop->aopu.aop_ptr->name,
4404 aopGet(AOP (result), 0));
4406 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
4407 aopGet (AOP (result), 0));
4408 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
4409 aopGet (AOP (result), 1));
4414 frname = aopGet(aop,0);
4417 aopOp (right, ic, FALSE);
4420 } else if (AOP_ISZ(aop)) {
4423 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4424 "pointer not in correct register");
4427 /* if bitfield then unpack the bits */
4428 if (IS_BITVAR (retype))
4429 genPackBits (retype, right, rname, POINTER);
4431 /* we have can just get the values */
4432 int size = AOP_SIZE (right);
4436 l = aopGet (AOP (right), offset);
4438 emitcode ("st", "%s+,%s", rname,l);
4440 emitcode ("st", "%s,%s", rname,l);
4445 /* now some housekeeping stuff */
4447 /* we had to allocate for this iCode */
4449 if (isRegPair (AOP (result) )) {
4450 emitcode ("movw", "%s,%s",
4451 aopGet(AOP(result),0),
4452 aop->aopu.aop_ptr->name);
4454 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
4455 aopGet (AOP (result), 0));
4456 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
4457 aopGet (AOP (result), 1));
4460 freeAsmop (NULL, aop, ic, TRUE);
4463 /* we did not allocate which means left
4464 already in a pointer register, then
4465 if size > 0 && this could be used again
4466 we have to point it back to where it
4468 if ((AOP_SIZE (right) > 1 &&
4469 !OP_SYMBOL (result)->remat &&
4470 (OP_SYMBOL (right)->liveTo > ic->seq || ic->depth)) && !pi) {
4471 int size = AOP_SIZE (right) - 1;
4472 emitcode ("sbiw", "%s,%d",frname,size);
4477 if (pi) pi->generated = 1;
4478 freeAsmop (result, NULL, ic, TRUE);
4479 freeAsmop (right, NULL, ic, TRUE);
4482 /*-----------------------------------------------------------------*/
4483 /* genGenPointerSet - set value from generic pointer space */
4484 /*-----------------------------------------------------------------*/
4486 genGenPointerSet (operand * right, operand * result, iCode * ic, iCode *pi)
4490 sym_link *retype = getSpec (operandType (right));
4493 aopOp (result, ic, FALSE);
4495 /* if the operand is already in dptr
4496 then we do nothing else we move the value to dptr */
4497 if (AOP_ISZ(AOP(result))) {
4501 getFreePtr(ic,&aop,FALSE,TRUE);
4502 if (isRegPair(AOP(result))) {
4503 emitcode ("movw", "r30,%s", aopGet (AOP (result), 0));
4505 emitcode ("mov", "r30,%s", aopGet (AOP (result), 0));
4506 emitcode ("mov", "r31,%s", aopGet (AOP (result), 1));
4508 emitcode ("mov", "r24,%s", aopGet (AOP (result), 2));
4512 /* so Z register now contains the address */
4513 aopOp (right, ic, FALSE);
4515 /* if bit then unpack */
4516 if (IS_BITVAR (retype))
4517 genUnpackBits (result, "Z", GPOINTER);
4519 size = AOP_SIZE (right);
4523 char *l = aopGet(AOP (right), offset++);
4527 emitcode ("call", "__gptrput_pi");
4529 emitcode ("call", "__gptrput");
4533 /* now some housekeeping stuff */
4535 /* we had to allocate for this iCode */
4537 if (isRegPair(AOP(result))) {
4538 emitcode ("movw", "%s,r30", aopGet (AOP (result), 0));
4540 emitcode ("mov", "%s,r30", aopGet (AOP (result), 0));
4541 emitcode ("mov", "%s,r31", aopGet (AOP (result), 1));
4544 freeAsmop (NULL, aop, ic, TRUE);
4547 /* we did not allocate which means left
4548 already in a pointer register, then
4549 if size > 0 && this could be used again
4550 we have to point it back to where it
4552 if ((AOP_SIZE (right) > 1 &&
4553 !OP_SYMBOL (result)->remat &&
4554 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) && !pi) {
4555 int size = AOP_SIZE (right) - 1;
4556 emitcode ("sbiw", "r30,%d",size);
4559 if (pi) pi->generated = 1;
4560 freeAsmop (right, NULL, ic, TRUE);
4561 freeAsmop (result, NULL, ic, TRUE);
4564 /*-----------------------------------------------------------------*/
4565 /* genPointerSet - stores the value into a pointer location */
4566 /*-----------------------------------------------------------------*/
4568 genPointerSet (iCode * ic, iCode *pi)
4570 operand *right, *result;
4571 sym_link *type, *etype;
4574 right = IC_RIGHT (ic);
4575 result = IC_RESULT (ic);
4577 /* depending on the type of pointer we need to
4578 move it to the correct pointer register */
4579 type = operandType (result);
4580 etype = getSpec (type);
4581 /* if left is of type of pointer then it is simple */
4582 if (IS_PTR (type) && !IS_FUNC (type->next)) {
4583 p_type = DCL_TYPE (type);
4586 /* we have to go by the storage class */
4587 p_type = PTR_TYPE (SPEC_OCLS (etype));
4591 /* now that we have the pointer type we assign
4592 the pointer values */
4599 genMemPointerSet (right, result, ic, pi);
4603 genGenPointerSet (right, result, ic, pi);
4607 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4608 "genPointerSet: illegal pointer type");
4613 /*-----------------------------------------------------------------*/
4614 /* genIfx - generate code for Ifx statement */
4615 /*-----------------------------------------------------------------*/
4617 genIfx (iCode * ic, iCode * popIc)
4619 operand *cond = IC_COND (ic);
4624 aopOp (cond, ic, FALSE);
4626 /* get the value into acc */
4627 if (AOP_SIZE(cond) == 1 && AOP_ISHIGHREG(AOP(cond),0)) {
4628 cname = aopGet(AOP(cond),0);
4630 toBoolean (cond, "r24", 0);
4634 /* the result is now in the accumulator */
4635 freeAsmop (cond, NULL, ic, TRUE);
4637 /* if there was something to be popped then do it */
4640 emitcode("cpi","%s,0",cname);
4641 } else if (!tob) emitcode("cpi","%s,0",cname);
4643 lbl = newiTempLabel(NULL);
4645 emitcode ("breq","L%05d",lbl->key);
4646 emitcode ("jmp","L%05d",IC_TRUE(ic)->key);
4647 emitcode ("","L%05d:",lbl->key);
4649 emitcode ("brne","L%05d",lbl->key);
4650 emitcode ("jmp","L%05d",IC_FALSE(ic)->key);
4651 emitcode ("","L%05d:",lbl->key);
4656 /*-----------------------------------------------------------------*/
4657 /* genAddrOf - generates code for address of */
4658 /*-----------------------------------------------------------------*/
4660 genAddrOf (iCode * ic)
4662 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
4665 aopOp (IC_RESULT (ic), ic, FALSE);
4666 assert(AOP_SIZE(IC_RESULT(ic)) >= 2);
4667 /* if the operand is on the stack then we
4668 need to get the stack offset of this
4671 /* if it has an offset then we need to compute it */
4673 if (allHigh(AOP(IC_RESULT(ic)))) {
4674 if (isRegPair (AOP(IC_RESULT(ic)))) {
4675 emitcode ("movw","%s,r28",aopGet(AOP(IC_RESULT(ic)),0));
4677 emitcode ("mov","%s,r28",aopGet(AOP(IC_RESULT(ic)),0));
4678 emitcode ("mov","%s,r29",aopGet(AOP(IC_RESULT(ic)),1));
4680 if (sym->stack < 0) {
4681 emitcode("subi","%s,<(%d)",aopGet(AOP(IC_RESULT(ic)),0),-sym->stack);
4682 emitcode("sbci","%s,>(%d)",aopGet(AOP(IC_RESULT(ic)),1),-sym->stack);
4684 emitcode("subi","%s,<(-%d)",aopGet(AOP(IC_RESULT(ic)),0),sym->stack);
4685 emitcode("sbci","%s,>(-%d)",aopGet(AOP(IC_RESULT(ic)),1),sym->stack);
4688 emitcode("movw","r24,r28");
4689 if (sym->stack > -63 && sym->stack < 63) {
4691 emitcode("sbiw","r24,%d",-sym->stack);
4693 emitcode("sbiw","r24,%d",sym->stack);
4695 if (sym->stack < 0) {
4696 emitcode("subi","r24,<(%d)",-sym->stack);
4697 emitcode("sbci","r25,>(%d)",-sym->stack);
4699 emitcode("subi","r24,<(-%d)",sym->stack);
4700 emitcode("sbci","r25,>(-%d)",sym->stack);
4704 aopPut(AOP(IC_RESULT(ic)),"r24",0);
4705 aopPut(AOP(IC_RESULT(ic)),"r25",1);
4709 aopPut(AOP(IC_RESULT(ic)),"r28",0);
4710 aopPut(AOP(IC_RESULT(ic)),"r29",1);
4712 /* fill the result with zero */
4713 size = AOP_SIZE (IC_RESULT (ic)) - 2;
4716 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
4722 /* object not on stack then we need the name */
4723 size = AOP_SIZE (IC_RESULT (ic));
4727 char s[SDCC_NAME_MAX];
4729 sprintf (s, ">(%s)", sym->rname);
4731 sprintf (s, "<(%s)", sym->rname);
4732 aopPut (AOP (IC_RESULT (ic)), s, offset++);
4736 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4740 /*-----------------------------------------------------------------*/
4741 /* genFarFarAssign - assignment when both are in far space */
4742 /*-----------------------------------------------------------------*/
4744 genFarFarAssign (operand * result, operand * right, iCode * ic)
4746 int size = AOP_SIZE (right);
4749 /* first push the right side on to the stack */
4751 l = aopGet (AOP (right), offset++);
4753 emitcode ("push", "acc");
4756 freeAsmop (right, NULL, ic, FALSE);
4757 /* now assign DPTR to result */
4758 aopOp (result, ic, FALSE);
4759 size = AOP_SIZE (result);
4761 emitcode ("pop", "acc");
4762 aopPut (AOP (result), "a", --offset);
4764 freeAsmop (result, NULL, ic, FALSE);
4768 /*-----------------------------------------------------------------*/
4769 /* genAssign - generate code for assignment */
4770 /*-----------------------------------------------------------------*/
4772 genAssign (iCode * ic)
4774 operand *result, *right;
4776 unsigned long lit = 0L;
4778 result = IC_RESULT (ic);
4779 right = IC_RIGHT (ic);
4781 /* if they are the same */
4782 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4785 aopOp (right, ic, FALSE);
4787 /* special case both in far space */
4788 if (AOP_TYPE (right) == AOP_DPTR &&
4789 IS_TRUE_SYMOP (result) && isOperandInFarSpace (result)) {
4791 genFarFarAssign (result, right, ic);
4795 aopOp (result, ic, TRUE);
4797 /* if they are the same registers */
4798 if (sameRegs (AOP (right), AOP (result)))
4801 /* if the result is a bit */
4802 if (AOP_TYPE (result) == AOP_CRY) {
4804 /* if the right size is a literal then
4805 we know what the value is */
4806 if (AOP_TYPE (right) == AOP_LIT) {
4807 if (((int) operandLitValue (right)))
4808 aopPut (AOP (result), one, 0);
4810 aopPut (AOP (result), zero, 0);
4814 /* the right is also a bit variable */
4815 if (AOP_TYPE (right) == AOP_CRY) {
4816 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4817 aopPut (AOP (result), "c", 0);
4822 toBoolean (right, "", 0);
4823 aopPut (AOP (result), "a", 0);
4827 /* bit variables done */
4829 size = AOP_SIZE (result);
4831 if (AOP_TYPE (right) == AOP_LIT)
4832 lit = ulFromVal (AOP (right)->aopu.
4834 if ((size > 1) && (AOP_TYPE (result) != AOP_REG)
4835 && (AOP_TYPE (right) == AOP_LIT)
4836 && !IS_FLOAT (operandType (right)) && (lit < 256L)) {
4837 emitcode ("clr", "a");
4839 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) ==
4840 0) aopPut (AOP (result), "a", size);
4842 aopPut (AOP (result),
4843 aopGet (AOP (right), size), size);
4848 aopPut (AOP (result),
4849 aopGet (AOP (right), offset), offset);
4855 freeAsmop (right, NULL, ic, FALSE);
4856 freeAsmop (result, NULL, ic, TRUE);
4859 /*-----------------------------------------------------------------*/
4860 /* genJumpTab - genrates code for jump table */
4861 /*-----------------------------------------------------------------*/
4863 genJumpTab (iCode * ic)
4868 aopOp (IC_JTCOND (ic), ic, FALSE);
4869 /* get the condition into accumulator */
4870 l = aopGet (AOP (IC_JTCOND (ic)), 0);
4872 /* multiply by three */
4873 emitcode ("add", "a,acc");
4874 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0));
4875 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
4877 jtab = newiTempLabel (NULL);
4878 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
4879 emitcode ("jmp", "@a+dptr");
4880 emitcode ("", "%05d$:", jtab->key + 100);
4881 /* now generate the jump labels */
4882 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
4883 jtab = setNextItem (IC_JTLABELS (ic)))
4884 emitcode ("ljmp", "%05d$", jtab->key + 100);
4888 /*-----------------------------------------------------------------*/
4889 /* genCast - gen code for casting */
4890 /*-----------------------------------------------------------------*/
4892 genCast (iCode * ic)
4894 operand *result = IC_RESULT (ic);
4895 sym_link *ctype = operandType (IC_LEFT (ic));
4896 sym_link *rtype = operandType (IC_RIGHT (ic));
4897 operand *right = IC_RIGHT (ic);
4900 /* if they are equivalent then do nothing */
4901 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4904 aopOp (right, ic, FALSE);
4905 aopOp (result, ic, FALSE);
4907 /* if the result is a bit */
4908 if (AOP_TYPE (result) == AOP_CRY) {
4909 /* if the right size is a literal then
4910 we know what the value is */
4911 if (AOP_TYPE (right) == AOP_LIT) {
4912 if (((int) operandLitValue (right)))
4913 aopPut (AOP (result), one, 0);
4915 aopPut (AOP (result), zero, 0);
4920 /* the right is also a bit variable */
4921 if (AOP_TYPE (right) == AOP_CRY) {
4922 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4923 aopPut (AOP (result), "c", 0);
4928 toBoolean (right, "", 0);
4929 aopPut (AOP (result), "a", 0);
4933 /* if they are the same size : or less */
4934 if (AOP_SIZE (result) <= AOP_SIZE (right)) {
4936 /* if they are in the same place */
4937 if (sameRegs (AOP (right), AOP (result)))
4940 /* if they in different places then copy */
4941 size = AOP_SIZE (result);
4944 aopPut (AOP (result),
4945 aopGet (AOP (right), offset), offset);
4952 /* if the result is of type pointer */
4953 if (IS_PTR (ctype)) {
4956 sym_link *type = operandType (right);
4957 sym_link *etype = getSpec (type);
4959 /* pointer to generic pointer */
4960 if (IS_GENPTR (ctype)) {
4962 p_type = DCL_TYPE (type);
4964 /* we have to go by the storage class */
4965 p_type = PTR_TYPE (SPEC_OCLS (etype));
4968 /* the first two bytes are known */
4969 size = GPTRSIZE - 1;
4972 aopPut (AOP (result),
4973 aopGet (AOP (right), offset), offset);
4977 /* the last byte depending on type */
4979 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
4984 // pointerTypeToGPByte will have bitched.
4988 sprintf(gpValStr, "#0x%x", gpVal);
4989 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
4994 /* just copy the pointers */
4995 size = AOP_SIZE (result);
4998 aopPut (AOP (result),
4999 aopGet (AOP (right), offset), offset);
5005 /* so we now know that the size of destination is greater
5006 than the size of the source */
5007 /* we move to result for the size of source */
5008 size = AOP_SIZE (right);
5011 aopPut (AOP (result), aopGet (AOP (right), offset), offset);
5015 /* now depending on the sign of the source && destination */
5016 size = AOP_SIZE (result) - AOP_SIZE (right);
5017 /* if unsigned or not an integral type */
5018 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype)) {
5020 aopPut (AOP (result), zero, offset++);
5023 /* we need to extend the sign :{ */
5024 // PENDING: Does nothing on avr
5026 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1);
5029 emitcode ("rlc", "a");
5030 emitcode ("subb", "a,acc");
5032 aopPut (AOP (result), "a", offset++);
5035 /* we are done hurray !!!! */
5038 freeAsmop (right, NULL, ic, TRUE);
5039 freeAsmop (result, NULL, ic, TRUE);
5043 /*-----------------------------------------------------------------*/
5044 /* genDjnz - generate decrement & jump if not zero instrucion */
5045 /*-----------------------------------------------------------------*/
5047 genDjnz (iCode * ic, iCode * ifx)
5053 /* if the if condition has a false label
5054 then we cannot save */
5058 /* if the minus is not of the form
5060 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
5061 !IS_OP_LITERAL (IC_RIGHT (ic)))
5064 if (operandLitValue (IC_RIGHT (ic)) != 1)
5067 /* if the size of this greater than one then no
5069 if (getSize (operandType (IC_RESULT (ic))) > 1)
5072 /* otherwise we can save BIG */
5073 lbl = newiTempLabel (NULL);
5074 lbl1 = newiTempLabel (NULL);
5076 aopOp (IC_RESULT (ic), ic, FALSE);
5078 if (IS_AOP_PREG (IC_RESULT (ic))) {
5079 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0));
5080 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0));
5081 emitcode ("jnz", "%05d$", lbl->key + 100);
5084 emitcode ("djnz", "%s,%05d$",
5085 aopGet (AOP (IC_RESULT (ic)), 0), lbl->key + 100);
5087 emitcode ("sjmp", "%05d$", lbl1->key + 100);
5088 emitcode ("", "%05d$:", lbl->key + 100);
5089 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5090 emitcode ("", "%05d$:", lbl1->key + 100);
5092 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5097 static char *recvregs[8] = {
5098 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23"
5101 static int recvCnt = 0;
5103 /*-----------------------------------------------------------------*/
5104 /* genReceive - generate code for a receive iCode */
5105 /*-----------------------------------------------------------------*/
5107 genReceive (iCode * ic)
5109 int size, offset = 0;
5110 aopOp (IC_RESULT (ic), ic, FALSE);
5111 size = AOP_SIZE (IC_RESULT (ic));
5113 aopPut (AOP (IC_RESULT (ic)), recvregs[recvCnt++], offset);
5116 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5119 /*-----------------------------------------------------------------*/
5120 /* genDummyRead - generate code for dummy read of volatiles */
5121 /*-----------------------------------------------------------------*/
5123 genDummyRead (iCode * ic)
5125 emitcode ("; genDummyRead","");
5126 emitcode ("; not implemented","");
5131 /*-----------------------------------------------------------------*/
5132 /* gen51Code - generate code for 8051 based controllers */
5133 /*-----------------------------------------------------------------*/
5135 genAVRCode (iCode * lic)
5140 lineHead = lineCurr = NULL;
5142 /* print the allocation information */
5144 printAllocInfo (currFunc, codeOutBuf);
5145 /* if debug information required */
5146 if (options.debug && currFunc) {
5147 debugFile->writeFunction (currFunc, lic);
5149 /* stack pointer name */
5153 for (ic = lic; ic; ic = ic->next) {
5155 if (cln != ic->lineno) {
5156 if (options.debug) {
5157 debugFile->writeCLine (ic);
5159 emitcode (";", "%s %d", ic->filename, ic->lineno);
5162 /* if the result is marked as
5163 spilt and rematerializable or code for
5164 this has already been generated then
5166 if (resultRemat (ic) || ic->generated)
5169 /* depending on the operation */
5188 /* IPOP happens only when trying to restore a
5189 spilt live range, if there is an ifx statement
5190 following this pop then the if statement might
5191 be using some of the registers being popped which
5192 would destory the contents of the register so
5193 we need to check for this condition and handle it */
5195 ic->next->op == IFX &&
5196 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
5197 genIfx (ic->next, ic);
5215 genEndFunction (ic);
5235 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
5252 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
5256 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
5260 genCmpLe (ic, ifxForOp (IC_RESULT (ic), ic));
5264 genCmpGe (ic, ifxForOp (IC_RESULT (ic), ic));
5268 genCmpNe (ic, ifxForOp (IC_RESULT (ic), ic));
5272 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
5284 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
5288 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
5292 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
5319 case GET_VALUE_AT_ADDRESS:
5320 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
5324 if (POINTER_SET (ic))
5325 genPointerSet (ic, hasInc(IC_RESULT(ic),ic));
5351 addSet (&_G.sendSet, ic);
5354 case DUMMY_READ_VOLATILE:
5364 /* now we are ready to call the
5365 peep hole optimizer */
5366 if (!options.nopeep)
5367 peepHole (&lineHead);
5369 /* now do the actual printing */
5370 printLine (lineHead, codeOutBuf);