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 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
787 /* force a new aop if sizes differ */
788 sym->usl.spillLoc->aop = NULL;
790 sym->aop = op->aop = aop =
791 aopForSym (ic, sym->usl.spillLoc, result);
792 aop->size = getSize (sym->type);
796 /* must be in a register */
797 sym->aop = op->aop = aop = newAsmop (AOP_REG);
798 aop->size = sym->nRegs;
799 for (i = 0; i < sym->nRegs; i++)
800 aop->aopu.aop_reg[i] = sym->regs[i];
803 /*-----------------------------------------------------------------*/
804 /* freeAsmop - free up the asmop given to an operand */
805 /*----------------------------------------------------------------*/
807 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
824 /* depending on the asmop type only three cases need work AOP_RO
825 , AOP_R1 && AOP_STK */
830 emitcode ("pop", "r26");
831 emitcode ("pop", "r27");
835 bitVectUnSetBit (ic->rUsed, X_IDX);
841 emitcode ("pop", "r30");
842 emitcode ("pop", "r31");
846 bitVectUnSetBit (ic->rUsed, Z_IDX);
852 int stk = aop->aopu.aop_stk + aop->size;
853 bitVectUnSetBit (ic->rUsed, X_IDX);
854 bitVectUnSetBit (ic->rUsed, Z_IDX);
856 getFreePtr (ic, &aop, FALSE, 0);
858 emitcode ("movw", "%s,r28");
860 if (stk <= 63 && stk > 0) {
861 emitcode ("adiw", "%s,0x%02x",
862 aop->aopu.aop_ptr->name,
866 emitcode ("subi", "%s,<(%d)",
867 aop->aopu.aop_ptr->name,
869 emitcode ("sbci", "%s,>(%d)",
876 emitcode ("pop", "r24");
877 emitcode ("st", "-%s,r24",
878 aop->type == AOP_X ? "X" : "Z");
883 freeAsmop (op, NULL, ic, TRUE);
885 emitcode ("pop", "r26");
886 emitcode ("pop", "r27");
891 emitcode ("pop", "r30");
892 emitcode ("pop", "r31");
899 /* all other cases just dealloc */
903 OP_SYMBOL (op)->aop = NULL;
904 /* if the symbol has a spill */
906 SPIL_LOC (op)->aop = NULL;
911 /*-----------------------------------------------------------------*/
912 /* aopGet - for fetching value of the aop */
913 /*-----------------------------------------------------------------*/
915 aopGet (asmop * aop, int offset)
920 /* offset is greater than
922 if (offset > (aop->size - 1) && aop->type != AOP_LIT)
925 /* depending on type */
929 if (offset > aop->coff) {
930 emitcode ("adiw", "%s,%d", aop->aopu.aop_ptr->name,
934 if (offset < aop->coff) {
935 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name,
940 emitcode ("ld", "%s,x",
941 (rs = ((offset & 1) ? "r25" : "r24")));
946 if (offset > aop->coff) {
947 emitcode ("adiw", "r30,%d",
951 emitcode ("sbiw", "r30,%d",
954 emitcode ("lpm", "%s,z",
955 (rs = ((offset & 1) ? "r25" : "r24")));
959 if (offset > aop->coff) {
960 emitcode ("ldd", "%s,z+%d",
962 ((offset & 1) ? "r25" : "r24")),
966 emitcode ("sbiw", "%s,%d",
967 aop->aopu.aop_ptr->name,
970 emitcode ("ld", "%s,z",
972 ((offset & 1) ? "r25" : "r24")));
979 emitcode ("lds", "%s,(%s)+%d",
980 (rs = ((offset & 1) ? "r25" : "r24")),
981 aop->aopu.aop_immd, offset);
985 emitcode ("lds", "%s,(%s)+%d",
986 (rs = ((offset & 1) ? "r25" : "r24")),
987 aop->aopu.aop_dir, offset);
991 return aop->aopu.aop_reg[offset]->name;
994 assert ("cannot be in bit space AOP_CRY\n");
998 s = aopLiteral (aop->aopu.aop_lit, offset);
999 emitcode ("ldi", "%s,<(%s)",
1000 (rs = ((offset & 1) ? "r24" : "r25")), s);
1005 return aop->aopu.aop_str[offset];
1008 emitcode ("ldd", "%s,Y+%d",
1009 (rs = ((offset & 1) ? "r25" : "r24")),
1010 aop->aopu.aop_stk + offset);
1014 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1015 "aopget got unsupported aop->type");
1019 /*-----------------------------------------------------------------*/
1020 /* aopPut - puts a string for a aop */
1021 /*-----------------------------------------------------------------*/
1023 aopPut (asmop * aop, char *s, int offset)
1027 if (aop->size && offset > (aop->size - 1)) {
1028 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1029 "aopPut got offset > aop->size");
1033 /* will assign value to value */
1034 /* depending on where it is ofcourse */
1035 switch (aop->type) {
1038 sprintf (d, "(%s)+%d", aop->aopu.aop_dir, offset);
1041 sprintf (d, "%s", aop->aopu.aop_dir);
1044 emitcode ("sts", "%s,%s", d, s);
1048 if (toupper (*s) != 'R') {
1050 emitcode ("clr", "%s",
1051 aop->aopu.aop_reg[offset]->name);
1054 emitcode ("ldi", "r25,%s", s);
1055 emitcode ("mov", "%s,r35",
1056 aop->aopu.aop_reg[offset]->name);
1060 if (strcmp (aop->aopu.aop_reg[offset]->name, s)) {
1061 emitcode ("mov", "%s,%s",
1062 aop->aopu.aop_reg[offset]->name, s);
1068 if (offset > aop->coff) {
1069 emitcode ("adiw", "%s,%d", aop->aopu.aop_ptr->name,
1070 offset - aop->coff);
1073 if (offset < aop->coff) {
1074 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name,
1075 aop->coff - offset);
1079 emitcode ("st", "x,%s", s);
1084 if (offset > aop->coff) {
1085 emitcode ("adiw", "r30,%d",
1086 offset - aop->coff);
1089 emitcode ("sbiw", "r30,%d",
1090 aop->coff - offset);
1092 emitcode ("lpm", "%s,z", s);
1095 /* we can use lds */
1096 if (offset > aop->coff) {
1097 emitcode ("sdd", "z+%d,%s",
1098 offset - aop->coff, s);
1101 emitcode ("sbiw", "%s,%d",
1102 aop->aopu.aop_ptr->name,
1103 aop->coff - offset);
1105 emitcode ("ld", "%s,z", s);
1111 emitcode ("push", "%s", s);
1115 /* if used only for a condition code check */
1116 assert (toupper (*s) == 'R');
1118 emitcode ("xrl", "r0,r0");
1119 emitcode ("cpi", "%s,0", s);
1122 emitcode ("cpc", "r0,%s", s);
1128 if (strcmp (aop->aopu.aop_str[offset], s))
1129 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset],
1134 emitcode ("std", "y+%d,%s", offset, s);
1138 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1139 "aopPut got unsupported aop->type");
1145 #define AOP(op) op->aop
1146 #define AOP_TYPE(op) AOP(op)->type
1147 #define AOP_SIZE(op) AOP(op)->size
1148 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_X || \
1149 AOP_TYPE(x) == AOP_Z))
1150 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1151 ((x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R27_IDX)) || \
1152 (x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R31_IDX)) )))
1153 #define AOP_ISX(x) (x && (x->type == AOP_REG && \
1154 ((x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R27_IDX)))))
1155 #define AOP_ISZ(x) (x && (x->type == AOP_REG && \
1156 ((x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R31_IDX)))))
1158 /*-----------------------------------------------------------------*/
1159 /* genNotFloat - generates not for float operations */
1160 /*-----------------------------------------------------------------*/
1162 genNotFloat (operand * op, operand * res)
1168 /* we will put 127 in the first byte of
1170 aopPut (AOP (res), "127", 0);
1171 size = AOP_SIZE (op) - 1;
1174 l = aopGet (op->aop, offset++);
1178 emitcode ("or", "R0,%s", aopGet (op->aop, offset++));
1180 tlbl = newiTempLabel (NULL);
1182 tlbl = newiTempLabel (NULL);
1183 aopPut (res->aop, zero, 1);
1184 emitcode ("cpi", "r0,0");
1185 emitcode ("breq", "L%05d", tlbl->key);
1186 aopPut (res->aop, one, 1);
1187 emitcode ("", "L%05d:", tlbl->key);
1189 size = res->aop->size - 2;
1191 /* put zeros in the rest */
1193 aopPut (res->aop, zero, offset++);
1196 /*-----------------------------------------------------------------*/
1197 /* opIsGptr: returns non-zero if the passed operand is */
1198 /* a generic pointer type. */
1199 /*-----------------------------------------------------------------*/
1201 opIsGptr (operand * op)
1203 sym_link *type = operandType (op);
1205 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type)) {
1211 /*-----------------------------------------------------------------*/
1212 /* getDataSize - get the operand data size */
1213 /*-----------------------------------------------------------------*/
1215 getDataSize (operand * op)
1218 size = AOP_SIZE (op);
1219 if (size == GPTRSIZE) {
1220 sym_link *type = operandType (op);
1221 if (IS_GENPTR (type)) {
1222 /* generic pointer; arithmetic operations
1223 * should ignore the high byte (pointer type).
1231 /*-----------------------------------------------------------------*/
1232 /* toBoolean - emit code for orl a,operator(sizeop) */
1233 /*-----------------------------------------------------------------*/
1235 toBoolean (operand * oper, char *r, bool clr)
1237 int size = AOP_SIZE (oper);
1240 emitcode ("clr", "%s", r);
1242 emitcode ("or", "%s,%s", r, aopGet (AOP (oper), offset++));
1245 emitcode("mov","%s,%s",r,aopGet (AOP (oper), offset++));
1246 if (size) while (size--) emitcode ("or", "%s,%s", r, aopGet (AOP (oper), offset++));
1251 /*-----------------------------------------------------------------*/
1252 /* genNot - generate code for ! operation */
1253 /*-----------------------------------------------------------------*/
1258 sym_link *optype = operandType (IC_LEFT (ic));
1259 int size, offset = 1;
1261 /* assign asmOps to operand & result */
1262 aopOp (IC_LEFT (ic), ic, FALSE);
1263 aopOp (IC_RESULT (ic), ic, TRUE);
1265 /* if type float then do float */
1266 if (IS_FLOAT (optype)) {
1267 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1270 emitcode ("clr", "r24");
1271 tlbl = newiTempLabel (NULL);
1272 size = AOP_SIZE (IC_LEFT (ic));
1275 emitcode ("cpse", "%s,r24", aopGet (AOP (IC_LEFT (ic)), 0));
1280 emitcode ("cpc", "%s,r24",
1281 aopGet (AOP (IC_LEFT (ic)),
1284 emitcode ("cpi", "%s,0",
1285 aopGet (AOP (IC_LEFT (ic)),
1289 emitcode ("bne", "L%05d", tlbl->key);
1291 emitcode ("ldi", "r24,1");
1292 emitcode ("", "L%05d:", tlbl->key);
1293 aopPut (AOP (IC_RESULT (ic)), "r24", 0);
1294 size = AOP_SIZE (IC_RESULT (ic)) - 1;
1297 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
1301 /* release the aops */
1302 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1303 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1307 /*-----------------------------------------------------------------*/
1308 /* genCpl - generate code for complement */
1309 /*-----------------------------------------------------------------*/
1317 /* assign asmOps to operand & result */
1318 aopOp (IC_LEFT (ic), ic, FALSE);
1319 aopOp (IC_RESULT (ic), ic, TRUE);
1320 samer = sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)));
1321 size = AOP_SIZE (IC_RESULT (ic));
1323 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
1325 emitcode ("com", "%s", l);
1328 aopPut (AOP (IC_RESULT (ic)), l, offset);
1329 emitcode ("com", "%s",
1330 aopGet (AOP (IC_RESULT (ic)), offset));
1335 /* release the aops */
1336 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1337 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1340 /*-----------------------------------------------------------------*/
1341 /* genUminusFloat - unary minus for floating points */
1342 /*-----------------------------------------------------------------*/
1344 genUminusFloat (operand * op, operand * result)
1346 int size, offset = 0;
1348 /* for this we just need to flip the
1349 first it then copy the rest in place */
1350 size = AOP_SIZE (op) - 1;
1351 l = aopGet (AOP (op), 3);
1353 emitcode ("ldi", "r24,0x80");
1354 if (sameRegs (AOP (op), AOP (result))) {
1355 emitcode ("eor", "%s,r24", l);
1358 aopPut (AOP (result), l, 3);
1359 emitcode ("eor", "%s,r24", aopGet (AOP (result), 3));
1362 aopPut (AOP (result), aopGet (AOP (op), offset), offset);
1367 /*-----------------------------------------------------------------*/
1368 /* genUminus - unary minus code generation */
1369 /*-----------------------------------------------------------------*/
1371 genUminus (iCode * ic)
1374 sym_link *optype, *rtype;
1378 aopOp (IC_LEFT (ic), ic, FALSE);
1379 aopOp (IC_RESULT (ic), ic, TRUE);
1381 optype = operandType (IC_LEFT (ic));
1382 rtype = operandType (IC_RESULT (ic));
1384 /* if float then do float stuff */
1385 if (IS_FLOAT (optype)) {
1386 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1390 /* otherwise subtract from zero */
1391 size = AOP_SIZE (IC_LEFT (ic));
1393 samer = sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)));
1396 emitcode ("neg", "%s",
1397 aopGet (AOP (IC_LEFT (ic)), 0));
1400 aopPut (AOP (IC_RESULT (ic)),
1401 aopGet (AOP (IC_LEFT (ic)), 0), 0);
1402 emitcode ("neg", "%s",
1403 aopGet (AOP (IC_RESULT (ic)), 0));
1409 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
1411 aopPut (AOP (IC_RESULT (ic)), l, offset);
1412 l = aopGet (AOP (IC_RESULT (ic)), offset);
1415 emitcode ("com", "%s", l);
1417 emitcode ("neg", "%s", l);
1420 size = AOP_SIZE (IC_LEFT (ic)) - 1;
1423 emitcode ("sbci", "%s,0xff",
1424 aopGet (AOP (IC_RESULT (ic)), offset++));
1428 /* if any remaining bytes in the result */
1429 /* we just need to propagate the sign */
1430 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic))))) {
1431 symbol *tlbl = newiTempLabel (NULL);
1432 emitcode ("clr", "r0");
1433 emitcode ("brcc", "L%05d", tlbl->key);
1434 emitcode ("com", "r0");
1435 emitcode ("", "L%05d:", tlbl->key);
1437 aopPut (AOP (IC_RESULT (ic)), "r0", offset++);
1441 /* release the aops */
1442 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1443 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1446 /*-----------------------------------------------------------------*/
1447 /* assignResultValue - */
1448 /*-----------------------------------------------------------------*/
1450 assignResultValue (operand * oper)
1453 int size = AOP_SIZE (oper);
1455 aopPut (AOP (oper), fAVRReturn[offset], offset);
1460 /*-----------------------------------------------------------------*/
1461 /* saveZreg - if indirect call then save z-pointer register */
1462 /*-----------------------------------------------------------------*/
1464 saveZreg (iCode * ic)
1466 /* only if live accross this call */
1467 if (ic->regsSaved == 0 &&
1468 (bitVectBitValue (ic->rMask, R30_IDX) ||
1469 bitVectBitValue (ic->rMask, R31_IDX))) {
1471 emitcode ("push", "r30");
1472 emitcode ("push", "r31");
1476 /*-----------------------------------------------------------------*/
1477 /* popZreg - restore values of zreg */
1478 /*-----------------------------------------------------------------*/
1480 popZreg (iCode * ic)
1482 if (ic->regsSaved) {
1483 emitcode ("pop", "r31");
1484 emitcode ("pop", "r30");
1488 /*-----------------------------------------------------------------*/
1489 /* genIpush - genrate code for pushing this gets a little complex */
1490 /*-----------------------------------------------------------------*/
1492 genIpush (iCode * ic)
1494 int size, offset = 0;
1498 if (!ic->parmPush) {
1499 /* and the item is spilt then do nothing */
1500 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1505 for (lic = ic->next; lic; lic = lic->next)
1506 if (lic->op == PCALL)
1512 /* this is a paramter push */
1513 aopOp (IC_LEFT (ic), ic, FALSE);
1514 size = AOP_SIZE (IC_LEFT (ic));
1516 l = aopGet (AOP (IC_LEFT (ic)), offset++);
1517 emitcode ("push", "%s", l);
1520 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1523 /*-----------------------------------------------------------------*/
1524 /* genIpop - recover the registers: can happen only for spilling */
1525 /*-----------------------------------------------------------------*/
1527 genIpop (iCode * ic)
1532 /* if the temp was not pushed then */
1533 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1536 aopOp (IC_LEFT (ic), ic, FALSE);
1537 size = AOP_SIZE (IC_LEFT (ic));
1538 offset = (size - 1);
1540 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--));
1542 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1545 /*-----------------------------------------------------------------*/
1546 /* genCall - generates a call statement */
1547 /*-----------------------------------------------------------------*/
1549 genCall (iCode * ic)
1552 /* if send set is not empty the assign */
1556 for (sic = setFirstItem (_G.sendSet); sic;
1557 sic = setNextItem (_G.sendSet)) {
1558 int size, offset = 0;
1559 aopOp (IC_LEFT (sic), sic, FALSE);
1560 size = AOP_SIZE (IC_LEFT (sic));
1563 aopGet (AOP (IC_LEFT (sic)), offset);
1565 sprintf (buffer, "r%d", rnum++);
1567 emitcode ("mov", "%s,%s", b, l);
1570 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1575 emitcode ("call", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1576 OP_SYMBOL (IC_LEFT (ic))->rname :
1577 OP_SYMBOL (IC_LEFT (ic))->name));
1579 /* if we need assign a result value */
1580 if ((IS_ITEMP (IC_RESULT (ic)) &&
1581 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1582 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1583 IS_TRUE_SYMOP (IC_RESULT (ic))) {
1585 aopOp (IC_RESULT (ic), ic, FALSE);
1586 assignResultValue (IC_RESULT (ic));
1587 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1590 /* adjust the stack for parameters if required */
1591 if (ic->parmBytes) {
1592 if (ic->parmBytes > 63) {
1593 emitcode ("sbiw", "r28,%d", ic->parmBytes);
1596 emitcode ("subi", "r28,<(%d)",
1598 emitcode ("sbci", "r29,>(%d)",
1605 /*-----------------------------------------------------------------*/
1606 /* genPcall - generates a call by pointer statement */
1607 /*-----------------------------------------------------------------*/
1609 genPcall (iCode * ic)
1615 aopOp (IC_LEFT (ic), ic, FALSE);
1616 emitcode ("mov", "r30", aopGet (AOP (IC_LEFT (ic)), 0));
1617 emitcode ("mov", "r31", aopGet (AOP (IC_RIGHT (ic)), 0));
1618 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1620 /* if send set is not empty the assign */
1624 for (sic = setFirstItem (_G.sendSet); sic;
1625 sic = setNextItem (_G.sendSet)) {
1626 int size, offset = 0;
1627 aopOp (IC_LEFT (sic), sic, FALSE);
1628 size = AOP_SIZE (IC_LEFT (sic));
1631 aopGet (AOP (IC_LEFT (sic)), offset);
1633 sprintf (b, "r%d", rnum++);
1635 emitcode ("mov", "%s,%s", b, l);
1638 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1643 emitcode ("icall", "");
1645 /* if we need assign a result value */
1646 if ((IS_ITEMP (IC_RESULT (ic)) &&
1647 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1648 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1649 IS_TRUE_SYMOP (IC_RESULT (ic))) {
1651 aopOp (IC_RESULT (ic), ic, FALSE);
1653 assignResultValue (IC_RESULT (ic));
1654 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1657 /* adjust the stack for parameters if
1659 if (ic->parmBytes) {
1661 if (ic->parmBytes > 3) {
1662 emitcode ("mov", "a,%s", spname);
1663 emitcode ("add", "a,#0x%02x",
1664 (-ic->parmBytes) & 0xff);
1665 emitcode ("mov", "%s,a", spname);
1668 for (i = 0; i < ic->parmBytes; i++)
1669 emitcode ("dec", "%s", spname);
1673 /* adjust the stack for parameters if required */
1674 if (ic->parmBytes) {
1675 if (ic->parmBytes > 63) {
1676 emitcode ("sbiw", "r28,%d", ic->parmBytes);
1679 emitcode ("subi", "r28,<(%d)",
1681 emitcode ("sbci", "r29,>(%d)",
1689 /*-----------------------------------------------------------------*/
1690 /* resultRemat - result is rematerializable */
1691 /*-----------------------------------------------------------------*/
1693 resultRemat (iCode * ic)
1695 if (SKIP_IC (ic) || ic->op == IFX)
1698 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic))) {
1699 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
1700 if (sym->remat && !POINTER_SET (ic))
1707 #if defined(__BORLANDC__) || defined(_MSC_VER)
1708 #define STRCASECMP stricmp
1710 #define STRCASECMP strcasecmp
1713 /*-----------------------------------------------------------------*/
1714 /* genFunction - generated code for function entry */
1715 /*-----------------------------------------------------------------*/
1717 genFunction (iCode * ic)
1724 /* create the function header */
1725 emitcode (";", "-----------------------------------------");
1726 emitcode (";", " function %s",
1727 (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
1728 emitcode (";", "-----------------------------------------");
1730 emitcode ("", "%s:", sym->rname);
1731 ftype = operandType (IC_LEFT (ic));
1733 /* if critical function then turn interrupts off */
1734 if (IFFUNC_ISCRITICAL (ftype))
1735 emitcode ("cli", "");
1737 if (IFFUNC_ISISR (sym->type)) {
1740 /* save the preserved registers that are used in this function */
1741 for (i = R2_IDX; i <= R15_IDX; i++) {
1742 if (bitVectBitValue (sym->regsUsed, i)) {
1744 emitcode ("push", "%s", avr_regWithIdx (i)->name);
1747 /* now for the pointer registers */
1748 if (bitVectBitValue (sym->regsUsed, R26_IDX)) {
1750 emitcode ("push", "r26");
1752 if (bitVectBitValue (sym->regsUsed, R27_IDX)) {
1754 emitcode ("push", "r27");
1756 if (bitVectBitValue (sym->regsUsed, R30_IDX)) {
1758 emitcode ("push", "r30");
1760 if (bitVectBitValue (sym->regsUsed, R31_IDX)) {
1762 emitcode ("push", "r31");
1764 /* adjust the stack for the function */
1766 emitcode ("push", "r28");
1767 emitcode ("push", "r29");
1768 emitcode ("in", "r28,__SP_L__");
1769 emitcode ("in", "r29,__SP_H__");
1770 if (sym->stack <= 63) {
1771 emitcode ("sbiw", "r28,%d", sym->stack);
1774 emitcode ("subi", "r28,<(%d)", sym->stack);
1775 emitcode ("sbci", "r29,>(%d)", sym->stack);
1777 emitcode ("out", "__SP_L__,r28");
1778 emitcode ("out", "__SP_H__,r29");
1782 /*-----------------------------------------------------------------*/
1783 /* genEndFunction - generates epilogue for functions */
1784 /*-----------------------------------------------------------------*/
1786 genEndFunction (iCode * ic)
1788 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
1791 /* restore stack pointer */
1793 if (sym->stack <= 63) {
1794 emitcode ("adiw", "r28,%d", sym->stack);
1797 emitcode ("subi", "r28,<(-%d)", sym->stack);
1798 emitcode ("sbci", "r29,>(-%d)", sym->stack);
1800 emitcode ("out", "__SP_L__,r28");
1801 emitcode ("out", "__SP_H__,r29");
1803 /* pop frame pointer */
1804 emitcode ("pop", "r29");
1805 emitcode ("pop", "r28");
1807 /* restore preserved registers */
1808 if (bitVectBitValue (sym->regsUsed, R31_IDX)) {
1810 emitcode ("pop", "r31");
1812 if (bitVectBitValue (sym->regsUsed, R30_IDX)) {
1814 emitcode ("pop", "r30");
1816 if (bitVectBitValue (sym->regsUsed, R27_IDX)) {
1818 emitcode ("pop", "r27");
1820 if (bitVectBitValue (sym->regsUsed, R26_IDX)) {
1822 emitcode ("pop", "r26");
1824 for (i = R15_IDX; i >= R2_IDX; i--) {
1825 if (bitVectBitValue (sym->regsUsed, i)) {
1827 emitcode ("pop", "%s", avr_regWithIdx (i)->name);
1831 if (IFFUNC_ISCRITICAL (sym->type))
1832 emitcode ("sti", "");
1834 if (IFFUNC_ISISR (sym->type)) {
1835 emitcode ("rti", "");
1838 emitcode ("ret", "");
1843 /*-----------------------------------------------------------------*/
1844 /* genRet - generate code for return statement */
1845 /*-----------------------------------------------------------------*/
1849 int size, offset = 0;
1851 /* if we have no return value then
1852 just generate the "ret" */
1856 /* we have something to return then
1857 move the return value into place */
1858 aopOp (IC_LEFT (ic), ic, FALSE);
1859 size = AOP_SIZE (IC_LEFT (ic));
1862 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) {
1863 emitcode ("ldi", "%s,%s(%d)", fAVRReturn[offset],
1865 (int) floatFromVal (AOP (IC_LEFT (ic))->
1866 aopu.aop_lit), offset);
1870 l = aopGet (AOP (IC_LEFT (ic)), offset);
1871 if (strcmp (fAVRReturn[offset], l))
1872 emitcode ("mov", "%s,%s", fAVRReturn[offset],
1878 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1881 /* generate a jump to the return label
1882 if the next is not the return statement */
1883 if (!(ic->next && ic->next->op == LABEL &&
1884 IC_LABEL (ic->next) == returnLabel))
1886 emitcode ("rjmp", "L%05d", returnLabel->key);
1890 /*-----------------------------------------------------------------*/
1891 /* genLabel - generates a label */
1892 /*-----------------------------------------------------------------*/
1894 genLabel (iCode * ic)
1896 /* special case never generate */
1897 if (IC_LABEL (ic) == entryLabel)
1900 emitcode ("", "L%05d:", IC_LABEL (ic)->key);
1903 /*-----------------------------------------------------------------*/
1904 /* genGoto - generates a ljmp */
1905 /*-----------------------------------------------------------------*/
1907 genGoto (iCode * ic)
1909 emitcode ("rjmp", "L%05d", (IC_LABEL (ic)->key));
1912 /*-----------------------------------------------------------------*/
1913 /* genPlusIncr :- does addition with increment if possible */
1914 /*-----------------------------------------------------------------*/
1916 genPlusIncr (iCode * ic)
1918 unsigned int icount;
1921 /* will try to generate an increment */
1922 /* if the right side is not a literal
1924 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
1927 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.
1930 /* if the sizes are greater than 2 or they are not the same regs
1932 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1935 /* so we know LEFT & RESULT in the same registers and add
1937 /* for short & char types */
1938 if (AOP_SIZE (IC_RESULT (ic)) < 2) {
1940 emitcode ("inc", "%s",
1941 aopGet (AOP (IC_LEFT (ic)), 0));
1944 if (AOP_ISHIGHREG( AOP (IC_LEFT (ic)),0)) {
1945 emitcode ("subi", "%s,<(%d)",
1946 aopGet (AOP (IC_LEFT (ic)), 0), 0-icount);
1951 for (offset = 0 ; offset < AOP_SIZE(IC_RESULT(ic)) ; offset++) {
1952 if (!(AOP_ISHIGHREG(AOP(IC_RESULT(ic)),offset))) return FALSE;
1955 if (AOP_SIZE (IC_RESULT (ic)) <= 3) {
1956 /* if register pair and starts with 26/30 then adiw */
1957 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0
1959 && (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX) ||
1960 IS_REGIDX (AOP (IC_RESULT (ic)), R24_IDX) ||
1961 IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX))) {
1962 emitcode ("adiw", "%s,%d",
1963 aopGet (AOP (IC_RESULT (ic)), 0), icount);
1968 emitcode ("subi", "%s,<(%d)",
1969 aopGet (AOP (IC_RESULT (ic)), 0), 0-icount);
1970 emitcode ("sbci", "%s,>(%d)",
1971 aopGet (AOP (IC_RESULT (ic)), 1), 0-icount);
1975 /* for 32 bit longs */
1976 emitcode ("subi", "%s,<(%d)", aopGet (AOP (IC_RESULT (ic)), 0),
1978 emitcode ("sbci", "%s,>(%d)", aopGet (AOP (IC_RESULT (ic)), 1),
1980 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2),
1982 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3),
1988 /* This is the pure and virtuous version of this code.
1989 * I'm pretty certain it's right, but not enough to toss the old
1993 adjustArithmeticResult (iCode * ic)
1995 if (opIsGptr (IC_RESULT (ic)) &&
1996 opIsGptr (IC_LEFT (ic)) &&
1997 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)))) {
1998 aopPut (AOP (IC_RESULT (ic)),
1999 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1),
2003 if (opIsGptr (IC_RESULT (ic)) &&
2004 opIsGptr (IC_RIGHT (ic)) &&
2005 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)))) {
2006 aopPut (AOP (IC_RESULT (ic)),
2007 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1),
2011 if (opIsGptr (IC_RESULT (ic)) &&
2012 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2013 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2014 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2015 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)))) {
2017 sprintf (buffer, "%d",
2018 pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2019 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2023 /*-----------------------------------------------------------------*/
2024 /* genPlus - generates code for addition */
2025 /*-----------------------------------------------------------------*/
2027 genPlus (iCode * ic)
2029 int size, offset = 0;
2033 /* special cases :- */
2035 aopOp (IC_LEFT (ic), ic, FALSE);
2036 aopOp (IC_RIGHT (ic), ic, FALSE);
2037 aopOp (IC_RESULT (ic), ic, TRUE);
2039 /* if I can do an increment instead
2040 of add then GOOD for ME */
2041 if (genPlusIncr (ic) == TRUE)
2044 size = getDataSize (IC_RESULT (ic));
2045 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2049 aopPut (AOP (IC_RESULT (ic)),
2050 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2052 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
2059 emitcode (l, "%s,%s",
2060 aopGet (AOP (IC_RESULT (ic)), offset),
2061 aopGet (AOP (IC_RIGHT (ic)), offset));
2064 if (AOP_ISHIGHREG( AOP( IC_RESULT(ic)),offset)) {
2070 emitcode (l, "%s,%s(-%d)",
2071 aopGet (AOP (IC_RESULT (ic)), offset),
2073 (int) floatFromVal (AOP (IC_RIGHT (ic))->
2081 emitcode (l, "%s,%s",
2082 aopGet (AOP (IC_RESULT (ic)), offset),
2083 aopGet (AOP (IC_RIGHT (ic)), offset));
2089 adjustArithmeticResult (ic);
2092 freeAsmop (IC_LEFT (ic), NULL, ic,
2093 (RESULTONSTACK (ic) ? FALSE : TRUE));
2094 freeAsmop (IC_RIGHT (ic), NULL, ic,
2095 (RESULTONSTACK (ic) ? FALSE : TRUE));
2096 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2099 /*-----------------------------------------------------------------*/
2100 /* genMinusDec :- does subtraction with deccrement if possible */
2101 /*-----------------------------------------------------------------*/
2103 genMinusDec (iCode * ic)
2105 unsigned int icount;
2108 /* will try to generate an increment */
2109 /* if the right side is not a literal
2111 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2115 (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.
2118 /* if the sizes are greater than 2 or they are not the same regs
2120 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2123 /* so we know LEFT & RESULT in the same registers and add
2125 /* for short & char types */
2126 if (AOP_SIZE (IC_RESULT (ic)) < 2) {
2128 emitcode ("dec", "%s",
2129 aopGet (AOP (IC_LEFT (ic)), 0));
2132 if (AOP_ISHIGHREG( AOP ( IC_LEFT(ic)),0)) {
2133 emitcode ("subi", "%s,<(%d)",
2134 aopGet (AOP (IC_LEFT (ic)), 0), icount);
2139 for (offset = 0 ; offset < AOP_SIZE(IC_RESULT(ic)) ; offset++) {
2140 if (!(AOP_ISHIGHREG(AOP(IC_RESULT(ic)),offset))) return FALSE;
2143 if (AOP_SIZE (IC_RESULT (ic)) <= 3) {
2144 /* if register pair and starts with 26/30 then adiw */
2145 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0
2147 && (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX) ||
2148 IS_REGIDX (AOP (IC_RESULT (ic)), R24_IDX) ||
2149 IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX))) {
2150 emitcode ("sbiw", "%s,%d",
2151 aopGet (AOP (IC_RESULT (ic)), 0), icount);
2156 emitcode ("subi", "%s,<(%d)",
2157 aopGet (AOP (IC_RESULT (ic)), 0), icount);
2158 emitcode ("sbci", "%s,>(%d)",
2159 aopGet (AOP (IC_RESULT (ic)), 1), icount);
2162 /* for 32 bit longs */
2163 emitcode ("subi", "%s,<(%d)", aopGet (AOP (IC_RESULT (ic)), 0),
2165 emitcode ("sbci", "%s,>(%d)", aopGet (AOP (IC_RESULT (ic)), 1),
2167 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2),
2169 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3),
2175 /*-----------------------------------------------------------------*/
2176 /* genMinus - generates code for subtraction */
2177 /*-----------------------------------------------------------------*/
2179 genMinus (iCode * ic)
2181 int size, offset = 0, samer;
2184 aopOp (IC_LEFT (ic), ic, FALSE);
2185 aopOp (IC_RIGHT (ic), ic, FALSE);
2186 aopOp (IC_RESULT (ic), ic, TRUE);
2188 /* if I can do an decrement instead
2189 of subtract then GOOD for ME */
2190 if (genMinusDec (ic) == TRUE)
2193 size = getDataSize (IC_RESULT (ic));
2194 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2197 aopPut (AOP (IC_RESULT (ic)),
2198 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2200 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
2207 emitcode (l, "%s,%s",
2208 aopGet (AOP (IC_RESULT (ic)), offset),
2209 aopGet (AOP (IC_RIGHT (ic)), offset));
2212 if (AOP_ISHIGHREG(AOP (IC_RESULT (ic)),offset)) {
2218 emitcode (l, "%s,%s(%d)",
2219 aopGet (AOP (IC_RESULT (ic)), offset),
2221 (int) floatFromVal (AOP (IC_RIGHT (ic))->
2229 emitcode (l, "%s,%s",
2230 aopGet (AOP (IC_RESULT (ic)), offset),
2231 aopGet (AOP (IC_RIGHT (ic)), offset));
2237 adjustArithmeticResult (ic);
2240 freeAsmop (IC_LEFT (ic), NULL, ic,
2241 (RESULTONSTACK (ic) ? FALSE : TRUE));
2242 freeAsmop (IC_RIGHT (ic), NULL, ic,
2243 (RESULTONSTACK (ic) ? FALSE : TRUE));
2244 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2247 /*-----------------------------------------------------------------*/
2248 /* genMultOneByte : 8 bit multiplication & division */
2249 /*-----------------------------------------------------------------*/
2251 genMultOneByte (operand * left, operand * right, operand * result)
2253 sym_link *opetype = operandType (result);
2257 /* (if two literals, the value is computed before) */
2258 /* if one literal, literal on the right */
2259 if (AOP_TYPE (left) == AOP_LIT) {
2265 size = AOP_SIZE (result);
2267 if (SPEC_USIGN (opetype)) {
2268 emitcode ("mul", "%s,%s", aopGet (AOP (left), 0),
2269 aopGet (AOP (right), 0));
2272 emitcode ("muls", "%s,%s", aopGet (AOP (left), 0),
2273 aopGet (AOP (right), 0));
2275 aopPut (AOP (result), "r0", 0);
2277 aopPut (AOP (result), "r1", 1);
2280 if (SPEC_USIGN (opetype)) {
2282 aopPut (AOP (result), zero, offset++);
2287 lbl = newiTempLabel (NULL);
2288 emitcode ("ldi", "r24,0");
2289 emitcode ("brcc", "L%05d", lbl->key);
2290 emitcode ("ldi", "r24,0xff)");
2291 emitcode ("", "L%05d:", lbl->key);
2293 aopPut (AOP (result), "r24",
2301 /*-----------------------------------------------------------------*/
2302 /* genMult - generates code for multiplication */
2303 /*-----------------------------------------------------------------*/
2305 genMult (iCode * ic)
2307 operand *left = IC_LEFT (ic);
2308 operand *right = IC_RIGHT (ic);
2309 operand *result = IC_RESULT (ic);
2311 /* assign the amsops */
2312 aopOp (left, ic, FALSE);
2313 aopOp (right, ic, FALSE);
2314 aopOp (result, ic, TRUE);
2316 /* if both are of size == 1 */
2317 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1) {
2318 genMultOneByte (left, right, result);
2322 /* should have been converted to function call */
2326 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2327 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2328 freeAsmop (result, NULL, ic, TRUE);
2331 /*-----------------------------------------------------------------*/
2332 /* genDiv - generates code for division */
2333 /*-----------------------------------------------------------------*/
2337 /* should have been converted to function call */
2341 /*-----------------------------------------------------------------*/
2342 /* genMod - generates code for division */
2343 /*-----------------------------------------------------------------*/
2347 /* should have been converted to function call */
2359 /*-----------------------------------------------------------------*/
2360 /* revavrcnd - reverse a conditional for avr */
2361 /*-----------------------------------------------------------------*/
2363 revavrcnd (int type)
2375 for (i = 0; i < (sizeof (rar) / sizeof (rar[0])); i++) {
2376 if (rar[i].type == type)
2377 return rar[i].rtype;
2378 if (rar[i].rtype == type)
2381 assert (0); /* cannot happen */
2382 return 0; /* makes the compiler happy */
2385 static char *br_name[4] = { "breq", "brne", "brlt", "brge" };
2386 static char *br_uname[4] = { "breq", "brne", "brlo", "brcc" };
2388 /*-----------------------------------------------------------------*/
2389 /* genBranch - generate the branch instruction */
2390 /*-----------------------------------------------------------------*/
2392 genBranch (iCode * ifx, int br_type, int sign)
2394 int tj = (IC_TRUE (ifx) ? 1 : 0);
2396 if (tj) { /* if true jump */
2397 char *nm = (sign ? br_name[br_type] : br_uname[br_type]);
2398 emitcode (nm, "L%05d", IC_TRUE (ifx)->key);
2400 else { /* if false jump */
2401 int rtype = revavrcnd (br_type);
2402 char *nm = (sign ? br_name[rtype] : br_uname[rtype]);
2403 emitcode (nm, "L%05d", IC_FALSE (ifx)->key);
2408 /*-----------------------------------------------------------------*/
2409 /* genCmp - compare & jump */
2410 /*-----------------------------------------------------------------*/
2412 genCmp (iCode * ic, iCode * ifx, int br_type)
2414 operand *left, *right, *result;
2415 sym_link *letype, *retype;
2417 int sign, size, offset = 0;
2419 left = IC_LEFT (ic);
2420 right = IC_RIGHT (ic);
2421 result = IC_RESULT (ic);
2423 letype = getSpec (operandType (left));
2424 retype = getSpec (operandType (right));
2425 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
2427 /* assign the amsops */
2428 aopOp (left, ic, FALSE);
2429 aopOp (right, ic, FALSE);
2430 aopOp (result, ic, TRUE);
2431 size = AOP_SIZE (left);
2435 if (AOP_TYPE (right) == AOP_LIT) {
2436 emitcode ("cpi", "%s,<(%d)",
2437 aopGet (AOP (left), 0),
2439 floatFromVal (AOP (IC_RIGHT (ic))->
2441 genBranch (ifx, br_type, sign);
2443 else { /* right != literal */
2444 emitcode ("cp", "%s,%s",
2445 aopGet (AOP (left), 0),
2446 aopGet (AOP (right), 0));
2447 genBranch (ifx, br_type, sign);
2450 else { /* size != 1 */
2453 emitcode ("cp", "%s,%s",
2454 aopGet (AOP (left), 0),
2455 aopGet (AOP (right), 0));
2457 emitcode ("cpc", "%s,%s",
2458 aopGet (AOP (left), offset),
2459 aopGet (AOP (right),
2463 genBranch (ifx, br_type, sign);
2467 emitcode ("clr", "r0");
2470 emitcode ("cp", "%s,%s",
2471 aopGet (AOP (left), 0),
2472 aopGet (AOP (right), 0));
2474 emitcode ("cpc", "%s,%s",
2475 aopGet (AOP (left), offset),
2476 aopGet (AOP (right), offset));
2479 lbl = newiTempLabel (NULL);
2480 br_type = revavrcnd (br_type);
2482 emitcode (br_uname[br_type], "L%05d", lbl->key);
2484 emitcode (br_name[br_type], "L%05d", lbl->key);
2485 emitcode ("inc", "r0");
2486 emitcode ("", "L%05d:", lbl->key);
2487 aopPut (AOP (result), "r0", 0);
2488 size = AOP_SIZE (result) - 1;
2491 aopPut (AOP (result), zero, offset++);
2494 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2495 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2496 freeAsmop (result, NULL, ic, TRUE);
2499 /*-----------------------------------------------------------------*/
2500 /* genCmpGt :- greater than comparison */
2501 /*-----------------------------------------------------------------*/
2503 genCmpGt (iCode * ic, iCode * ifx)
2505 /* should have transformed by the parser */
2509 /*-----------------------------------------------------------------*/
2510 /* genCmpLt - less than comparisons */
2511 /*-----------------------------------------------------------------*/
2513 genCmpLt (iCode * ic, iCode * ifx)
2515 genCmp (ic, ifx, AVR_LT);
2518 /*-----------------------------------------------------------------*/
2519 /* genCmpEq - generates code for equal to */
2520 /*-----------------------------------------------------------------*/
2522 genCmpEq (iCode * ic, iCode * ifx)
2524 genCmp (ic, ifx, AVR_EQ);
2527 /*-----------------------------------------------------------------*/
2528 /* genCmpNe - generates code for not equal to */
2529 /*-----------------------------------------------------------------*/
2531 genCmpNe (iCode * ic, iCode * ifx)
2533 genCmp (ic, ifx, AVR_NE);
2536 /*-----------------------------------------------------------------*/
2537 /* genCmpGe - generates code for greater than equal to */
2538 /*-----------------------------------------------------------------*/
2540 genCmpGe (iCode * ic, iCode * ifx)
2542 genCmp (ic, ifx, AVR_GE);
2545 /*-----------------------------------------------------------------*/
2546 /* genCmpLe - generates code for less than equal to */
2547 /*-----------------------------------------------------------------*/
2549 genCmpLe (iCode * ic, iCode * ifx)
2551 operand *left = IC_LEFT (ic);
2552 operand *right = IC_RIGHT (ic);
2554 IC_RIGHT (ic) = left;
2555 IC_LEFT (ic) = right;
2556 genCmp (ic, ifx, AVR_GE);
2559 /*-----------------------------------------------------------------*/
2560 /* ifxForOp - returns the icode containing the ifx for operand */
2561 /*-----------------------------------------------------------------*/
2563 ifxForOp (operand * op, iCode * ic)
2565 /* if true symbol then needs to be assigned */
2566 if (IS_TRUE_SYMOP (op))
2569 /* if this has register type condition and
2570 the next instruction is ifx with the same operand
2571 and live to of the operand is upto the ifx only then */
2573 ic->next->op == IFX &&
2574 IC_COND (ic->next)->key == op->key &&
2575 OP_SYMBOL (op)->liveTo <= ic->next->seq) return ic->next;
2580 /*-----------------------------------------------------------------*/
2581 /* genAndOp - for && operation */
2582 /*-----------------------------------------------------------------*/
2584 genAndOp (iCode * ic)
2586 operand *left, *right, *result;
2590 /* note here that && operations that are in an
2591 if statement are taken away by backPatchLabels
2592 only those used in arthmetic operations remain */
2593 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2594 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2595 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
2597 tlbl = newiTempLabel (NULL);
2598 toBoolean (left, "r0", TRUE);
2599 toBoolean (right, "r1", TRUE);
2600 emitcode ("and", "r0,r1");
2601 emitcode ("ldi", "r24,1");
2602 emitcode ("breq", "L%05d", tlbl->key);
2603 emitcode ("dec", "r24");
2604 emitcode ("", "L%05d:", tlbl->key);
2605 aopPut (AOP (result), "r24", 0);
2606 size = AOP_SIZE (result) - 1;
2609 aopPut (AOP (result), zero, offset++);
2611 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2612 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2613 freeAsmop (result, NULL, ic, TRUE);
2617 /*-----------------------------------------------------------------*/
2618 /* genOrOp - for || operation */
2619 /*-----------------------------------------------------------------*/
2621 genOrOp (iCode * ic)
2623 operand *left, *right, *result;
2627 /* note here that || operations that are in an
2628 if statement are taken away by backPatchLabels
2629 only those used in arthmetic operations remain */
2630 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2631 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2632 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
2634 tlbl = newiTempLabel (NULL);
2635 toBoolean (left, "r0", TRUE);
2636 toBoolean (right, "r0", FALSE);
2637 emitcode ("ldi", "r24,1");
2638 emitcode ("breq", "L%05d", tlbl->key);
2639 emitcode ("dec", "r24");
2640 emitcode ("", "L%05d:", tlbl->key);
2641 aopPut (AOP (result), "r24", 0);
2642 size = AOP_SIZE (result) - 1;
2645 aopPut (AOP (result), zero, offset++);
2647 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2648 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2649 freeAsmop (result, NULL, ic, TRUE);
2653 AVR_AND = 0, AVR_OR, AVR_XOR
2655 static char *bopnames_lit[] = { "andi", "ori" };
2656 static char *bopnames[] = { "and", "or", "eor" };
2657 /*-----------------------------------------------------------------*/
2658 /* genBitWise - generate bitwise operations */
2659 /*-----------------------------------------------------------------*/
2661 genBitWise (iCode * ic, iCode * ifx, int bitop)
2663 operand *left, *right, *result;
2664 int size, offset = 0;
2669 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2670 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2671 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
2673 size = AOP_SIZE (left);
2675 if (ifx) { /* used only for jumps */
2676 if (AOP_TYPE (right) == AOP_LIT &&
2677 (bitop == AVR_AND || bitop == AVR_OR)) {
2679 (int) floatFromVal (AOP (right)->aopu.
2681 int p2 = powof2 (lit);
2682 if (bitop == AVR_AND && p2) { /* right side is a power of 2 */
2683 l = aopGet (AOP (left), p2 / 8);
2684 if (IC_TRUE (ifx)) {
2685 emitcode ("sbrc", "%s,%d", l,
2687 emitcode ("rjmp", "L%05d",
2688 IC_TRUE (ifx)->key);
2691 emitcode ("sbrs", "%s,%d", l,
2693 emitcode ("rjmp", "L%05d",
2694 IC_FALSE (ifx)->key);
2697 else { /* right not power of two */
2698 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2700 if (eh && AOP_ISHIGHREG(AOP(IC_LEFT(ic)),0)) {
2701 emitcode (bopnames_lit[bitop],
2703 aopGet (AOP (IC_LEFT (ic)), 0), lit);
2706 MOVR24 (aopGet (AOP (IC_LEFT (ic)), 0));
2707 emitcode (bopnames_lit[bitop], "r24,<(%d)", lit);
2709 lbl = newiTempLabel (NULL);
2710 if (IC_TRUE (ifx)) {
2711 emitcode ("breq", "L%05d", lbl->key);
2712 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2715 emitcode ("brne", "L%05d", lbl->key);
2716 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)-> key);
2718 emitcode ("", "L%05d:", lbl->key);
2720 else if (size == 2) {
2721 emitcode ("mov", "r24,%s", aopGet (AOP (IC_LEFT (ic)), 0));
2722 emitcode ("mov", "r25,%s", aopGet (AOP (IC_LEFT (ic)), 1));
2723 emitcode (bopnames_lit[bitop], "r24,<(%d)", lit);
2724 emitcode (bopnames_lit[bitop], "r25,>(%d)", lit);
2725 emitcode ("sbiw", "r24,0");
2726 lbl = newiTempLabel (NULL);
2727 if (IC_TRUE (ifx)) {
2728 emitcode ("breq", "L%05d", lbl->key);
2729 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2732 emitcode ("brne", "L%05d", lbl->key);
2733 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2735 emitcode ("", "L%05d:", lbl->key);
2738 lbl = newiTempLabel (NULL);
2739 lbl1 = newiTempLabel (NULL);
2741 if (eh && AOP_ISHIGHREG(AOP(IC_LEFT(ic)),offset)) {
2742 emitcode (bopnames_lit [bitop], "%s,<(%d)",
2743 aopGet (AOP (IC_LEFT (ic)), offset),
2747 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
2749 emitcode ("andi", "r24,<(%d)", lit);
2751 emitcode ("brne", "L%05d", lbl->key);
2756 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)-> key);
2758 emitcode ("rjmp", "L%05d", lbl1->key);
2759 emitcode ("", "L%05d:", lbl->key);
2762 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2763 emitcode ("", "L%05d:", lbl1->key);
2768 else { /* right is not a literal */
2769 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2770 int reh = OP_SYMBOL (right)->liveTo <= ic->seq;
2773 emitcode (bopnames[bitop], "%s,%s", aopGet (AOP (IC_LEFT (ic)), 0),
2774 aopGet (AOP (IC_RIGHT (ic)), 0));
2777 emitcode (bopnames[bitop], "%s,%s",
2778 aopGet (AOP (IC_RIGHT (ic)), 0),
2779 aopGet (AOP (IC_LEFT (ic)), 0));
2782 MOVR0 (aopGet (AOP (IC_LEFT (ic)), 0));
2783 emitcode (bopnames[bitop], "r0,%s",
2784 aopGet (AOP (IC_RIGHT (ic)), 0));
2786 lbl = newiTempLabel (NULL);
2787 if (IC_TRUE (ifx)) {
2788 emitcode ("breq", "L%05d", lbl->key);
2789 emitcode ("rjmp", "L%05d",
2790 IC_TRUE (ifx)->key);
2793 emitcode ("brne", "L%05d", lbl->key);
2794 emitcode ("rjmp", "L%05d",
2795 IC_FALSE (ifx)->key);
2797 emitcode ("", "L%05d:", lbl->key);
2799 else if (size == 2) {
2800 emitcode ("mov", "r24,%s",
2801 aopGet (AOP (IC_LEFT (ic)), 0));
2802 emitcode ("mov", "r25,%s",
2803 aopGet (AOP (IC_LEFT (ic)), 1));
2804 emitcode (bopnames[bitop], "r24,%s",
2805 aopGet (AOP (IC_RIGHT (ic)), 0));
2806 emitcode (bopnames[bitop], "r25,%s",
2807 aopGet (AOP (IC_RIGHT (ic)), 1));
2808 emitcode ("sbiw", "r24,0");
2809 lbl = newiTempLabel (NULL);
2810 if (IC_TRUE (ifx)) {
2811 emitcode ("breq", "L%05d", lbl->key);
2812 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2815 emitcode ("brne", "L%05d", lbl->key);
2816 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2818 emitcode ("", "L%05d:", lbl->key);
2821 lbl = newiTempLabel (NULL);
2822 lbl1 = newiTempLabel (NULL);
2825 emitcode (bopnames[bitop], "%s,%s",
2826 aopGet (AOP (IC_LEFT (ic)), offset),
2827 aopGet (AOP (IC_RIGHT (ic)), offset));
2830 emitcode (bopnames[bitop], "%s,%s",
2831 aopGet (AOP (IC_RIGHT (ic)), offset),
2832 aopGet (AOP (IC_LEFT (ic)), offset));
2835 MOVR0 (aopGet (AOP (IC_LEFT (ic)), offset));
2836 emitcode (bopnames[bitop], "r0,%s",
2837 aopGet (AOP (IC_RIGHT (ic)), offset));
2839 emitcode ("brne", "L%05d", lbl->key);
2844 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2846 emitcode ("rjmp", "L%05d", lbl1->key);
2847 emitcode ("", "L%05d:", lbl->key);
2850 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2851 emitcode ("", "L%05d:", lbl1->key);
2858 /* result needs to go a register */
2859 samerl = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2860 samerr = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)));
2862 if (AOP_TYPE (right) == AOP_LIT) {
2864 (int) floatFromVal (AOP (right)->aopu.
2866 if (((lit >> (8 * offset)) & 0xff) == 0) {
2867 if (bitop == AVR_AND) {
2868 aopPut (AOP (result), zero, offset++);
2871 else if (bitop == AVR_OR) {
2873 aopPut (AOP (result),
2883 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT &&
2884 AOP_ISHIGHREG(AOP(IC_LEFT(ic)),offset) &&
2885 (bitop == AVR_AND || bitop == AVR_OR)) {
2886 emitcode (bopnames_lit[bitop], "%s,%s(%d)",
2887 aopGet (AOP (IC_LEFT (ic)), offset),
2889 (int) floatFromVal (AOP (right)-> aopu.aop_lit));
2892 emitcode (bopnames[bitop], "%s,%s",
2893 aopGet (AOP (IC_LEFT (ic)), offset),
2894 aopGet (AOP (IC_RIGHT (ic)), offset));
2898 emitcode (bopnames[bitop], "%s,%s",
2899 aopGet (AOP (IC_RIGHT (ic)), offset),
2900 aopGet (AOP (IC_LEFT (ic)), offset));
2903 aopPut (AOP (IC_RESULT (ic)),
2904 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2905 emitcode (bopnames[bitop],
2906 aopGet (AOP (IC_RESULT (ic)), offset),
2907 aopGet (AOP (IC_RIGHT (ic)), offset));
2912 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2913 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2914 freeAsmop (result, NULL, ic, TRUE);
2917 /*-----------------------------------------------------------------*/
2918 /* genAnd - code for and */
2919 /*-----------------------------------------------------------------*/
2921 genAnd (iCode * ic, iCode * ifx)
2923 genBitWise (ic, ifx, AVR_AND);
2926 /*-----------------------------------------------------------------*/
2927 /* genOr - code for or */
2928 /*-----------------------------------------------------------------*/
2930 genOr (iCode * ic, iCode * ifx)
2932 genBitWise (ic, ifx, AVR_OR);
2935 /*-----------------------------------------------------------------*/
2936 /* genXor - code for xclusive or */
2937 /*-----------------------------------------------------------------*/
2939 genXor (iCode * ic, iCode * ifx)
2941 genBitWise (ic, ifx, AVR_XOR);
2944 /*-----------------------------------------------------------------*/
2945 /* genInline - write the inline code out */
2946 /*-----------------------------------------------------------------*/
2948 genInline (iCode * ic)
2950 char *buffer, *bp, *bp1;
2952 _G.inLine += (!options.asmpeep);
2954 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
2955 strcpy (buffer, IC_INLINE (ic));
2957 /* emit each line as a code */
2978 /* emitcode("",buffer); */
2979 _G.inLine -= (!options.asmpeep);
2982 /*-----------------------------------------------------------------*/
2983 /* genRotC - rotate right/left with carry , lr = 1 rotate right */
2984 /*-----------------------------------------------------------------*/
2986 genRotC (iCode * ic, int lr)
2988 operand *left, *result;
2989 int size, offset = 0;
2991 /* rotate right with carry */
2992 left = IC_LEFT (ic);
2993 result = IC_RESULT (ic);
2994 aopOp (left, ic, FALSE);
2995 aopOp (result, ic, FALSE);
2997 /* move it to the result */
2998 size = AOP_SIZE (result);
2999 if (!sameRegs (AOP (left), AOP (result))) {
3002 aopPut (AOP (result),
3003 aopGet (AOP (left), offset), offset);
3006 size = AOP_SIZE (result);
3014 emitcode ("sbrc", "%s,%d", aopGet (AOP (result), offset),
3016 emitcode ("sec", "");
3019 emitcode ((lr ? "ror" : "rol"), "%s",
3020 aopGet (AOP (result), offset));
3026 freeAsmop (left, NULL, ic, TRUE);
3027 freeAsmop (result, NULL, ic, TRUE);
3030 /*-----------------------------------------------------------------*/
3031 /* genRRC - rotate right with carry */
3032 /*-----------------------------------------------------------------*/
3039 /*-----------------------------------------------------------------*/
3040 /* genRLC - generate code for rotate left with carry */
3041 /*-----------------------------------------------------------------*/
3048 /*-----------------------------------------------------------------*/
3049 /* genGetHbit - generates code get highest order bit */
3050 /*-----------------------------------------------------------------*/
3052 genGetHbit (iCode * ic)
3054 operand *left, *result;
3057 left = IC_LEFT (ic);
3058 result = IC_RESULT (ic);
3059 aopOp (left, ic, FALSE);
3060 aopOp (result, ic, FALSE);
3062 size = AOP_SIZE (result);
3063 if (!sameRegs (AOP (left), AOP (result))) {
3064 emitcode ("clr", "%s", aopGet (AOP (result), size - 1));
3065 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3066 emitcode ("subi", "%s,<(-1)",
3067 aopGet (AOP (result), size - 1));
3070 emitcode ("clr", "r0");
3071 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3072 emitcode ("subi", "r0,<(-1)");
3073 aopPut (AOP (result), "r0", 0);
3078 emitcode ("clr", aopGet (AOP (result), offset++));
3080 freeAsmop (left, NULL, ic, TRUE);
3081 freeAsmop (result, NULL, ic, TRUE);
3084 /*-----------------------------------------------------------------*/
3085 /* genShiftLeftLit - shift left by a known amount */
3086 /*-----------------------------------------------------------------*/
3088 genShiftLeftLit (iCode * ic)
3090 operand *left, *right, *result;
3091 int size, shCount, offset = 0;
3094 right = IC_RIGHT (ic);
3095 left = IC_LEFT (ic);
3096 result = IC_RESULT (ic);
3098 aopOp (left, ic, FALSE);
3099 aopOp (result, ic, FALSE);
3100 size = AOP_SIZE (result);
3101 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3103 if (shCount > (size * 8 - 1)) {
3105 aopPut (AOP (result), zero, offset++);
3110 if (!sameRegs (AOP (left), AOP (result)))
3111 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3113 if (AOP_ISHIGHREG(AOP(result),0)) {
3114 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3115 emitcode ("andi", "%s,0xf0");
3117 emitcode ("ldi","r24,0xf0");
3118 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3119 emitcode ("and", "%s,r24");
3124 emitcode ("add", "%s,%s", aopGet (AOP (result), 0),
3125 aopGet (AOP (result), 0));
3129 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3132 if (shCount >= 12) {
3133 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3134 aopPut (AOP (result), zero, 0);
3135 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3136 if (AOP_ISHIGHREG(AOP(result),1)) {
3137 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3139 emitcode ("ldi","r24,0xf0");
3140 emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
3146 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3147 aopPut (AOP (result), zero, 0);
3153 if (!sameRegs (AOP (left), AOP (result))) {
3154 aopPut (AOP (result), aopGet (AOP (left), 0),
3156 aopPut (AOP (result), aopGet (AOP (left), 1),
3159 emitcode ("mov", "r24,%s", aopGet (AOP (result), 0));
3160 emitcode ("andi", "r24,0x0f");
3161 if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
3162 emitcode("ldi","r25,0xf0");
3164 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3165 if (AOP_ISHIGHREG(AOP(result),0)) {
3166 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 0));
3168 emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
3170 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3171 if (AOP_ISHIGHREG(AOP(result),1)) {
3172 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3174 emitcode ("and", "%s,r25", aopGet (AOP (result), 1));
3176 emitcode ("or", "%s,r24", aopGet (AOP (result), 1));
3178 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3179 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3182 if (!lByteZ && !sameRegs (AOP (result), AOP (left))
3186 aopPut (AOP (result),
3187 aopGet (AOP (left), offset), offset);
3193 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3196 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3197 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3202 assert ("shifting generic pointer ?\n");
3205 /* 32 bits we do only byte boundaries */
3206 if (shCount >= 24) {
3207 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3208 aopPut (AOP (result), zero, 2);
3209 aopPut (AOP (result), zero, 1);
3210 aopPut (AOP (result), zero, 0);
3214 if (shCount >= 16) {
3215 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3216 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3217 aopPut (AOP (result), zero, 1);
3218 aopPut (AOP (result), zero, 0);
3223 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3224 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3225 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3226 aopPut (AOP (result), zero, 0);
3230 if (!lByteZ && !sameRegs (AOP (left), AOP (right))) {
3233 aopPut (AOP (result),
3234 aopGet (AOP (left), offset), offset);
3238 size = AOP_SIZE (result);
3244 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3245 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3246 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3247 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3252 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3253 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3254 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3259 emitcode ("lsl", "%s", aopGet (AOP (result), 2));
3260 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3265 emitcode ("lsl", "%s", aopGet (AOP (result), 3));
3273 freeAsmop (left, NULL, ic, TRUE);
3274 freeAsmop (right, NULL, ic, TRUE);
3275 freeAsmop (result, NULL, ic, TRUE);
3278 /*-----------------------------------------------------------------*/
3279 /* genLeftShift - generates code for left shifting */
3280 /*-----------------------------------------------------------------*/
3282 genLeftShift (iCode * ic)
3284 operand *left, *right, *result;
3288 right = IC_RIGHT (ic);
3289 left = IC_LEFT (ic);
3290 result = IC_RESULT (ic);
3292 aopOp (right, ic, FALSE);
3294 if (AOP_TYPE (right) == AOP_LIT) {
3295 genShiftLeftLit (ic);
3300 aopOp (left, ic, FALSE);
3301 aopOp (result, ic, FALSE);
3302 size = AOP_SIZE (result);
3304 if (AOP_SIZE (right) > 1) {
3305 if (isRegPair (AOP (right))) {
3306 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3309 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3310 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3314 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3316 if (!sameRegs (AOP (left), AOP (result))) {
3318 aopPut (AOP (result), aopGet (AOP (left), offset),
3322 size = AOP_SIZE (result);
3324 tlbl = newiTempLabel (NULL);
3325 emitcode ("", "L%05d:", tlbl->key);
3329 emitcode ("rol", "%s", aopGet (AOP (result), offset));
3331 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3334 if (AOP_SIZE (right) > 1)
3335 emitcode ("sbiw", "r24,1");
3337 emitcode ("dec", "r24");
3338 emitcode ("brne", "L%05d", tlbl->key);
3340 freeAsmop (left, NULL, ic, TRUE);
3341 freeAsmop (right, NULL, ic, TRUE);
3342 freeAsmop (result, NULL, ic, TRUE);
3345 /*-----------------------------------------------------------------*/
3346 /* genShiftRightLit - generate for right shift with known count */
3347 /*-----------------------------------------------------------------*/
3349 genShiftRightLit (iCode * ic)
3351 operand *left = IC_LEFT (ic)
3352 , *right = IC_RIGHT (ic)
3353 , *result = IC_RESULT (ic);
3354 int size, shCount, offset = 0;
3356 sym_link *letype = getSpec (operandType (left));
3357 int sign = !SPEC_USIGN (letype);
3359 right = IC_RIGHT (ic);
3360 left = IC_LEFT (ic);
3361 result = IC_RESULT (ic);
3363 aopOp (left, ic, FALSE);
3364 aopOp (result, ic, FALSE);
3365 size = AOP_SIZE (result);
3366 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3368 /* if signed then give up and use a loop to shift */
3371 if (!sameRegs (AOP (left), AOP (result))) {
3373 aopPut (AOP (result),
3374 aopGet (AOP (left), offset), offset);
3377 size = AOP_SIZE (result);
3380 /* be as economical as possible */
3383 size = AOP_SIZE (result);
3386 /* highest order byte */
3387 if (offset == (AOP_SIZE(result)-1))
3388 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3390 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3396 emitcode ("ldi", "r24,<(%d)", shCount);
3397 tlbl = newiTempLabel (NULL);
3398 emitcode ("", "L%05d:", tlbl->key);
3401 if (offset == (AOP_SIZE(result) - 1))
3402 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3404 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3407 emitcode ("dec", "r24");
3408 emitcode ("brne", "L%05d", tlbl->key);
3412 if (shCount > (size * 8 - 1)) {
3414 aopPut (AOP (result), zero, offset++);
3417 /* for unsigned we can much more efficient */
3420 if (!sameRegs (AOP (left), AOP (result)))
3421 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3423 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3424 if (AOP_ISHIGHREG(AOP(result),0)) {
3425 emitcode ("andi", "%s,0x0f",aopGet(AOP(result),0));
3427 emitcode ("ldi","r24,0x0f");
3428 emitcode ("and", "%s,r24",aopGet(AOP(result),0));
3433 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3436 if (shCount >= 12) {
3437 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3438 aopPut (AOP (result), zero, 1);
3439 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3440 if (AOP_ISHIGHREG(AOP(result),0)) {
3441 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3443 emitcode ("ldi","r24,0x0f");
3444 emitcode ("and", "%s,r24",aopGet(AOP(result),0));
3450 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3451 aopPut (AOP (result), zero, 1);
3457 if (!sameRegs (AOP (left), AOP (result))) {
3458 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3459 aopPut (AOP (result), aopGet (AOP (left), 1), 1);
3461 if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
3462 emitcode("ldi","r25,0x0f");
3464 emitcode ("mov", "r24,%s", aopGet (AOP (result), 1));
3465 emitcode ("andi", "r24,0xf0");
3466 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3467 if (AOP_ISHIGHREG(AOP(result),0)) {
3468 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3470 emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
3472 emitcode ("or", "%s,r24", aopGet (AOP (result), 0));
3473 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3474 if (AOP_ISHIGHREG(AOP(result),1)) {
3475 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 1));
3477 emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
3480 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3481 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3485 if (!hByteZ && !sameRegs (AOP (result), AOP (left))
3489 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3495 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3498 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3499 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3505 assert ("shifting generic pointer ?\n");
3508 /* 32 bits we do only byte boundaries */
3509 if (shCount >= 24) {
3510 aopPut (AOP (result), aopGet (AOP (left), 3), 0);
3511 aopPut (AOP (result), zero, 1);
3512 aopPut (AOP (result), zero, 2);
3513 aopPut (AOP (result), zero, 3);
3517 if (shCount >= 16) {
3518 aopPut (AOP (result), aopGet (AOP (left), 3), 1);
3519 aopPut (AOP (result), aopGet (AOP (left), 2), 0);
3520 aopPut (AOP (result), zero, 2);
3521 aopPut (AOP (result), zero, 3);
3526 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3527 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3528 aopPut (AOP (result), aopGet (AOP (left), 3), 2);
3529 aopPut (AOP (result), zero, 3);
3533 if (!hByteZ && !sameRegs (AOP (left), AOP (right))) {
3536 aopPut (AOP (result),
3537 aopGet (AOP (left), offset), offset);
3541 size = AOP_SIZE (result);
3547 emitcode ("lsr", "%s", aopGet (AOP (result), 3));
3548 emitcode ("ror", "%s", aopGet (AOP (result), 2));
3549 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3550 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3555 emitcode ("lsr", "%s", aopGet (AOP (result), 2));
3556 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3557 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3562 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3563 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3568 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3575 freeAsmop (left, NULL, ic, TRUE);
3576 freeAsmop (right, NULL, ic, TRUE);
3577 freeAsmop (result, NULL, ic, TRUE);
3580 /*-----------------------------------------------------------------*/
3581 /* genRightShift - generate code for right shifting */
3582 /*-----------------------------------------------------------------*/
3584 genRightShift (iCode * ic)
3586 operand *right, *left, *result;
3589 int sign = 0, first = 1;
3592 aopOp (right = IC_RIGHT (ic), ic, FALSE);
3594 if (AOP_TYPE (right) == AOP_LIT) {
3595 genShiftRightLit (ic);
3599 if (AOP_SIZE (right) > 1) {
3600 if (isRegPair (AOP (right))) {
3601 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3604 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3605 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3609 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3611 aopOp (left = IC_LEFT (ic), ic, FALSE);
3612 aopOp (result = IC_RESULT (ic), ic, FALSE);
3613 size = AOP_SIZE (result);
3614 tlbl = newiTempLabel (NULL);
3615 emitcode ("", "L%05d:", tlbl->key);
3617 letype = getSpec (operandType (left));
3618 sign = !SPEC_USIGN (letype);
3619 if (!sameRegs (AOP (left), AOP (result))) {
3621 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3624 size = AOP_SIZE (result);
3626 size = AOP_SIZE (result);
3630 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3632 emitcode ("lsr", "%s", aopGet (AOP (result), offset));
3636 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3639 if (AOP_SIZE (right) > 1)
3640 emitcode ("sbiw", "r24,1");
3642 emitcode ("dec", "r24");
3643 emitcode ("brne", "L%05d", tlbl->key);
3645 freeAsmop (left, NULL, ic, TRUE);
3646 freeAsmop (result, NULL, ic, TRUE);
3649 /*-----------------------------------------------------------------*/
3650 /* RRsh - shift right rn by known count */
3651 /*-----------------------------------------------------------------*/
3653 RRsh (int shCount,int reg)
3655 shCount &= 0x0007; // shCount : 0..7
3661 emitcode ("lsr", "r%d",reg);
3664 emitcode ("lsr", "r%d",reg);
3665 emitcode ("lsr", "r%d",reg);
3668 emitcode ("swap", "r%d",reg);
3669 emitcode ("lsl", "r%d",reg);
3672 emitcode ("swap", "r%d",reg);
3675 emitcode ("swap", "r%d",reg);
3676 emitcode ("lsr", "r%d",reg);
3679 emitcode ("swap","r%d",reg);
3680 emitcode ("lsr", "r%d",reg);
3681 emitcode ("lsr", "r%d",reg);
3684 emitcode ("swap","r%d",reg);
3685 emitcode ("lsr", "r%d",reg);
3686 emitcode ("lsr", "r%d",reg);
3687 emitcode ("lsr", "r%d",reg);
3692 /*-----------------------------------------------------------------*/
3693 /* RLsh - shift left rn by known count */
3694 /*-----------------------------------------------------------------*/
3696 RLsh (int shCount, int reg)
3698 shCount &= 0x0007; // shCount : 0..7
3704 emitcode ("lsl", "r%d",reg);
3707 emitcode ("lsl", "r%d",reg);
3708 emitcode ("lsl", "r%d",reg);
3711 emitcode ("swap","r%d",reg);
3712 emitcode ("lsr", "r%d",reg);
3715 emitcode ("swap", "r%d",reg);
3718 emitcode ("swap","r%d",reg);
3719 emitcode ("lsl", "r%d",reg);
3722 emitcode ("swap","r%d",reg);
3723 emitcode ("lsl", "r%d",reg);
3724 emitcode ("lsl", "r%d",reg);
3727 emitcode ("swap","r%d",reg);
3728 emitcode ("lsl", "r%d",reg);
3729 emitcode ("lsl", "r%d",reg);
3730 emitcode ("lsl", "r%d",reg);
3735 /*-----------------------------------------------------------------*/
3736 /* genUnpackBits - generates code for unpacking bits */
3737 /*-----------------------------------------------------------------*/
3739 genUnpackBits (operand * result, char *rname, int ptype)
3747 etype = getSpec (operandType (result));
3748 rsize = getSize (operandType (result));
3749 /* read the first byte */
3756 emitcode ("ld", "r24,%s+", rname);
3760 emitcode ("lpm", "r24,%s+", rname);
3764 emitcode ("call","__gptrget_pi");
3765 emitcode ("mov","r24,r0");
3769 rlen = SPEC_BLEN (etype);
3771 /* if we have bitdisplacement then it fits */
3772 /* into this byte completely or if length is */
3773 /* less than a byte */
3774 if ((shCnt = SPEC_BSTR (etype)) || (SPEC_BLEN (etype) <= 8)) {
3776 /* shift right acc */
3779 emitcode ("andi", "r24,lo(0x%x)",
3780 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
3781 aopPut (AOP (result), "r24", offset++);
3785 /* bit field did not fit in a byte */
3786 aopPut (AOP (result), "r24", offset++);
3796 emitcode ("ld", "r24,%s+");
3800 emitcode ("lpm", "r24,%s+");
3804 emitcode ("call", "__gptrget_pi");
3809 /* if we are done */
3813 aopPut (AOP (result), "r24", offset++);
3818 aopPut (AOP (result), "r24", offset++);
3822 if (offset < rsize) {
3825 aopPut (AOP (result), zero, offset++);
3830 /*-----------------------------------------------------------------*/
3831 /* genDataPointerGet - generates code when ptr offset is known */
3832 /*-----------------------------------------------------------------*/
3834 genDataPointerGet (operand * left, operand * result, iCode * ic)
3838 int size, offset = 0;
3839 aopOp (result, ic, TRUE);
3841 /* get the string representation of the name */
3842 l = aopGet (AOP (left), 0);
3843 size = AOP_SIZE (result);
3846 sprintf (buffer, "(%s + %d)", l, offset);
3848 sprintf (buffer, "%s", l);
3849 emitcode ("lds", "%s,%s", aopGet (AOP (result), offset++),
3853 freeAsmop (left, NULL, ic, TRUE);
3854 freeAsmop (result, NULL, ic, TRUE);
3857 /*-----------------------------------------------------------------*/
3858 /* genNearPointerGet - emitcode for near pointer fetch */
3859 /*-----------------------------------------------------------------*/
3861 genMemPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
3866 char *rname, *frname = NULL;
3867 sym_link *rtype, *retype;
3868 sym_link *ltype = operandType (left);
3870 rtype = operandType (result);
3871 retype = getSpec (rtype);
3873 aopOp (left, ic, FALSE);
3875 /* if left is rematerialisable and
3876 result is not bit variable type and
3877 the left is pointer to data space i.e
3878 lower 128 bytes of space */
3879 if (AOP_TYPE (left) == AOP_IMMD &&
3880 !IS_BITVAR (retype) && DCL_TYPE (ltype) == POINTER) {
3881 genDataPointerGet (left, result, ic);
3885 /* if the value is already in a pointer register
3886 then don't need anything more */
3887 if (!AOP_INPREG (AOP (left))) {
3888 /* otherwise get a free pointer register */
3890 preg = getFreePtr (ic, &aop, FALSE, 0);
3891 if (isRegPair (AOP (left) )) {
3892 emitcode ("movw", "%s,%s",
3893 aop->aopu.aop_ptr->name,
3894 aopGet(AOP(left),0));
3896 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
3897 aopGet (AOP (left), 0));
3898 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
3899 aopGet (AOP (left), 1));
3905 frname = aopGet(aop,0);
3909 } else if (AOP_ISZ(aop)) {
3912 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
3913 "pointer not in correct register");
3917 aopOp (result, ic, FALSE);
3919 /* if bitfield then unpack the bits */
3920 if (IS_BITVAR (retype))
3921 genUnpackBits (result, rname, POINTER);
3923 /* we have can just get the values */
3924 int size = AOP_SIZE (result);
3929 emitcode ("ld","%s,%s+",aopGet(AOP(result),offset), rname);
3931 emitcode ("ld","%s,%s",aopGet(AOP(result),offset), rname);
3936 /* now some housekeeping stuff */
3938 /* we had to allocate for this iCode */
3940 if (isRegPair (AOP (left) )) {
3941 emitcode ("movw", "%s,%s",
3942 aopGet (AOP(left),0),
3943 aop->aopu.aop_ptr->name);
3945 emitcode ("mov", "%s,%s",
3946 aopGet (AOP (left), 0),
3947 aop->aopu.aop_ptr->name);
3948 emitcode ("mov", "%s,%s",
3949 aopGet (AOP (left), 1),
3950 aop->aop_ptr2->name);
3953 freeAsmop (NULL, aop, ic, TRUE);
3956 /* we did not allocate which means left
3957 already in a pointer register, then
3958 if size > 0 && this could be used again
3959 we have to point it back to where it
3961 if ((AOP_SIZE (result) > 1 &&
3962 !OP_SYMBOL (left)->remat &&
3963 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) && !pi) {
3964 int size = AOP_SIZE (result) - 1;
3965 emitcode ("sbiw", "%s,%d",frname,size);
3970 if (pi) pi->generated = 1;
3971 freeAsmop (left, NULL, ic, TRUE);
3972 freeAsmop (result, NULL, ic, TRUE);
3976 /*-----------------------------------------------------------------*/
3977 /* genCodePointerGet - gget value from code space */
3978 /*-----------------------------------------------------------------*/
3980 genCodePointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
3983 sym_link *retype = getSpec (operandType (result));
3987 aopOp (left, ic, FALSE);
3989 /* if the operand is already in Z register
3990 then we do nothing else we move the value to Z register */
3991 if (AOP_ISZ(AOP(left))) {
3995 getFreePtr(ic,&aop,FALSE,TRUE);
3996 if (isRegPair(AOP (left))) {
3997 emitcode ("movw","r30,%s",aopGet (AOP (left), 0));
3999 emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
4000 emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
4005 aopOp (result, ic, FALSE);
4007 /* if bit then unpack */
4008 if (IS_BITVAR (retype))
4009 genUnpackBits (result, "Z", CPOINTER);
4011 size = AOP_SIZE (result);
4016 emitcode ("lpm","%s,Z+",aopGet(AOP(result),offset++));
4018 emitcode ("lpm","%s,Z",aopGet(AOP(result),offset++));
4023 /* now some housekeeping stuff */
4025 /* we had to allocate for this iCode */
4027 if (isRegPair(AOP (left))) {
4028 emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
4030 emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
4031 emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
4034 freeAsmop (NULL, aop, ic, TRUE);
4037 /* we did not allocate which means left
4038 already in a pointer register, then
4039 if size > 0 && this could be used again
4040 we have to point it back to where it
4042 if ((AOP_SIZE (result) > 1 &&
4043 !OP_SYMBOL (left)->remat &&
4044 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) &&
4046 int size = AOP_SIZE (result) - 1;
4047 emitcode ("sbiw", "r30,%d",size);
4052 if (pi) pi->generated=1;
4053 freeAsmop (left, NULL, ic, TRUE);
4054 freeAsmop (result, NULL, ic, TRUE);
4058 /*-----------------------------------------------------------------*/
4059 /* genGenPointerGet - gget value from generic pointer space */
4060 /*-----------------------------------------------------------------*/
4062 genGenPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
4066 sym_link *retype = getSpec (operandType (result));
4069 aopOp (left, ic, FALSE);
4071 /* if the operand is already in dptr
4072 then we do nothing else we move the value to dptr */
4073 if (AOP_ISZ(AOP(left))) {
4077 getFreePtr(ic,&aop,FALSE,TRUE);
4078 if (isRegPair(AOP(left))) {
4079 emitcode ("movw", "r30,%s", aopGet (AOP (left), 0));
4081 emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
4082 emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
4084 emitcode ("mov", "r24,%s", aopGet (AOP (left), 2));
4088 /* so Z register now contains the address */
4090 aopOp (result, ic, FALSE);
4092 /* if bit then unpack */
4093 if (IS_BITVAR (retype))
4094 genUnpackBits (result, "Z", GPOINTER);
4096 size = AOP_SIZE (result);
4101 emitcode ("call", "__gptrget_pi");
4103 emitcode ("call", "__gptrget");
4104 aopPut (AOP (result), "r0", offset++);
4109 /* now some housekeeping stuff */
4111 /* we had to allocate for this iCode */
4113 if (isRegPair(AOP (left))) {
4114 emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
4116 emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
4117 emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
4120 freeAsmop (NULL, aop, ic, TRUE);
4123 /* we did not allocate which means left
4124 already in a pointer register, then
4125 if size > 0 && this could be used again
4126 we have to point it back to where it
4128 if ((AOP_SIZE (result) > 1 &&
4129 !OP_SYMBOL (left)->remat &&
4130 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) &&
4132 int size = AOP_SIZE (result) - 1;
4133 emitcode ("sbiw", "r30,%d",size);
4136 if (pi) pi->generated=1;
4137 freeAsmop (left, NULL, ic, TRUE);
4138 freeAsmop (result, NULL, ic, TRUE);
4141 /*-----------------------------------------------------------------*/
4142 /* genPointerGet - generate code for pointer get */
4143 /*-----------------------------------------------------------------*/
4145 genPointerGet (iCode * ic, iCode *pi)
4147 operand *left, *result;
4148 sym_link *type, *etype;
4151 left = IC_LEFT (ic);
4152 result = IC_RESULT (ic);
4154 /* depending on the type of pointer we need to
4155 move it to the correct pointer register */
4156 type = operandType (left);
4157 etype = getSpec (type);
4158 /* if left is of type of pointer then it is simple */
4159 if (IS_PTR (type) && !IS_FUNC (type->next))
4160 p_type = DCL_TYPE (type);
4162 /* we have to go by the storage class */
4163 p_type = PTR_TYPE (SPEC_OCLS (etype));
4168 /* now that we have the pointer type we assign
4169 the pointer values */
4176 genMemPointerGet (left, result, ic, pi);
4180 genCodePointerGet (left, result, ic, pi);
4184 genGenPointerGet (left, result, ic, pi);
4190 /*-----------------------------------------------------------------*/
4191 /* genPackBits - generates code for packed bit storage */
4192 /*-----------------------------------------------------------------*/
4194 genPackBits (sym_link * etype,
4196 char *rname, int p_type)
4204 blen = SPEC_BLEN (etype);
4205 bstr = SPEC_BSTR (etype);
4207 l = aopGet (AOP (right), offset++);
4210 /* if the bit lenth is less than or */
4211 /* it exactly fits a byte then */
4212 if (SPEC_BLEN (etype) <= 8) {
4213 shCount = SPEC_BSTR (etype);
4215 /* shift left acc */
4218 if (SPEC_BLEN (etype) < 8) { /* if smaller than a byte */
4225 emitcode ("ld", "r1,%s",rname);
4229 emitcode ("push", "r1");
4230 emitcode ("push", "r24");
4231 emitcode ("call", "__gptrget");
4232 emitcode ("pop", "r1");
4233 emitcode ("mov","r24,r0");
4237 emitcode ("andi", "r24,#0x%02x", (unsigned char)
4238 ((unsigned char) (0xFF << (blen + bstr)) |
4239 (unsigned char) (0xFF >> (8 - bstr))));
4240 emitcode ("or", "r24,r1");
4241 if (p_type == GPOINTER)
4242 emitcode ("pop", "r1");
4251 emitcode("st","%s+,r24");
4255 emitcode("mov","r0,r24");
4256 emitcode ("call", "__gptrput_pi");
4261 if (SPEC_BLEN (etype) <= 8)
4264 rLen = SPEC_BLEN (etype);
4266 /* now generate for lengths greater than one byte */
4269 l = aopGet (AOP (right), offset++);
4280 emitcode ("st", "%s+,%s",rname,l);
4285 emitcode ("lcall", "__gptrput_pi");
4292 /* last last was not complete */
4294 /* save the byte & read byte */
4300 emitcode ("st","%s+,r24",rname);
4303 emitcode ("push", "r1");
4304 emitcode ("push", "r24");
4305 emitcode ("lcall", "__gptrget");
4306 emitcode ("mov","r24,r0");
4307 emitcode ("pop", "r1");
4311 emitcode ("andi", "r24,0x%02x", (((unsigned char) -1 << rLen) & 0xff));
4312 emitcode ("or", "r24,r1");
4315 if (p_type == GPOINTER)
4316 emitcode ("pop", "r1");
4324 emitcode ("st", "%s,r24", rname);
4328 emitcode ("mov","r0,r24");
4329 emitcode ("call", "__gptrput");
4334 /*-----------------------------------------------------------------*/
4335 /* genDataPointerSet - remat pointer to data space */
4336 /*-----------------------------------------------------------------*/
4338 genDataPointerSet (operand * right, operand * result, iCode * ic)
4340 int size, offset = 0;
4341 char *l, buffer[256];
4343 aopOp (right, ic, FALSE);
4345 l = aopGet (AOP (result), 0);
4346 size = AOP_SIZE (right);
4349 sprintf (buffer, "(%s + %d)", l, offset);
4351 sprintf (buffer, "%s", l);
4352 emitcode ("sts", "%s,%s", buffer,
4353 aopGet (AOP (right), offset++));
4356 freeAsmop (right, NULL, ic, TRUE);
4357 freeAsmop (result, NULL, ic, TRUE);
4360 /*-----------------------------------------------------------------*/
4361 /* genNearPointerSet - emitcode for near pointer put */
4362 /*-----------------------------------------------------------------*/
4364 genMemPointerSet (operand * right, operand * result, iCode * ic, iCode *pi)
4367 char *frname = NULL, *rname, *l;
4370 sym_link *ptype = operandType (result);
4372 retype = getSpec (operandType (right));
4374 aopOp (result, ic, FALSE);
4376 /* if the result is rematerializable &
4377 in data space & not a bit variable */
4378 if (AOP_TYPE (result) == AOP_IMMD &&
4379 DCL_TYPE (ptype) == POINTER && !IS_BITVAR (retype)) {
4380 genDataPointerSet (right, result, ic);
4383 if (!AOP_INPREG(AOP(result))) {
4384 /* otherwise get a free pointer register */
4386 getFreePtr (ic, &aop, FALSE, 0);
4387 if (isRegPair (AOP (result) )) {
4388 emitcode ("movw", "%s,%s",aop->aopu.aop_ptr->name,
4389 aopGet(AOP (result), 0));
4391 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
4392 aopGet (AOP (result), 0));
4393 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
4394 aopGet (AOP (result), 1));
4399 frname = aopGet(aop,0);
4402 aopOp (right, ic, FALSE);
4405 } else if (AOP_ISZ(aop)) {
4408 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4409 "pointer not in correct register");
4412 /* if bitfield then unpack the bits */
4413 if (IS_BITVAR (retype))
4414 genPackBits (retype, right, rname, POINTER);
4416 /* we have can just get the values */
4417 int size = AOP_SIZE (right);
4421 l = aopGet (AOP (right), offset);
4423 emitcode ("st", "%s+,%s", rname,l);
4425 emitcode ("st", "%s,%s", rname,l);
4430 /* now some housekeeping stuff */
4432 /* we had to allocate for this iCode */
4434 if (isRegPair (AOP (result) )) {
4435 emitcode ("movw", "%s,%s",
4436 aopGet(AOP(result),0),
4437 aop->aopu.aop_ptr->name);
4439 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
4440 aopGet (AOP (result), 0));
4441 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
4442 aopGet (AOP (result), 1));
4445 freeAsmop (NULL, aop, ic, TRUE);
4448 /* we did not allocate which means left
4449 already in a pointer register, then
4450 if size > 0 && this could be used again
4451 we have to point it back to where it
4453 if ((AOP_SIZE (right) > 1 &&
4454 !OP_SYMBOL (result)->remat &&
4455 (OP_SYMBOL (right)->liveTo > ic->seq || ic->depth)) && !pi) {
4456 int size = AOP_SIZE (right) - 1;
4457 emitcode ("sbiw", "%s,%d",frname,size);
4462 if (pi) pi->generated = 1;
4463 freeAsmop (result, NULL, ic, TRUE);
4464 freeAsmop (right, NULL, ic, TRUE);
4467 /*-----------------------------------------------------------------*/
4468 /* genGenPointerSet - set value from generic pointer space */
4469 /*-----------------------------------------------------------------*/
4471 genGenPointerSet (operand * right, operand * result, iCode * ic, iCode *pi)
4475 sym_link *retype = getSpec (operandType (right));
4478 aopOp (result, ic, FALSE);
4480 /* if the operand is already in dptr
4481 then we do nothing else we move the value to dptr */
4482 if (AOP_ISZ(AOP(result))) {
4486 getFreePtr(ic,&aop,FALSE,TRUE);
4487 if (isRegPair(AOP(result))) {
4488 emitcode ("movw", "r30,%s", aopGet (AOP (result), 0));
4490 emitcode ("mov", "r30,%s", aopGet (AOP (result), 0));
4491 emitcode ("mov", "r31,%s", aopGet (AOP (result), 1));
4493 emitcode ("mov", "r24,%s", aopGet (AOP (result), 2));
4497 /* so Z register now contains the address */
4498 aopOp (right, ic, FALSE);
4500 /* if bit then unpack */
4501 if (IS_BITVAR (retype))
4502 genUnpackBits (result, "Z", GPOINTER);
4504 size = AOP_SIZE (right);
4508 char *l = aopGet(AOP (right), offset++);
4512 emitcode ("call", "__gptrput_pi");
4514 emitcode ("call", "__gptrput");
4518 /* now some housekeeping stuff */
4520 /* we had to allocate for this iCode */
4522 if (isRegPair(AOP(result))) {
4523 emitcode ("movw", "%s,r30", aopGet (AOP (result), 0));
4525 emitcode ("mov", "%s,r30", aopGet (AOP (result), 0));
4526 emitcode ("mov", "%s,r31", aopGet (AOP (result), 1));
4529 freeAsmop (NULL, aop, ic, TRUE);
4532 /* we did not allocate which means left
4533 already in a pointer register, then
4534 if size > 0 && this could be used again
4535 we have to point it back to where it
4537 if ((AOP_SIZE (right) > 1 &&
4538 !OP_SYMBOL (result)->remat &&
4539 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) && !pi) {
4540 int size = AOP_SIZE (right) - 1;
4541 emitcode ("sbiw", "r30,%d",size);
4544 if (pi) pi->generated = 1;
4545 freeAsmop (right, NULL, ic, TRUE);
4546 freeAsmop (result, NULL, ic, TRUE);
4549 /*-----------------------------------------------------------------*/
4550 /* genPointerSet - stores the value into a pointer location */
4551 /*-----------------------------------------------------------------*/
4553 genPointerSet (iCode * ic, iCode *pi)
4555 operand *right, *result;
4556 sym_link *type, *etype;
4559 right = IC_RIGHT (ic);
4560 result = IC_RESULT (ic);
4562 /* depending on the type of pointer we need to
4563 move it to the correct pointer register */
4564 type = operandType (result);
4565 etype = getSpec (type);
4566 /* if left is of type of pointer then it is simple */
4567 if (IS_PTR (type) && !IS_FUNC (type->next)) {
4568 p_type = DCL_TYPE (type);
4571 /* we have to go by the storage class */
4572 p_type = PTR_TYPE (SPEC_OCLS (etype));
4576 /* now that we have the pointer type we assign
4577 the pointer values */
4584 genMemPointerSet (right, result, ic, pi);
4588 genGenPointerSet (right, result, ic, pi);
4594 /*-----------------------------------------------------------------*/
4595 /* genIfx - generate code for Ifx statement */
4596 /*-----------------------------------------------------------------*/
4598 genIfx (iCode * ic, iCode * popIc)
4600 operand *cond = IC_COND (ic);
4605 aopOp (cond, ic, FALSE);
4607 /* get the value into acc */
4608 if (AOP_SIZE(cond) == 1 && AOP_ISHIGHREG(AOP(cond),0)) {
4609 cname = aopGet(AOP(cond),0);
4611 toBoolean (cond, "r24", 0);
4615 /* the result is now in the accumulator */
4616 freeAsmop (cond, NULL, ic, TRUE);
4618 /* if there was something to be popped then do it */
4621 emitcode("cpi","%s,0",cname);
4622 } else if (!tob) emitcode("cpi","%s,0",cname);
4624 lbl = newiTempLabel(NULL);
4626 emitcode ("breq","L%05d",lbl->key);
4627 emitcode ("jmp","L%05d",IC_TRUE(ic)->key);
4628 emitcode ("","L%05d:",lbl->key);
4630 emitcode ("brne","L%05d",lbl->key);
4631 emitcode ("jmp","L%05d",IC_FALSE(ic)->key);
4632 emitcode ("","L%05d:",lbl->key);
4637 /*-----------------------------------------------------------------*/
4638 /* genAddrOf - generates code for address of */
4639 /*-----------------------------------------------------------------*/
4641 genAddrOf (iCode * ic)
4643 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
4646 aopOp (IC_RESULT (ic), ic, FALSE);
4647 assert(AOP_SIZE(IC_RESULT(ic)) >= 2);
4648 /* if the operand is on the stack then we
4649 need to get the stack offset of this
4652 /* if it has an offset then we need to compute it */
4654 if (allHigh(AOP(IC_RESULT(ic)))) {
4655 if (isRegPair (AOP(IC_RESULT(ic)))) {
4656 emitcode ("movw","%s,r28",aopGet(AOP(IC_RESULT(ic)),0));
4658 emitcode ("mov","%s,r28",aopGet(AOP(IC_RESULT(ic)),0));
4659 emitcode ("mov","%s,r29",aopGet(AOP(IC_RESULT(ic)),1));
4661 if (sym->stack < 0) {
4662 emitcode("subi","%s,<(%d)",aopGet(AOP(IC_RESULT(ic)),0),-sym->stack);
4663 emitcode("sbci","%s,>(%d)",aopGet(AOP(IC_RESULT(ic)),1),-sym->stack);
4665 emitcode("subi","%s,<(-%d)",aopGet(AOP(IC_RESULT(ic)),0),sym->stack);
4666 emitcode("sbci","%s,>(-%d)",aopGet(AOP(IC_RESULT(ic)),1),sym->stack);
4669 emitcode("movw","r24,r28");
4670 if (sym->stack > -63 && sym->stack < 63) {
4672 emitcode("sbiw","r24,%d",-sym->stack);
4674 emitcode("sbiw","r24,%d",sym->stack);
4676 if (sym->stack < 0) {
4677 emitcode("subi","r24,<(%d)",-sym->stack);
4678 emitcode("sbci","r25,>(%d)",-sym->stack);
4680 emitcode("subi","r24,<(-%d)",sym->stack);
4681 emitcode("sbci","r25,>(-%d)",sym->stack);
4685 aopPut(AOP(IC_RESULT(ic)),"r24",0);
4686 aopPut(AOP(IC_RESULT(ic)),"r25",1);
4690 aopPut(AOP(IC_RESULT(ic)),"r28",0);
4691 aopPut(AOP(IC_RESULT(ic)),"r29",1);
4693 /* fill the result with zero */
4694 size = AOP_SIZE (IC_RESULT (ic)) - 2;
4697 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
4703 /* object not on stack then we need the name */
4704 size = AOP_SIZE (IC_RESULT (ic));
4708 char s[SDCC_NAME_MAX];
4710 sprintf (s, ">(%s)", sym->rname);
4712 sprintf (s, "<(%s)", sym->rname);
4713 aopPut (AOP (IC_RESULT (ic)), s, offset++);
4717 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4721 /*-----------------------------------------------------------------*/
4722 /* genFarFarAssign - assignment when both are in far space */
4723 /*-----------------------------------------------------------------*/
4725 genFarFarAssign (operand * result, operand * right, iCode * ic)
4727 int size = AOP_SIZE (right);
4730 /* first push the right side on to the stack */
4732 l = aopGet (AOP (right), offset++);
4734 emitcode ("push", "acc");
4737 freeAsmop (right, NULL, ic, FALSE);
4738 /* now assign DPTR to result */
4739 aopOp (result, ic, FALSE);
4740 size = AOP_SIZE (result);
4742 emitcode ("pop", "acc");
4743 aopPut (AOP (result), "a", --offset);
4745 freeAsmop (result, NULL, ic, FALSE);
4749 /*-----------------------------------------------------------------*/
4750 /* genAssign - generate code for assignment */
4751 /*-----------------------------------------------------------------*/
4753 genAssign (iCode * ic)
4755 operand *result, *right;
4757 unsigned long lit = 0L;
4759 result = IC_RESULT (ic);
4760 right = IC_RIGHT (ic);
4762 /* if they are the same */
4763 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4766 aopOp (right, ic, FALSE);
4768 /* special case both in far space */
4769 if (AOP_TYPE (right) == AOP_DPTR &&
4770 IS_TRUE_SYMOP (result) && isOperandInFarSpace (result)) {
4772 genFarFarAssign (result, right, ic);
4776 aopOp (result, ic, TRUE);
4778 /* if they are the same registers */
4779 if (sameRegs (AOP (right), AOP (result)))
4782 /* if the result is a bit */
4783 if (AOP_TYPE (result) == AOP_CRY) {
4785 /* if the right size is a literal then
4786 we know what the value is */
4787 if (AOP_TYPE (right) == AOP_LIT) {
4788 if (((int) operandLitValue (right)))
4789 aopPut (AOP (result), one, 0);
4791 aopPut (AOP (result), zero, 0);
4795 /* the right is also a bit variable */
4796 if (AOP_TYPE (right) == AOP_CRY) {
4797 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4798 aopPut (AOP (result), "c", 0);
4803 toBoolean (right, "", 0);
4804 aopPut (AOP (result), "a", 0);
4808 /* bit variables done */
4810 size = AOP_SIZE (result);
4812 if (AOP_TYPE (right) == AOP_LIT)
4814 (unsigned long) floatFromVal (AOP (right)->aopu.
4816 if ((size > 1) && (AOP_TYPE (result) != AOP_REG)
4817 && (AOP_TYPE (right) == AOP_LIT)
4818 && !IS_FLOAT (operandType (right)) && (lit < 256L)) {
4819 emitcode ("clr", "a");
4821 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) ==
4822 0) aopPut (AOP (result), "a", size);
4824 aopPut (AOP (result),
4825 aopGet (AOP (right), size), size);
4830 aopPut (AOP (result),
4831 aopGet (AOP (right), offset), offset);
4837 freeAsmop (right, NULL, ic, FALSE);
4838 freeAsmop (result, NULL, ic, TRUE);
4841 /*-----------------------------------------------------------------*/
4842 /* genJumpTab - genrates code for jump table */
4843 /*-----------------------------------------------------------------*/
4845 genJumpTab (iCode * ic)
4850 aopOp (IC_JTCOND (ic), ic, FALSE);
4851 /* get the condition into accumulator */
4852 l = aopGet (AOP (IC_JTCOND (ic)), 0);
4854 /* multiply by three */
4855 emitcode ("add", "a,acc");
4856 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0));
4857 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
4859 jtab = newiTempLabel (NULL);
4860 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
4861 emitcode ("jmp", "@a+dptr");
4862 emitcode ("", "%05d$:", jtab->key + 100);
4863 /* now generate the jump labels */
4864 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
4865 jtab = setNextItem (IC_JTLABELS (ic)))
4866 emitcode ("ljmp", "%05d$", jtab->key + 100);
4870 /*-----------------------------------------------------------------*/
4871 /* genCast - gen code for casting */
4872 /*-----------------------------------------------------------------*/
4874 genCast (iCode * ic)
4876 operand *result = IC_RESULT (ic);
4877 sym_link *ctype = operandType (IC_LEFT (ic));
4878 sym_link *rtype = operandType (IC_RIGHT (ic));
4879 operand *right = IC_RIGHT (ic);
4882 /* if they are equivalent then do nothing */
4883 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4886 aopOp (right, ic, FALSE);
4887 aopOp (result, ic, FALSE);
4889 /* if the result is a bit */
4890 if (AOP_TYPE (result) == AOP_CRY) {
4891 /* if the right size is a literal then
4892 we know what the value is */
4893 if (AOP_TYPE (right) == AOP_LIT) {
4894 if (((int) operandLitValue (right)))
4895 aopPut (AOP (result), one, 0);
4897 aopPut (AOP (result), zero, 0);
4902 /* the right is also a bit variable */
4903 if (AOP_TYPE (right) == AOP_CRY) {
4904 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4905 aopPut (AOP (result), "c", 0);
4910 toBoolean (right, "", 0);
4911 aopPut (AOP (result), "a", 0);
4915 /* if they are the same size : or less */
4916 if (AOP_SIZE (result) <= AOP_SIZE (right)) {
4918 /* if they are in the same place */
4919 if (sameRegs (AOP (right), AOP (result)))
4922 /* if they in different places then copy */
4923 size = AOP_SIZE (result);
4926 aopPut (AOP (result),
4927 aopGet (AOP (right), offset), offset);
4934 /* if the result is of type pointer */
4935 if (IS_PTR (ctype)) {
4938 sym_link *type = operandType (right);
4939 sym_link *etype = getSpec (type);
4941 /* pointer to generic pointer */
4942 if (IS_GENPTR (ctype)) {
4946 p_type = DCL_TYPE (type);
4948 /* we have to go by the storage class */
4949 p_type = PTR_TYPE (SPEC_OCLS (etype));
4952 /* the first two bytes are known */
4953 size = GPTRSIZE - 1;
4956 aopPut (AOP (result),
4957 aopGet (AOP (right), offset), offset);
4960 /* the last byte depending on type */
4977 /* this should never happen */
4978 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4979 "got unknown pointer type");
4982 aopPut (AOP (result), l, GPTRSIZE - 1);
4986 /* just copy the pointers */
4987 size = AOP_SIZE (result);
4990 aopPut (AOP (result),
4991 aopGet (AOP (right), offset), offset);
4997 /* so we now know that the size of destination is greater
4998 than the size of the source */
4999 /* we move to result for the size of source */
5000 size = AOP_SIZE (right);
5003 aopPut (AOP (result), aopGet (AOP (right), offset), offset);
5007 /* now depending on the sign of the source && destination */
5008 size = AOP_SIZE (result) - AOP_SIZE (right);
5009 /* if unsigned or not an integral type */
5010 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype)) {
5012 aopPut (AOP (result), zero, offset++);
5015 /* we need to extend the sign :{ */
5016 // PENDING: Does nothing on avr
5018 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1);
5021 emitcode ("rlc", "a");
5022 emitcode ("subb", "a,acc");
5024 aopPut (AOP (result), "a", offset++);
5027 /* we are done hurray !!!! */
5030 freeAsmop (right, NULL, ic, TRUE);
5031 freeAsmop (result, NULL, ic, TRUE);
5035 /*-----------------------------------------------------------------*/
5036 /* genDjnz - generate decrement & jump if not zero instrucion */
5037 /*-----------------------------------------------------------------*/
5039 genDjnz (iCode * ic, iCode * ifx)
5045 /* if the if condition has a false label
5046 then we cannot save */
5050 /* if the minus is not of the form
5052 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
5053 !IS_OP_LITERAL (IC_RIGHT (ic)))
5056 if (operandLitValue (IC_RIGHT (ic)) != 1)
5059 /* if the size of this greater than one then no
5061 if (getSize (operandType (IC_RESULT (ic))) > 1)
5064 /* otherwise we can save BIG */
5065 lbl = newiTempLabel (NULL);
5066 lbl1 = newiTempLabel (NULL);
5068 aopOp (IC_RESULT (ic), ic, FALSE);
5070 if (IS_AOP_PREG (IC_RESULT (ic))) {
5071 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0));
5072 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0));
5073 emitcode ("jnz", "%05d$", lbl->key + 100);
5076 emitcode ("djnz", "%s,%05d$",
5077 aopGet (AOP (IC_RESULT (ic)), 0), lbl->key + 100);
5079 emitcode ("sjmp", "%05d$", lbl1->key + 100);
5080 emitcode ("", "%05d$:", lbl->key + 100);
5081 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5082 emitcode ("", "%05d$:", lbl1->key + 100);
5084 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5089 static char *recvregs[8] = {
5090 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23"
5093 static int recvCnt = 0;
5095 /*-----------------------------------------------------------------*/
5096 /* genReceive - generate code for a receive iCode */
5097 /*-----------------------------------------------------------------*/
5099 genReceive (iCode * ic)
5101 int size, offset = 0;
5102 aopOp (IC_RESULT (ic), ic, FALSE);
5103 size = AOP_SIZE (IC_RESULT (ic));
5105 aopPut (AOP (IC_RESULT (ic)), recvregs[recvCnt++], offset);
5108 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5111 /*-----------------------------------------------------------------*/
5112 /* gen51Code - generate code for 8051 based controllers */
5113 /*-----------------------------------------------------------------*/
5115 genAVRCode (iCode * lic)
5120 lineHead = lineCurr = NULL;
5122 /* print the allocation information */
5124 printAllocInfo (currFunc, codeOutFile);
5125 /* if debug information required */
5126 /* if (options.debug && currFunc) { */
5128 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
5130 /* emitcode ("", ".type %s,@function", currFunc->name); */
5133 /* stack pointer name */
5137 for (ic = lic; ic; ic = ic->next) {
5139 if (cln != ic->lineno) {
5140 if (options.debug) {
5142 emitcode ("", "C$%s$%d$%d$%d ==.",
5143 FileBaseName (ic->filename),
5144 ic->lineno, ic->level, ic->block);
5147 emitcode (";", "%s %d", ic->filename, ic->lineno);
5150 /* if the result is marked as
5151 spilt and rematerializable or code for
5152 this has already been generated then
5154 if (resultRemat (ic) || ic->generated)
5157 /* depending on the operation */
5176 /* IPOP happens only when trying to restore a
5177 spilt live range, if there is an ifx statement
5178 following this pop then the if statement might
5179 be using some of the registers being popped which
5180 would destory the contents of the register so
5181 we need to check for this condition and handle it */
5183 ic->next->op == IFX &&
5184 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
5185 genIfx (ic->next, ic);
5203 genEndFunction (ic);
5223 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
5240 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
5244 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
5248 genCmpLe (ic, ifxForOp (IC_RESULT (ic), ic));
5252 genCmpGe (ic, ifxForOp (IC_RESULT (ic), ic));
5256 genCmpNe (ic, ifxForOp (IC_RESULT (ic), ic));
5260 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
5272 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
5276 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
5280 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
5307 case GET_VALUE_AT_ADDRESS:
5308 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
5312 if (POINTER_SET (ic))
5313 genPointerSet (ic, hasInc(IC_RESULT(ic),ic));
5339 addSet (&_G.sendSet, ic);
5348 /* now we are ready to call the
5349 peep hole optimizer */
5350 if (!options.nopeep)
5351 peepHole (&lineHead);
5353 /* now do the actual printing */
5354 printLine (lineHead, codeOutFile);