1 /*-------------------------------------------------------------------------
2 avrgen.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"
34 #ifdef HAVE_SYS_ISA_DEFS_H
35 #include <sys/isa_defs.h>
37 #ifdef HAVE_MACHINE_ENDIAN_H
38 #include <machine/endian.h>
43 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
44 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
45 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
52 #include "SDCCpeeph.h"
56 char *aopLiteral (value * val, int offset);
59 /* this is the down and dirty file with all kinds of
60 kludgy & hacky stuff. This is what it is all about
61 CODE GENERATION for a specific MCU . some of the
62 routines may be reusable, will have to see */
64 static char *zero = "0x00";
65 static char *one = "0x01";
68 char *fReturnAVR[] = { "r16", "r17", "r18", "r19" };
69 unsigned fAVRReturnSize = 4; /* shared with ralloc.c */
70 char **fAVRReturn = fReturnAVR;
71 static char *larray[4] = { ">", "<", "hlo8", "hhi8" };
83 extern int avr_ptrRegReq;
85 extern FILE *codeOutFile;
86 #define RESULTONSTACK(x) \
87 (IC_RESULT(x) && IC_RESULT(x)->aop && \
88 IC_RESULT(x)->aop->type == AOP_STK )
90 #define MOVR0(x) if (strcmp(x,"r0")) emitcode("mov","r0,%s",x);
91 #define MOVR24(x) if (strcmp(x,"r24")) emitcode("mov","r24,%s",x);
92 #define AOP_ISHIGHREG(a,n) (a->type == AOP_REG && a->aopu.aop_reg[n] && a->aopu.aop_reg[n]->rIdx >= R16_IDX)
93 #define CLRC emitcode("clc","")
94 #define SETC emitcode("stc","")
96 #define IS_REGIDX(a,r) (a->type == AOP_REG && a->aopu.aop_reg[0]->rIdx == r)
98 static lineNode *lineHead = NULL;
99 static lineNode *lineCurr = NULL;
108 /*-----------------------------------------------------------------*/
109 /* reAdjustPreg - points a register back to where it should */
110 /*-----------------------------------------------------------------*/
112 reAdjustPreg (asmop * aop)
117 if ((size = aop->size) <= 1)
123 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name, size);
129 /*-----------------------------------------------------------------*/
130 /* outBitC - output a bit C */
131 /*-----------------------------------------------------------------*/
133 outBitC (operand * result)
135 emitcode ("clr", "r0");
136 emitcode ("rol", "r0");
140 /*-----------------------------------------------------------------*/
141 /* inExcludeList - return 1 if the string is in exclude Reg list */
142 /*-----------------------------------------------------------------*/
144 inExcludeList (char *s)
148 if (options.excludeRegs[i] &&
149 STRCASECMP (options.excludeRegs[i], "none") == 0)
152 for (i = 0; options.excludeRegs[i]; i++) {
153 if (options.excludeRegs[i] &&
154 STRCASECMP (s, options.excludeRegs[i]) == 0)
160 /*-----------------------------------------------------------------*/
161 /* findLabelBackwards: walks back through the iCode chain looking */
162 /* for the given label. Returns number of iCode instructions */
163 /* between that label and given ic. */
164 /* Returns zero if label not found. */
165 /*-----------------------------------------------------------------*/
167 findLabelBackwards (iCode * ic, int key)
175 if (ic->op == LABEL && IC_LABEL (ic)->key == key) {
176 /* printf("findLabelBackwards = %d\n", count); */
184 /*-----------------------------------------------------------------*/
185 /* addSign - complete with sign */
186 /*-----------------------------------------------------------------*/
188 addSign (operand * result, int offset, int sign)
190 int size = (getDataSize (result) - offset);
193 emitcode ("rlc", "a");
194 emitcode ("subb", "a,acc");
196 aopPut (AOP (result), "a", offset++);
200 aopPut (AOP (result), zero, offset++);
204 /*-----------------------------------------------------------------*/
205 /* isLiteralBit - test if lit == 2^n */
206 /*-----------------------------------------------------------------*/
208 isLiteralBit (unsigned long lit)
210 unsigned long pw[32] = { 1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
211 0x100L, 0x200L, 0x400L, 0x800L,
212 0x1000L, 0x2000L, 0x4000L, 0x8000L,
213 0x10000L, 0x20000L, 0x40000L, 0x80000L,
214 0x100000L, 0x200000L, 0x400000L, 0x800000L,
215 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
216 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L
220 for (idx = 0; idx < 32; idx++)
226 /*-----------------------------------------------------------------*/
227 /* outAcc - output Acc */
228 /*-----------------------------------------------------------------*/
230 outAcc (operand * result)
233 size = getDataSize (result);
235 aopPut (AOP (result), "r0", 0);
238 /* unsigned or positive */
240 aopPut (AOP (result), zero, offset++);
245 #endif // End Unused code section
247 /*-----------------------------------------------------------------*/
248 /* emitcode - writes the code into a file : for now it is simple */
249 /*-----------------------------------------------------------------*/
251 emitcode (char *inst, char *fmt, ...)
254 char lb[INITIAL_INLINEASM];
261 sprintf (lb, "%s\t", inst);
263 sprintf (lb, "%s", inst);
264 vsprintf (lb + (strlen (lb)), fmt, ap);
267 vsprintf (lb, fmt, ap);
269 while (isspace (*lbp))
273 lineCurr = (lineCurr ?
274 connectLine (lineCurr, newLineNode (lb)) :
275 (lineHead = newLineNode (lb)));
276 lineCurr->isInline = _G.inLine;
277 lineCurr->isDebug = _G.debugLine;
281 /*-----------------------------------------------------------------*/
282 /* hasInc - operand is incremented before any other use */
283 /*-----------------------------------------------------------------*/
285 hasInc (operand *op, iCode *ic)
287 sym_link *type = operandType(op);
288 sym_link *retype = getSpec (type);
289 iCode *lic = ic->next;
292 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
293 isize = getSize(type->next);
295 /* if operand of the form op = op + <sizeof *op> */
296 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
297 isOperandEqual(IC_RESULT(lic),op) &&
298 isOperandLiteral(IC_RIGHT(lic)) &&
299 operandLitValue(IC_RIGHT(lic)) == isize) {
302 /* if the operand used or deffed */
303 if (bitVectBitValue(OP_USES(op),lic->key) || ((unsigned) lic->defKey == op->key)) {
311 /*-----------------------------------------------------------------*/
312 /* getFreePtr - returns X or Z whichever is free or can be pushed */
313 /*-----------------------------------------------------------------*/
315 getFreePtr (iCode * ic, asmop ** aopp, bool result, bool zonly)
317 bool xiu = FALSE, ziu = FALSE;
318 bool xou = FALSE, zou = FALSE;
320 /* the logic: if x & z used in the instruction
321 then we are in trouble otherwise */
323 /* first check if x & z are used by this
324 instruction, in which case we are in trouble */
325 if ((xiu = bitVectBitValue (ic->rUsed, X_IDX)) &&
326 (ziu = bitVectBitValue (ic->rUsed, Z_IDX))) {
330 xou = bitVectBitValue (ic->rMask, X_IDX);
331 zou = bitVectBitValue (ic->rMask, Z_IDX);
333 /* if no usage of Z then return it */
335 ic->rUsed = bitVectSetBit (ic->rUsed, Z_IDX);
336 (*aopp)->type = AOP_Z;
338 (*aopp)->aop_ptr2 = avr_regWithIdx (R31_IDX);
339 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R30_IDX);
342 /* if no usage of X then return it */
343 if (!xiu && !xou && !zonly) {
344 ic->rUsed = bitVectSetBit (ic->rUsed, X_IDX);
345 (*aopp)->type = AOP_X;
347 (*aopp)->aop_ptr2 = avr_regWithIdx (R27_IDX);
348 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R26_IDX);
351 /* if z not used then */
354 /* push it if not already pushed */
356 emitcode ("push", "%s",
357 avr_regWithIdx (R30_IDX)->dname);
358 emitcode ("push", "%s",
359 avr_regWithIdx (R31_IDX)->dname);
363 ic->rUsed = bitVectSetBit (ic->rUsed, Z_IDX);
364 (*aopp)->type = AOP_Z;
365 (*aopp)->aop_ptr2 = avr_regWithIdx (R31_IDX);
366 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R30_IDX);
369 /* now we know they both have usage */
370 /* if x not used in this instruction */
371 if (!xiu && !zonly) {
372 /* push it if not already pushed */
374 emitcode ("push", "%s",
375 avr_regWithIdx (R26_IDX)->dname);
376 emitcode ("push", "%s",
377 avr_regWithIdx (R27_IDX)->dname);
381 ic->rUsed = bitVectSetBit (ic->rUsed, X_IDX);
382 (*aopp)->type = AOP_X;
384 (*aopp)->aop_ptr2 = avr_regWithIdx (R27_IDX);
385 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R26_IDX);
390 /* I said end of world but not quite end of world yet */
391 /* if this is a result then we can push it on the stack */
393 (*aopp)->type = AOP_STK;
397 /* other wise this is true end of the world */
398 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
399 "getFreePtr should never reach here");
403 /*-----------------------------------------------------------------*/
404 /* newAsmop - creates a new asmOp */
405 /*-----------------------------------------------------------------*/
407 newAsmop (short type)
411 aop = Safe_calloc (1, sizeof (asmop));
416 /*-----------------------------------------------------------------*/
417 /* pointerCode - returns the code for a pointer type */
418 /*-----------------------------------------------------------------*/
420 pointerCode (sym_link * etype)
423 return PTR_TYPE (SPEC_OCLS (etype));
427 /*-----------------------------------------------------------------*/
428 /* aopForSym - for a true symbol */
429 /*-----------------------------------------------------------------*/
431 aopForSym (iCode * ic, symbol * sym, bool result)
434 memmap *space = SPEC_OCLS (sym->etype);
436 /* if already has one */
440 /* assign depending on the storage class */
441 /* if it is on the stack */
443 sym->aop = aop = newAsmop (0);
444 aop->size = getSize (sym->type);
446 /* we can use std / ldd instruction */
448 && (sym->stack + getSize (sym->type) - 1) <= 63) {
449 aop->type = AOP_STK_D;
450 aop->aopu.aop_stk = sym->stack;
454 /* otherwise get a free pointer register X/Z */
455 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result, FALSE);
457 /* now assign the address of the variable to
458 the pointer register */
459 if (aop->type != AOP_STK) {
460 emitcode ("movw", "%s,r28", aop->aopu.aop_ptr->name);
461 if (sym->stack < 0) {
462 if ((sym->stack - _G.nRegsSaved) > -63) {
463 emitcode ("sbiw", "%s,0x%02x",
464 aop->aopu.aop_ptr->name,
469 emitcode ("subi", "%s,<(%d)",
470 aop->aopu.aop_ptr->name,
471 sym->stack - _G.nRegsSaved);
472 emitcode ("sbci", "%s,>(%d)",
474 sym->stack - _G.nRegsSaved);
478 if (sym->stack <= 63) {
479 emitcode ("adiw", "%s,0x%02x",
480 aop->aopu.aop_ptr->name,
484 emitcode ("subi", "%s,<(-%d)",
485 aop->aopu.aop_ptr->name,
487 emitcode ("sbci", "%s,>(-%d)",
496 /* if in bit space */
497 if (IN_BITSPACE (space)) {
498 sym->aop = aop = newAsmop (AOP_CRY);
499 aop->aopu.aop_dir = sym->rname;
500 aop->size = getSize (sym->type);
503 /* if it is in direct space */
504 if (IN_DIRSPACE (space)) {
505 sym->aop = aop = newAsmop (AOP_DIR);
506 aop->aopu.aop_dir = sym->rname;
507 aop->size = getSize (sym->type);
511 /* special case for a function */
512 if (IS_FUNC (sym->type)) {
513 sym->aop = aop = newAsmop (AOP_IMMD);
514 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
515 strcpy (aop->aopu.aop_immd, sym->rname);
516 aop->size = FPTRSIZE;
520 /* only remaining is code / eeprom which will need pointer reg */
521 /* if it is in code space */
523 sym->aop = aop = newAsmop (0);
525 if (IN_CODESPACE (space))
528 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result, aop->code);
529 aop->size = getSize (sym->type);
530 emitcode ("ldi", "%s,<(%s)", aop->aopu.aop_ptr->name, sym->rname);
531 emitcode ("ldi", "%s,>(%s)", aop->aop_ptr2);
536 /*-----------------------------------------------------------------*/
537 /* aopForRemat - rematerialzes an object */
538 /*-----------------------------------------------------------------*/
540 aopForRemat (symbol * sym)
542 iCode *ic = sym->rematiCode;
543 asmop *aop = newAsmop (AOP_IMMD);
548 val += (int) operandLitValue (IC_RIGHT (ic));
549 else if (ic->op == '-')
550 val -= (int) operandLitValue (IC_RIGHT (ic));
554 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
558 sprintf (buffer, "(%s %c 0x%04x)",
559 OP_SYMBOL (IC_LEFT (ic))->rname,
560 val >= 0 ? '+' : '-', abs (val) & 0xffff);
562 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
564 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
565 strcpy (aop->aopu.aop_immd, buffer);
569 /*-----------------------------------------------------------------*/
570 /* regsInCommon - two operands have some registers in common */
571 /*-----------------------------------------------------------------*/
573 regsInCommon (operand * op1, operand * op2)
578 /* if they have registers in common */
579 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
582 sym1 = OP_SYMBOL (op1);
583 sym2 = OP_SYMBOL (op2);
585 if (sym1->nRegs == 0 || sym2->nRegs == 0)
588 for (i = 0; i < sym1->nRegs; i++) {
593 for (j = 0; j < sym2->nRegs; j++) {
597 if (sym2->regs[j] == sym1->regs[i])
605 /*-----------------------------------------------------------------*/
606 /* operandsEqu - equivalent */
607 /*-----------------------------------------------------------------*/
609 operandsEqu (operand * op1, operand * op2)
613 /* if they not symbols */
614 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
617 sym1 = OP_SYMBOL (op1);
618 sym2 = OP_SYMBOL (op2);
620 /* if both are itemps & one is spilt
621 and the other is not then false */
622 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
623 sym1->isspilt != sym2->isspilt) return FALSE;
625 /* if they are the same */
629 if (strcmp (sym1->rname, sym2->rname) == 0)
633 /* if left is a tmp & right is not */
634 if (IS_ITEMP (op1) &&
635 !IS_ITEMP (op2) && sym1->isspilt && (sym1->usl.spillLoc == sym2))
638 if (IS_ITEMP (op2) &&
640 sym2->isspilt && sym1->level > 0 && (sym2->usl.spillLoc == sym1))
646 /*-----------------------------------------------------------------*/
647 /* sameRegs - two asmops have the same registers */
648 /*-----------------------------------------------------------------*/
650 sameRegs (asmop * aop1, asmop * aop2)
657 if (aop1->type != AOP_REG || aop2->type != AOP_REG)
660 if (aop1->size != aop2->size)
663 for (i = 0; i < aop1->size; i++)
664 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
670 /*-----------------------------------------------------------------*/
671 /* isRegPair - for size 2 if this operand has a register pair */
672 /*-----------------------------------------------------------------*/
674 isRegPair (asmop * aop)
676 if (!aop || aop->size < 2)
678 if (aop->type == AOP_X || aop->type == AOP_Z)
680 if (aop->type != AOP_REG)
682 if ( ((aop->aopu.aop_reg[1]->rIdx - aop->aopu.aop_reg[0]->rIdx) == 1) &&
683 (aop->aopu.aop_reg[0]->rIdx & 1) == 0)
689 /*-----------------------------------------------------------------*/
690 /* allHigh - all registers are high registers */
691 /*-----------------------------------------------------------------*/
692 static int allHigh (asmop * aop)
696 if (aop->type == AOP_X || aop->type == AOP_Z)
698 if (aop->type != AOP_REG)
700 for (i=0; i < aop->size ; i++ )
701 if (aop->aopu.aop_reg[i]->rIdx < R16_IDX) return 0;
705 /*-----------------------------------------------------------------*/
706 /* aopOp - allocates an asmop for an operand : */
707 /*-----------------------------------------------------------------*/
709 aopOp (operand * op, iCode * ic, bool result)
718 /* if this a literal */
719 if (IS_OP_LITERAL (op)) {
720 op->aop = aop = newAsmop (AOP_LIT);
721 aop->aopu.aop_lit = op->operand.valOperand;
722 aop->size = getSize (operandType (op));
726 /* if already has a asmop then continue */
730 /* if the underlying symbol has a aop */
731 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop) {
732 op->aop = OP_SYMBOL (op)->aop;
736 /* if this is a true symbol */
737 if (IS_TRUE_SYMOP (op)) {
738 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
742 /* this is a temporary : this has
748 e) can be a return use only */
750 sym = OP_SYMBOL (op);
753 /* if the type is a conditional */
754 if (sym->regType & REG_CND) {
755 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
760 /* if it is spilt then two situations
762 b) has a spill location */
763 if (sym->isspilt || sym->nRegs == 0) {
765 /* rematerialize it NOW */
767 sym->aop = op->aop = aop = aopForRemat (sym);
768 aop->size = getSize (sym->type);
773 assert ("ACC_USE cannot happen in AVR\n");
778 aop = op->aop = sym->aop = newAsmop (AOP_STR);
779 aop->size = getSize (sym->type);
780 for (i = 0; i < (int) fAVRReturnSize; i++)
781 aop->aopu.aop_str[i] = fAVRReturn[i];
785 /* else spill location */
786 sym->aop = op->aop = aop =
787 aopForSym (ic, sym->usl.spillLoc, result);
788 aop->size = getSize (sym->type);
792 /* must be in a register */
793 sym->aop = op->aop = aop = newAsmop (AOP_REG);
794 aop->size = sym->nRegs;
795 for (i = 0; i < sym->nRegs; i++)
796 aop->aopu.aop_reg[i] = sym->regs[i];
799 /*-----------------------------------------------------------------*/
800 /* freeAsmop - free up the asmop given to an operand */
801 /*----------------------------------------------------------------*/
803 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
820 /* depending on the asmop type only three cases need work AOP_RO
821 , AOP_R1 && AOP_STK */
826 emitcode ("pop", "r26");
827 emitcode ("pop", "r27");
831 bitVectUnSetBit (ic->rUsed, X_IDX);
837 emitcode ("pop", "r30");
838 emitcode ("pop", "r31");
842 bitVectUnSetBit (ic->rUsed, Z_IDX);
848 int stk = aop->aopu.aop_stk + aop->size;
849 bitVectUnSetBit (ic->rUsed, X_IDX);
850 bitVectUnSetBit (ic->rUsed, Z_IDX);
852 getFreePtr (ic, &aop, FALSE, 0);
854 emitcode ("movw", "%s,r28");
856 if (stk <= 63 && stk > 0) {
857 emitcode ("adiw", "%s,0x%02x",
858 aop->aopu.aop_ptr->name,
862 emitcode ("subi", "%s,<(%d)",
863 aop->aopu.aop_ptr->name,
865 emitcode ("sbci", "%s,>(%d)",
872 emitcode ("pop", "r24");
873 emitcode ("st", "-%s,r24",
874 aop->type == AOP_X ? "X" : "Z");
879 freeAsmop (op, NULL, ic, TRUE);
881 emitcode ("pop", "r26");
882 emitcode ("pop", "r27");
887 emitcode ("pop", "r30");
888 emitcode ("pop", "r31");
895 /* all other cases just dealloc */
899 OP_SYMBOL (op)->aop = NULL;
900 /* if the symbol has a spill */
902 SPIL_LOC (op)->aop = NULL;
907 /*-----------------------------------------------------------------*/
908 /* aopGet - for fetching value of the aop */
909 /*-----------------------------------------------------------------*/
911 aopGet (asmop * aop, int offset)
916 /* offset is greater than
918 if (offset > (aop->size - 1) && aop->type != AOP_LIT)
921 /* depending on type */
925 if (offset > aop->coff) {
926 emitcode ("adiw", "%s,%d", aop->aopu.aop_ptr->name,
930 if (offset < aop->coff) {
931 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name,
936 emitcode ("ld", "%s,x",
937 (rs = ((offset & 1) ? "r25" : "r24")));
942 if (offset > aop->coff) {
943 emitcode ("adiw", "r30,%d",
947 emitcode ("sbiw", "r30,%d",
950 emitcode ("lpm", "%s,z",
951 (rs = ((offset & 1) ? "r25" : "r24")));
955 if (offset > aop->coff) {
956 emitcode ("ldd", "%s,z+%d",
958 ((offset & 1) ? "r25" : "r24")),
962 emitcode ("sbiw", "%s,%d",
963 aop->aopu.aop_ptr->name,
966 emitcode ("ld", "%s,z",
968 ((offset & 1) ? "r25" : "r24")));
975 emitcode ("lds", "%s,(%s)+%d",
976 (rs = ((offset & 1) ? "r25" : "r24")),
977 aop->aopu.aop_immd, offset);
981 emitcode ("lds", "%s,(%s)+%d",
982 (rs = ((offset & 1) ? "r25" : "r24")),
983 aop->aopu.aop_dir, offset);
987 return aop->aopu.aop_reg[offset]->name;
990 assert ("cannot be in bit space AOP_CRY\n");
994 s = aopLiteral (aop->aopu.aop_lit, offset);
995 emitcode ("ldi", "%s,<(%s)",
996 (rs = ((offset & 1) ? "r24" : "r25")), s);
1001 return aop->aopu.aop_str[offset];
1004 emitcode ("ldd", "%s,Y+%d",
1005 (rs = ((offset & 1) ? "r25" : "r24")),
1006 aop->aopu.aop_stk + offset);
1010 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1011 "aopget got unsupported aop->type");
1015 /*-----------------------------------------------------------------*/
1016 /* aopPut - puts a string for a aop */
1017 /*-----------------------------------------------------------------*/
1019 aopPut (asmop * aop, char *s, int offset)
1023 if (aop->size && offset > (aop->size - 1)) {
1024 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1025 "aopPut got offset > aop->size");
1029 /* will assign value to value */
1030 /* depending on where it is ofcourse */
1031 switch (aop->type) {
1034 sprintf (d, "(%s)+%d", aop->aopu.aop_dir, offset);
1037 sprintf (d, "%s", aop->aopu.aop_dir);
1040 emitcode ("sts", "%s,%s", d, s);
1044 if (toupper (*s) != 'R') {
1046 emitcode ("clr", "%s",
1047 aop->aopu.aop_reg[offset]->name);
1050 emitcode ("ldi", "r25,%s", s);
1051 emitcode ("mov", "%s,r35",
1052 aop->aopu.aop_reg[offset]->name);
1056 if (strcmp (aop->aopu.aop_reg[offset]->name, s)) {
1057 emitcode ("mov", "%s,%s",
1058 aop->aopu.aop_reg[offset]->name, s);
1064 if (offset > aop->coff) {
1065 emitcode ("adiw", "%s,%d", aop->aopu.aop_ptr->name,
1066 offset - aop->coff);
1069 if (offset < aop->coff) {
1070 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name,
1071 aop->coff - offset);
1075 emitcode ("st", "x,%s", s);
1080 if (offset > aop->coff) {
1081 emitcode ("adiw", "r30,%d",
1082 offset - aop->coff);
1085 emitcode ("sbiw", "r30,%d",
1086 aop->coff - offset);
1088 emitcode ("lpm", "%s,z", s);
1091 /* we can use lds */
1092 if (offset > aop->coff) {
1093 emitcode ("sdd", "z+%d,%s",
1094 offset - aop->coff, s);
1097 emitcode ("sbiw", "%s,%d",
1098 aop->aopu.aop_ptr->name,
1099 aop->coff - offset);
1101 emitcode ("ld", "%s,z", s);
1107 emitcode ("push", "%s", s);
1111 /* if used only for a condition code check */
1112 assert (toupper (*s) == 'R');
1114 emitcode ("xrl", "r0,r0");
1115 emitcode ("cpi", "%s,0", s);
1118 emitcode ("cpc", "r0,%s", s);
1124 if (strcmp (aop->aopu.aop_str[offset], s))
1125 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset],
1130 emitcode ("std", "y+%d,%s", offset, s);
1134 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1135 "aopPut got unsupported aop->type");
1141 #define AOP(op) op->aop
1142 #define AOP_TYPE(op) AOP(op)->type
1143 #define AOP_SIZE(op) AOP(op)->size
1144 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_X || \
1145 AOP_TYPE(x) == AOP_Z))
1146 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1147 ((x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R27_IDX)) || \
1148 (x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R31_IDX)) )))
1149 #define AOP_ISX(x) (x && (x->type == AOP_REG && \
1150 ((x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R27_IDX)))))
1151 #define AOP_ISZ(x) (x && (x->type == AOP_REG && \
1152 ((x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R31_IDX)))))
1154 /*-----------------------------------------------------------------*/
1155 /* genNotFloat - generates not for float operations */
1156 /*-----------------------------------------------------------------*/
1158 genNotFloat (operand * op, operand * res)
1164 /* we will put 127 in the first byte of
1166 aopPut (AOP (res), "127", 0);
1167 size = AOP_SIZE (op) - 1;
1170 l = aopGet (op->aop, offset++);
1174 emitcode ("or", "R0,%s", aopGet (op->aop, offset++));
1176 tlbl = newiTempLabel (NULL);
1178 tlbl = newiTempLabel (NULL);
1179 aopPut (res->aop, zero, 1);
1180 emitcode ("cpi", "r0,0");
1181 emitcode ("breq", "L%05d", tlbl->key);
1182 aopPut (res->aop, one, 1);
1183 emitcode ("", "L%05d:", tlbl->key);
1185 size = res->aop->size - 2;
1187 /* put zeros in the rest */
1189 aopPut (res->aop, zero, offset++);
1192 /*-----------------------------------------------------------------*/
1193 /* opIsGptr: returns non-zero if the passed operand is */
1194 /* a generic pointer type. */
1195 /*-----------------------------------------------------------------*/
1197 opIsGptr (operand * op)
1199 sym_link *type = operandType (op);
1201 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type)) {
1207 /*-----------------------------------------------------------------*/
1208 /* getDataSize - get the operand data size */
1209 /*-----------------------------------------------------------------*/
1211 getDataSize (operand * op)
1214 size = AOP_SIZE (op);
1215 if (size == GPTRSIZE) {
1216 sym_link *type = operandType (op);
1217 if (IS_GENPTR (type)) {
1218 /* generic pointer; arithmetic operations
1219 * should ignore the high byte (pointer type).
1227 /*-----------------------------------------------------------------*/
1228 /* toBoolean - emit code for orl a,operator(sizeop) */
1229 /*-----------------------------------------------------------------*/
1231 toBoolean (operand * oper, char *r, bool clr)
1233 int size = AOP_SIZE (oper);
1236 emitcode ("clr", "%s", r);
1238 emitcode ("or", "%s,%s", r, aopGet (AOP (oper), offset++));
1241 emitcode("mov","%s,%s",r,aopGet (AOP (oper), offset++));
1242 if (size) while (size--) emitcode ("or", "%s,%s", r, aopGet (AOP (oper), offset++));
1247 /*-----------------------------------------------------------------*/
1248 /* genNot - generate code for ! operation */
1249 /*-----------------------------------------------------------------*/
1254 sym_link *optype = operandType (IC_LEFT (ic));
1255 int size, offset = 1;
1257 /* assign asmOps to operand & result */
1258 aopOp (IC_LEFT (ic), ic, FALSE);
1259 aopOp (IC_RESULT (ic), ic, TRUE);
1261 /* if type float then do float */
1262 if (IS_FLOAT (optype)) {
1263 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1266 emitcode ("clr", "r24");
1267 tlbl = newiTempLabel (NULL);
1268 size = AOP_SIZE (IC_LEFT (ic));
1271 emitcode ("cpse", "%s,r24", aopGet (AOP (IC_LEFT (ic)), 0));
1276 emitcode ("cpc", "%s,r24",
1277 aopGet (AOP (IC_LEFT (ic)),
1280 emitcode ("cpi", "%s,0",
1281 aopGet (AOP (IC_LEFT (ic)),
1285 emitcode ("bne", "L%05d", tlbl->key);
1287 emitcode ("ldi", "r24,1");
1288 emitcode ("", "L%05d:", tlbl->key);
1289 aopPut (AOP (IC_RESULT (ic)), "r24", 0);
1290 size = AOP_SIZE (IC_RESULT (ic)) - 1;
1293 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
1297 /* release the aops */
1298 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1299 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1303 /*-----------------------------------------------------------------*/
1304 /* genCpl - generate code for complement */
1305 /*-----------------------------------------------------------------*/
1313 /* assign asmOps to operand & result */
1314 aopOp (IC_LEFT (ic), ic, FALSE);
1315 aopOp (IC_RESULT (ic), ic, TRUE);
1316 samer = sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)));
1317 size = AOP_SIZE (IC_RESULT (ic));
1319 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
1321 emitcode ("com", "%s", l);
1324 aopPut (AOP (IC_RESULT (ic)), l, offset);
1325 emitcode ("com", "%s",
1326 aopGet (AOP (IC_RESULT (ic)), offset));
1331 /* release the aops */
1332 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1333 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1336 /*-----------------------------------------------------------------*/
1337 /* genUminusFloat - unary minus for floating points */
1338 /*-----------------------------------------------------------------*/
1340 genUminusFloat (operand * op, operand * result)
1342 int size, offset = 0;
1344 /* for this we just need to flip the
1345 first it then copy the rest in place */
1346 size = AOP_SIZE (op) - 1;
1347 l = aopGet (AOP (op), 3);
1349 emitcode ("ldi", "r24,0x80");
1350 if (sameRegs (AOP (op), AOP (result))) {
1351 emitcode ("eor", "%s,r24", l);
1354 aopPut (AOP (result), l, 3);
1355 emitcode ("eor", "%s,r24", aopGet (AOP (result), 3));
1358 aopPut (AOP (result), aopGet (AOP (op), offset), offset);
1363 /*-----------------------------------------------------------------*/
1364 /* genUminus - unary minus code generation */
1365 /*-----------------------------------------------------------------*/
1367 genUminus (iCode * ic)
1370 sym_link *optype, *rtype;
1374 aopOp (IC_LEFT (ic), ic, FALSE);
1375 aopOp (IC_RESULT (ic), ic, TRUE);
1377 optype = operandType (IC_LEFT (ic));
1378 rtype = operandType (IC_RESULT (ic));
1380 /* if float then do float stuff */
1381 if (IS_FLOAT (optype)) {
1382 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1386 /* otherwise subtract from zero */
1387 size = AOP_SIZE (IC_LEFT (ic));
1389 samer = sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)));
1392 emitcode ("neg", "%s",
1393 aopGet (AOP (IC_LEFT (ic)), 0));
1396 aopPut (AOP (IC_RESULT (ic)),
1397 aopGet (AOP (IC_LEFT (ic)), 0), 0);
1398 emitcode ("neg", "%s",
1399 aopGet (AOP (IC_RESULT (ic)), 0));
1405 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
1407 aopPut (AOP (IC_RESULT (ic)), l, offset);
1408 l = aopGet (AOP (IC_RESULT (ic)), offset);
1411 emitcode ("com", "%s", l);
1413 emitcode ("neg", "%s", l);
1416 size = AOP_SIZE (IC_LEFT (ic)) - 1;
1419 emitcode ("sbci", "%s,0xff",
1420 aopGet (AOP (IC_RESULT (ic)), offset++));
1424 /* if any remaining bytes in the result */
1425 /* we just need to propagate the sign */
1426 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic))))) {
1427 symbol *tlbl = newiTempLabel (NULL);
1428 emitcode ("clr", "r0");
1429 emitcode ("brcc", "L%05d", tlbl->key);
1430 emitcode ("com", "r0");
1431 emitcode ("", "L%05d:", tlbl->key);
1433 aopPut (AOP (IC_RESULT (ic)), "r0", offset++);
1437 /* release the aops */
1438 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1439 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1442 /*-----------------------------------------------------------------*/
1443 /* assignResultValue - */
1444 /*-----------------------------------------------------------------*/
1446 assignResultValue (operand * oper)
1449 int size = AOP_SIZE (oper);
1451 aopPut (AOP (oper), fAVRReturn[offset], offset);
1456 /*-----------------------------------------------------------------*/
1457 /* saveZreg - if indirect call then save z-pointer register */
1458 /*-----------------------------------------------------------------*/
1460 saveZreg (iCode * ic)
1462 /* only if live accross this call */
1463 if (ic->regsSaved == 0 &&
1464 (bitVectBitValue (ic->rMask, R30_IDX) ||
1465 bitVectBitValue (ic->rMask, R31_IDX))) {
1467 emitcode ("push", "r30");
1468 emitcode ("push", "r31");
1472 /*-----------------------------------------------------------------*/
1473 /* popZreg - restore values of zreg */
1474 /*-----------------------------------------------------------------*/
1476 popZreg (iCode * ic)
1478 if (ic->regsSaved) {
1479 emitcode ("pop", "r31");
1480 emitcode ("pop", "r30");
1484 /*-----------------------------------------------------------------*/
1485 /* genIpush - genrate code for pushing this gets a little complex */
1486 /*-----------------------------------------------------------------*/
1488 genIpush (iCode * ic)
1490 int size, offset = 0;
1494 if (!ic->parmPush) {
1495 /* and the item is spilt then do nothing */
1496 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1501 for (lic = ic->next; lic; lic = lic->next)
1502 if (lic->op == PCALL)
1508 /* this is a paramter push */
1509 aopOp (IC_LEFT (ic), ic, FALSE);
1510 size = AOP_SIZE (IC_LEFT (ic));
1512 l = aopGet (AOP (IC_LEFT (ic)), offset++);
1513 emitcode ("push", "%s", l);
1516 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1519 /*-----------------------------------------------------------------*/
1520 /* genIpop - recover the registers: can happen only for spilling */
1521 /*-----------------------------------------------------------------*/
1523 genIpop (iCode * ic)
1528 /* if the temp was not pushed then */
1529 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1532 aopOp (IC_LEFT (ic), ic, FALSE);
1533 size = AOP_SIZE (IC_LEFT (ic));
1534 offset = (size - 1);
1536 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--));
1538 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1541 /*-----------------------------------------------------------------*/
1542 /* genCall - generates a call statement */
1543 /*-----------------------------------------------------------------*/
1545 genCall (iCode * ic)
1548 /* if send set is not empty the assign */
1552 for (sic = setFirstItem (_G.sendSet); sic;
1553 sic = setNextItem (_G.sendSet)) {
1554 int size, offset = 0;
1555 aopOp (IC_LEFT (sic), sic, FALSE);
1556 size = AOP_SIZE (IC_LEFT (sic));
1559 aopGet (AOP (IC_LEFT (sic)), offset);
1561 sprintf (buffer, "r%d", rnum++);
1563 emitcode ("mov", "%s,%s", b, l);
1566 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1571 emitcode ("call", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1572 OP_SYMBOL (IC_LEFT (ic))->rname :
1573 OP_SYMBOL (IC_LEFT (ic))->name));
1575 /* if we need assign a result value */
1576 if ((IS_ITEMP (IC_RESULT (ic)) &&
1577 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1578 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1579 IS_TRUE_SYMOP (IC_RESULT (ic))) {
1581 aopOp (IC_RESULT (ic), ic, FALSE);
1582 assignResultValue (IC_RESULT (ic));
1583 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1586 /* adjust the stack for parameters if required */
1587 if (ic->parmBytes) {
1588 if (ic->parmBytes > 63) {
1589 emitcode ("sbiw", "r28,%d", ic->parmBytes);
1592 emitcode ("subi", "r28,<(%d)",
1594 emitcode ("sbci", "r29,>(%d)",
1601 /*-----------------------------------------------------------------*/
1602 /* genPcall - generates a call by pointer statement */
1603 /*-----------------------------------------------------------------*/
1605 genPcall (iCode * ic)
1611 aopOp (IC_LEFT (ic), ic, FALSE);
1612 emitcode ("mov", "r30", aopGet (AOP (IC_LEFT (ic)), 0));
1613 emitcode ("mov", "r31", aopGet (AOP (IC_RIGHT (ic)), 0));
1614 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1616 /* if send set is not empty the assign */
1620 for (sic = setFirstItem (_G.sendSet); sic;
1621 sic = setNextItem (_G.sendSet)) {
1622 int size, offset = 0;
1623 aopOp (IC_LEFT (sic), sic, FALSE);
1624 size = AOP_SIZE (IC_LEFT (sic));
1627 aopGet (AOP (IC_LEFT (sic)), offset);
1629 sprintf (b, "r%d", rnum++);
1631 emitcode ("mov", "%s,%s", b, l);
1634 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1639 emitcode ("icall", "");
1641 /* if we need assign a result value */
1642 if ((IS_ITEMP (IC_RESULT (ic)) &&
1643 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1644 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1645 IS_TRUE_SYMOP (IC_RESULT (ic))) {
1647 aopOp (IC_RESULT (ic), ic, FALSE);
1649 assignResultValue (IC_RESULT (ic));
1650 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1653 /* adjust the stack for parameters if
1655 if (ic->parmBytes) {
1657 if (ic->parmBytes > 3) {
1658 emitcode ("mov", "a,%s", spname);
1659 emitcode ("add", "a,#0x%02x",
1660 (-ic->parmBytes) & 0xff);
1661 emitcode ("mov", "%s,a", spname);
1664 for (i = 0; i < ic->parmBytes; i++)
1665 emitcode ("dec", "%s", spname);
1669 /* adjust the stack for parameters if required */
1670 if (ic->parmBytes) {
1671 if (ic->parmBytes > 63) {
1672 emitcode ("sbiw", "r28,%d", ic->parmBytes);
1675 emitcode ("subi", "r28,<(%d)",
1677 emitcode ("sbci", "r29,>(%d)",
1685 /*-----------------------------------------------------------------*/
1686 /* resultRemat - result is rematerializable */
1687 /*-----------------------------------------------------------------*/
1689 resultRemat (iCode * ic)
1691 if (SKIP_IC (ic) || ic->op == IFX)
1694 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic))) {
1695 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
1696 if (sym->remat && !POINTER_SET (ic))
1703 #if defined(__BORLANDC__) || defined(_MSC_VER)
1704 #define STRCASECMP stricmp
1706 #define STRCASECMP strcasecmp
1709 /*-----------------------------------------------------------------*/
1710 /* genFunction - generated code for function entry */
1711 /*-----------------------------------------------------------------*/
1713 genFunction (iCode * ic)
1720 /* create the function header */
1721 emitcode (";", "-----------------------------------------");
1722 emitcode (";", " function %s",
1723 (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
1724 emitcode (";", "-----------------------------------------");
1726 emitcode ("", "%s:", sym->rname);
1727 ftype = operandType (IC_LEFT (ic));
1729 /* if critical function then turn interrupts off */
1730 if (IFFUNC_ISCRITICAL (ftype))
1731 emitcode ("cli", "");
1733 if (IFFUNC_ISISR (sym->type)) {
1736 /* save the preserved registers that are used in this function */
1737 for (i = R2_IDX; i <= R15_IDX; i++) {
1738 if (bitVectBitValue (sym->regsUsed, i)) {
1740 emitcode ("push", "%s", avr_regWithIdx (i)->name);
1743 /* now for the pointer registers */
1744 if (bitVectBitValue (sym->regsUsed, R26_IDX)) {
1746 emitcode ("push", "r26");
1748 if (bitVectBitValue (sym->regsUsed, R27_IDX)) {
1750 emitcode ("push", "r27");
1752 if (bitVectBitValue (sym->regsUsed, R30_IDX)) {
1754 emitcode ("push", "r30");
1756 if (bitVectBitValue (sym->regsUsed, R31_IDX)) {
1758 emitcode ("push", "r31");
1760 /* adjust the stack for the function */
1762 emitcode ("push", "r28");
1763 emitcode ("push", "r29");
1764 emitcode ("in", "r28,__SP_L__");
1765 emitcode ("in", "r29,__SP_H__");
1766 if (sym->stack <= 63) {
1767 emitcode ("sbiw", "r28,%d", sym->stack);
1770 emitcode ("subi", "r28,<(%d)", sym->stack);
1771 emitcode ("sbci", "r29,>(%d)", sym->stack);
1773 emitcode ("out", "__SP_L__,r28");
1774 emitcode ("out", "__SP_H__,r29");
1778 /*-----------------------------------------------------------------*/
1779 /* genEndFunction - generates epilogue for functions */
1780 /*-----------------------------------------------------------------*/
1782 genEndFunction (iCode * ic)
1784 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
1787 /* restore stack pointer */
1789 if (sym->stack <= 63) {
1790 emitcode ("adiw", "r28,%d", sym->stack);
1793 emitcode ("subi", "r28,<(-%d)", sym->stack);
1794 emitcode ("sbci", "r29,>(-%d)", sym->stack);
1796 emitcode ("out", "__SP_L__,r28");
1797 emitcode ("out", "__SP_H__,r29");
1799 /* pop frame pointer */
1800 emitcode ("pop", "r29");
1801 emitcode ("pop", "r28");
1803 /* restore preserved registers */
1804 if (bitVectBitValue (sym->regsUsed, R31_IDX)) {
1806 emitcode ("pop", "r31");
1808 if (bitVectBitValue (sym->regsUsed, R30_IDX)) {
1810 emitcode ("pop", "r30");
1812 if (bitVectBitValue (sym->regsUsed, R27_IDX)) {
1814 emitcode ("pop", "r27");
1816 if (bitVectBitValue (sym->regsUsed, R26_IDX)) {
1818 emitcode ("pop", "r26");
1820 for (i = R15_IDX; i >= R2_IDX; i--) {
1821 if (bitVectBitValue (sym->regsUsed, i)) {
1823 emitcode ("pop", "%s", avr_regWithIdx (i)->name);
1827 if (IFFUNC_ISCRITICAL (sym->type))
1828 emitcode ("sti", "");
1830 if (IFFUNC_ISISR (sym->type)) {
1831 emitcode ("rti", "");
1834 emitcode ("ret", "");
1839 /*-----------------------------------------------------------------*/
1840 /* genRet - generate code for return statement */
1841 /*-----------------------------------------------------------------*/
1845 int size, offset = 0;
1847 /* if we have no return value then
1848 just generate the "ret" */
1852 /* we have something to return then
1853 move the return value into place */
1854 aopOp (IC_LEFT (ic), ic, FALSE);
1855 size = AOP_SIZE (IC_LEFT (ic));
1858 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) {
1859 emitcode ("ldi", "%s,%s(%d)", fAVRReturn[offset],
1861 (int) floatFromVal (AOP (IC_LEFT (ic))->
1862 aopu.aop_lit), offset);
1866 l = aopGet (AOP (IC_LEFT (ic)), offset);
1867 if (strcmp (fAVRReturn[offset], l))
1868 emitcode ("mov", "%s,%s", fAVRReturn[offset],
1874 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1877 /* generate a jump to the return label
1878 if the next is not the return statement */
1879 if (!(ic->next && ic->next->op == LABEL &&
1880 IC_LABEL (ic->next) == returnLabel))
1882 emitcode ("rjmp", "L%05d", returnLabel->key);
1886 /*-----------------------------------------------------------------*/
1887 /* genLabel - generates a label */
1888 /*-----------------------------------------------------------------*/
1890 genLabel (iCode * ic)
1892 /* special case never generate */
1893 if (IC_LABEL (ic) == entryLabel)
1896 emitcode ("", "L%05d:", IC_LABEL (ic)->key);
1899 /*-----------------------------------------------------------------*/
1900 /* genGoto - generates a ljmp */
1901 /*-----------------------------------------------------------------*/
1903 genGoto (iCode * ic)
1905 emitcode ("rjmp", "L%05d", (IC_LABEL (ic)->key));
1908 /*-----------------------------------------------------------------*/
1909 /* genPlusIncr :- does addition with increment if possible */
1910 /*-----------------------------------------------------------------*/
1912 genPlusIncr (iCode * ic)
1914 unsigned int icount;
1917 /* will try to generate an increment */
1918 /* if the right side is not a literal
1920 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
1923 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.
1926 /* if the sizes are greater than 2 or they are not the same regs
1928 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1931 /* so we know LEFT & RESULT in the same registers and add
1933 /* for short & char types */
1934 if (AOP_SIZE (IC_RESULT (ic)) < 2) {
1936 emitcode ("inc", "%s",
1937 aopGet (AOP (IC_LEFT (ic)), 0));
1940 if (AOP_ISHIGHREG( AOP (IC_LEFT (ic)),0)) {
1941 emitcode ("subi", "%s,<(%d)",
1942 aopGet (AOP (IC_LEFT (ic)), 0), 0-icount);
1947 for (offset = 0 ; offset < AOP_SIZE(IC_RESULT(ic)) ; offset++) {
1948 if (!(AOP_ISHIGHREG(AOP(IC_RESULT(ic)),offset))) return FALSE;
1951 if (AOP_SIZE (IC_RESULT (ic)) <= 3) {
1952 /* if register pair and starts with 26/30 then adiw */
1953 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0
1955 && (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX) ||
1956 IS_REGIDX (AOP (IC_RESULT (ic)), R24_IDX) ||
1957 IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX))) {
1958 emitcode ("adiw", "%s,%d",
1959 aopGet (AOP (IC_RESULT (ic)), 0), icount);
1964 emitcode ("subi", "%s,<(%d)",
1965 aopGet (AOP (IC_RESULT (ic)), 0), 0-icount);
1966 emitcode ("sbci", "%s,>(%d)",
1967 aopGet (AOP (IC_RESULT (ic)), 1), 0-icount);
1971 /* for 32 bit longs */
1972 emitcode ("subi", "%s,<(%d)", aopGet (AOP (IC_RESULT (ic)), 0),
1974 emitcode ("sbci", "%s,>(%d)", aopGet (AOP (IC_RESULT (ic)), 1),
1976 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2),
1978 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3),
1984 /* This is the pure and virtuous version of this code.
1985 * I'm pretty certain it's right, but not enough to toss the old
1989 adjustArithmeticResult (iCode * ic)
1991 if (opIsGptr (IC_RESULT (ic)) &&
1992 opIsGptr (IC_LEFT (ic)) &&
1993 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)))) {
1994 aopPut (AOP (IC_RESULT (ic)),
1995 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1),
1999 if (opIsGptr (IC_RESULT (ic)) &&
2000 opIsGptr (IC_RIGHT (ic)) &&
2001 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)))) {
2002 aopPut (AOP (IC_RESULT (ic)),
2003 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1),
2007 if (opIsGptr (IC_RESULT (ic)) &&
2008 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2009 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2010 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2011 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)))) {
2013 sprintf (buffer, "%d",
2014 pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2015 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2019 /*-----------------------------------------------------------------*/
2020 /* genPlus - generates code for addition */
2021 /*-----------------------------------------------------------------*/
2023 genPlus (iCode * ic)
2025 int size, offset = 0;
2029 /* special cases :- */
2031 aopOp (IC_LEFT (ic), ic, FALSE);
2032 aopOp (IC_RIGHT (ic), ic, FALSE);
2033 aopOp (IC_RESULT (ic), ic, TRUE);
2035 /* if I can do an increment instead
2036 of add then GOOD for ME */
2037 if (genPlusIncr (ic) == TRUE)
2040 size = getDataSize (IC_RESULT (ic));
2041 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2045 aopPut (AOP (IC_RESULT (ic)),
2046 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2048 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
2055 emitcode (l, "%s,%s",
2056 aopGet (AOP (IC_RESULT (ic)), offset),
2057 aopGet (AOP (IC_RIGHT (ic)), offset));
2060 if (AOP_ISHIGHREG( AOP( IC_RESULT(ic)),offset)) {
2066 emitcode (l, "%s,%s(-%d)",
2067 aopGet (AOP (IC_RESULT (ic)), offset),
2069 (int) floatFromVal (AOP (IC_RIGHT (ic))->
2077 emitcode (l, "%s,%s",
2078 aopGet (AOP (IC_RESULT (ic)), offset),
2079 aopGet (AOP (IC_RIGHT (ic)), offset));
2085 adjustArithmeticResult (ic);
2088 freeAsmop (IC_LEFT (ic), NULL, ic,
2089 (RESULTONSTACK (ic) ? FALSE : TRUE));
2090 freeAsmop (IC_RIGHT (ic), NULL, ic,
2091 (RESULTONSTACK (ic) ? FALSE : TRUE));
2092 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2095 /*-----------------------------------------------------------------*/
2096 /* genMinusDec :- does subtraction with deccrement if possible */
2097 /*-----------------------------------------------------------------*/
2099 genMinusDec (iCode * ic)
2101 unsigned int icount;
2104 /* will try to generate an increment */
2105 /* if the right side is not a literal
2107 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2111 (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.
2114 /* if the sizes are greater than 2 or they are not the same regs
2116 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2119 /* so we know LEFT & RESULT in the same registers and add
2121 /* for short & char types */
2122 if (AOP_SIZE (IC_RESULT (ic)) < 2) {
2124 emitcode ("dec", "%s",
2125 aopGet (AOP (IC_LEFT (ic)), 0));
2128 if (AOP_ISHIGHREG( AOP ( IC_LEFT(ic)),0)) {
2129 emitcode ("subi", "%s,<(%d)",
2130 aopGet (AOP (IC_LEFT (ic)), 0), icount);
2135 for (offset = 0 ; offset < AOP_SIZE(IC_RESULT(ic)) ; offset++) {
2136 if (!(AOP_ISHIGHREG(AOP(IC_RESULT(ic)),offset))) return FALSE;
2139 if (AOP_SIZE (IC_RESULT (ic)) <= 3) {
2140 /* if register pair and starts with 26/30 then adiw */
2141 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0
2143 && (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX) ||
2144 IS_REGIDX (AOP (IC_RESULT (ic)), R24_IDX) ||
2145 IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX))) {
2146 emitcode ("sbiw", "%s,%d",
2147 aopGet (AOP (IC_RESULT (ic)), 0), icount);
2152 emitcode ("subi", "%s,<(%d)",
2153 aopGet (AOP (IC_RESULT (ic)), 0), icount);
2154 emitcode ("sbci", "%s,>(%d)",
2155 aopGet (AOP (IC_RESULT (ic)), 1), icount);
2158 /* for 32 bit longs */
2159 emitcode ("subi", "%s,<(%d)", aopGet (AOP (IC_RESULT (ic)), 0),
2161 emitcode ("sbci", "%s,>(%d)", aopGet (AOP (IC_RESULT (ic)), 1),
2163 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2),
2165 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3),
2171 /*-----------------------------------------------------------------*/
2172 /* genMinus - generates code for subtraction */
2173 /*-----------------------------------------------------------------*/
2175 genMinus (iCode * ic)
2177 int size, offset = 0, samer;
2180 aopOp (IC_LEFT (ic), ic, FALSE);
2181 aopOp (IC_RIGHT (ic), ic, FALSE);
2182 aopOp (IC_RESULT (ic), ic, TRUE);
2184 /* if I can do an decrement instead
2185 of subtract then GOOD for ME */
2186 if (genMinusDec (ic) == TRUE)
2189 size = getDataSize (IC_RESULT (ic));
2190 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2193 aopPut (AOP (IC_RESULT (ic)),
2194 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2196 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
2203 emitcode (l, "%s,%s",
2204 aopGet (AOP (IC_RESULT (ic)), offset),
2205 aopGet (AOP (IC_RIGHT (ic)), offset));
2208 if (AOP_ISHIGHREG(AOP (IC_RESULT (ic)),offset)) {
2214 emitcode (l, "%s,%s(%d)",
2215 aopGet (AOP (IC_RESULT (ic)), offset),
2217 (int) floatFromVal (AOP (IC_RIGHT (ic))->
2225 emitcode (l, "%s,%s",
2226 aopGet (AOP (IC_RESULT (ic)), offset),
2227 aopGet (AOP (IC_RIGHT (ic)), offset));
2233 adjustArithmeticResult (ic);
2236 freeAsmop (IC_LEFT (ic), NULL, ic,
2237 (RESULTONSTACK (ic) ? FALSE : TRUE));
2238 freeAsmop (IC_RIGHT (ic), NULL, ic,
2239 (RESULTONSTACK (ic) ? FALSE : TRUE));
2240 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2243 /*-----------------------------------------------------------------*/
2244 /* genMultOneByte : 8 bit multiplication & division */
2245 /*-----------------------------------------------------------------*/
2247 genMultOneByte (operand * left, operand * right, operand * result)
2249 sym_link *opetype = operandType (result);
2253 /* (if two literals, the value is computed before) */
2254 /* if one literal, literal on the right */
2255 if (AOP_TYPE (left) == AOP_LIT) {
2261 size = AOP_SIZE (result);
2263 if (SPEC_USIGN (opetype)) {
2264 emitcode ("mul", "%s,%s", aopGet (AOP (left), 0),
2265 aopGet (AOP (right), 0));
2268 emitcode ("muls", "%s,%s", aopGet (AOP (left), 0),
2269 aopGet (AOP (right), 0));
2271 aopPut (AOP (result), "r0", 0);
2273 aopPut (AOP (result), "r1", 1);
2276 if (SPEC_USIGN (opetype)) {
2278 aopPut (AOP (result), zero, offset++);
2283 lbl = newiTempLabel (NULL);
2284 emitcode ("ldi", "r24,0");
2285 emitcode ("brcc", "L%05d", lbl->key);
2286 emitcode ("ldi", "r24,0xff)");
2287 emitcode ("", "L%05d:", lbl->key);
2289 aopPut (AOP (result), "r24",
2297 /*-----------------------------------------------------------------*/
2298 /* genMult - generates code for multiplication */
2299 /*-----------------------------------------------------------------*/
2301 genMult (iCode * ic)
2303 operand *left = IC_LEFT (ic);
2304 operand *right = IC_RIGHT (ic);
2305 operand *result = IC_RESULT (ic);
2307 /* assign the amsops */
2308 aopOp (left, ic, FALSE);
2309 aopOp (right, ic, FALSE);
2310 aopOp (result, ic, TRUE);
2312 /* if both are of size == 1 */
2313 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1) {
2314 genMultOneByte (left, right, result);
2318 /* should have been converted to function call */
2322 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2323 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2324 freeAsmop (result, NULL, ic, TRUE);
2327 /*-----------------------------------------------------------------*/
2328 /* genDiv - generates code for division */
2329 /*-----------------------------------------------------------------*/
2333 /* should have been converted to function call */
2337 /*-----------------------------------------------------------------*/
2338 /* genMod - generates code for division */
2339 /*-----------------------------------------------------------------*/
2343 /* should have been converted to function call */
2355 /*-----------------------------------------------------------------*/
2356 /* revavrcnd - reverse a conditional for avr */
2357 /*-----------------------------------------------------------------*/
2359 revavrcnd (int type)
2371 for (i = 0; i < (sizeof (rar) / sizeof (rar[0])); i++) {
2372 if (rar[i].type == type)
2373 return rar[i].rtype;
2374 if (rar[i].rtype == type)
2377 assert (0); /* cannot happen */
2378 return 0; /* makes the compiler happy */
2381 static char *br_name[4] = { "breq", "brne", "brlt", "brge" };
2382 static char *br_uname[4] = { "breq", "brne", "brlo", "brcc" };
2384 /*-----------------------------------------------------------------*/
2385 /* genBranch - generate the branch instruction */
2386 /*-----------------------------------------------------------------*/
2388 genBranch (iCode * ifx, int br_type, int sign)
2390 int tj = (IC_TRUE (ifx) ? 1 : 0);
2392 if (tj) { /* if true jump */
2393 char *nm = (sign ? br_name[br_type] : br_uname[br_type]);
2394 emitcode (nm, "L%05d", IC_TRUE (ifx)->key);
2396 else { /* if false jump */
2397 int rtype = revavrcnd (br_type);
2398 char *nm = (sign ? br_name[rtype] : br_uname[rtype]);
2399 emitcode (nm, "L%05d", IC_FALSE (ifx)->key);
2404 /*-----------------------------------------------------------------*/
2405 /* genCmp - compare & jump */
2406 /*-----------------------------------------------------------------*/
2408 genCmp (iCode * ic, iCode * ifx, int br_type)
2410 operand *left, *right, *result;
2411 sym_link *letype, *retype;
2413 int sign, size, offset = 0;
2415 left = IC_LEFT (ic);
2416 right = IC_RIGHT (ic);
2417 result = IC_RESULT (ic);
2419 letype = getSpec (operandType (left));
2420 retype = getSpec (operandType (right));
2421 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
2423 /* assign the amsops */
2424 aopOp (left, ic, FALSE);
2425 aopOp (right, ic, FALSE);
2426 aopOp (result, ic, TRUE);
2427 size = AOP_SIZE (left);
2431 if (AOP_TYPE (right) == AOP_LIT) {
2432 emitcode ("cpi", "%s,<(%d)",
2433 aopGet (AOP (left), 0),
2435 floatFromVal (AOP (IC_RIGHT (ic))->
2437 genBranch (ifx, br_type, sign);
2439 else { /* right != literal */
2440 emitcode ("cp", "%s,%s",
2441 aopGet (AOP (left), 0),
2442 aopGet (AOP (right), 0));
2443 genBranch (ifx, br_type, sign);
2446 else { /* size != 1 */
2449 emitcode ("cp", "%s,%s",
2450 aopGet (AOP (left), 0),
2451 aopGet (AOP (right), 0));
2453 emitcode ("cpc", "%s,%s",
2454 aopGet (AOP (left), offset),
2455 aopGet (AOP (right),
2459 genBranch (ifx, br_type, sign);
2463 emitcode ("clr", "r0");
2466 emitcode ("cp", "%s,%s",
2467 aopGet (AOP (left), 0),
2468 aopGet (AOP (right), 0));
2470 emitcode ("cpc", "%s,%s",
2471 aopGet (AOP (left), offset),
2472 aopGet (AOP (right), offset));
2475 lbl = newiTempLabel (NULL);
2476 br_type = revavrcnd (br_type);
2478 emitcode (br_uname[br_type], "L%05d", lbl->key);
2480 emitcode (br_name[br_type], "L%05d", lbl->key);
2481 emitcode ("inc", "r0");
2482 emitcode ("", "L%05d:", lbl->key);
2483 aopPut (AOP (result), "r0", 0);
2484 size = AOP_SIZE (result) - 1;
2487 aopPut (AOP (result), zero, offset++);
2490 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2491 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2492 freeAsmop (result, NULL, ic, TRUE);
2495 /*-----------------------------------------------------------------*/
2496 /* genCmpGt :- greater than comparison */
2497 /*-----------------------------------------------------------------*/
2499 genCmpGt (iCode * ic, iCode * ifx)
2501 /* should have transformed by the parser */
2505 /*-----------------------------------------------------------------*/
2506 /* genCmpLt - less than comparisons */
2507 /*-----------------------------------------------------------------*/
2509 genCmpLt (iCode * ic, iCode * ifx)
2511 genCmp (ic, ifx, AVR_LT);
2514 /*-----------------------------------------------------------------*/
2515 /* genCmpEq - generates code for equal to */
2516 /*-----------------------------------------------------------------*/
2518 genCmpEq (iCode * ic, iCode * ifx)
2520 genCmp (ic, ifx, AVR_EQ);
2523 /*-----------------------------------------------------------------*/
2524 /* genCmpNe - generates code for not equal to */
2525 /*-----------------------------------------------------------------*/
2527 genCmpNe (iCode * ic, iCode * ifx)
2529 genCmp (ic, ifx, AVR_NE);
2532 /*-----------------------------------------------------------------*/
2533 /* genCmpGe - generates code for greater than equal to */
2534 /*-----------------------------------------------------------------*/
2536 genCmpGe (iCode * ic, iCode * ifx)
2538 genCmp (ic, ifx, AVR_GE);
2541 /*-----------------------------------------------------------------*/
2542 /* genCmpLe - generates code for less than equal to */
2543 /*-----------------------------------------------------------------*/
2545 genCmpLe (iCode * ic, iCode * ifx)
2547 operand *left = IC_LEFT (ic);
2548 operand *right = IC_RIGHT (ic);
2550 IC_RIGHT (ic) = left;
2551 IC_LEFT (ic) = right;
2552 genCmp (ic, ifx, AVR_GE);
2555 /*-----------------------------------------------------------------*/
2556 /* ifxForOp - returns the icode containing the ifx for operand */
2557 /*-----------------------------------------------------------------*/
2559 ifxForOp (operand * op, iCode * ic)
2561 /* if true symbol then needs to be assigned */
2562 if (IS_TRUE_SYMOP (op))
2565 /* if this has register type condition and
2566 the next instruction is ifx with the same operand
2567 and live to of the operand is upto the ifx only then */
2569 ic->next->op == IFX &&
2570 IC_COND (ic->next)->key == op->key &&
2571 OP_SYMBOL (op)->liveTo <= ic->next->seq) return ic->next;
2576 /*-----------------------------------------------------------------*/
2577 /* genAndOp - for && operation */
2578 /*-----------------------------------------------------------------*/
2580 genAndOp (iCode * ic)
2582 operand *left, *right, *result;
2586 /* note here that && operations that are in an
2587 if statement are taken away by backPatchLabels
2588 only those used in arthmetic operations remain */
2589 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2590 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2591 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
2593 tlbl = newiTempLabel (NULL);
2594 toBoolean (left, "r0", TRUE);
2595 toBoolean (right, "r1", TRUE);
2596 emitcode ("and", "r0,r1");
2597 emitcode ("ldi", "r24,1");
2598 emitcode ("breq", "L%05d", tlbl->key);
2599 emitcode ("dec", "r24");
2600 emitcode ("", "L%05d:", tlbl->key);
2601 aopPut (AOP (result), "r24", 0);
2602 size = AOP_SIZE (result) - 1;
2605 aopPut (AOP (result), zero, offset++);
2607 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2608 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2609 freeAsmop (result, NULL, ic, TRUE);
2613 /*-----------------------------------------------------------------*/
2614 /* genOrOp - for || operation */
2615 /*-----------------------------------------------------------------*/
2617 genOrOp (iCode * ic)
2619 operand *left, *right, *result;
2623 /* note here that || operations that are in an
2624 if statement are taken away by backPatchLabels
2625 only those used in arthmetic operations remain */
2626 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2627 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2628 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
2630 tlbl = newiTempLabel (NULL);
2631 toBoolean (left, "r0", TRUE);
2632 toBoolean (right, "r0", FALSE);
2633 emitcode ("ldi", "r24,1");
2634 emitcode ("breq", "L%05d", tlbl->key);
2635 emitcode ("dec", "r24");
2636 emitcode ("", "L%05d:", tlbl->key);
2637 aopPut (AOP (result), "r24", 0);
2638 size = AOP_SIZE (result) - 1;
2641 aopPut (AOP (result), zero, offset++);
2643 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2644 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2645 freeAsmop (result, NULL, ic, TRUE);
2649 AVR_AND = 0, AVR_OR, AVR_XOR
2651 static char *bopnames_lit[] = { "andi", "ori" };
2652 static char *bopnames[] = { "and", "or", "eor" };
2653 /*-----------------------------------------------------------------*/
2654 /* genBitWise - generate bitwise operations */
2655 /*-----------------------------------------------------------------*/
2657 genBitWise (iCode * ic, iCode * ifx, int bitop)
2659 operand *left, *right, *result;
2660 int size, offset = 0;
2665 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2666 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2667 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
2669 size = AOP_SIZE (left);
2671 if (ifx) { /* used only for jumps */
2672 if (AOP_TYPE (right) == AOP_LIT &&
2673 (bitop == AVR_AND || bitop == AVR_OR)) {
2675 (int) floatFromVal (AOP (right)->aopu.
2677 int p2 = powof2 (lit);
2678 if (bitop == AVR_AND && p2) { /* right side is a power of 2 */
2679 l = aopGet (AOP (left), p2 / 8);
2680 if (IC_TRUE (ifx)) {
2681 emitcode ("sbrc", "%s,%d", l,
2683 emitcode ("rjmp", "L%05d",
2684 IC_TRUE (ifx)->key);
2687 emitcode ("sbrs", "%s,%d", l,
2689 emitcode ("rjmp", "L%05d",
2690 IC_FALSE (ifx)->key);
2693 else { /* right not power of two */
2694 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2696 if (eh && AOP_ISHIGHREG(AOP(IC_LEFT(ic)),0)) {
2697 emitcode (bopnames_lit[bitop],
2699 aopGet (AOP (IC_LEFT (ic)), 0), lit);
2702 MOVR24 (aopGet (AOP (IC_LEFT (ic)), 0));
2703 emitcode (bopnames_lit[bitop], "r24,<(%d)", lit);
2705 lbl = newiTempLabel (NULL);
2706 if (IC_TRUE (ifx)) {
2707 emitcode ("breq", "L%05d", lbl->key);
2708 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2711 emitcode ("brne", "L%05d", lbl->key);
2712 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)-> key);
2714 emitcode ("", "L%05d:", lbl->key);
2716 else if (size == 2) {
2717 emitcode ("mov", "r24,%s", aopGet (AOP (IC_LEFT (ic)), 0));
2718 emitcode ("mov", "r25,%s", aopGet (AOP (IC_LEFT (ic)), 1));
2719 emitcode (bopnames_lit[bitop], "r24,<(%d)", lit);
2720 emitcode (bopnames_lit[bitop], "r25,>(%d)", lit);
2721 emitcode ("sbiw", "r24,0");
2722 lbl = newiTempLabel (NULL);
2723 if (IC_TRUE (ifx)) {
2724 emitcode ("breq", "L%05d", lbl->key);
2725 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2728 emitcode ("brne", "L%05d", lbl->key);
2729 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2731 emitcode ("", "L%05d:", lbl->key);
2734 lbl = newiTempLabel (NULL);
2735 lbl1 = newiTempLabel (NULL);
2737 if (eh && AOP_ISHIGHREG(AOP(IC_LEFT(ic)),offset)) {
2738 emitcode (bopnames_lit [bitop], "%s,<(%d)",
2739 aopGet (AOP (IC_LEFT (ic)), offset),
2743 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
2745 emitcode ("andi", "r24,<(%d)", lit);
2747 emitcode ("brne", "L%05d", lbl->key);
2752 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)-> key);
2754 emitcode ("rjmp", "L%05d", lbl1->key);
2755 emitcode ("", "L%05d:", lbl->key);
2758 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2759 emitcode ("", "L%05d:", lbl1->key);
2764 else { /* right is not a literal */
2765 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2766 int reh = OP_SYMBOL (right)->liveTo <= ic->seq;
2769 emitcode (bopnames[bitop], "%s,%s", aopGet (AOP (IC_LEFT (ic)), 0),
2770 aopGet (AOP (IC_RIGHT (ic)), 0));
2773 emitcode (bopnames[bitop], "%s,%s",
2774 aopGet (AOP (IC_RIGHT (ic)), 0),
2775 aopGet (AOP (IC_LEFT (ic)), 0));
2778 MOVR0 (aopGet (AOP (IC_LEFT (ic)), 0));
2779 emitcode (bopnames[bitop], "r0,%s",
2780 aopGet (AOP (IC_RIGHT (ic)), 0));
2782 lbl = newiTempLabel (NULL);
2783 if (IC_TRUE (ifx)) {
2784 emitcode ("breq", "L%05d", lbl->key);
2785 emitcode ("rjmp", "L%05d",
2786 IC_TRUE (ifx)->key);
2789 emitcode ("brne", "L%05d", lbl->key);
2790 emitcode ("rjmp", "L%05d",
2791 IC_FALSE (ifx)->key);
2793 emitcode ("", "L%05d:", lbl->key);
2795 else if (size == 2) {
2796 emitcode ("mov", "r24,%s",
2797 aopGet (AOP (IC_LEFT (ic)), 0));
2798 emitcode ("mov", "r25,%s",
2799 aopGet (AOP (IC_LEFT (ic)), 1));
2800 emitcode (bopnames[bitop], "r24,%s",
2801 aopGet (AOP (IC_RIGHT (ic)), 0));
2802 emitcode (bopnames[bitop], "r25,%s",
2803 aopGet (AOP (IC_RIGHT (ic)), 1));
2804 emitcode ("sbiw", "r24,0");
2805 lbl = newiTempLabel (NULL);
2806 if (IC_TRUE (ifx)) {
2807 emitcode ("breq", "L%05d", lbl->key);
2808 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2811 emitcode ("brne", "L%05d", lbl->key);
2812 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2814 emitcode ("", "L%05d:", lbl->key);
2817 lbl = newiTempLabel (NULL);
2818 lbl1 = newiTempLabel (NULL);
2821 emitcode (bopnames[bitop], "%s,%s",
2822 aopGet (AOP (IC_LEFT (ic)), offset),
2823 aopGet (AOP (IC_RIGHT (ic)), offset));
2826 emitcode (bopnames[bitop], "%s,%s",
2827 aopGet (AOP (IC_RIGHT (ic)), offset),
2828 aopGet (AOP (IC_LEFT (ic)), offset));
2831 MOVR0 (aopGet (AOP (IC_LEFT (ic)), offset));
2832 emitcode (bopnames[bitop], "r0,%s",
2833 aopGet (AOP (IC_RIGHT (ic)), offset));
2835 emitcode ("brne", "L%05d", lbl->key);
2840 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2842 emitcode ("rjmp", "L%05d", lbl1->key);
2843 emitcode ("", "L%05d:", lbl->key);
2846 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2847 emitcode ("", "L%05d:", lbl1->key);
2854 /* result needs to go a register */
2855 samerl = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2856 samerr = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)));
2858 if (AOP_TYPE (right) == AOP_LIT) {
2860 (int) floatFromVal (AOP (right)->aopu.
2862 if (((lit >> (8 * offset)) & 0xff) == 0) {
2863 if (bitop == AVR_AND) {
2864 aopPut (AOP (result), zero, offset++);
2867 else if (bitop == AVR_OR) {
2869 aopPut (AOP (result),
2879 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT &&
2880 AOP_ISHIGHREG(AOP(IC_LEFT(ic)),offset) &&
2881 (bitop == AVR_AND || bitop == AVR_OR)) {
2882 emitcode (bopnames_lit[bitop], "%s,%s(%d)",
2883 aopGet (AOP (IC_LEFT (ic)), offset),
2885 (int) floatFromVal (AOP (right)-> aopu.aop_lit));
2888 emitcode (bopnames[bitop], "%s,%s",
2889 aopGet (AOP (IC_LEFT (ic)), offset),
2890 aopGet (AOP (IC_RIGHT (ic)), offset));
2894 emitcode (bopnames[bitop], "%s,%s",
2895 aopGet (AOP (IC_RIGHT (ic)), offset),
2896 aopGet (AOP (IC_LEFT (ic)), offset));
2899 aopPut (AOP (IC_RESULT (ic)),
2900 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2901 emitcode (bopnames[bitop],
2902 aopGet (AOP (IC_RESULT (ic)), offset),
2903 aopGet (AOP (IC_RIGHT (ic)), offset));
2908 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2909 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2910 freeAsmop (result, NULL, ic, TRUE);
2913 /*-----------------------------------------------------------------*/
2914 /* genAnd - code for and */
2915 /*-----------------------------------------------------------------*/
2917 genAnd (iCode * ic, iCode * ifx)
2919 genBitWise (ic, ifx, AVR_AND);
2922 /*-----------------------------------------------------------------*/
2923 /* genOr - code for or */
2924 /*-----------------------------------------------------------------*/
2926 genOr (iCode * ic, iCode * ifx)
2928 genBitWise (ic, ifx, AVR_OR);
2931 /*-----------------------------------------------------------------*/
2932 /* genXor - code for xclusive or */
2933 /*-----------------------------------------------------------------*/
2935 genXor (iCode * ic, iCode * ifx)
2937 genBitWise (ic, ifx, AVR_XOR);
2940 /*-----------------------------------------------------------------*/
2941 /* genInline - write the inline code out */
2942 /*-----------------------------------------------------------------*/
2944 genInline (iCode * ic)
2946 char *buffer, *bp, *bp1;
2948 _G.inLine += (!options.asmpeep);
2950 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
2951 strcpy (buffer, IC_INLINE (ic));
2953 /* emit each line as a code */
2974 /* emitcode("",buffer); */
2975 _G.inLine -= (!options.asmpeep);
2978 /*-----------------------------------------------------------------*/
2979 /* genRotC - rotate right/left with carry , lr = 1 rotate right */
2980 /*-----------------------------------------------------------------*/
2982 genRotC (iCode * ic, int lr)
2984 operand *left, *result;
2985 int size, offset = 0;
2987 /* rotate right with carry */
2988 left = IC_LEFT (ic);
2989 result = IC_RESULT (ic);
2990 aopOp (left, ic, FALSE);
2991 aopOp (result, ic, FALSE);
2993 /* move it to the result */
2994 size = AOP_SIZE (result);
2995 if (!sameRegs (AOP (left), AOP (result))) {
2998 aopPut (AOP (result),
2999 aopGet (AOP (left), offset), offset);
3002 size = AOP_SIZE (result);
3010 emitcode ("sbrc", "%s,%d", aopGet (AOP (result), offset),
3012 emitcode ("sec", "");
3015 emitcode ((lr ? "ror" : "rol"), "%s",
3016 aopGet (AOP (result), offset));
3022 freeAsmop (left, NULL, ic, TRUE);
3023 freeAsmop (result, NULL, ic, TRUE);
3026 /*-----------------------------------------------------------------*/
3027 /* genRRC - rotate right with carry */
3028 /*-----------------------------------------------------------------*/
3035 /*-----------------------------------------------------------------*/
3036 /* genRLC - generate code for rotate left with carry */
3037 /*-----------------------------------------------------------------*/
3044 /*-----------------------------------------------------------------*/
3045 /* genGetHbit - generates code get highest order bit */
3046 /*-----------------------------------------------------------------*/
3048 genGetHbit (iCode * ic)
3050 operand *left, *result;
3053 left = IC_LEFT (ic);
3054 result = IC_RESULT (ic);
3055 aopOp (left, ic, FALSE);
3056 aopOp (result, ic, FALSE);
3058 size = AOP_SIZE (result);
3059 if (!sameRegs (AOP (left), AOP (result))) {
3060 emitcode ("clr", "%s", aopGet (AOP (result), size - 1));
3061 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3062 emitcode ("subi", "%s,<(-1)",
3063 aopGet (AOP (result), size - 1));
3066 emitcode ("clr", "r0");
3067 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3068 emitcode ("subi", "r0,<(-1)");
3069 aopPut (AOP (result), "r0", 0);
3074 emitcode ("clr", aopGet (AOP (result), offset++));
3076 freeAsmop (left, NULL, ic, TRUE);
3077 freeAsmop (result, NULL, ic, TRUE);
3080 /*-----------------------------------------------------------------*/
3081 /* genShiftLeftLit - shift left by a known amount */
3082 /*-----------------------------------------------------------------*/
3084 genShiftLeftLit (iCode * ic)
3086 operand *left, *right, *result;
3087 int size, shCount, offset = 0;
3090 right = IC_RIGHT (ic);
3091 left = IC_LEFT (ic);
3092 result = IC_RESULT (ic);
3094 aopOp (left, ic, FALSE);
3095 aopOp (result, ic, FALSE);
3096 size = AOP_SIZE (result);
3097 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3099 if (shCount > (size * 8 - 1)) {
3101 aopPut (AOP (result), zero, offset++);
3106 if (!sameRegs (AOP (left), AOP (result)))
3107 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3109 if (AOP_ISHIGHREG(AOP(result),0)) {
3110 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3111 emitcode ("andi", "%s,0xf0");
3113 emitcode ("ldi","r24,0xf0");
3114 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3115 emitcode ("and", "%s,r24");
3120 emitcode ("add", "%s,%s", aopGet (AOP (result), 0),
3121 aopGet (AOP (result), 0));
3125 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3128 if (shCount >= 12) {
3129 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3130 aopPut (AOP (result), zero, 0);
3131 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3132 if (AOP_ISHIGHREG(AOP(result),1)) {
3133 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3135 emitcode ("ldi","r24,0xf0");
3136 emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
3142 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3143 aopPut (AOP (result), zero, 0);
3149 if (!sameRegs (AOP (left), AOP (result))) {
3150 aopPut (AOP (result), aopGet (AOP (left), 0),
3152 aopPut (AOP (result), aopGet (AOP (left), 1),
3155 emitcode ("mov", "r24,%s", aopGet (AOP (result), 0));
3156 emitcode ("andi", "r24,0x0f");
3157 if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
3158 emitcode("ldi","r25,0xf0");
3160 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3161 if (AOP_ISHIGHREG(AOP(result),0)) {
3162 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 0));
3164 emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
3166 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3167 if (AOP_ISHIGHREG(AOP(result),1)) {
3168 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3170 emitcode ("and", "%s,r25", aopGet (AOP (result), 1));
3172 emitcode ("or", "%s,r24", aopGet (AOP (result), 1));
3174 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3175 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3178 if (!lByteZ && !sameRegs (AOP (result), AOP (left))
3182 aopPut (AOP (result),
3183 aopGet (AOP (left), offset), offset);
3189 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3192 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3193 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3198 assert ("shifting generic pointer ?\n");
3201 /* 32 bits we do only byte boundaries */
3202 if (shCount >= 24) {
3203 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3204 aopPut (AOP (result), zero, 2);
3205 aopPut (AOP (result), zero, 1);
3206 aopPut (AOP (result), zero, 0);
3210 if (shCount >= 16) {
3211 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3212 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3213 aopPut (AOP (result), zero, 1);
3214 aopPut (AOP (result), zero, 0);
3219 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3220 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3221 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3222 aopPut (AOP (result), zero, 0);
3226 if (!lByteZ && !sameRegs (AOP (left), AOP (right))) {
3229 aopPut (AOP (result),
3230 aopGet (AOP (left), offset), offset);
3234 size = AOP_SIZE (result);
3240 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3241 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3242 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3243 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3248 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3249 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3250 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3255 emitcode ("lsl", "%s", aopGet (AOP (result), 2));
3256 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3261 emitcode ("lsl", "%s", aopGet (AOP (result), 3));
3269 freeAsmop (left, NULL, ic, TRUE);
3270 freeAsmop (right, NULL, ic, TRUE);
3271 freeAsmop (result, NULL, ic, TRUE);
3274 /*-----------------------------------------------------------------*/
3275 /* genLeftShift - generates code for left shifting */
3276 /*-----------------------------------------------------------------*/
3278 genLeftShift (iCode * ic)
3280 operand *left, *right, *result;
3284 right = IC_RIGHT (ic);
3285 left = IC_LEFT (ic);
3286 result = IC_RESULT (ic);
3288 aopOp (right, ic, FALSE);
3290 if (AOP_TYPE (right) == AOP_LIT) {
3291 genShiftLeftLit (ic);
3296 aopOp (left, ic, FALSE);
3297 aopOp (result, ic, FALSE);
3298 size = AOP_SIZE (result);
3300 if (AOP_SIZE (right) > 1) {
3301 if (isRegPair (AOP (right))) {
3302 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3305 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3306 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3310 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3312 if (!sameRegs (AOP (left), AOP (result))) {
3314 aopPut (AOP (result), aopGet (AOP (left), offset),
3318 size = AOP_SIZE (result);
3320 tlbl = newiTempLabel (NULL);
3321 emitcode ("", "L%05d:", tlbl->key);
3325 emitcode ("rol", "%s", aopGet (AOP (result), offset));
3327 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3330 if (AOP_SIZE (right) > 1)
3331 emitcode ("sbiw", "r24,1");
3333 emitcode ("dec", "r24");
3334 emitcode ("brne", "L%05d", tlbl->key);
3336 freeAsmop (left, NULL, ic, TRUE);
3337 freeAsmop (right, NULL, ic, TRUE);
3338 freeAsmop (result, NULL, ic, TRUE);
3341 /*-----------------------------------------------------------------*/
3342 /* genShiftRightLit - generate for right shift with known count */
3343 /*-----------------------------------------------------------------*/
3345 genShiftRightLit (iCode * ic)
3347 operand *left = IC_LEFT (ic)
3348 , *right = IC_RIGHT (ic)
3349 , *result = IC_RESULT (ic);
3350 int size, shCount, offset = 0;
3352 sym_link *letype = getSpec (operandType (left));
3353 int sign = !SPEC_USIGN (letype);
3355 right = IC_RIGHT (ic);
3356 left = IC_LEFT (ic);
3357 result = IC_RESULT (ic);
3359 aopOp (left, ic, FALSE);
3360 aopOp (result, ic, FALSE);
3361 size = AOP_SIZE (result);
3362 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3364 /* if signed then give up and use a loop to shift */
3367 if (!sameRegs (AOP (left), AOP (result))) {
3369 aopPut (AOP (result),
3370 aopGet (AOP (left), offset), offset);
3373 size = AOP_SIZE (result);
3376 /* be as economical as possible */
3379 size = AOP_SIZE (result);
3382 /* highest order byte */
3383 if (offset == (AOP_SIZE(result)-1))
3384 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3386 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3392 emitcode ("ldi", "r24,<(%d)", shCount);
3393 tlbl = newiTempLabel (NULL);
3394 emitcode ("", "L%05d:", tlbl->key);
3397 if (offset == (AOP_SIZE(result) - 1))
3398 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3400 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3403 emitcode ("dec", "r24");
3404 emitcode ("brne", "L%05d", tlbl->key);
3408 if (shCount > (size * 8 - 1)) {
3410 aopPut (AOP (result), zero, offset++);
3413 /* for unsigned we can much more efficient */
3416 if (!sameRegs (AOP (left), AOP (result)))
3417 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3419 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3420 if (AOP_ISHIGHREG(AOP(result),0)) {
3421 emitcode ("andi", "%s,0x0f",aopGet(AOP(result),0));
3423 emitcode ("ldi","r24,0x0f");
3424 emitcode ("and", "%s,r24",aopGet(AOP(result),0));
3429 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3432 if (shCount >= 12) {
3433 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3434 aopPut (AOP (result), zero, 1);
3435 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3436 if (AOP_ISHIGHREG(AOP(result),0)) {
3437 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3439 emitcode ("ldi","r24,0x0f");
3440 emitcode ("and", "%s,r24",aopGet(AOP(result),0));
3446 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3447 aopPut (AOP (result), zero, 1);
3453 if (!sameRegs (AOP (left), AOP (result))) {
3454 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3455 aopPut (AOP (result), aopGet (AOP (left), 1), 1);
3457 if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
3458 emitcode("ldi","r25,0x0f");
3460 emitcode ("mov", "r24,%s", aopGet (AOP (result), 1));
3461 emitcode ("andi", "r24,0xf0");
3462 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3463 if (AOP_ISHIGHREG(AOP(result),0)) {
3464 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3466 emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
3468 emitcode ("or", "%s,r24", aopGet (AOP (result), 0));
3469 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3470 if (AOP_ISHIGHREG(AOP(result),1)) {
3471 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 1));
3473 emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
3476 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3477 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3481 if (!hByteZ && !sameRegs (AOP (result), AOP (left))
3485 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3491 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3494 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3495 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3501 assert ("shifting generic pointer ?\n");
3504 /* 32 bits we do only byte boundaries */
3505 if (shCount >= 24) {
3506 aopPut (AOP (result), aopGet (AOP (left), 3), 0);
3507 aopPut (AOP (result), zero, 1);
3508 aopPut (AOP (result), zero, 2);
3509 aopPut (AOP (result), zero, 3);
3513 if (shCount >= 16) {
3514 aopPut (AOP (result), aopGet (AOP (left), 3), 1);
3515 aopPut (AOP (result), aopGet (AOP (left), 2), 0);
3516 aopPut (AOP (result), zero, 2);
3517 aopPut (AOP (result), zero, 3);
3522 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3523 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3524 aopPut (AOP (result), aopGet (AOP (left), 3), 2);
3525 aopPut (AOP (result), zero, 3);
3529 if (!hByteZ && !sameRegs (AOP (left), AOP (right))) {
3532 aopPut (AOP (result),
3533 aopGet (AOP (left), offset), offset);
3537 size = AOP_SIZE (result);
3543 emitcode ("lsr", "%s", aopGet (AOP (result), 3));
3544 emitcode ("ror", "%s", aopGet (AOP (result), 2));
3545 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3546 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3551 emitcode ("lsr", "%s", aopGet (AOP (result), 2));
3552 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3553 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3558 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3559 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3564 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3571 freeAsmop (left, NULL, ic, TRUE);
3572 freeAsmop (right, NULL, ic, TRUE);
3573 freeAsmop (result, NULL, ic, TRUE);
3576 /*-----------------------------------------------------------------*/
3577 /* genRightShift - generate code for right shifting */
3578 /*-----------------------------------------------------------------*/
3580 genRightShift (iCode * ic)
3582 operand *right, *left, *result;
3585 int sign = 0, first = 1;
3588 aopOp (right = IC_RIGHT (ic), ic, FALSE);
3590 if (AOP_TYPE (right) == AOP_LIT) {
3591 genShiftRightLit (ic);
3595 if (AOP_SIZE (right) > 1) {
3596 if (isRegPair (AOP (right))) {
3597 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3600 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3601 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3605 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3607 aopOp (left = IC_LEFT (ic), ic, FALSE);
3608 aopOp (result = IC_RESULT (ic), ic, FALSE);
3609 size = AOP_SIZE (result);
3610 tlbl = newiTempLabel (NULL);
3611 emitcode ("", "L%05d:", tlbl->key);
3613 letype = getSpec (operandType (left));
3614 sign = !SPEC_USIGN (letype);
3615 if (!sameRegs (AOP (left), AOP (result))) {
3617 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3620 size = AOP_SIZE (result);
3622 size = AOP_SIZE (result);
3626 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3628 emitcode ("lsr", "%s", aopGet (AOP (result), offset));
3632 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3635 if (AOP_SIZE (right) > 1)
3636 emitcode ("sbiw", "r24,1");
3638 emitcode ("dec", "r24");
3639 emitcode ("brne", "L%05d", tlbl->key);
3641 freeAsmop (left, NULL, ic, TRUE);
3642 freeAsmop (result, NULL, ic, TRUE);
3645 /*-----------------------------------------------------------------*/
3646 /* RRsh - shift right rn by known count */
3647 /*-----------------------------------------------------------------*/
3649 RRsh (int shCount,int reg)
3651 shCount &= 0x0007; // shCount : 0..7
3657 emitcode ("lsr", "r%d",reg);
3660 emitcode ("lsr", "r%d",reg);
3661 emitcode ("lsr", "r%d",reg);
3664 emitcode ("swap", "r%d",reg);
3665 emitcode ("lsl", "r%d",reg);
3668 emitcode ("swap", "r%d",reg);
3671 emitcode ("swap", "r%d",reg);
3672 emitcode ("lsr", "r%d",reg);
3675 emitcode ("swap","r%d",reg);
3676 emitcode ("lsr", "r%d",reg);
3677 emitcode ("lsr", "r%d",reg);
3680 emitcode ("swap","r%d",reg);
3681 emitcode ("lsr", "r%d",reg);
3682 emitcode ("lsr", "r%d",reg);
3683 emitcode ("lsr", "r%d",reg);
3688 /*-----------------------------------------------------------------*/
3689 /* RLsh - shift left rn by known count */
3690 /*-----------------------------------------------------------------*/
3692 RLsh (int shCount, int reg)
3694 shCount &= 0x0007; // shCount : 0..7
3700 emitcode ("lsl", "r%d",reg);
3703 emitcode ("lsl", "r%d",reg);
3704 emitcode ("lsl", "r%d",reg);
3707 emitcode ("swap","r%d",reg);
3708 emitcode ("lsr", "r%d",reg);
3711 emitcode ("swap", "r%d",reg);
3714 emitcode ("swap","r%d",reg);
3715 emitcode ("lsl", "r%d",reg);
3718 emitcode ("swap","r%d",reg);
3719 emitcode ("lsl", "r%d",reg);
3720 emitcode ("lsl", "r%d",reg);
3723 emitcode ("swap","r%d",reg);
3724 emitcode ("lsl", "r%d",reg);
3725 emitcode ("lsl", "r%d",reg);
3726 emitcode ("lsl", "r%d",reg);
3731 /*-----------------------------------------------------------------*/
3732 /* genUnpackBits - generates code for unpacking bits */
3733 /*-----------------------------------------------------------------*/
3735 genUnpackBits (operand * result, char *rname, int ptype)
3743 etype = getSpec (operandType (result));
3744 rsize = getSize (operandType (result));
3745 /* read the first byte */
3752 emitcode ("ld", "r24,%s+", rname);
3756 emitcode ("lpm", "r24,%s+", rname);
3760 emitcode ("call","__gptrget_pi");
3761 emitcode ("mov","r24,r0");
3765 rlen = SPEC_BLEN (etype);
3767 /* if we have bitdisplacement then it fits */
3768 /* into this byte completely or if length is */
3769 /* less than a byte */
3770 if ((shCnt = SPEC_BSTR (etype)) || (SPEC_BLEN (etype) <= 8)) {
3772 /* shift right acc */
3775 emitcode ("andi", "r24,lo(0x%x)",
3776 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
3777 aopPut (AOP (result), "r24", offset++);
3781 /* bit field did not fit in a byte */
3782 aopPut (AOP (result), "r24", offset++);
3792 emitcode ("ld", "r24,%s+");
3796 emitcode ("lpm", "r24,%s+");
3800 emitcode ("call", "__gptrget_pi");
3805 /* if we are done */
3809 aopPut (AOP (result), "r24", offset++);
3814 aopPut (AOP (result), "r24", offset++);
3818 if (offset < rsize) {
3821 aopPut (AOP (result), zero, offset++);
3826 /*-----------------------------------------------------------------*/
3827 /* genDataPointerGet - generates code when ptr offset is known */
3828 /*-----------------------------------------------------------------*/
3830 genDataPointerGet (operand * left, operand * result, iCode * ic)
3834 int size, offset = 0;
3835 aopOp (result, ic, TRUE);
3837 /* get the string representation of the name */
3838 l = aopGet (AOP (left), 0);
3839 size = AOP_SIZE (result);
3842 sprintf (buffer, "(%s + %d)", l, offset);
3844 sprintf (buffer, "%s", l);
3845 emitcode ("lds", "%s,%s", aopGet (AOP (result), offset++),
3849 freeAsmop (left, NULL, ic, TRUE);
3850 freeAsmop (result, NULL, ic, TRUE);
3853 /*-----------------------------------------------------------------*/
3854 /* genNearPointerGet - emitcode for near pointer fetch */
3855 /*-----------------------------------------------------------------*/
3857 genMemPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
3862 char *rname, *frname = NULL;
3863 sym_link *rtype, *retype;
3864 sym_link *ltype = operandType (left);
3866 rtype = operandType (result);
3867 retype = getSpec (rtype);
3869 aopOp (left, ic, FALSE);
3871 /* if left is rematerialisable and
3872 result is not bit variable type and
3873 the left is pointer to data space i.e
3874 lower 128 bytes of space */
3875 if (AOP_TYPE (left) == AOP_IMMD &&
3876 !IS_BITVAR (retype) && DCL_TYPE (ltype) == POINTER) {
3877 genDataPointerGet (left, result, ic);
3881 /* if the value is already in a pointer register
3882 then don't need anything more */
3883 if (!AOP_INPREG (AOP (left))) {
3884 /* otherwise get a free pointer register */
3886 preg = getFreePtr (ic, &aop, FALSE, 0);
3887 if (isRegPair (AOP (left) )) {
3888 emitcode ("movw", "%s,%s",
3889 aop->aopu.aop_ptr->name,
3890 aopGet(AOP(left),0));
3892 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
3893 aopGet (AOP (left), 0));
3894 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
3895 aopGet (AOP (left), 1));
3901 frname = aopGet(aop,0);
3905 } else if (AOP_ISZ(aop)) {
3908 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
3909 "pointer not in correct register");
3913 aopOp (result, ic, FALSE);
3915 /* if bitfield then unpack the bits */
3916 if (IS_BITVAR (retype))
3917 genUnpackBits (result, rname, POINTER);
3919 /* we have can just get the values */
3920 int size = AOP_SIZE (result);
3925 emitcode ("ld","%s,%s+",aopGet(AOP(result),offset), rname);
3927 emitcode ("ld","%s,%s",aopGet(AOP(result),offset), rname);
3932 /* now some housekeeping stuff */
3934 /* we had to allocate for this iCode */
3936 if (isRegPair (AOP (left) )) {
3937 emitcode ("movw", "%s,%s",
3938 aopGet (AOP(left),0),
3939 aop->aopu.aop_ptr->name);
3941 emitcode ("mov", "%s,%s",
3942 aopGet (AOP (left), 0),
3943 aop->aopu.aop_ptr->name);
3944 emitcode ("mov", "%s,%s",
3945 aopGet (AOP (left), 1),
3946 aop->aop_ptr2->name);
3949 freeAsmop (NULL, aop, ic, TRUE);
3952 /* we did not allocate which means left
3953 already in a pointer register, then
3954 if size > 0 && this could be used again
3955 we have to point it back to where it
3957 if ((AOP_SIZE (result) > 1 &&
3958 !OP_SYMBOL (left)->remat &&
3959 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) && !pi) {
3960 int size = AOP_SIZE (result) - 1;
3961 emitcode ("sbiw", "%s,%d",frname,size);
3966 if (pi) pi->generated = 1;
3967 freeAsmop (left, NULL, ic, TRUE);
3968 freeAsmop (result, NULL, ic, TRUE);
3972 /*-----------------------------------------------------------------*/
3973 /* genCodePointerGet - gget value from code space */
3974 /*-----------------------------------------------------------------*/
3976 genCodePointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
3979 sym_link *retype = getSpec (operandType (result));
3983 aopOp (left, ic, FALSE);
3985 /* if the operand is already in Z register
3986 then we do nothing else we move the value to Z register */
3987 if (AOP_ISZ(AOP(left))) {
3991 getFreePtr(ic,&aop,FALSE,TRUE);
3992 if (isRegPair(AOP (left))) {
3993 emitcode ("movw","r30,%s",aopGet (AOP (left), 0));
3995 emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
3996 emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
4001 aopOp (result, ic, FALSE);
4003 /* if bit then unpack */
4004 if (IS_BITVAR (retype))
4005 genUnpackBits (result, "Z", CPOINTER);
4007 size = AOP_SIZE (result);
4012 emitcode ("lpm","%s,Z+",aopGet(AOP(result),offset++));
4014 emitcode ("lpm","%s,Z",aopGet(AOP(result),offset++));
4019 /* now some housekeeping stuff */
4021 /* we had to allocate for this iCode */
4023 if (isRegPair(AOP (left))) {
4024 emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
4026 emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
4027 emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
4030 freeAsmop (NULL, aop, ic, TRUE);
4033 /* we did not allocate which means left
4034 already in a pointer register, then
4035 if size > 0 && this could be used again
4036 we have to point it back to where it
4038 if ((AOP_SIZE (result) > 1 &&
4039 !OP_SYMBOL (left)->remat &&
4040 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) &&
4042 int size = AOP_SIZE (result) - 1;
4043 emitcode ("sbiw", "r30,%d",size);
4048 if (pi) pi->generated=1;
4049 freeAsmop (left, NULL, ic, TRUE);
4050 freeAsmop (result, NULL, ic, TRUE);
4054 /*-----------------------------------------------------------------*/
4055 /* genGenPointerGet - gget value from generic pointer space */
4056 /*-----------------------------------------------------------------*/
4058 genGenPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
4062 sym_link *retype = getSpec (operandType (result));
4065 aopOp (left, ic, FALSE);
4067 /* if the operand is already in dptr
4068 then we do nothing else we move the value to dptr */
4069 if (AOP_ISZ(AOP(left))) {
4073 getFreePtr(ic,&aop,FALSE,TRUE);
4074 if (isRegPair(AOP(left))) {
4075 emitcode ("movw", "r30,%s", aopGet (AOP (left), 0));
4077 emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
4078 emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
4080 emitcode ("mov", "r24,%s", aopGet (AOP (left), 2));
4084 /* so Z register now contains the address */
4086 aopOp (result, ic, FALSE);
4088 /* if bit then unpack */
4089 if (IS_BITVAR (retype))
4090 genUnpackBits (result, "Z", GPOINTER);
4092 size = AOP_SIZE (result);
4097 emitcode ("call", "__gptrget_pi");
4099 emitcode ("call", "__gptrget");
4100 aopPut (AOP (result), "r0", offset++);
4105 /* now some housekeeping stuff */
4107 /* we had to allocate for this iCode */
4109 if (isRegPair(AOP (left))) {
4110 emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
4112 emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
4113 emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
4116 freeAsmop (NULL, aop, ic, TRUE);
4119 /* we did not allocate which means left
4120 already in a pointer register, then
4121 if size > 0 && this could be used again
4122 we have to point it back to where it
4124 if ((AOP_SIZE (result) > 1 &&
4125 !OP_SYMBOL (left)->remat &&
4126 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) &&
4128 int size = AOP_SIZE (result) - 1;
4129 emitcode ("sbiw", "r30,%d",size);
4132 if (pi) pi->generated=1;
4133 freeAsmop (left, NULL, ic, TRUE);
4134 freeAsmop (result, NULL, ic, TRUE);
4137 /*-----------------------------------------------------------------*/
4138 /* genPointerGet - generate code for pointer get */
4139 /*-----------------------------------------------------------------*/
4141 genPointerGet (iCode * ic, iCode *pi)
4143 operand *left, *result;
4144 sym_link *type, *etype;
4147 left = IC_LEFT (ic);
4148 result = IC_RESULT (ic);
4150 /* depending on the type of pointer we need to
4151 move it to the correct pointer register */
4152 type = operandType (left);
4153 etype = getSpec (type);
4154 /* if left is of type of pointer then it is simple */
4155 if (IS_PTR (type) && !IS_FUNC (type->next))
4156 p_type = DCL_TYPE (type);
4158 /* we have to go by the storage class */
4159 p_type = PTR_TYPE (SPEC_OCLS (etype));
4164 /* now that we have the pointer type we assign
4165 the pointer values */
4172 genMemPointerGet (left, result, ic, pi);
4176 genCodePointerGet (left, result, ic, pi);
4180 genGenPointerGet (left, result, ic, pi);
4186 /*-----------------------------------------------------------------*/
4187 /* genPackBits - generates code for packed bit storage */
4188 /*-----------------------------------------------------------------*/
4190 genPackBits (sym_link * etype,
4192 char *rname, int p_type)
4200 blen = SPEC_BLEN (etype);
4201 bstr = SPEC_BSTR (etype);
4203 l = aopGet (AOP (right), offset++);
4206 /* if the bit lenth is less than or */
4207 /* it exactly fits a byte then */
4208 if (SPEC_BLEN (etype) <= 8) {
4209 shCount = SPEC_BSTR (etype);
4211 /* shift left acc */
4214 if (SPEC_BLEN (etype) < 8) { /* if smaller than a byte */
4221 emitcode ("ld", "r1,%s",rname);
4225 emitcode ("push", "r1");
4226 emitcode ("push", "r24");
4227 emitcode ("call", "__gptrget");
4228 emitcode ("pop", "r1");
4229 emitcode ("mov","r24,r0");
4233 emitcode ("andi", "r24,#0x%02x", (unsigned char)
4234 ((unsigned char) (0xFF << (blen + bstr)) |
4235 (unsigned char) (0xFF >> (8 - bstr))));
4236 emitcode ("or", "r24,r1");
4237 if (p_type == GPOINTER)
4238 emitcode ("pop", "r1");
4247 emitcode("st","%s+,r24");
4251 emitcode("mov","r0,r24");
4252 emitcode ("call", "__gptrput_pi");
4257 if (SPEC_BLEN (etype) <= 8)
4260 rLen = SPEC_BLEN (etype);
4262 /* now generate for lengths greater than one byte */
4265 l = aopGet (AOP (right), offset++);
4276 emitcode ("st", "%s+,%s",rname,l);
4281 emitcode ("lcall", "__gptrput_pi");
4288 /* last last was not complete */
4290 /* save the byte & read byte */
4296 emitcode ("st","%s+,r24",rname);
4299 emitcode ("push", "r1");
4300 emitcode ("push", "r24");
4301 emitcode ("lcall", "__gptrget");
4302 emitcode ("mov","r24,r0");
4303 emitcode ("pop", "r1");
4307 emitcode ("andi", "r24,0x%02x", (((unsigned char) -1 << rLen) & 0xff));
4308 emitcode ("or", "r24,r1");
4311 if (p_type == GPOINTER)
4312 emitcode ("pop", "r1");
4320 emitcode ("st", "%s,r24", rname);
4324 emitcode ("mov","r0,r24");
4325 emitcode ("call", "__gptrput");
4330 /*-----------------------------------------------------------------*/
4331 /* genDataPointerSet - remat pointer to data space */
4332 /*-----------------------------------------------------------------*/
4334 genDataPointerSet (operand * right, operand * result, iCode * ic)
4336 int size, offset = 0;
4337 char *l, buffer[256];
4339 aopOp (right, ic, FALSE);
4341 l = aopGet (AOP (result), 0);
4342 size = AOP_SIZE (right);
4345 sprintf (buffer, "(%s + %d)", l, offset);
4347 sprintf (buffer, "%s", l);
4348 emitcode ("sts", "%s,%s", buffer,
4349 aopGet (AOP (right), offset++));
4352 freeAsmop (right, NULL, ic, TRUE);
4353 freeAsmop (result, NULL, ic, TRUE);
4356 /*-----------------------------------------------------------------*/
4357 /* genNearPointerSet - emitcode for near pointer put */
4358 /*-----------------------------------------------------------------*/
4360 genMemPointerSet (operand * right, operand * result, iCode * ic, iCode *pi)
4363 char *frname = NULL, *rname, *l;
4366 sym_link *ptype = operandType (result);
4368 retype = getSpec (operandType (right));
4370 aopOp (result, ic, FALSE);
4372 /* if the result is rematerializable &
4373 in data space & not a bit variable */
4374 if (AOP_TYPE (result) == AOP_IMMD &&
4375 DCL_TYPE (ptype) == POINTER && !IS_BITVAR (retype)) {
4376 genDataPointerSet (right, result, ic);
4379 if (!AOP_INPREG(AOP(result))) {
4380 /* otherwise get a free pointer register */
4382 getFreePtr (ic, &aop, FALSE, 0);
4383 if (isRegPair (AOP (result) )) {
4384 emitcode ("movw", "%s,%s",aop->aopu.aop_ptr->name,
4385 aopGet(AOP (result), 0));
4387 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
4388 aopGet (AOP (result), 0));
4389 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
4390 aopGet (AOP (result), 1));
4395 frname = aopGet(aop,0);
4398 aopOp (right, ic, FALSE);
4401 } else if (AOP_ISZ(aop)) {
4404 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4405 "pointer not in correct register");
4408 /* if bitfield then unpack the bits */
4409 if (IS_BITVAR (retype))
4410 genPackBits (retype, right, rname, POINTER);
4412 /* we have can just get the values */
4413 int size = AOP_SIZE (right);
4417 l = aopGet (AOP (right), offset);
4419 emitcode ("st", "%s+,%s", rname,l);
4421 emitcode ("st", "%s,%s", rname,l);
4426 /* now some housekeeping stuff */
4428 /* we had to allocate for this iCode */
4430 if (isRegPair (AOP (result) )) {
4431 emitcode ("movw", "%s,%s",
4432 aopGet(AOP(result),0),
4433 aop->aopu.aop_ptr->name);
4435 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
4436 aopGet (AOP (result), 0));
4437 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
4438 aopGet (AOP (result), 1));
4441 freeAsmop (NULL, aop, ic, TRUE);
4444 /* we did not allocate which means left
4445 already in a pointer register, then
4446 if size > 0 && this could be used again
4447 we have to point it back to where it
4449 if ((AOP_SIZE (right) > 1 &&
4450 !OP_SYMBOL (result)->remat &&
4451 (OP_SYMBOL (right)->liveTo > ic->seq || ic->depth)) && !pi) {
4452 int size = AOP_SIZE (right) - 1;
4453 emitcode ("sbiw", "%s,%d",frname,size);
4458 if (pi) pi->generated = 1;
4459 freeAsmop (result, NULL, ic, TRUE);
4460 freeAsmop (right, NULL, ic, TRUE);
4463 /*-----------------------------------------------------------------*/
4464 /* genGenPointerSet - set value from generic pointer space */
4465 /*-----------------------------------------------------------------*/
4467 genGenPointerSet (operand * right, operand * result, iCode * ic, iCode *pi)
4471 sym_link *retype = getSpec (operandType (right));
4474 aopOp (result, ic, FALSE);
4476 /* if the operand is already in dptr
4477 then we do nothing else we move the value to dptr */
4478 if (AOP_ISZ(AOP(result))) {
4482 getFreePtr(ic,&aop,FALSE,TRUE);
4483 if (isRegPair(AOP(result))) {
4484 emitcode ("movw", "r30,%s", aopGet (AOP (result), 0));
4486 emitcode ("mov", "r30,%s", aopGet (AOP (result), 0));
4487 emitcode ("mov", "r31,%s", aopGet (AOP (result), 1));
4489 emitcode ("mov", "r24,%s", aopGet (AOP (result), 2));
4493 /* so Z register now contains the address */
4494 aopOp (right, ic, FALSE);
4496 /* if bit then unpack */
4497 if (IS_BITVAR (retype))
4498 genUnpackBits (result, "Z", GPOINTER);
4500 size = AOP_SIZE (right);
4504 char *l = aopGet(AOP (right), offset++);
4508 emitcode ("call", "__gptrput_pi");
4510 emitcode ("call", "__gptrput");
4514 /* now some housekeeping stuff */
4516 /* we had to allocate for this iCode */
4518 if (isRegPair(AOP(result))) {
4519 emitcode ("movw", "%s,r30", aopGet (AOP (result), 0));
4521 emitcode ("mov", "%s,r30", aopGet (AOP (result), 0));
4522 emitcode ("mov", "%s,r31", aopGet (AOP (result), 1));
4525 freeAsmop (NULL, aop, ic, TRUE);
4528 /* we did not allocate which means left
4529 already in a pointer register, then
4530 if size > 0 && this could be used again
4531 we have to point it back to where it
4533 if ((AOP_SIZE (right) > 1 &&
4534 !OP_SYMBOL (result)->remat &&
4535 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) && !pi) {
4536 int size = AOP_SIZE (right) - 1;
4537 emitcode ("sbiw", "r30,%d",size);
4540 if (pi) pi->generated = 1;
4541 freeAsmop (right, NULL, ic, TRUE);
4542 freeAsmop (result, NULL, ic, TRUE);
4545 /*-----------------------------------------------------------------*/
4546 /* genPointerSet - stores the value into a pointer location */
4547 /*-----------------------------------------------------------------*/
4549 genPointerSet (iCode * ic, iCode *pi)
4551 operand *right, *result;
4552 sym_link *type, *etype;
4555 right = IC_RIGHT (ic);
4556 result = IC_RESULT (ic);
4558 /* depending on the type of pointer we need to
4559 move it to the correct pointer register */
4560 type = operandType (result);
4561 etype = getSpec (type);
4562 /* if left is of type of pointer then it is simple */
4563 if (IS_PTR (type) && !IS_FUNC (type->next)) {
4564 p_type = DCL_TYPE (type);
4567 /* we have to go by the storage class */
4568 p_type = PTR_TYPE (SPEC_OCLS (etype));
4572 /* now that we have the pointer type we assign
4573 the pointer values */
4580 genMemPointerSet (right, result, ic, pi);
4584 genGenPointerSet (right, result, ic, pi);
4590 /*-----------------------------------------------------------------*/
4591 /* genIfx - generate code for Ifx statement */
4592 /*-----------------------------------------------------------------*/
4594 genIfx (iCode * ic, iCode * popIc)
4596 operand *cond = IC_COND (ic);
4601 aopOp (cond, ic, FALSE);
4603 /* get the value into acc */
4604 if (AOP_SIZE(cond) == 1 && AOP_ISHIGHREG(AOP(cond),0)) {
4605 cname = aopGet(AOP(cond),0);
4607 toBoolean (cond, "r24", 0);
4611 /* the result is now in the accumulator */
4612 freeAsmop (cond, NULL, ic, TRUE);
4614 /* if there was something to be popped then do it */
4617 emitcode("cpi","%s,0",cname);
4618 } else if (!tob) emitcode("cpi","%s,0",cname);
4620 lbl = newiTempLabel(NULL);
4622 emitcode ("breq","L%05d",lbl->key);
4623 emitcode ("jmp","L%05d",IC_TRUE(ic)->key);
4624 emitcode ("","L%05d:",lbl->key);
4626 emitcode ("brne","L%05d",lbl->key);
4627 emitcode ("jmp","L%05d",IC_FALSE(ic)->key);
4628 emitcode ("","L%05d:",lbl->key);
4633 /*-----------------------------------------------------------------*/
4634 /* genAddrOf - generates code for address of */
4635 /*-----------------------------------------------------------------*/
4637 genAddrOf (iCode * ic)
4639 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
4642 aopOp (IC_RESULT (ic), ic, FALSE);
4643 assert(AOP_SIZE(IC_RESULT(ic)) >= 2);
4644 /* if the operand is on the stack then we
4645 need to get the stack offset of this
4648 /* if it has an offset then we need to compute it */
4650 if (allHigh(AOP(IC_RESULT(ic)))) {
4651 if (isRegPair (AOP(IC_RESULT(ic)))) {
4652 emitcode ("movw","%s,r28",aopGet(AOP(IC_RESULT(ic)),0));
4654 emitcode ("mov","%s,r28",aopGet(AOP(IC_RESULT(ic)),0));
4655 emitcode ("mov","%s,r29",aopGet(AOP(IC_RESULT(ic)),1));
4657 if (sym->stack < 0) {
4658 emitcode("subi","%s,<(%d)",aopGet(AOP(IC_RESULT(ic)),0),-sym->stack);
4659 emitcode("sbci","%s,>(%d)",aopGet(AOP(IC_RESULT(ic)),1),-sym->stack);
4661 emitcode("subi","%s,<(-%d)",aopGet(AOP(IC_RESULT(ic)),0),sym->stack);
4662 emitcode("sbci","%s,>(-%d)",aopGet(AOP(IC_RESULT(ic)),1),sym->stack);
4665 emitcode("movw","r24,r28");
4666 if (sym->stack > -63 && sym->stack < 63) {
4668 emitcode("sbiw","r24,%d",-sym->stack);
4670 emitcode("sbiw","r24,%d",sym->stack);
4672 if (sym->stack < 0) {
4673 emitcode("subi","r24,<(%d)",-sym->stack);
4674 emitcode("sbci","r25,>(%d)",-sym->stack);
4676 emitcode("subi","r24,<(-%d)",sym->stack);
4677 emitcode("sbci","r25,>(-%d)",sym->stack);
4681 aopPut(AOP(IC_RESULT(ic)),"r24",0);
4682 aopPut(AOP(IC_RESULT(ic)),"r25",1);
4686 aopPut(AOP(IC_RESULT(ic)),"r28",0);
4687 aopPut(AOP(IC_RESULT(ic)),"r29",1);
4689 /* fill the result with zero */
4690 size = AOP_SIZE (IC_RESULT (ic)) - 2;
4693 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
4699 /* object not on stack then we need the name */
4700 size = AOP_SIZE (IC_RESULT (ic));
4704 char s[SDCC_NAME_MAX];
4706 sprintf (s, ">(%s)", sym->rname);
4708 sprintf (s, "<(%s)", sym->rname);
4709 aopPut (AOP (IC_RESULT (ic)), s, offset++);
4713 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4717 /*-----------------------------------------------------------------*/
4718 /* genFarFarAssign - assignment when both are in far space */
4719 /*-----------------------------------------------------------------*/
4721 genFarFarAssign (operand * result, operand * right, iCode * ic)
4723 int size = AOP_SIZE (right);
4726 /* first push the right side on to the stack */
4728 l = aopGet (AOP (right), offset++);
4730 emitcode ("push", "acc");
4733 freeAsmop (right, NULL, ic, FALSE);
4734 /* now assign DPTR to result */
4735 aopOp (result, ic, FALSE);
4736 size = AOP_SIZE (result);
4738 emitcode ("pop", "acc");
4739 aopPut (AOP (result), "a", --offset);
4741 freeAsmop (result, NULL, ic, FALSE);
4745 /*-----------------------------------------------------------------*/
4746 /* genAssign - generate code for assignment */
4747 /*-----------------------------------------------------------------*/
4749 genAssign (iCode * ic)
4751 operand *result, *right;
4753 unsigned long lit = 0L;
4755 result = IC_RESULT (ic);
4756 right = IC_RIGHT (ic);
4758 /* if they are the same */
4759 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4762 aopOp (right, ic, FALSE);
4764 /* special case both in far space */
4765 if (AOP_TYPE (right) == AOP_DPTR &&
4766 IS_TRUE_SYMOP (result) && isOperandInFarSpace (result)) {
4768 genFarFarAssign (result, right, ic);
4772 aopOp (result, ic, TRUE);
4774 /* if they are the same registers */
4775 if (sameRegs (AOP (right), AOP (result)))
4778 /* if the result is a bit */
4779 if (AOP_TYPE (result) == AOP_CRY) {
4781 /* if the right size is a literal then
4782 we know what the value is */
4783 if (AOP_TYPE (right) == AOP_LIT) {
4784 if (((int) operandLitValue (right)))
4785 aopPut (AOP (result), one, 0);
4787 aopPut (AOP (result), zero, 0);
4791 /* the right is also a bit variable */
4792 if (AOP_TYPE (right) == AOP_CRY) {
4793 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4794 aopPut (AOP (result), "c", 0);
4799 toBoolean (right, "", 0);
4800 aopPut (AOP (result), "a", 0);
4804 /* bit variables done */
4806 size = AOP_SIZE (result);
4808 if (AOP_TYPE (right) == AOP_LIT)
4810 (unsigned long) floatFromVal (AOP (right)->aopu.
4812 if ((size > 1) && (AOP_TYPE (result) != AOP_REG)
4813 && (AOP_TYPE (right) == AOP_LIT)
4814 && !IS_FLOAT (operandType (right)) && (lit < 256L)) {
4815 emitcode ("clr", "a");
4817 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) ==
4818 0) aopPut (AOP (result), "a", size);
4820 aopPut (AOP (result),
4821 aopGet (AOP (right), size), size);
4826 aopPut (AOP (result),
4827 aopGet (AOP (right), offset), offset);
4833 freeAsmop (right, NULL, ic, FALSE);
4834 freeAsmop (result, NULL, ic, TRUE);
4837 /*-----------------------------------------------------------------*/
4838 /* genJumpTab - genrates code for jump table */
4839 /*-----------------------------------------------------------------*/
4841 genJumpTab (iCode * ic)
4846 aopOp (IC_JTCOND (ic), ic, FALSE);
4847 /* get the condition into accumulator */
4848 l = aopGet (AOP (IC_JTCOND (ic)), 0);
4850 /* multiply by three */
4851 emitcode ("add", "a,acc");
4852 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0));
4853 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
4855 jtab = newiTempLabel (NULL);
4856 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
4857 emitcode ("jmp", "@a+dptr");
4858 emitcode ("", "%05d$:", jtab->key + 100);
4859 /* now generate the jump labels */
4860 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
4861 jtab = setNextItem (IC_JTLABELS (ic)))
4862 emitcode ("ljmp", "%05d$", jtab->key + 100);
4866 /*-----------------------------------------------------------------*/
4867 /* genCast - gen code for casting */
4868 /*-----------------------------------------------------------------*/
4870 genCast (iCode * ic)
4872 operand *result = IC_RESULT (ic);
4873 sym_link *ctype = operandType (IC_LEFT (ic));
4874 sym_link *rtype = operandType (IC_RIGHT (ic));
4875 operand *right = IC_RIGHT (ic);
4878 /* if they are equivalent then do nothing */
4879 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4882 aopOp (right, ic, FALSE);
4883 aopOp (result, ic, FALSE);
4885 /* if the result is a bit */
4886 if (AOP_TYPE (result) == AOP_CRY) {
4887 /* if the right size is a literal then
4888 we know what the value is */
4889 if (AOP_TYPE (right) == AOP_LIT) {
4890 if (((int) operandLitValue (right)))
4891 aopPut (AOP (result), one, 0);
4893 aopPut (AOP (result), zero, 0);
4898 /* the right is also a bit variable */
4899 if (AOP_TYPE (right) == AOP_CRY) {
4900 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4901 aopPut (AOP (result), "c", 0);
4906 toBoolean (right, "", 0);
4907 aopPut (AOP (result), "a", 0);
4911 /* if they are the same size : or less */
4912 if (AOP_SIZE (result) <= AOP_SIZE (right)) {
4914 /* if they are in the same place */
4915 if (sameRegs (AOP (right), AOP (result)))
4918 /* if they in different places then copy */
4919 size = AOP_SIZE (result);
4922 aopPut (AOP (result),
4923 aopGet (AOP (right), offset), offset);
4930 /* if the result is of type pointer */
4931 if (IS_PTR (ctype)) {
4934 sym_link *type = operandType (right);
4935 sym_link *etype = getSpec (type);
4937 /* pointer to generic pointer */
4938 if (IS_GENPTR (ctype)) {
4942 p_type = DCL_TYPE (type);
4944 /* we have to go by the storage class */
4945 p_type = PTR_TYPE (SPEC_OCLS (etype));
4948 /* the first two bytes are known */
4949 size = GPTRSIZE - 1;
4952 aopPut (AOP (result),
4953 aopGet (AOP (right), offset), offset);
4956 /* the last byte depending on type */
4973 /* this should never happen */
4974 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4975 "got unknown pointer type");
4978 aopPut (AOP (result), l, GPTRSIZE - 1);
4982 /* just copy the pointers */
4983 size = AOP_SIZE (result);
4986 aopPut (AOP (result),
4987 aopGet (AOP (right), offset), offset);
4993 /* so we now know that the size of destination is greater
4994 than the size of the source */
4995 /* we move to result for the size of source */
4996 size = AOP_SIZE (right);
4999 aopPut (AOP (result), aopGet (AOP (right), offset), offset);
5003 /* now depending on the sign of the source && destination */
5004 size = AOP_SIZE (result) - AOP_SIZE (right);
5005 /* if unsigned or not an integral type */
5006 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype)) {
5008 aopPut (AOP (result), zero, offset++);
5011 /* we need to extend the sign :{ */
5012 // PENDING: Does nothing on avr
5014 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1);
5017 emitcode ("rlc", "a");
5018 emitcode ("subb", "a,acc");
5020 aopPut (AOP (result), "a", offset++);
5023 /* we are done hurray !!!! */
5026 freeAsmop (right, NULL, ic, TRUE);
5027 freeAsmop (result, NULL, ic, TRUE);
5031 /*-----------------------------------------------------------------*/
5032 /* genDjnz - generate decrement & jump if not zero instrucion */
5033 /*-----------------------------------------------------------------*/
5035 genDjnz (iCode * ic, iCode * ifx)
5041 /* if the if condition has a false label
5042 then we cannot save */
5046 /* if the minus is not of the form
5048 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
5049 !IS_OP_LITERAL (IC_RIGHT (ic)))
5052 if (operandLitValue (IC_RIGHT (ic)) != 1)
5055 /* if the size of this greater than one then no
5057 if (getSize (operandType (IC_RESULT (ic))) > 1)
5060 /* otherwise we can save BIG */
5061 lbl = newiTempLabel (NULL);
5062 lbl1 = newiTempLabel (NULL);
5064 aopOp (IC_RESULT (ic), ic, FALSE);
5066 if (IS_AOP_PREG (IC_RESULT (ic))) {
5067 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0));
5068 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0));
5069 emitcode ("jnz", "%05d$", lbl->key + 100);
5072 emitcode ("djnz", "%s,%05d$",
5073 aopGet (AOP (IC_RESULT (ic)), 0), lbl->key + 100);
5075 emitcode ("sjmp", "%05d$", lbl1->key + 100);
5076 emitcode ("", "%05d$:", lbl->key + 100);
5077 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5078 emitcode ("", "%05d$:", lbl1->key + 100);
5080 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5085 static char *recvregs[8] = {
5086 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23"
5089 static int recvCnt = 0;
5091 /*-----------------------------------------------------------------*/
5092 /* genReceive - generate code for a receive iCode */
5093 /*-----------------------------------------------------------------*/
5095 genReceive (iCode * ic)
5097 int size, offset = 0;
5098 aopOp (IC_RESULT (ic), ic, FALSE);
5099 size = AOP_SIZE (IC_RESULT (ic));
5101 aopPut (AOP (IC_RESULT (ic)), recvregs[recvCnt++], offset);
5104 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5107 /*-----------------------------------------------------------------*/
5108 /* gen51Code - generate code for 8051 based controllers */
5109 /*-----------------------------------------------------------------*/
5111 genAVRCode (iCode * lic)
5116 lineHead = lineCurr = NULL;
5118 /* print the allocation information */
5120 printAllocInfo (currFunc, codeOutFile);
5121 /* if debug information required */
5122 /* if (options.debug && currFunc) { */
5124 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
5126 /* emitcode ("", ".type %s,@function", currFunc->name); */
5129 /* stack pointer name */
5133 for (ic = lic; ic; ic = ic->next) {
5135 if (cln != ic->lineno) {
5136 if (options.debug) {
5138 emitcode ("", "C$%s$%d$%d$%d ==.",
5139 FileBaseName (ic->filename),
5140 ic->lineno, ic->level, ic->block);
5143 emitcode (";", "%s %d", ic->filename, ic->lineno);
5146 /* if the result is marked as
5147 spilt and rematerializable or code for
5148 this has already been generated then
5150 if (resultRemat (ic) || ic->generated)
5153 /* depending on the operation */
5172 /* IPOP happens only when trying to restore a
5173 spilt live range, if there is an ifx statement
5174 following this pop then the if statement might
5175 be using some of the registers being popped which
5176 would destory the contents of the register so
5177 we need to check for this condition and handle it */
5179 ic->next->op == IFX &&
5180 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
5181 genIfx (ic->next, ic);
5199 genEndFunction (ic);
5219 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
5236 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
5240 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
5244 genCmpLe (ic, ifxForOp (IC_RESULT (ic), ic));
5248 genCmpGe (ic, ifxForOp (IC_RESULT (ic), ic));
5252 genCmpNe (ic, ifxForOp (IC_RESULT (ic), ic));
5256 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
5268 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
5272 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
5276 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
5303 case GET_VALUE_AT_ADDRESS:
5304 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
5308 if (POINTER_SET (ic))
5309 genPointerSet (ic, hasInc(IC_RESULT(ic),ic));
5335 addSet (&_G.sendSet, ic);
5344 /* now we are ready to call the
5345 peep hole optimizer */
5346 if (!options.nopeep)
5347 peepHole (&lineHead);
5349 /* now do the actual printing */
5350 printLine (lineHead, codeOutFile);