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 if (IS_AGGREGATE(type->next)) return NULL;
294 isize = getSize(type->next);
296 /* if operand of the form op = op + <sizeof *op> */
297 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
298 isOperandEqual(IC_RESULT(lic),op) &&
299 isOperandLiteral(IC_RIGHT(lic)) &&
300 operandLitValue(IC_RIGHT(lic)) == isize) {
303 /* if the operand used or deffed */
304 if (bitVectBitValue(OP_USES(op),lic->key) || ((unsigned) lic->defKey == op->key)) {
312 /*-----------------------------------------------------------------*/
313 /* getFreePtr - returns X or Z whichever is free or can be pushed */
314 /*-----------------------------------------------------------------*/
316 getFreePtr (iCode * ic, asmop ** aopp, bool result, bool zonly)
318 bool xiu = FALSE, ziu = FALSE;
319 bool xou = FALSE, zou = FALSE;
321 /* the logic: if x & z used in the instruction
322 then we are in trouble otherwise */
324 /* first check if x & z are used by this
325 instruction, in which case we are in trouble */
326 if ((xiu = bitVectBitValue (ic->rUsed, X_IDX)) &&
327 (ziu = bitVectBitValue (ic->rUsed, Z_IDX))) {
331 xou = bitVectBitValue (ic->rMask, X_IDX);
332 zou = bitVectBitValue (ic->rMask, Z_IDX);
334 /* if no usage of Z then return it */
336 ic->rUsed = bitVectSetBit (ic->rUsed, Z_IDX);
337 (*aopp)->type = AOP_Z;
339 (*aopp)->aop_ptr2 = avr_regWithIdx (R31_IDX);
340 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R30_IDX);
343 /* if no usage of X then return it */
344 if (!xiu && !xou && !zonly) {
345 ic->rUsed = bitVectSetBit (ic->rUsed, X_IDX);
346 (*aopp)->type = AOP_X;
348 (*aopp)->aop_ptr2 = avr_regWithIdx (R27_IDX);
349 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R26_IDX);
352 /* if z not used then */
355 /* push it if not already pushed */
357 emitcode ("push", "%s",
358 avr_regWithIdx (R30_IDX)->dname);
359 emitcode ("push", "%s",
360 avr_regWithIdx (R31_IDX)->dname);
364 ic->rUsed = bitVectSetBit (ic->rUsed, Z_IDX);
365 (*aopp)->type = AOP_Z;
366 (*aopp)->aop_ptr2 = avr_regWithIdx (R31_IDX);
367 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R30_IDX);
370 /* now we know they both have usage */
371 /* if x not used in this instruction */
372 if (!xiu && !zonly) {
373 /* push it if not already pushed */
375 emitcode ("push", "%s",
376 avr_regWithIdx (R26_IDX)->dname);
377 emitcode ("push", "%s",
378 avr_regWithIdx (R27_IDX)->dname);
382 ic->rUsed = bitVectSetBit (ic->rUsed, X_IDX);
383 (*aopp)->type = AOP_X;
385 (*aopp)->aop_ptr2 = avr_regWithIdx (R27_IDX);
386 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R26_IDX);
391 /* I said end of world but not quite end of world yet */
392 /* if this is a result then we can push it on the stack */
394 (*aopp)->type = AOP_STK;
398 /* other wise this is true end of the world */
399 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
400 "getFreePtr should never reach here");
404 /*-----------------------------------------------------------------*/
405 /* newAsmop - creates a new asmOp */
406 /*-----------------------------------------------------------------*/
408 newAsmop (short type)
412 aop = Safe_calloc (1, sizeof (asmop));
417 /*-----------------------------------------------------------------*/
418 /* pointerCode - returns the code for a pointer type */
419 /*-----------------------------------------------------------------*/
421 pointerCode (sym_link * etype)
424 return PTR_TYPE (SPEC_OCLS (etype));
428 /*-----------------------------------------------------------------*/
429 /* aopForSym - for a true symbol */
430 /*-----------------------------------------------------------------*/
432 aopForSym (iCode * ic, symbol * sym, bool result)
435 memmap *space = SPEC_OCLS (sym->etype);
437 /* if already has one */
441 /* assign depending on the storage class */
442 /* if it is on the stack */
444 sym->aop = aop = newAsmop (0);
445 aop->size = getSize (sym->type);
447 /* we can use std / ldd instruction */
449 && (sym->stack + getSize (sym->type) - 1) <= 63) {
450 aop->type = AOP_STK_D;
451 aop->aopu.aop_stk = sym->stack;
455 /* otherwise get a free pointer register X/Z */
456 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result, FALSE);
458 /* now assign the address of the variable to
459 the pointer register */
460 if (aop->type != AOP_STK) {
461 emitcode ("movw", "%s,r28", aop->aopu.aop_ptr->name);
462 if (sym->stack < 0) {
463 if ((sym->stack - _G.nRegsSaved) > -63) {
464 emitcode ("sbiw", "%s,0x%02x",
465 aop->aopu.aop_ptr->name,
470 emitcode ("subi", "%s,<(%d)",
471 aop->aopu.aop_ptr->name,
472 sym->stack - _G.nRegsSaved);
473 emitcode ("sbci", "%s,>(%d)",
475 sym->stack - _G.nRegsSaved);
479 if (sym->stack <= 63) {
480 emitcode ("adiw", "%s,0x%02x",
481 aop->aopu.aop_ptr->name,
485 emitcode ("subi", "%s,<(-%d)",
486 aop->aopu.aop_ptr->name,
488 emitcode ("sbci", "%s,>(-%d)",
497 /* if in bit space */
498 if (IN_BITSPACE (space)) {
499 sym->aop = aop = newAsmop (AOP_CRY);
500 aop->aopu.aop_dir = sym->rname;
501 aop->size = getSize (sym->type);
504 /* if it is in direct space */
505 if (IN_DIRSPACE (space)) {
506 sym->aop = aop = newAsmop (AOP_DIR);
507 aop->aopu.aop_dir = sym->rname;
508 aop->size = getSize (sym->type);
512 /* special case for a function */
513 if (IS_FUNC (sym->type)) {
514 sym->aop = aop = newAsmop (AOP_IMMD);
515 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
516 strcpy (aop->aopu.aop_immd, sym->rname);
517 aop->size = FPTRSIZE;
521 /* only remaining is code / eeprom which will need pointer reg */
522 /* if it is in code space */
524 sym->aop = aop = newAsmop (0);
526 if (IN_CODESPACE (space))
529 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result, aop->code);
530 aop->size = getSize (sym->type);
531 emitcode ("ldi", "%s,<(%s)", aop->aopu.aop_ptr->name, sym->rname);
532 emitcode ("ldi", "%s,>(%s)", aop->aop_ptr2);
537 /*-----------------------------------------------------------------*/
538 /* aopForRemat - rematerialzes an object */
539 /*-----------------------------------------------------------------*/
541 aopForRemat (symbol * sym)
543 iCode *ic = sym->rematiCode;
544 asmop *aop = newAsmop (AOP_IMMD);
549 val += (int) operandLitValue (IC_RIGHT (ic));
550 else if (ic->op == '-')
551 val -= (int) operandLitValue (IC_RIGHT (ic));
555 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
559 sprintf (buffer, "(%s %c 0x%04x)",
560 OP_SYMBOL (IC_LEFT (ic))->rname,
561 val >= 0 ? '+' : '-', abs (val) & 0xffff);
563 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
565 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
566 strcpy (aop->aopu.aop_immd, buffer);
570 /*-----------------------------------------------------------------*/
571 /* regsInCommon - two operands have some registers in common */
572 /*-----------------------------------------------------------------*/
574 regsInCommon (operand * op1, operand * op2)
579 /* if they have registers in common */
580 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
583 sym1 = OP_SYMBOL (op1);
584 sym2 = OP_SYMBOL (op2);
586 if (sym1->nRegs == 0 || sym2->nRegs == 0)
589 for (i = 0; i < sym1->nRegs; i++) {
594 for (j = 0; j < sym2->nRegs; j++) {
598 if (sym2->regs[j] == sym1->regs[i])
606 /*-----------------------------------------------------------------*/
607 /* operandsEqu - equivalent */
608 /*-----------------------------------------------------------------*/
610 operandsEqu (operand * op1, operand * op2)
614 /* if they not symbols */
615 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
618 sym1 = OP_SYMBOL (op1);
619 sym2 = OP_SYMBOL (op2);
621 /* if both are itemps & one is spilt
622 and the other is not then false */
623 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
624 sym1->isspilt != sym2->isspilt) return FALSE;
626 /* if they are the same */
630 if (strcmp (sym1->rname, sym2->rname) == 0)
634 /* if left is a tmp & right is not */
635 if (IS_ITEMP (op1) &&
636 !IS_ITEMP (op2) && sym1->isspilt && (sym1->usl.spillLoc == sym2))
639 if (IS_ITEMP (op2) &&
641 sym2->isspilt && sym1->level > 0 && (sym2->usl.spillLoc == sym1))
647 /*-----------------------------------------------------------------*/
648 /* sameRegs - two asmops have the same registers */
649 /*-----------------------------------------------------------------*/
651 sameRegs (asmop * aop1, asmop * aop2)
658 if (aop1->type != AOP_REG || aop2->type != AOP_REG)
661 if (aop1->size != aop2->size)
664 for (i = 0; i < aop1->size; i++)
665 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
671 /*-----------------------------------------------------------------*/
672 /* isRegPair - for size 2 if this operand has a register pair */
673 /*-----------------------------------------------------------------*/
675 isRegPair (asmop * aop)
677 if (!aop || aop->size < 2)
679 if (aop->type == AOP_X || aop->type == AOP_Z)
681 if (aop->type != AOP_REG)
683 if ( ((aop->aopu.aop_reg[1]->rIdx - aop->aopu.aop_reg[0]->rIdx) == 1) &&
684 (aop->aopu.aop_reg[0]->rIdx & 1) == 0)
690 /*-----------------------------------------------------------------*/
691 /* allHigh - all registers are high registers */
692 /*-----------------------------------------------------------------*/
693 static int allHigh (asmop * aop)
697 if (aop->type == AOP_X || aop->type == AOP_Z)
699 if (aop->type != AOP_REG)
701 for (i=0; i < aop->size ; i++ )
702 if (aop->aopu.aop_reg[i]->rIdx < R16_IDX) return 0;
706 /*-----------------------------------------------------------------*/
707 /* aopOp - allocates an asmop for an operand : */
708 /*-----------------------------------------------------------------*/
710 aopOp (operand * op, iCode * ic, bool result)
719 /* if this a literal */
720 if (IS_OP_LITERAL (op)) {
721 op->aop = aop = newAsmop (AOP_LIT);
722 aop->aopu.aop_lit = op->operand.valOperand;
723 aop->size = getSize (operandType (op));
727 /* if already has a asmop then continue */
731 /* if the underlying symbol has a aop */
732 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop) {
733 op->aop = OP_SYMBOL (op)->aop;
737 /* if this is a true symbol */
738 if (IS_TRUE_SYMOP (op)) {
739 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
743 /* this is a temporary : this has
749 e) can be a return use only */
751 sym = OP_SYMBOL (op);
754 /* if the type is a conditional */
755 if (sym->regType & REG_CND) {
756 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
761 /* if it is spilt then two situations
763 b) has a spill location */
764 if (sym->isspilt || sym->nRegs == 0) {
766 /* rematerialize it NOW */
768 sym->aop = op->aop = aop = aopForRemat (sym);
769 aop->size = getSize (sym->type);
774 assert ("ACC_USE cannot happen in AVR\n");
779 aop = op->aop = sym->aop = newAsmop (AOP_STR);
780 aop->size = getSize (sym->type);
781 for (i = 0; i < (int) fAVRReturnSize; i++)
782 aop->aopu.aop_str[i] = fAVRReturn[i];
786 /* else spill location */
787 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
788 /* force a new aop if sizes differ */
789 sym->usl.spillLoc->aop = NULL;
791 sym->aop = op->aop = aop =
792 aopForSym (ic, sym->usl.spillLoc, result);
793 aop->size = getSize (sym->type);
797 /* must be in a register */
798 sym->aop = op->aop = aop = newAsmop (AOP_REG);
799 aop->size = sym->nRegs;
800 for (i = 0; i < sym->nRegs; i++)
801 aop->aopu.aop_reg[i] = sym->regs[i];
804 /*-----------------------------------------------------------------*/
805 /* freeAsmop - free up the asmop given to an operand */
806 /*----------------------------------------------------------------*/
808 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
825 /* depending on the asmop type only three cases need work AOP_RO
826 , AOP_R1 && AOP_STK */
831 emitcode ("pop", "r26");
832 emitcode ("pop", "r27");
836 bitVectUnSetBit (ic->rUsed, X_IDX);
842 emitcode ("pop", "r30");
843 emitcode ("pop", "r31");
847 bitVectUnSetBit (ic->rUsed, Z_IDX);
853 int stk = aop->aopu.aop_stk + aop->size;
854 bitVectUnSetBit (ic->rUsed, X_IDX);
855 bitVectUnSetBit (ic->rUsed, Z_IDX);
857 getFreePtr (ic, &aop, FALSE, 0);
859 emitcode ("movw", "%s,r28");
861 if (stk <= 63 && stk > 0) {
862 emitcode ("adiw", "%s,0x%02x",
863 aop->aopu.aop_ptr->name,
867 emitcode ("subi", "%s,<(%d)",
868 aop->aopu.aop_ptr->name,
870 emitcode ("sbci", "%s,>(%d)",
877 emitcode ("pop", "r24");
878 emitcode ("st", "-%s,r24",
879 aop->type == AOP_X ? "X" : "Z");
884 freeAsmop (op, NULL, ic, TRUE);
886 emitcode ("pop", "r26");
887 emitcode ("pop", "r27");
892 emitcode ("pop", "r30");
893 emitcode ("pop", "r31");
900 /* all other cases just dealloc */
904 OP_SYMBOL (op)->aop = NULL;
905 /* if the symbol has a spill */
907 SPIL_LOC (op)->aop = NULL;
912 /*-----------------------------------------------------------------*/
913 /* aopGet - for fetching value of the aop */
914 /*-----------------------------------------------------------------*/
916 aopGet (asmop * aop, int offset)
921 /* offset is greater than
923 if (offset > (aop->size - 1) && aop->type != AOP_LIT)
926 /* depending on type */
930 if (offset > aop->coff) {
931 emitcode ("adiw", "%s,%d", aop->aopu.aop_ptr->name,
935 if (offset < aop->coff) {
936 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name,
941 emitcode ("ld", "%s,x",
942 (rs = ((offset & 1) ? "r25" : "r24")));
947 if (offset > aop->coff) {
948 emitcode ("adiw", "r30,%d",
952 emitcode ("sbiw", "r30,%d",
955 emitcode ("lpm", "%s,z",
956 (rs = ((offset & 1) ? "r25" : "r24")));
960 if (offset > aop->coff) {
961 emitcode ("ldd", "%s,z+%d",
963 ((offset & 1) ? "r25" : "r24")),
967 emitcode ("sbiw", "%s,%d",
968 aop->aopu.aop_ptr->name,
971 emitcode ("ld", "%s,z",
973 ((offset & 1) ? "r25" : "r24")));
980 emitcode ("lds", "%s,(%s)+%d",
981 (rs = ((offset & 1) ? "r25" : "r24")),
982 aop->aopu.aop_immd, offset);
986 emitcode ("lds", "%s,(%s)+%d",
987 (rs = ((offset & 1) ? "r25" : "r24")),
988 aop->aopu.aop_dir, offset);
992 return aop->aopu.aop_reg[offset]->name;
995 assert ("cannot be in bit space AOP_CRY\n");
999 s = aopLiteral (aop->aopu.aop_lit, offset);
1000 emitcode ("ldi", "%s,<(%s)",
1001 (rs = ((offset & 1) ? "r24" : "r25")), s);
1006 return aop->aopu.aop_str[offset];
1009 emitcode ("ldd", "%s,Y+%d",
1010 (rs = ((offset & 1) ? "r25" : "r24")),
1011 aop->aopu.aop_stk + offset);
1015 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1016 "aopget got unsupported aop->type");
1020 /*-----------------------------------------------------------------*/
1021 /* aopPut - puts a string for a aop */
1022 /*-----------------------------------------------------------------*/
1024 aopPut (asmop * aop, char *s, int offset)
1028 if (aop->size && offset > (aop->size - 1)) {
1029 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1030 "aopPut got offset > aop->size");
1034 /* will assign value to value */
1035 /* depending on where it is ofcourse */
1036 switch (aop->type) {
1039 sprintf (d, "(%s)+%d", aop->aopu.aop_dir, offset);
1042 sprintf (d, "%s", aop->aopu.aop_dir);
1045 emitcode ("sts", "%s,%s", d, s);
1049 if (toupper (*s) != 'R') {
1051 emitcode ("clr", "%s",
1052 aop->aopu.aop_reg[offset]->name);
1055 emitcode ("ldi", "r25,%s", s);
1056 emitcode ("mov", "%s,r35",
1057 aop->aopu.aop_reg[offset]->name);
1061 if (strcmp (aop->aopu.aop_reg[offset]->name, s)) {
1062 emitcode ("mov", "%s,%s",
1063 aop->aopu.aop_reg[offset]->name, s);
1069 if (offset > aop->coff) {
1070 emitcode ("adiw", "%s,%d", aop->aopu.aop_ptr->name,
1071 offset - aop->coff);
1074 if (offset < aop->coff) {
1075 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name,
1076 aop->coff - offset);
1080 emitcode ("st", "x,%s", s);
1085 if (offset > aop->coff) {
1086 emitcode ("adiw", "r30,%d",
1087 offset - aop->coff);
1090 emitcode ("sbiw", "r30,%d",
1091 aop->coff - offset);
1093 emitcode ("lpm", "%s,z", s);
1096 /* we can use lds */
1097 if (offset > aop->coff) {
1098 emitcode ("sdd", "z+%d,%s",
1099 offset - aop->coff, s);
1102 emitcode ("sbiw", "%s,%d",
1103 aop->aopu.aop_ptr->name,
1104 aop->coff - offset);
1106 emitcode ("ld", "%s,z", s);
1112 emitcode ("push", "%s", s);
1116 /* if used only for a condition code check */
1117 assert (toupper (*s) == 'R');
1119 emitcode ("xrl", "r0,r0");
1120 emitcode ("cpi", "%s,0", s);
1123 emitcode ("cpc", "r0,%s", s);
1129 if (strcmp (aop->aopu.aop_str[offset], s))
1130 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset],
1135 emitcode ("std", "y+%d,%s", offset, s);
1139 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1140 "aopPut got unsupported aop->type");
1146 #define AOP(op) op->aop
1147 #define AOP_TYPE(op) AOP(op)->type
1148 #define AOP_SIZE(op) AOP(op)->size
1149 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_X || \
1150 AOP_TYPE(x) == AOP_Z))
1151 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1152 ((x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R27_IDX)) || \
1153 (x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R31_IDX)) )))
1154 #define AOP_ISX(x) (x && (x->type == AOP_REG && \
1155 ((x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R27_IDX)))))
1156 #define AOP_ISZ(x) (x && (x->type == AOP_REG && \
1157 ((x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R31_IDX)))))
1159 /*-----------------------------------------------------------------*/
1160 /* genNotFloat - generates not for float operations */
1161 /*-----------------------------------------------------------------*/
1163 genNotFloat (operand * op, operand * res)
1169 /* we will put 127 in the first byte of
1171 aopPut (AOP (res), "127", 0);
1172 size = AOP_SIZE (op) - 1;
1175 l = aopGet (op->aop, offset++);
1179 emitcode ("or", "R0,%s", aopGet (op->aop, offset++));
1181 tlbl = newiTempLabel (NULL);
1183 tlbl = newiTempLabel (NULL);
1184 aopPut (res->aop, zero, 1);
1185 emitcode ("cpi", "r0,0");
1186 emitcode ("breq", "L%05d", tlbl->key);
1187 aopPut (res->aop, one, 1);
1188 emitcode ("", "L%05d:", tlbl->key);
1190 size = res->aop->size - 2;
1192 /* put zeros in the rest */
1194 aopPut (res->aop, zero, offset++);
1197 /*-----------------------------------------------------------------*/
1198 /* opIsGptr: returns non-zero if the passed operand is */
1199 /* a generic pointer type. */
1200 /*-----------------------------------------------------------------*/
1202 opIsGptr (operand * op)
1204 sym_link *type = operandType (op);
1206 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type)) {
1212 /*-----------------------------------------------------------------*/
1213 /* getDataSize - get the operand data size */
1214 /*-----------------------------------------------------------------*/
1216 getDataSize (operand * op)
1219 size = AOP_SIZE (op);
1220 if (size == GPTRSIZE) {
1221 sym_link *type = operandType (op);
1222 if (IS_GENPTR (type)) {
1223 /* generic pointer; arithmetic operations
1224 * should ignore the high byte (pointer type).
1232 /*-----------------------------------------------------------------*/
1233 /* toBoolean - emit code for orl a,operator(sizeop) */
1234 /*-----------------------------------------------------------------*/
1236 toBoolean (operand * oper, char *r, bool clr)
1238 int size = AOP_SIZE (oper);
1241 emitcode ("clr", "%s", r);
1243 emitcode ("or", "%s,%s", r, aopGet (AOP (oper), offset++));
1246 emitcode("mov","%s,%s",r,aopGet (AOP (oper), offset++));
1247 if (size) while (size--) emitcode ("or", "%s,%s", r, aopGet (AOP (oper), offset++));
1252 /*-----------------------------------------------------------------*/
1253 /* genNot - generate code for ! operation */
1254 /*-----------------------------------------------------------------*/
1259 sym_link *optype = operandType (IC_LEFT (ic));
1260 int size, offset = 1;
1262 /* assign asmOps to operand & result */
1263 aopOp (IC_LEFT (ic), ic, FALSE);
1264 aopOp (IC_RESULT (ic), ic, TRUE);
1266 /* if type float then do float */
1267 if (IS_FLOAT (optype)) {
1268 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1271 emitcode ("clr", "r24");
1272 tlbl = newiTempLabel (NULL);
1273 size = AOP_SIZE (IC_LEFT (ic));
1276 emitcode ("cpse", "%s,r24", aopGet (AOP (IC_LEFT (ic)), 0));
1281 emitcode ("cpc", "%s,r24",
1282 aopGet (AOP (IC_LEFT (ic)),
1285 emitcode ("cpi", "%s,0",
1286 aopGet (AOP (IC_LEFT (ic)),
1290 emitcode ("bne", "L%05d", tlbl->key);
1292 emitcode ("ldi", "r24,1");
1293 emitcode ("", "L%05d:", tlbl->key);
1294 aopPut (AOP (IC_RESULT (ic)), "r24", 0);
1295 size = AOP_SIZE (IC_RESULT (ic)) - 1;
1298 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
1302 /* release the aops */
1303 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1304 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1308 /*-----------------------------------------------------------------*/
1309 /* genCpl - generate code for complement */
1310 /*-----------------------------------------------------------------*/
1318 /* assign asmOps to operand & result */
1319 aopOp (IC_LEFT (ic), ic, FALSE);
1320 aopOp (IC_RESULT (ic), ic, TRUE);
1321 samer = sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)));
1322 size = AOP_SIZE (IC_RESULT (ic));
1324 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
1326 emitcode ("com", "%s", l);
1329 aopPut (AOP (IC_RESULT (ic)), l, offset);
1330 emitcode ("com", "%s",
1331 aopGet (AOP (IC_RESULT (ic)), offset));
1336 /* release the aops */
1337 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1338 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1341 /*-----------------------------------------------------------------*/
1342 /* genUminusFloat - unary minus for floating points */
1343 /*-----------------------------------------------------------------*/
1345 genUminusFloat (operand * op, operand * result)
1347 int size, offset = 0;
1349 /* for this we just need to flip the
1350 first it then copy the rest in place */
1351 size = AOP_SIZE (op) - 1;
1352 l = aopGet (AOP (op), 3);
1354 emitcode ("ldi", "r24,0x80");
1355 if (sameRegs (AOP (op), AOP (result))) {
1356 emitcode ("eor", "%s,r24", l);
1359 aopPut (AOP (result), l, 3);
1360 emitcode ("eor", "%s,r24", aopGet (AOP (result), 3));
1363 aopPut (AOP (result), aopGet (AOP (op), offset), offset);
1368 /*-----------------------------------------------------------------*/
1369 /* genUminus - unary minus code generation */
1370 /*-----------------------------------------------------------------*/
1372 genUminus (iCode * ic)
1375 sym_link *optype, *rtype;
1379 aopOp (IC_LEFT (ic), ic, FALSE);
1380 aopOp (IC_RESULT (ic), ic, TRUE);
1382 optype = operandType (IC_LEFT (ic));
1383 rtype = operandType (IC_RESULT (ic));
1385 /* if float then do float stuff */
1386 if (IS_FLOAT (optype)) {
1387 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1391 /* otherwise subtract from zero */
1392 size = AOP_SIZE (IC_LEFT (ic));
1394 samer = sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)));
1397 emitcode ("neg", "%s",
1398 aopGet (AOP (IC_LEFT (ic)), 0));
1401 aopPut (AOP (IC_RESULT (ic)),
1402 aopGet (AOP (IC_LEFT (ic)), 0), 0);
1403 emitcode ("neg", "%s",
1404 aopGet (AOP (IC_RESULT (ic)), 0));
1410 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
1412 aopPut (AOP (IC_RESULT (ic)), l, offset);
1413 l = aopGet (AOP (IC_RESULT (ic)), offset);
1416 emitcode ("com", "%s", l);
1418 emitcode ("neg", "%s", l);
1421 size = AOP_SIZE (IC_LEFT (ic)) - 1;
1424 emitcode ("sbci", "%s,0xff",
1425 aopGet (AOP (IC_RESULT (ic)), offset++));
1429 /* if any remaining bytes in the result */
1430 /* we just need to propagate the sign */
1431 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic))))) {
1432 symbol *tlbl = newiTempLabel (NULL);
1433 emitcode ("clr", "r0");
1434 emitcode ("brcc", "L%05d", tlbl->key);
1435 emitcode ("com", "r0");
1436 emitcode ("", "L%05d:", tlbl->key);
1438 aopPut (AOP (IC_RESULT (ic)), "r0", offset++);
1442 /* release the aops */
1443 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1444 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1447 /*-----------------------------------------------------------------*/
1448 /* assignResultValue - */
1449 /*-----------------------------------------------------------------*/
1451 assignResultValue (operand * oper)
1454 int size = AOP_SIZE (oper);
1456 aopPut (AOP (oper), fAVRReturn[offset], offset);
1461 /*-----------------------------------------------------------------*/
1462 /* saveZreg - if indirect call then save z-pointer register */
1463 /*-----------------------------------------------------------------*/
1465 saveZreg (iCode * ic)
1467 /* only if live accross this call */
1468 if (ic->regsSaved == 0 &&
1469 (bitVectBitValue (ic->rMask, R30_IDX) ||
1470 bitVectBitValue (ic->rMask, R31_IDX))) {
1472 emitcode ("push", "r30");
1473 emitcode ("push", "r31");
1477 /*-----------------------------------------------------------------*/
1478 /* popZreg - restore values of zreg */
1479 /*-----------------------------------------------------------------*/
1481 popZreg (iCode * ic)
1483 if (ic->regsSaved) {
1484 emitcode ("pop", "r31");
1485 emitcode ("pop", "r30");
1489 /*-----------------------------------------------------------------*/
1490 /* genIpush - genrate code for pushing this gets a little complex */
1491 /*-----------------------------------------------------------------*/
1493 genIpush (iCode * ic)
1495 int size, offset = 0;
1499 if (!ic->parmPush) {
1500 /* and the item is spilt then do nothing */
1501 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1506 for (lic = ic->next; lic; lic = lic->next)
1507 if (lic->op == PCALL)
1513 /* this is a paramter push */
1514 aopOp (IC_LEFT (ic), ic, FALSE);
1515 size = AOP_SIZE (IC_LEFT (ic));
1517 l = aopGet (AOP (IC_LEFT (ic)), offset++);
1518 emitcode ("push", "%s", l);
1521 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1524 /*-----------------------------------------------------------------*/
1525 /* genIpop - recover the registers: can happen only for spilling */
1526 /*-----------------------------------------------------------------*/
1528 genIpop (iCode * ic)
1533 /* if the temp was not pushed then */
1534 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1537 aopOp (IC_LEFT (ic), ic, FALSE);
1538 size = AOP_SIZE (IC_LEFT (ic));
1539 offset = (size - 1);
1541 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--));
1543 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1546 /*-----------------------------------------------------------------*/
1547 /* genCall - generates a call statement */
1548 /*-----------------------------------------------------------------*/
1550 genCall (iCode * ic)
1553 /* if send set is not empty the assign */
1557 for (sic = setFirstItem (_G.sendSet); sic;
1558 sic = setNextItem (_G.sendSet)) {
1559 int size, offset = 0;
1560 aopOp (IC_LEFT (sic), sic, FALSE);
1561 size = AOP_SIZE (IC_LEFT (sic));
1564 aopGet (AOP (IC_LEFT (sic)), offset);
1566 sprintf (buffer, "r%d", rnum++);
1568 emitcode ("mov", "%s,%s", b, l);
1571 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1576 emitcode ("call", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1577 OP_SYMBOL (IC_LEFT (ic))->rname :
1578 OP_SYMBOL (IC_LEFT (ic))->name));
1580 /* if we need assign a result value */
1581 if ((IS_ITEMP (IC_RESULT (ic)) &&
1582 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1583 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1584 IS_TRUE_SYMOP (IC_RESULT (ic))) {
1586 aopOp (IC_RESULT (ic), ic, FALSE);
1587 assignResultValue (IC_RESULT (ic));
1588 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1591 /* adjust the stack for parameters if required */
1592 if (ic->parmBytes) {
1593 if (ic->parmBytes > 63) {
1594 emitcode ("sbiw", "r28,%d", ic->parmBytes);
1597 emitcode ("subi", "r28,<(%d)",
1599 emitcode ("sbci", "r29,>(%d)",
1606 /*-----------------------------------------------------------------*/
1607 /* genPcall - generates a call by pointer statement */
1608 /*-----------------------------------------------------------------*/
1610 genPcall (iCode * ic)
1616 aopOp (IC_LEFT (ic), ic, FALSE);
1617 emitcode ("mov", "r30", aopGet (AOP (IC_LEFT (ic)), 0));
1618 emitcode ("mov", "r31", aopGet (AOP (IC_RIGHT (ic)), 0));
1619 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1621 /* if send set is not empty the assign */
1625 for (sic = setFirstItem (_G.sendSet); sic;
1626 sic = setNextItem (_G.sendSet)) {
1627 int size, offset = 0;
1628 aopOp (IC_LEFT (sic), sic, FALSE);
1629 size = AOP_SIZE (IC_LEFT (sic));
1632 aopGet (AOP (IC_LEFT (sic)), offset);
1634 sprintf (b, "r%d", rnum++);
1636 emitcode ("mov", "%s,%s", b, l);
1639 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1644 emitcode ("icall", "");
1646 /* if we need assign a result value */
1647 if ((IS_ITEMP (IC_RESULT (ic)) &&
1648 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1649 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1650 IS_TRUE_SYMOP (IC_RESULT (ic))) {
1652 aopOp (IC_RESULT (ic), ic, FALSE);
1654 assignResultValue (IC_RESULT (ic));
1655 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1658 /* adjust the stack for parameters if
1660 if (ic->parmBytes) {
1662 if (ic->parmBytes > 3) {
1663 emitcode ("mov", "a,%s", spname);
1664 emitcode ("add", "a,#0x%02x",
1665 (-ic->parmBytes) & 0xff);
1666 emitcode ("mov", "%s,a", spname);
1669 for (i = 0; i < ic->parmBytes; i++)
1670 emitcode ("dec", "%s", spname);
1674 /* adjust the stack for parameters if required */
1675 if (ic->parmBytes) {
1676 if (ic->parmBytes > 63) {
1677 emitcode ("sbiw", "r28,%d", ic->parmBytes);
1680 emitcode ("subi", "r28,<(%d)",
1682 emitcode ("sbci", "r29,>(%d)",
1690 /*-----------------------------------------------------------------*/
1691 /* resultRemat - result is rematerializable */
1692 /*-----------------------------------------------------------------*/
1694 resultRemat (iCode * ic)
1696 if (SKIP_IC (ic) || ic->op == IFX)
1699 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic))) {
1700 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
1701 if (sym->remat && !POINTER_SET (ic))
1708 #if defined(__BORLANDC__) || defined(_MSC_VER)
1709 #define STRCASECMP stricmp
1711 #define STRCASECMP strcasecmp
1714 /*-----------------------------------------------------------------*/
1715 /* genFunction - generated code for function entry */
1716 /*-----------------------------------------------------------------*/
1718 genFunction (iCode * ic)
1725 /* create the function header */
1726 emitcode (";", "-----------------------------------------");
1727 emitcode (";", " function %s",
1728 (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
1729 emitcode (";", "-----------------------------------------");
1731 emitcode ("", "%s:", sym->rname);
1732 ftype = operandType (IC_LEFT (ic));
1734 /* if critical function then turn interrupts off */
1735 if (IFFUNC_ISCRITICAL (ftype))
1736 emitcode ("cli", "");
1738 if (IFFUNC_ISISR (sym->type)) {
1741 /* save the preserved registers that are used in this function */
1742 for (i = R2_IDX; i <= R15_IDX; i++) {
1743 if (bitVectBitValue (sym->regsUsed, i)) {
1745 emitcode ("push", "%s", avr_regWithIdx (i)->name);
1748 /* now for the pointer registers */
1749 if (bitVectBitValue (sym->regsUsed, R26_IDX)) {
1751 emitcode ("push", "r26");
1753 if (bitVectBitValue (sym->regsUsed, R27_IDX)) {
1755 emitcode ("push", "r27");
1757 if (bitVectBitValue (sym->regsUsed, R30_IDX)) {
1759 emitcode ("push", "r30");
1761 if (bitVectBitValue (sym->regsUsed, R31_IDX)) {
1763 emitcode ("push", "r31");
1765 /* adjust the stack for the function */
1767 emitcode ("push", "r28");
1768 emitcode ("push", "r29");
1769 emitcode ("in", "r28,__SP_L__");
1770 emitcode ("in", "r29,__SP_H__");
1771 if (sym->stack <= 63) {
1772 emitcode ("sbiw", "r28,%d", sym->stack);
1775 emitcode ("subi", "r28,<(%d)", sym->stack);
1776 emitcode ("sbci", "r29,>(%d)", sym->stack);
1778 emitcode ("out", "__SP_L__,r28");
1779 emitcode ("out", "__SP_H__,r29");
1783 /*-----------------------------------------------------------------*/
1784 /* genEndFunction - generates epilogue for functions */
1785 /*-----------------------------------------------------------------*/
1787 genEndFunction (iCode * ic)
1789 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
1792 /* restore stack pointer */
1794 if (sym->stack <= 63) {
1795 emitcode ("adiw", "r28,%d", sym->stack);
1798 emitcode ("subi", "r28,<(-%d)", sym->stack);
1799 emitcode ("sbci", "r29,>(-%d)", sym->stack);
1801 emitcode ("out", "__SP_L__,r28");
1802 emitcode ("out", "__SP_H__,r29");
1804 /* pop frame pointer */
1805 emitcode ("pop", "r29");
1806 emitcode ("pop", "r28");
1808 /* restore preserved registers */
1809 if (bitVectBitValue (sym->regsUsed, R31_IDX)) {
1811 emitcode ("pop", "r31");
1813 if (bitVectBitValue (sym->regsUsed, R30_IDX)) {
1815 emitcode ("pop", "r30");
1817 if (bitVectBitValue (sym->regsUsed, R27_IDX)) {
1819 emitcode ("pop", "r27");
1821 if (bitVectBitValue (sym->regsUsed, R26_IDX)) {
1823 emitcode ("pop", "r26");
1825 for (i = R15_IDX; i >= R2_IDX; i--) {
1826 if (bitVectBitValue (sym->regsUsed, i)) {
1828 emitcode ("pop", "%s", avr_regWithIdx (i)->name);
1832 if (IFFUNC_ISCRITICAL (sym->type))
1833 emitcode ("sti", "");
1835 if (IFFUNC_ISISR (sym->type)) {
1836 emitcode ("rti", "");
1839 emitcode ("ret", "");
1844 /*-----------------------------------------------------------------*/
1845 /* genRet - generate code for return statement */
1846 /*-----------------------------------------------------------------*/
1850 int size, offset = 0;
1852 /* if we have no return value then
1853 just generate the "ret" */
1857 /* we have something to return then
1858 move the return value into place */
1859 aopOp (IC_LEFT (ic), ic, FALSE);
1860 size = AOP_SIZE (IC_LEFT (ic));
1863 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) {
1864 emitcode ("ldi", "%s,%s(%d)", fAVRReturn[offset],
1866 (int) floatFromVal (AOP (IC_LEFT (ic))->
1867 aopu.aop_lit), offset);
1871 l = aopGet (AOP (IC_LEFT (ic)), offset);
1872 if (strcmp (fAVRReturn[offset], l))
1873 emitcode ("mov", "%s,%s", fAVRReturn[offset],
1879 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1882 /* generate a jump to the return label
1883 if the next is not the return statement */
1884 if (!(ic->next && ic->next->op == LABEL &&
1885 IC_LABEL (ic->next) == returnLabel))
1887 emitcode ("rjmp", "L%05d", returnLabel->key);
1891 /*-----------------------------------------------------------------*/
1892 /* genLabel - generates a label */
1893 /*-----------------------------------------------------------------*/
1895 genLabel (iCode * ic)
1897 /* special case never generate */
1898 if (IC_LABEL (ic) == entryLabel)
1901 emitcode ("", "L%05d:", IC_LABEL (ic)->key);
1904 /*-----------------------------------------------------------------*/
1905 /* genGoto - generates a ljmp */
1906 /*-----------------------------------------------------------------*/
1908 genGoto (iCode * ic)
1910 emitcode ("rjmp", "L%05d", (IC_LABEL (ic)->key));
1913 /*-----------------------------------------------------------------*/
1914 /* genPlusIncr :- does addition with increment if possible */
1915 /*-----------------------------------------------------------------*/
1917 genPlusIncr (iCode * ic)
1919 unsigned int icount;
1922 /* will try to generate an increment */
1923 /* if the right side is not a literal
1925 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
1928 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.
1931 /* if the sizes are greater than 2 or they are not the same regs
1933 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1936 /* so we know LEFT & RESULT in the same registers and add
1938 /* for short & char types */
1939 if (AOP_SIZE (IC_RESULT (ic)) < 2) {
1941 emitcode ("inc", "%s",
1942 aopGet (AOP (IC_LEFT (ic)), 0));
1945 if (AOP_ISHIGHREG( AOP (IC_LEFT (ic)),0)) {
1946 emitcode ("subi", "%s,<(%d)",
1947 aopGet (AOP (IC_LEFT (ic)), 0), 0-icount);
1952 for (offset = 0 ; offset < AOP_SIZE(IC_RESULT(ic)) ; offset++) {
1953 if (!(AOP_ISHIGHREG(AOP(IC_RESULT(ic)),offset))) return FALSE;
1956 if (AOP_SIZE (IC_RESULT (ic)) <= 3) {
1957 /* if register pair and starts with 26/30 then adiw */
1958 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0
1960 && (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX) ||
1961 IS_REGIDX (AOP (IC_RESULT (ic)), R24_IDX) ||
1962 IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX))) {
1963 emitcode ("adiw", "%s,%d",
1964 aopGet (AOP (IC_RESULT (ic)), 0), icount);
1969 emitcode ("subi", "%s,<(%d)",
1970 aopGet (AOP (IC_RESULT (ic)), 0), 0-icount);
1971 emitcode ("sbci", "%s,>(%d)",
1972 aopGet (AOP (IC_RESULT (ic)), 1), 0-icount);
1976 /* for 32 bit longs */
1977 emitcode ("subi", "%s,<(%d)", aopGet (AOP (IC_RESULT (ic)), 0),
1979 emitcode ("sbci", "%s,>(%d)", aopGet (AOP (IC_RESULT (ic)), 1),
1981 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2),
1983 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3),
1989 /* This is the pure and virtuous version of this code.
1990 * I'm pretty certain it's right, but not enough to toss the old
1994 adjustArithmeticResult (iCode * ic)
1996 if (opIsGptr (IC_RESULT (ic)) &&
1997 opIsGptr (IC_LEFT (ic)) &&
1998 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)))) {
1999 aopPut (AOP (IC_RESULT (ic)),
2000 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1),
2004 if (opIsGptr (IC_RESULT (ic)) &&
2005 opIsGptr (IC_RIGHT (ic)) &&
2006 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)))) {
2007 aopPut (AOP (IC_RESULT (ic)),
2008 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1),
2012 if (opIsGptr (IC_RESULT (ic)) &&
2013 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2014 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2015 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2016 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)))) {
2018 sprintf (buffer, "%d",
2019 pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2020 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2024 /*-----------------------------------------------------------------*/
2025 /* genPlus - generates code for addition */
2026 /*-----------------------------------------------------------------*/
2028 genPlus (iCode * ic)
2030 int size, offset = 0;
2034 /* special cases :- */
2036 aopOp (IC_LEFT (ic), ic, FALSE);
2037 aopOp (IC_RIGHT (ic), ic, FALSE);
2038 aopOp (IC_RESULT (ic), ic, TRUE);
2040 /* if I can do an increment instead
2041 of add then GOOD for ME */
2042 if (genPlusIncr (ic) == TRUE)
2045 size = getDataSize (IC_RESULT (ic));
2046 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2050 aopPut (AOP (IC_RESULT (ic)),
2051 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2053 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
2060 emitcode (l, "%s,%s",
2061 aopGet (AOP (IC_RESULT (ic)), offset),
2062 aopGet (AOP (IC_RIGHT (ic)), offset));
2065 if (AOP_ISHIGHREG( AOP( IC_RESULT(ic)),offset)) {
2071 emitcode (l, "%s,%s(-%d)",
2072 aopGet (AOP (IC_RESULT (ic)), offset),
2074 (int) floatFromVal (AOP (IC_RIGHT (ic))->
2082 emitcode (l, "%s,%s",
2083 aopGet (AOP (IC_RESULT (ic)), offset),
2084 aopGet (AOP (IC_RIGHT (ic)), offset));
2090 adjustArithmeticResult (ic);
2093 freeAsmop (IC_LEFT (ic), NULL, ic,
2094 (RESULTONSTACK (ic) ? FALSE : TRUE));
2095 freeAsmop (IC_RIGHT (ic), NULL, ic,
2096 (RESULTONSTACK (ic) ? FALSE : TRUE));
2097 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2100 /*-----------------------------------------------------------------*/
2101 /* genMinusDec :- does subtraction with deccrement if possible */
2102 /*-----------------------------------------------------------------*/
2104 genMinusDec (iCode * ic)
2106 unsigned int icount;
2109 /* will try to generate an increment */
2110 /* if the right side is not a literal
2112 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2116 (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.
2119 /* if the sizes are greater than 2 or they are not the same regs
2121 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2124 /* so we know LEFT & RESULT in the same registers and add
2126 /* for short & char types */
2127 if (AOP_SIZE (IC_RESULT (ic)) < 2) {
2129 emitcode ("dec", "%s",
2130 aopGet (AOP (IC_LEFT (ic)), 0));
2133 if (AOP_ISHIGHREG( AOP ( IC_LEFT(ic)),0)) {
2134 emitcode ("subi", "%s,<(%d)",
2135 aopGet (AOP (IC_LEFT (ic)), 0), icount);
2140 for (offset = 0 ; offset < AOP_SIZE(IC_RESULT(ic)) ; offset++) {
2141 if (!(AOP_ISHIGHREG(AOP(IC_RESULT(ic)),offset))) return FALSE;
2144 if (AOP_SIZE (IC_RESULT (ic)) <= 3) {
2145 /* if register pair and starts with 26/30 then adiw */
2146 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0
2148 && (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX) ||
2149 IS_REGIDX (AOP (IC_RESULT (ic)), R24_IDX) ||
2150 IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX))) {
2151 emitcode ("sbiw", "%s,%d",
2152 aopGet (AOP (IC_RESULT (ic)), 0), icount);
2157 emitcode ("subi", "%s,<(%d)",
2158 aopGet (AOP (IC_RESULT (ic)), 0), icount);
2159 emitcode ("sbci", "%s,>(%d)",
2160 aopGet (AOP (IC_RESULT (ic)), 1), icount);
2163 /* for 32 bit longs */
2164 emitcode ("subi", "%s,<(%d)", aopGet (AOP (IC_RESULT (ic)), 0),
2166 emitcode ("sbci", "%s,>(%d)", aopGet (AOP (IC_RESULT (ic)), 1),
2168 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2),
2170 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3),
2176 /*-----------------------------------------------------------------*/
2177 /* genMinus - generates code for subtraction */
2178 /*-----------------------------------------------------------------*/
2180 genMinus (iCode * ic)
2182 int size, offset = 0, samer;
2185 aopOp (IC_LEFT (ic), ic, FALSE);
2186 aopOp (IC_RIGHT (ic), ic, FALSE);
2187 aopOp (IC_RESULT (ic), ic, TRUE);
2189 /* if I can do an decrement instead
2190 of subtract then GOOD for ME */
2191 if (genMinusDec (ic) == TRUE)
2194 size = getDataSize (IC_RESULT (ic));
2195 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2198 aopPut (AOP (IC_RESULT (ic)),
2199 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2201 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
2208 emitcode (l, "%s,%s",
2209 aopGet (AOP (IC_RESULT (ic)), offset),
2210 aopGet (AOP (IC_RIGHT (ic)), offset));
2213 if (AOP_ISHIGHREG(AOP (IC_RESULT (ic)),offset)) {
2219 emitcode (l, "%s,%s(%d)",
2220 aopGet (AOP (IC_RESULT (ic)), offset),
2222 (int) floatFromVal (AOP (IC_RIGHT (ic))->
2230 emitcode (l, "%s,%s",
2231 aopGet (AOP (IC_RESULT (ic)), offset),
2232 aopGet (AOP (IC_RIGHT (ic)), offset));
2238 adjustArithmeticResult (ic);
2241 freeAsmop (IC_LEFT (ic), NULL, ic,
2242 (RESULTONSTACK (ic) ? FALSE : TRUE));
2243 freeAsmop (IC_RIGHT (ic), NULL, ic,
2244 (RESULTONSTACK (ic) ? FALSE : TRUE));
2245 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2248 /*-----------------------------------------------------------------*/
2249 /* genMultOneByte : 8 bit multiplication & division */
2250 /*-----------------------------------------------------------------*/
2252 genMultOneByte (operand * left, operand * right, operand * result)
2254 sym_link *opetype = operandType (result);
2258 /* (if two literals, the value is computed before) */
2259 /* if one literal, literal on the right */
2260 if (AOP_TYPE (left) == AOP_LIT) {
2266 size = AOP_SIZE (result);
2268 if (SPEC_USIGN (opetype)) {
2269 emitcode ("mul", "%s,%s", aopGet (AOP (left), 0),
2270 aopGet (AOP (right), 0));
2273 emitcode ("muls", "%s,%s", aopGet (AOP (left), 0),
2274 aopGet (AOP (right), 0));
2276 aopPut (AOP (result), "r0", 0);
2278 aopPut (AOP (result), "r1", 1);
2281 if (SPEC_USIGN (opetype)) {
2283 aopPut (AOP (result), zero, offset++);
2288 lbl = newiTempLabel (NULL);
2289 emitcode ("ldi", "r24,0");
2290 emitcode ("brcc", "L%05d", lbl->key);
2291 emitcode ("ldi", "r24,0xff)");
2292 emitcode ("", "L%05d:", lbl->key);
2294 aopPut (AOP (result), "r24",
2302 /*-----------------------------------------------------------------*/
2303 /* genMult - generates code for multiplication */
2304 /*-----------------------------------------------------------------*/
2306 genMult (iCode * ic)
2308 operand *left = IC_LEFT (ic);
2309 operand *right = IC_RIGHT (ic);
2310 operand *result = IC_RESULT (ic);
2312 /* assign the amsops */
2313 aopOp (left, ic, FALSE);
2314 aopOp (right, ic, FALSE);
2315 aopOp (result, ic, TRUE);
2317 /* if both are of size == 1 */
2318 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1) {
2319 genMultOneByte (left, right, result);
2323 /* should have been converted to function call */
2327 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2328 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2329 freeAsmop (result, NULL, ic, TRUE);
2332 /*-----------------------------------------------------------------*/
2333 /* genDiv - generates code for division */
2334 /*-----------------------------------------------------------------*/
2338 /* should have been converted to function call */
2342 /*-----------------------------------------------------------------*/
2343 /* genMod - generates code for division */
2344 /*-----------------------------------------------------------------*/
2348 /* should have been converted to function call */
2360 /*-----------------------------------------------------------------*/
2361 /* revavrcnd - reverse a conditional for avr */
2362 /*-----------------------------------------------------------------*/
2364 revavrcnd (int type)
2376 for (i = 0; i < (sizeof (rar) / sizeof (rar[0])); i++) {
2377 if (rar[i].type == type)
2378 return rar[i].rtype;
2379 if (rar[i].rtype == type)
2382 assert (0); /* cannot happen */
2383 return 0; /* makes the compiler happy */
2386 static char *br_name[4] = { "breq", "brne", "brlt", "brge" };
2387 static char *br_uname[4] = { "breq", "brne", "brlo", "brcc" };
2389 /*-----------------------------------------------------------------*/
2390 /* genBranch - generate the branch instruction */
2391 /*-----------------------------------------------------------------*/
2393 genBranch (iCode * ifx, int br_type, int sign)
2395 int tj = (IC_TRUE (ifx) ? 1 : 0);
2397 if (tj) { /* if true jump */
2398 char *nm = (sign ? br_name[br_type] : br_uname[br_type]);
2399 emitcode (nm, "L%05d", IC_TRUE (ifx)->key);
2401 else { /* if false jump */
2402 int rtype = revavrcnd (br_type);
2403 char *nm = (sign ? br_name[rtype] : br_uname[rtype]);
2404 emitcode (nm, "L%05d", IC_FALSE (ifx)->key);
2409 /*-----------------------------------------------------------------*/
2410 /* genCmp - compare & jump */
2411 /*-----------------------------------------------------------------*/
2413 genCmp (iCode * ic, iCode * ifx, int br_type)
2415 operand *left, *right, *result;
2416 sym_link *letype, *retype;
2418 int sign, size, offset = 0;
2420 left = IC_LEFT (ic);
2421 right = IC_RIGHT (ic);
2422 result = IC_RESULT (ic);
2424 letype = getSpec (operandType (left));
2425 retype = getSpec (operandType (right));
2426 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
2428 /* assign the amsops */
2429 aopOp (left, ic, FALSE);
2430 aopOp (right, ic, FALSE);
2431 aopOp (result, ic, TRUE);
2432 size = AOP_SIZE (left);
2436 if (AOP_TYPE (right) == AOP_LIT) {
2437 emitcode ("cpi", "%s,<(%d)",
2438 aopGet (AOP (left), 0),
2440 floatFromVal (AOP (IC_RIGHT (ic))->
2442 genBranch (ifx, br_type, sign);
2444 else { /* right != literal */
2445 emitcode ("cp", "%s,%s",
2446 aopGet (AOP (left), 0),
2447 aopGet (AOP (right), 0));
2448 genBranch (ifx, br_type, sign);
2451 else { /* size != 1 */
2454 emitcode ("cp", "%s,%s",
2455 aopGet (AOP (left), 0),
2456 aopGet (AOP (right), 0));
2458 emitcode ("cpc", "%s,%s",
2459 aopGet (AOP (left), offset),
2460 aopGet (AOP (right),
2464 genBranch (ifx, br_type, sign);
2468 emitcode ("clr", "r0");
2471 emitcode ("cp", "%s,%s",
2472 aopGet (AOP (left), 0),
2473 aopGet (AOP (right), 0));
2475 emitcode ("cpc", "%s,%s",
2476 aopGet (AOP (left), offset),
2477 aopGet (AOP (right), offset));
2480 lbl = newiTempLabel (NULL);
2481 br_type = revavrcnd (br_type);
2483 emitcode (br_uname[br_type], "L%05d", lbl->key);
2485 emitcode (br_name[br_type], "L%05d", lbl->key);
2486 emitcode ("inc", "r0");
2487 emitcode ("", "L%05d:", lbl->key);
2488 aopPut (AOP (result), "r0", 0);
2489 size = AOP_SIZE (result) - 1;
2492 aopPut (AOP (result), zero, offset++);
2495 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2496 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2497 freeAsmop (result, NULL, ic, TRUE);
2500 /*-----------------------------------------------------------------*/
2501 /* genCmpGt :- greater than comparison */
2502 /*-----------------------------------------------------------------*/
2504 genCmpGt (iCode * ic, iCode * ifx)
2506 /* should have transformed by the parser */
2510 /*-----------------------------------------------------------------*/
2511 /* genCmpLt - less than comparisons */
2512 /*-----------------------------------------------------------------*/
2514 genCmpLt (iCode * ic, iCode * ifx)
2516 genCmp (ic, ifx, AVR_LT);
2519 /*-----------------------------------------------------------------*/
2520 /* genCmpEq - generates code for equal to */
2521 /*-----------------------------------------------------------------*/
2523 genCmpEq (iCode * ic, iCode * ifx)
2525 genCmp (ic, ifx, AVR_EQ);
2528 /*-----------------------------------------------------------------*/
2529 /* genCmpNe - generates code for not equal to */
2530 /*-----------------------------------------------------------------*/
2532 genCmpNe (iCode * ic, iCode * ifx)
2534 genCmp (ic, ifx, AVR_NE);
2537 /*-----------------------------------------------------------------*/
2538 /* genCmpGe - generates code for greater than equal to */
2539 /*-----------------------------------------------------------------*/
2541 genCmpGe (iCode * ic, iCode * ifx)
2543 genCmp (ic, ifx, AVR_GE);
2546 /*-----------------------------------------------------------------*/
2547 /* genCmpLe - generates code for less than equal to */
2548 /*-----------------------------------------------------------------*/
2550 genCmpLe (iCode * ic, iCode * ifx)
2552 operand *left = IC_LEFT (ic);
2553 operand *right = IC_RIGHT (ic);
2555 IC_RIGHT (ic) = left;
2556 IC_LEFT (ic) = right;
2557 genCmp (ic, ifx, AVR_GE);
2560 /*-----------------------------------------------------------------*/
2561 /* ifxForOp - returns the icode containing the ifx for operand */
2562 /*-----------------------------------------------------------------*/
2564 ifxForOp (operand * op, iCode * ic)
2566 /* if true symbol then needs to be assigned */
2567 if (IS_TRUE_SYMOP (op))
2570 /* if this has register type condition and
2571 the next instruction is ifx with the same operand
2572 and live to of the operand is upto the ifx only then */
2574 ic->next->op == IFX &&
2575 IC_COND (ic->next)->key == op->key &&
2576 OP_SYMBOL (op)->liveTo <= ic->next->seq) return ic->next;
2581 /*-----------------------------------------------------------------*/
2582 /* genAndOp - for && operation */
2583 /*-----------------------------------------------------------------*/
2585 genAndOp (iCode * ic)
2587 operand *left, *right, *result;
2591 /* note here that && operations that are in an
2592 if statement are taken away by backPatchLabels
2593 only those used in arthmetic operations remain */
2594 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2595 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2596 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
2598 tlbl = newiTempLabel (NULL);
2599 toBoolean (left, "r0", TRUE);
2600 toBoolean (right, "r1", TRUE);
2601 emitcode ("and", "r0,r1");
2602 emitcode ("ldi", "r24,1");
2603 emitcode ("breq", "L%05d", tlbl->key);
2604 emitcode ("dec", "r24");
2605 emitcode ("", "L%05d:", tlbl->key);
2606 aopPut (AOP (result), "r24", 0);
2607 size = AOP_SIZE (result) - 1;
2610 aopPut (AOP (result), zero, offset++);
2612 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2613 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2614 freeAsmop (result, NULL, ic, TRUE);
2618 /*-----------------------------------------------------------------*/
2619 /* genOrOp - for || operation */
2620 /*-----------------------------------------------------------------*/
2622 genOrOp (iCode * ic)
2624 operand *left, *right, *result;
2628 /* note here that || operations that are in an
2629 if statement are taken away by backPatchLabels
2630 only those used in arthmetic operations remain */
2631 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2632 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2633 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
2635 tlbl = newiTempLabel (NULL);
2636 toBoolean (left, "r0", TRUE);
2637 toBoolean (right, "r0", FALSE);
2638 emitcode ("ldi", "r24,1");
2639 emitcode ("breq", "L%05d", tlbl->key);
2640 emitcode ("dec", "r24");
2641 emitcode ("", "L%05d:", tlbl->key);
2642 aopPut (AOP (result), "r24", 0);
2643 size = AOP_SIZE (result) - 1;
2646 aopPut (AOP (result), zero, offset++);
2648 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2649 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2650 freeAsmop (result, NULL, ic, TRUE);
2654 AVR_AND = 0, AVR_OR, AVR_XOR
2656 static char *bopnames_lit[] = { "andi", "ori" };
2657 static char *bopnames[] = { "and", "or", "eor" };
2658 /*-----------------------------------------------------------------*/
2659 /* genBitWise - generate bitwise operations */
2660 /*-----------------------------------------------------------------*/
2662 genBitWise (iCode * ic, iCode * ifx, int bitop)
2664 operand *left, *right, *result;
2665 int size, offset = 0;
2670 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2671 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2672 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
2674 size = AOP_SIZE (left);
2676 if (ifx) { /* used only for jumps */
2677 if (AOP_TYPE (right) == AOP_LIT &&
2678 (bitop == AVR_AND || bitop == AVR_OR)) {
2680 (int) floatFromVal (AOP (right)->aopu.
2682 int p2 = powof2 (lit);
2683 if (bitop == AVR_AND && p2) { /* right side is a power of 2 */
2684 l = aopGet (AOP (left), p2 / 8);
2685 if (IC_TRUE (ifx)) {
2686 emitcode ("sbrc", "%s,%d", l,
2688 emitcode ("rjmp", "L%05d",
2689 IC_TRUE (ifx)->key);
2692 emitcode ("sbrs", "%s,%d", l,
2694 emitcode ("rjmp", "L%05d",
2695 IC_FALSE (ifx)->key);
2698 else { /* right not power of two */
2699 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2701 if (eh && AOP_ISHIGHREG(AOP(IC_LEFT(ic)),0)) {
2702 emitcode (bopnames_lit[bitop],
2704 aopGet (AOP (IC_LEFT (ic)), 0), lit);
2707 MOVR24 (aopGet (AOP (IC_LEFT (ic)), 0));
2708 emitcode (bopnames_lit[bitop], "r24,<(%d)", lit);
2710 lbl = newiTempLabel (NULL);
2711 if (IC_TRUE (ifx)) {
2712 emitcode ("breq", "L%05d", lbl->key);
2713 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2716 emitcode ("brne", "L%05d", lbl->key);
2717 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)-> key);
2719 emitcode ("", "L%05d:", lbl->key);
2721 else if (size == 2) {
2722 emitcode ("mov", "r24,%s", aopGet (AOP (IC_LEFT (ic)), 0));
2723 emitcode ("mov", "r25,%s", aopGet (AOP (IC_LEFT (ic)), 1));
2724 emitcode (bopnames_lit[bitop], "r24,<(%d)", lit);
2725 emitcode (bopnames_lit[bitop], "r25,>(%d)", lit);
2726 emitcode ("sbiw", "r24,0");
2727 lbl = newiTempLabel (NULL);
2728 if (IC_TRUE (ifx)) {
2729 emitcode ("breq", "L%05d", lbl->key);
2730 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2733 emitcode ("brne", "L%05d", lbl->key);
2734 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2736 emitcode ("", "L%05d:", lbl->key);
2739 lbl = newiTempLabel (NULL);
2740 lbl1 = newiTempLabel (NULL);
2742 if (eh && AOP_ISHIGHREG(AOP(IC_LEFT(ic)),offset)) {
2743 emitcode (bopnames_lit [bitop], "%s,<(%d)",
2744 aopGet (AOP (IC_LEFT (ic)), offset),
2748 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
2750 emitcode ("andi", "r24,<(%d)", lit);
2752 emitcode ("brne", "L%05d", lbl->key);
2757 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)-> key);
2759 emitcode ("rjmp", "L%05d", lbl1->key);
2760 emitcode ("", "L%05d:", lbl->key);
2763 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2764 emitcode ("", "L%05d:", lbl1->key);
2769 else { /* right is not a literal */
2770 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2771 int reh = OP_SYMBOL (right)->liveTo <= ic->seq;
2774 emitcode (bopnames[bitop], "%s,%s", aopGet (AOP (IC_LEFT (ic)), 0),
2775 aopGet (AOP (IC_RIGHT (ic)), 0));
2778 emitcode (bopnames[bitop], "%s,%s",
2779 aopGet (AOP (IC_RIGHT (ic)), 0),
2780 aopGet (AOP (IC_LEFT (ic)), 0));
2783 MOVR0 (aopGet (AOP (IC_LEFT (ic)), 0));
2784 emitcode (bopnames[bitop], "r0,%s",
2785 aopGet (AOP (IC_RIGHT (ic)), 0));
2787 lbl = newiTempLabel (NULL);
2788 if (IC_TRUE (ifx)) {
2789 emitcode ("breq", "L%05d", lbl->key);
2790 emitcode ("rjmp", "L%05d",
2791 IC_TRUE (ifx)->key);
2794 emitcode ("brne", "L%05d", lbl->key);
2795 emitcode ("rjmp", "L%05d",
2796 IC_FALSE (ifx)->key);
2798 emitcode ("", "L%05d:", lbl->key);
2800 else if (size == 2) {
2801 emitcode ("mov", "r24,%s",
2802 aopGet (AOP (IC_LEFT (ic)), 0));
2803 emitcode ("mov", "r25,%s",
2804 aopGet (AOP (IC_LEFT (ic)), 1));
2805 emitcode (bopnames[bitop], "r24,%s",
2806 aopGet (AOP (IC_RIGHT (ic)), 0));
2807 emitcode (bopnames[bitop], "r25,%s",
2808 aopGet (AOP (IC_RIGHT (ic)), 1));
2809 emitcode ("sbiw", "r24,0");
2810 lbl = newiTempLabel (NULL);
2811 if (IC_TRUE (ifx)) {
2812 emitcode ("breq", "L%05d", lbl->key);
2813 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2816 emitcode ("brne", "L%05d", lbl->key);
2817 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2819 emitcode ("", "L%05d:", lbl->key);
2822 lbl = newiTempLabel (NULL);
2823 lbl1 = newiTempLabel (NULL);
2826 emitcode (bopnames[bitop], "%s,%s",
2827 aopGet (AOP (IC_LEFT (ic)), offset),
2828 aopGet (AOP (IC_RIGHT (ic)), offset));
2831 emitcode (bopnames[bitop], "%s,%s",
2832 aopGet (AOP (IC_RIGHT (ic)), offset),
2833 aopGet (AOP (IC_LEFT (ic)), offset));
2836 MOVR0 (aopGet (AOP (IC_LEFT (ic)), offset));
2837 emitcode (bopnames[bitop], "r0,%s",
2838 aopGet (AOP (IC_RIGHT (ic)), offset));
2840 emitcode ("brne", "L%05d", lbl->key);
2845 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2847 emitcode ("rjmp", "L%05d", lbl1->key);
2848 emitcode ("", "L%05d:", lbl->key);
2851 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2852 emitcode ("", "L%05d:", lbl1->key);
2859 /* result needs to go a register */
2860 samerl = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2861 samerr = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)));
2863 if (AOP_TYPE (right) == AOP_LIT) {
2865 (int) floatFromVal (AOP (right)->aopu.
2867 if (((lit >> (8 * offset)) & 0xff) == 0) {
2868 if (bitop == AVR_AND) {
2869 aopPut (AOP (result), zero, offset++);
2872 else if (bitop == AVR_OR) {
2874 aopPut (AOP (result),
2884 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT &&
2885 AOP_ISHIGHREG(AOP(IC_LEFT(ic)),offset) &&
2886 (bitop == AVR_AND || bitop == AVR_OR)) {
2887 emitcode (bopnames_lit[bitop], "%s,%s(%d)",
2888 aopGet (AOP (IC_LEFT (ic)), offset),
2890 (int) floatFromVal (AOP (right)-> aopu.aop_lit));
2893 emitcode (bopnames[bitop], "%s,%s",
2894 aopGet (AOP (IC_LEFT (ic)), offset),
2895 aopGet (AOP (IC_RIGHT (ic)), offset));
2899 emitcode (bopnames[bitop], "%s,%s",
2900 aopGet (AOP (IC_RIGHT (ic)), offset),
2901 aopGet (AOP (IC_LEFT (ic)), offset));
2904 aopPut (AOP (IC_RESULT (ic)),
2905 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2906 emitcode (bopnames[bitop],
2907 aopGet (AOP (IC_RESULT (ic)), offset),
2908 aopGet (AOP (IC_RIGHT (ic)), offset));
2913 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2914 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2915 freeAsmop (result, NULL, ic, TRUE);
2918 /*-----------------------------------------------------------------*/
2919 /* genAnd - code for and */
2920 /*-----------------------------------------------------------------*/
2922 genAnd (iCode * ic, iCode * ifx)
2924 genBitWise (ic, ifx, AVR_AND);
2927 /*-----------------------------------------------------------------*/
2928 /* genOr - code for or */
2929 /*-----------------------------------------------------------------*/
2931 genOr (iCode * ic, iCode * ifx)
2933 genBitWise (ic, ifx, AVR_OR);
2936 /*-----------------------------------------------------------------*/
2937 /* genXor - code for xclusive or */
2938 /*-----------------------------------------------------------------*/
2940 genXor (iCode * ic, iCode * ifx)
2942 genBitWise (ic, ifx, AVR_XOR);
2945 /*-----------------------------------------------------------------*/
2946 /* genInline - write the inline code out */
2947 /*-----------------------------------------------------------------*/
2949 genInline (iCode * ic)
2951 char *buffer, *bp, *bp1;
2953 _G.inLine += (!options.asmpeep);
2955 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
2956 strcpy (buffer, IC_INLINE (ic));
2958 /* emit each line as a code */
2979 /* emitcode("",buffer); */
2980 _G.inLine -= (!options.asmpeep);
2983 /*-----------------------------------------------------------------*/
2984 /* genRotC - rotate right/left with carry , lr = 1 rotate right */
2985 /*-----------------------------------------------------------------*/
2987 genRotC (iCode * ic, int lr)
2989 operand *left, *result;
2990 int size, offset = 0;
2992 /* rotate right with carry */
2993 left = IC_LEFT (ic);
2994 result = IC_RESULT (ic);
2995 aopOp (left, ic, FALSE);
2996 aopOp (result, ic, FALSE);
2998 /* move it to the result */
2999 size = AOP_SIZE (result);
3000 if (!sameRegs (AOP (left), AOP (result))) {
3003 aopPut (AOP (result),
3004 aopGet (AOP (left), offset), offset);
3007 size = AOP_SIZE (result);
3015 emitcode ("sbrc", "%s,%d", aopGet (AOP (result), offset),
3017 emitcode ("sec", "");
3020 emitcode ((lr ? "ror" : "rol"), "%s",
3021 aopGet (AOP (result), offset));
3027 freeAsmop (left, NULL, ic, TRUE);
3028 freeAsmop (result, NULL, ic, TRUE);
3031 /*-----------------------------------------------------------------*/
3032 /* genRRC - rotate right with carry */
3033 /*-----------------------------------------------------------------*/
3040 /*-----------------------------------------------------------------*/
3041 /* genRLC - generate code for rotate left with carry */
3042 /*-----------------------------------------------------------------*/
3049 /*-----------------------------------------------------------------*/
3050 /* genGetHbit - generates code get highest order bit */
3051 /*-----------------------------------------------------------------*/
3053 genGetHbit (iCode * ic)
3055 operand *left, *result;
3058 left = IC_LEFT (ic);
3059 result = IC_RESULT (ic);
3060 aopOp (left, ic, FALSE);
3061 aopOp (result, ic, FALSE);
3063 size = AOP_SIZE (result);
3064 if (!sameRegs (AOP (left), AOP (result))) {
3065 emitcode ("clr", "%s", aopGet (AOP (result), size - 1));
3066 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3067 emitcode ("subi", "%s,<(-1)",
3068 aopGet (AOP (result), size - 1));
3071 emitcode ("clr", "r0");
3072 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3073 emitcode ("subi", "r0,<(-1)");
3074 aopPut (AOP (result), "r0", 0);
3079 emitcode ("clr", aopGet (AOP (result), offset++));
3081 freeAsmop (left, NULL, ic, TRUE);
3082 freeAsmop (result, NULL, ic, TRUE);
3085 /*-----------------------------------------------------------------*/
3086 /* genShiftLeftLit - shift left by a known amount */
3087 /*-----------------------------------------------------------------*/
3089 genShiftLeftLit (iCode * ic)
3091 operand *left, *right, *result;
3092 int size, shCount, offset = 0;
3095 right = IC_RIGHT (ic);
3096 left = IC_LEFT (ic);
3097 result = IC_RESULT (ic);
3099 aopOp (left, ic, FALSE);
3100 aopOp (result, ic, FALSE);
3101 size = AOP_SIZE (result);
3102 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3104 if (shCount > (size * 8 - 1)) {
3106 aopPut (AOP (result), zero, offset++);
3111 if (!sameRegs (AOP (left), AOP (result)))
3112 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3114 if (AOP_ISHIGHREG(AOP(result),0)) {
3115 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3116 emitcode ("andi", "%s,0xf0");
3118 emitcode ("ldi","r24,0xf0");
3119 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3120 emitcode ("and", "%s,r24");
3125 emitcode ("add", "%s,%s", aopGet (AOP (result), 0),
3126 aopGet (AOP (result), 0));
3130 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3133 if (shCount >= 12) {
3134 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3135 aopPut (AOP (result), zero, 0);
3136 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3137 if (AOP_ISHIGHREG(AOP(result),1)) {
3138 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3140 emitcode ("ldi","r24,0xf0");
3141 emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
3147 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3148 aopPut (AOP (result), zero, 0);
3154 if (!sameRegs (AOP (left), AOP (result))) {
3155 aopPut (AOP (result), aopGet (AOP (left), 0),
3157 aopPut (AOP (result), aopGet (AOP (left), 1),
3160 emitcode ("mov", "r24,%s", aopGet (AOP (result), 0));
3161 emitcode ("andi", "r24,0x0f");
3162 if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
3163 emitcode("ldi","r25,0xf0");
3165 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3166 if (AOP_ISHIGHREG(AOP(result),0)) {
3167 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 0));
3169 emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
3171 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3172 if (AOP_ISHIGHREG(AOP(result),1)) {
3173 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3175 emitcode ("and", "%s,r25", aopGet (AOP (result), 1));
3177 emitcode ("or", "%s,r24", aopGet (AOP (result), 1));
3179 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3180 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3183 if (!lByteZ && !sameRegs (AOP (result), AOP (left))
3187 aopPut (AOP (result),
3188 aopGet (AOP (left), offset), offset);
3194 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3197 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3198 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3203 assert ("shifting generic pointer ?\n");
3206 /* 32 bits we do only byte boundaries */
3207 if (shCount >= 24) {
3208 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3209 aopPut (AOP (result), zero, 2);
3210 aopPut (AOP (result), zero, 1);
3211 aopPut (AOP (result), zero, 0);
3215 if (shCount >= 16) {
3216 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3217 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3218 aopPut (AOP (result), zero, 1);
3219 aopPut (AOP (result), zero, 0);
3224 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3225 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3226 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3227 aopPut (AOP (result), zero, 0);
3231 if (!lByteZ && !sameRegs (AOP (left), AOP (right))) {
3234 aopPut (AOP (result),
3235 aopGet (AOP (left), offset), offset);
3239 size = AOP_SIZE (result);
3245 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3246 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3247 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3248 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3253 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3254 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3255 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3260 emitcode ("lsl", "%s", aopGet (AOP (result), 2));
3261 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3266 emitcode ("lsl", "%s", aopGet (AOP (result), 3));
3274 freeAsmop (left, NULL, ic, TRUE);
3275 freeAsmop (right, NULL, ic, TRUE);
3276 freeAsmop (result, NULL, ic, TRUE);
3279 /*-----------------------------------------------------------------*/
3280 /* genLeftShift - generates code for left shifting */
3281 /*-----------------------------------------------------------------*/
3283 genLeftShift (iCode * ic)
3285 operand *left, *right, *result;
3289 right = IC_RIGHT (ic);
3290 left = IC_LEFT (ic);
3291 result = IC_RESULT (ic);
3293 aopOp (right, ic, FALSE);
3295 if (AOP_TYPE (right) == AOP_LIT) {
3296 genShiftLeftLit (ic);
3301 aopOp (left, ic, FALSE);
3302 aopOp (result, ic, FALSE);
3303 size = AOP_SIZE (result);
3305 if (AOP_SIZE (right) > 1) {
3306 if (isRegPair (AOP (right))) {
3307 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3310 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3311 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3315 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3317 if (!sameRegs (AOP (left), AOP (result))) {
3319 aopPut (AOP (result), aopGet (AOP (left), offset),
3323 size = AOP_SIZE (result);
3325 tlbl = newiTempLabel (NULL);
3326 emitcode ("", "L%05d:", tlbl->key);
3330 emitcode ("rol", "%s", aopGet (AOP (result), offset));
3332 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3335 if (AOP_SIZE (right) > 1)
3336 emitcode ("sbiw", "r24,1");
3338 emitcode ("dec", "r24");
3339 emitcode ("brne", "L%05d", tlbl->key);
3341 freeAsmop (left, NULL, ic, TRUE);
3342 freeAsmop (right, NULL, ic, TRUE);
3343 freeAsmop (result, NULL, ic, TRUE);
3346 /*-----------------------------------------------------------------*/
3347 /* genShiftRightLit - generate for right shift with known count */
3348 /*-----------------------------------------------------------------*/
3350 genShiftRightLit (iCode * ic)
3352 operand *left = IC_LEFT (ic)
3353 , *right = IC_RIGHT (ic)
3354 , *result = IC_RESULT (ic);
3355 int size, shCount, offset = 0;
3357 sym_link *letype = getSpec (operandType (left));
3358 int sign = !SPEC_USIGN (letype);
3360 right = IC_RIGHT (ic);
3361 left = IC_LEFT (ic);
3362 result = IC_RESULT (ic);
3364 aopOp (left, ic, FALSE);
3365 aopOp (result, ic, FALSE);
3366 size = AOP_SIZE (result);
3367 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3369 /* if signed then give up and use a loop to shift */
3372 if (!sameRegs (AOP (left), AOP (result))) {
3374 aopPut (AOP (result),
3375 aopGet (AOP (left), offset), offset);
3378 size = AOP_SIZE (result);
3381 /* be as economical as possible */
3384 size = AOP_SIZE (result);
3387 /* highest order byte */
3388 if (offset == (AOP_SIZE(result)-1))
3389 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3391 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3397 emitcode ("ldi", "r24,<(%d)", shCount);
3398 tlbl = newiTempLabel (NULL);
3399 emitcode ("", "L%05d:", tlbl->key);
3402 if (offset == (AOP_SIZE(result) - 1))
3403 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3405 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3408 emitcode ("dec", "r24");
3409 emitcode ("brne", "L%05d", tlbl->key);
3413 if (shCount > (size * 8 - 1)) {
3415 aopPut (AOP (result), zero, offset++);
3418 /* for unsigned we can much more efficient */
3421 if (!sameRegs (AOP (left), AOP (result)))
3422 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3424 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3425 if (AOP_ISHIGHREG(AOP(result),0)) {
3426 emitcode ("andi", "%s,0x0f",aopGet(AOP(result),0));
3428 emitcode ("ldi","r24,0x0f");
3429 emitcode ("and", "%s,r24",aopGet(AOP(result),0));
3434 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3437 if (shCount >= 12) {
3438 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3439 aopPut (AOP (result), zero, 1);
3440 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3441 if (AOP_ISHIGHREG(AOP(result),0)) {
3442 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3444 emitcode ("ldi","r24,0x0f");
3445 emitcode ("and", "%s,r24",aopGet(AOP(result),0));
3451 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3452 aopPut (AOP (result), zero, 1);
3458 if (!sameRegs (AOP (left), AOP (result))) {
3459 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3460 aopPut (AOP (result), aopGet (AOP (left), 1), 1);
3462 if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
3463 emitcode("ldi","r25,0x0f");
3465 emitcode ("mov", "r24,%s", aopGet (AOP (result), 1));
3466 emitcode ("andi", "r24,0xf0");
3467 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3468 if (AOP_ISHIGHREG(AOP(result),0)) {
3469 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3471 emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
3473 emitcode ("or", "%s,r24", aopGet (AOP (result), 0));
3474 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3475 if (AOP_ISHIGHREG(AOP(result),1)) {
3476 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 1));
3478 emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
3481 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3482 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3486 if (!hByteZ && !sameRegs (AOP (result), AOP (left))
3490 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3496 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3499 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3500 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3506 assert ("shifting generic pointer ?\n");
3509 /* 32 bits we do only byte boundaries */
3510 if (shCount >= 24) {
3511 aopPut (AOP (result), aopGet (AOP (left), 3), 0);
3512 aopPut (AOP (result), zero, 1);
3513 aopPut (AOP (result), zero, 2);
3514 aopPut (AOP (result), zero, 3);
3518 if (shCount >= 16) {
3519 aopPut (AOP (result), aopGet (AOP (left), 3), 1);
3520 aopPut (AOP (result), aopGet (AOP (left), 2), 0);
3521 aopPut (AOP (result), zero, 2);
3522 aopPut (AOP (result), zero, 3);
3527 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3528 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3529 aopPut (AOP (result), aopGet (AOP (left), 3), 2);
3530 aopPut (AOP (result), zero, 3);
3534 if (!hByteZ && !sameRegs (AOP (left), AOP (right))) {
3537 aopPut (AOP (result),
3538 aopGet (AOP (left), offset), offset);
3542 size = AOP_SIZE (result);
3548 emitcode ("lsr", "%s", aopGet (AOP (result), 3));
3549 emitcode ("ror", "%s", aopGet (AOP (result), 2));
3550 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3551 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3556 emitcode ("lsr", "%s", aopGet (AOP (result), 2));
3557 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3558 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3563 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3564 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3569 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3576 freeAsmop (left, NULL, ic, TRUE);
3577 freeAsmop (right, NULL, ic, TRUE);
3578 freeAsmop (result, NULL, ic, TRUE);
3581 /*-----------------------------------------------------------------*/
3582 /* genRightShift - generate code for right shifting */
3583 /*-----------------------------------------------------------------*/
3585 genRightShift (iCode * ic)
3587 operand *right, *left, *result;
3590 int sign = 0, first = 1;
3593 aopOp (right = IC_RIGHT (ic), ic, FALSE);
3595 if (AOP_TYPE (right) == AOP_LIT) {
3596 genShiftRightLit (ic);
3600 if (AOP_SIZE (right) > 1) {
3601 if (isRegPair (AOP (right))) {
3602 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3605 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3606 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3610 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3612 aopOp (left = IC_LEFT (ic), ic, FALSE);
3613 aopOp (result = IC_RESULT (ic), ic, FALSE);
3614 size = AOP_SIZE (result);
3615 tlbl = newiTempLabel (NULL);
3616 emitcode ("", "L%05d:", tlbl->key);
3618 letype = getSpec (operandType (left));
3619 sign = !SPEC_USIGN (letype);
3620 if (!sameRegs (AOP (left), AOP (result))) {
3622 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3625 size = AOP_SIZE (result);
3627 size = AOP_SIZE (result);
3631 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3633 emitcode ("lsr", "%s", aopGet (AOP (result), offset));
3637 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3640 if (AOP_SIZE (right) > 1)
3641 emitcode ("sbiw", "r24,1");
3643 emitcode ("dec", "r24");
3644 emitcode ("brne", "L%05d", tlbl->key);
3646 freeAsmop (left, NULL, ic, TRUE);
3647 freeAsmop (result, NULL, ic, TRUE);
3650 /*-----------------------------------------------------------------*/
3651 /* RRsh - shift right rn by known count */
3652 /*-----------------------------------------------------------------*/
3654 RRsh (int shCount,int reg)
3656 shCount &= 0x0007; // shCount : 0..7
3662 emitcode ("lsr", "r%d",reg);
3665 emitcode ("lsr", "r%d",reg);
3666 emitcode ("lsr", "r%d",reg);
3669 emitcode ("swap", "r%d",reg);
3670 emitcode ("lsl", "r%d",reg);
3673 emitcode ("swap", "r%d",reg);
3676 emitcode ("swap", "r%d",reg);
3677 emitcode ("lsr", "r%d",reg);
3680 emitcode ("swap","r%d",reg);
3681 emitcode ("lsr", "r%d",reg);
3682 emitcode ("lsr", "r%d",reg);
3685 emitcode ("swap","r%d",reg);
3686 emitcode ("lsr", "r%d",reg);
3687 emitcode ("lsr", "r%d",reg);
3688 emitcode ("lsr", "r%d",reg);
3693 /*-----------------------------------------------------------------*/
3694 /* RLsh - shift left rn by known count */
3695 /*-----------------------------------------------------------------*/
3697 RLsh (int shCount, int reg)
3699 shCount &= 0x0007; // shCount : 0..7
3705 emitcode ("lsl", "r%d",reg);
3708 emitcode ("lsl", "r%d",reg);
3709 emitcode ("lsl", "r%d",reg);
3712 emitcode ("swap","r%d",reg);
3713 emitcode ("lsr", "r%d",reg);
3716 emitcode ("swap", "r%d",reg);
3719 emitcode ("swap","r%d",reg);
3720 emitcode ("lsl", "r%d",reg);
3723 emitcode ("swap","r%d",reg);
3724 emitcode ("lsl", "r%d",reg);
3725 emitcode ("lsl", "r%d",reg);
3728 emitcode ("swap","r%d",reg);
3729 emitcode ("lsl", "r%d",reg);
3730 emitcode ("lsl", "r%d",reg);
3731 emitcode ("lsl", "r%d",reg);
3736 /*-----------------------------------------------------------------*/
3737 /* genUnpackBits - generates code for unpacking bits */
3738 /*-----------------------------------------------------------------*/
3740 genUnpackBits (operand * result, char *rname, int ptype)
3748 etype = getSpec (operandType (result));
3749 rsize = getSize (operandType (result));
3750 /* read the first byte */
3757 emitcode ("ld", "r24,%s+", rname);
3761 emitcode ("lpm", "r24,%s+", rname);
3765 emitcode ("call","__gptrget_pi");
3766 emitcode ("mov","r24,r0");
3770 rlen = SPEC_BLEN (etype);
3772 /* if we have bitdisplacement then it fits */
3773 /* into this byte completely or if length is */
3774 /* less than a byte */
3775 if ((shCnt = SPEC_BSTR (etype)) || (SPEC_BLEN (etype) <= 8)) {
3777 /* shift right acc */
3780 emitcode ("andi", "r24,lo(0x%x)",
3781 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
3782 aopPut (AOP (result), "r24", offset++);
3786 /* bit field did not fit in a byte */
3787 aopPut (AOP (result), "r24", offset++);
3797 emitcode ("ld", "r24,%s+");
3801 emitcode ("lpm", "r24,%s+");
3805 emitcode ("call", "__gptrget_pi");
3810 /* if we are done */
3814 aopPut (AOP (result), "r24", offset++);
3819 aopPut (AOP (result), "r24", offset++);
3823 if (offset < rsize) {
3826 aopPut (AOP (result), zero, offset++);
3831 /*-----------------------------------------------------------------*/
3832 /* genDataPointerGet - generates code when ptr offset is known */
3833 /*-----------------------------------------------------------------*/
3835 genDataPointerGet (operand * left, operand * result, iCode * ic)
3839 int size, offset = 0;
3840 aopOp (result, ic, TRUE);
3842 /* get the string representation of the name */
3843 l = aopGet (AOP (left), 0);
3844 size = AOP_SIZE (result);
3847 sprintf (buffer, "(%s + %d)", l, offset);
3849 sprintf (buffer, "%s", l);
3850 emitcode ("lds", "%s,%s", aopGet (AOP (result), offset++),
3854 freeAsmop (left, NULL, ic, TRUE);
3855 freeAsmop (result, NULL, ic, TRUE);
3858 /*-----------------------------------------------------------------*/
3859 /* genNearPointerGet - emitcode for near pointer fetch */
3860 /*-----------------------------------------------------------------*/
3862 genMemPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
3867 char *rname, *frname = NULL;
3868 sym_link *rtype, *retype;
3869 sym_link *ltype = operandType (left);
3871 rtype = operandType (result);
3872 retype = getSpec (rtype);
3874 aopOp (left, ic, FALSE);
3876 /* if left is rematerialisable and
3877 result is not bit variable type and
3878 the left is pointer to data space i.e
3879 lower 128 bytes of space */
3880 if (AOP_TYPE (left) == AOP_IMMD &&
3881 !IS_BITVAR (retype) && DCL_TYPE (ltype) == POINTER) {
3882 genDataPointerGet (left, result, ic);
3886 /* if the value is already in a pointer register
3887 then don't need anything more */
3888 if (!AOP_INPREG (AOP (left))) {
3889 /* otherwise get a free pointer register */
3891 preg = getFreePtr (ic, &aop, FALSE, 0);
3892 if (isRegPair (AOP (left) )) {
3893 emitcode ("movw", "%s,%s",
3894 aop->aopu.aop_ptr->name,
3895 aopGet(AOP(left),0));
3897 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
3898 aopGet (AOP (left), 0));
3899 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
3900 aopGet (AOP (left), 1));
3906 frname = aopGet(aop,0);
3910 } else if (AOP_ISZ(aop)) {
3913 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
3914 "pointer not in correct register");
3918 aopOp (result, ic, FALSE);
3920 /* if bitfield then unpack the bits */
3921 if (IS_BITVAR (retype))
3922 genUnpackBits (result, rname, POINTER);
3924 /* we have can just get the values */
3925 int size = AOP_SIZE (result);
3930 emitcode ("ld","%s,%s+",aopGet(AOP(result),offset), rname);
3932 emitcode ("ld","%s,%s",aopGet(AOP(result),offset), rname);
3937 /* now some housekeeping stuff */
3939 /* we had to allocate for this iCode */
3941 if (isRegPair (AOP (left) )) {
3942 emitcode ("movw", "%s,%s",
3943 aopGet (AOP(left),0),
3944 aop->aopu.aop_ptr->name);
3946 emitcode ("mov", "%s,%s",
3947 aopGet (AOP (left), 0),
3948 aop->aopu.aop_ptr->name);
3949 emitcode ("mov", "%s,%s",
3950 aopGet (AOP (left), 1),
3951 aop->aop_ptr2->name);
3954 freeAsmop (NULL, aop, ic, TRUE);
3957 /* we did not allocate which means left
3958 already in a pointer register, then
3959 if size > 0 && this could be used again
3960 we have to point it back to where it
3962 if ((AOP_SIZE (result) > 1 &&
3963 !OP_SYMBOL (left)->remat &&
3964 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) && !pi) {
3965 int size = AOP_SIZE (result) - 1;
3966 emitcode ("sbiw", "%s,%d",frname,size);
3971 if (pi) pi->generated = 1;
3972 freeAsmop (left, NULL, ic, TRUE);
3973 freeAsmop (result, NULL, ic, TRUE);
3977 /*-----------------------------------------------------------------*/
3978 /* genCodePointerGet - gget value from code space */
3979 /*-----------------------------------------------------------------*/
3981 genCodePointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
3984 sym_link *retype = getSpec (operandType (result));
3988 aopOp (left, ic, FALSE);
3990 /* if the operand is already in Z register
3991 then we do nothing else we move the value to Z register */
3992 if (AOP_ISZ(AOP(left))) {
3996 getFreePtr(ic,&aop,FALSE,TRUE);
3997 if (isRegPair(AOP (left))) {
3998 emitcode ("movw","r30,%s",aopGet (AOP (left), 0));
4000 emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
4001 emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
4006 aopOp (result, ic, FALSE);
4008 /* if bit then unpack */
4009 if (IS_BITVAR (retype))
4010 genUnpackBits (result, "Z", CPOINTER);
4012 size = AOP_SIZE (result);
4017 emitcode ("lpm","%s,Z+",aopGet(AOP(result),offset++));
4019 emitcode ("lpm","%s,Z",aopGet(AOP(result),offset++));
4024 /* now some housekeeping stuff */
4026 /* we had to allocate for this iCode */
4028 if (isRegPair(AOP (left))) {
4029 emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
4031 emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
4032 emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
4035 freeAsmop (NULL, aop, ic, TRUE);
4038 /* we did not allocate which means left
4039 already in a pointer register, then
4040 if size > 0 && this could be used again
4041 we have to point it back to where it
4043 if ((AOP_SIZE (result) > 1 &&
4044 !OP_SYMBOL (left)->remat &&
4045 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) &&
4047 int size = AOP_SIZE (result) - 1;
4048 emitcode ("sbiw", "r30,%d",size);
4053 if (pi) pi->generated=1;
4054 freeAsmop (left, NULL, ic, TRUE);
4055 freeAsmop (result, NULL, ic, TRUE);
4059 /*-----------------------------------------------------------------*/
4060 /* genGenPointerGet - gget value from generic pointer space */
4061 /*-----------------------------------------------------------------*/
4063 genGenPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
4067 sym_link *retype = getSpec (operandType (result));
4070 aopOp (left, ic, FALSE);
4072 /* if the operand is already in dptr
4073 then we do nothing else we move the value to dptr */
4074 if (AOP_ISZ(AOP(left))) {
4078 getFreePtr(ic,&aop,FALSE,TRUE);
4079 if (isRegPair(AOP(left))) {
4080 emitcode ("movw", "r30,%s", aopGet (AOP (left), 0));
4082 emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
4083 emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
4085 emitcode ("mov", "r24,%s", aopGet (AOP (left), 2));
4089 /* so Z register now contains the address */
4091 aopOp (result, ic, FALSE);
4093 /* if bit then unpack */
4094 if (IS_BITVAR (retype))
4095 genUnpackBits (result, "Z", GPOINTER);
4097 size = AOP_SIZE (result);
4102 emitcode ("call", "__gptrget_pi");
4104 emitcode ("call", "__gptrget");
4105 aopPut (AOP (result), "r0", offset++);
4110 /* now some housekeeping stuff */
4112 /* we had to allocate for this iCode */
4114 if (isRegPair(AOP (left))) {
4115 emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
4117 emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
4118 emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
4121 freeAsmop (NULL, aop, ic, TRUE);
4124 /* we did not allocate which means left
4125 already in a pointer register, then
4126 if size > 0 && this could be used again
4127 we have to point it back to where it
4129 if ((AOP_SIZE (result) > 1 &&
4130 !OP_SYMBOL (left)->remat &&
4131 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) &&
4133 int size = AOP_SIZE (result) - 1;
4134 emitcode ("sbiw", "r30,%d",size);
4137 if (pi) pi->generated=1;
4138 freeAsmop (left, NULL, ic, TRUE);
4139 freeAsmop (result, NULL, ic, TRUE);
4142 /*-----------------------------------------------------------------*/
4143 /* genPointerGet - generate code for pointer get */
4144 /*-----------------------------------------------------------------*/
4146 genPointerGet (iCode * ic, iCode *pi)
4148 operand *left, *result;
4149 sym_link *type, *etype;
4152 left = IC_LEFT (ic);
4153 result = IC_RESULT (ic);
4155 /* depending on the type of pointer we need to
4156 move it to the correct pointer register */
4157 type = operandType (left);
4158 etype = getSpec (type);
4159 /* if left is of type of pointer then it is simple */
4160 if (IS_PTR (type) && !IS_FUNC (type->next))
4161 p_type = DCL_TYPE (type);
4163 /* we have to go by the storage class */
4164 p_type = PTR_TYPE (SPEC_OCLS (etype));
4169 /* now that we have the pointer type we assign
4170 the pointer values */
4177 genMemPointerGet (left, result, ic, pi);
4181 genCodePointerGet (left, result, ic, pi);
4185 genGenPointerGet (left, result, ic, pi);
4191 /*-----------------------------------------------------------------*/
4192 /* genPackBits - generates code for packed bit storage */
4193 /*-----------------------------------------------------------------*/
4195 genPackBits (sym_link * etype,
4197 char *rname, int p_type)
4205 blen = SPEC_BLEN (etype);
4206 bstr = SPEC_BSTR (etype);
4208 l = aopGet (AOP (right), offset++);
4211 /* if the bit lenth is less than or */
4212 /* it exactly fits a byte then */
4213 if (SPEC_BLEN (etype) <= 8) {
4214 shCount = SPEC_BSTR (etype);
4216 /* shift left acc */
4219 if (SPEC_BLEN (etype) < 8) { /* if smaller than a byte */
4226 emitcode ("ld", "r1,%s",rname);
4230 emitcode ("push", "r1");
4231 emitcode ("push", "r24");
4232 emitcode ("call", "__gptrget");
4233 emitcode ("pop", "r1");
4234 emitcode ("mov","r24,r0");
4238 emitcode ("andi", "r24,#0x%02x", (unsigned char)
4239 ((unsigned char) (0xFF << (blen + bstr)) |
4240 (unsigned char) (0xFF >> (8 - bstr))));
4241 emitcode ("or", "r24,r1");
4242 if (p_type == GPOINTER)
4243 emitcode ("pop", "r1");
4252 emitcode("st","%s+,r24");
4256 emitcode("mov","r0,r24");
4257 emitcode ("call", "__gptrput_pi");
4262 if (SPEC_BLEN (etype) <= 8)
4265 rLen = SPEC_BLEN (etype);
4267 /* now generate for lengths greater than one byte */
4270 l = aopGet (AOP (right), offset++);
4281 emitcode ("st", "%s+,%s",rname,l);
4286 emitcode ("lcall", "__gptrput_pi");
4293 /* last last was not complete */
4295 /* save the byte & read byte */
4301 emitcode ("st","%s+,r24",rname);
4304 emitcode ("push", "r1");
4305 emitcode ("push", "r24");
4306 emitcode ("lcall", "__gptrget");
4307 emitcode ("mov","r24,r0");
4308 emitcode ("pop", "r1");
4312 emitcode ("andi", "r24,0x%02x", (((unsigned char) -1 << rLen) & 0xff));
4313 emitcode ("or", "r24,r1");
4316 if (p_type == GPOINTER)
4317 emitcode ("pop", "r1");
4325 emitcode ("st", "%s,r24", rname);
4329 emitcode ("mov","r0,r24");
4330 emitcode ("call", "__gptrput");
4335 /*-----------------------------------------------------------------*/
4336 /* genDataPointerSet - remat pointer to data space */
4337 /*-----------------------------------------------------------------*/
4339 genDataPointerSet (operand * right, operand * result, iCode * ic)
4341 int size, offset = 0;
4342 char *l, buffer[256];
4344 aopOp (right, ic, FALSE);
4346 l = aopGet (AOP (result), 0);
4347 size = AOP_SIZE (right);
4350 sprintf (buffer, "(%s + %d)", l, offset);
4352 sprintf (buffer, "%s", l);
4353 emitcode ("sts", "%s,%s", buffer,
4354 aopGet (AOP (right), offset++));
4357 freeAsmop (right, NULL, ic, TRUE);
4358 freeAsmop (result, NULL, ic, TRUE);
4361 /*-----------------------------------------------------------------*/
4362 /* genNearPointerSet - emitcode for near pointer put */
4363 /*-----------------------------------------------------------------*/
4365 genMemPointerSet (operand * right, operand * result, iCode * ic, iCode *pi)
4368 char *frname = NULL, *rname, *l;
4371 sym_link *ptype = operandType (result);
4373 retype = getSpec (operandType (right));
4375 aopOp (result, ic, FALSE);
4377 /* if the result is rematerializable &
4378 in data space & not a bit variable */
4379 if (AOP_TYPE (result) == AOP_IMMD &&
4380 DCL_TYPE (ptype) == POINTER && !IS_BITVAR (retype)) {
4381 genDataPointerSet (right, result, ic);
4384 if (!AOP_INPREG(AOP(result))) {
4385 /* otherwise get a free pointer register */
4387 getFreePtr (ic, &aop, FALSE, 0);
4388 if (isRegPair (AOP (result) )) {
4389 emitcode ("movw", "%s,%s",aop->aopu.aop_ptr->name,
4390 aopGet(AOP (result), 0));
4392 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
4393 aopGet (AOP (result), 0));
4394 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
4395 aopGet (AOP (result), 1));
4400 frname = aopGet(aop,0);
4403 aopOp (right, ic, FALSE);
4406 } else if (AOP_ISZ(aop)) {
4409 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4410 "pointer not in correct register");
4413 /* if bitfield then unpack the bits */
4414 if (IS_BITVAR (retype))
4415 genPackBits (retype, right, rname, POINTER);
4417 /* we have can just get the values */
4418 int size = AOP_SIZE (right);
4422 l = aopGet (AOP (right), offset);
4424 emitcode ("st", "%s+,%s", rname,l);
4426 emitcode ("st", "%s,%s", rname,l);
4431 /* now some housekeeping stuff */
4433 /* we had to allocate for this iCode */
4435 if (isRegPair (AOP (result) )) {
4436 emitcode ("movw", "%s,%s",
4437 aopGet(AOP(result),0),
4438 aop->aopu.aop_ptr->name);
4440 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
4441 aopGet (AOP (result), 0));
4442 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
4443 aopGet (AOP (result), 1));
4446 freeAsmop (NULL, aop, ic, TRUE);
4449 /* we did not allocate which means left
4450 already in a pointer register, then
4451 if size > 0 && this could be used again
4452 we have to point it back to where it
4454 if ((AOP_SIZE (right) > 1 &&
4455 !OP_SYMBOL (result)->remat &&
4456 (OP_SYMBOL (right)->liveTo > ic->seq || ic->depth)) && !pi) {
4457 int size = AOP_SIZE (right) - 1;
4458 emitcode ("sbiw", "%s,%d",frname,size);
4463 if (pi) pi->generated = 1;
4464 freeAsmop (result, NULL, ic, TRUE);
4465 freeAsmop (right, NULL, ic, TRUE);
4468 /*-----------------------------------------------------------------*/
4469 /* genGenPointerSet - set value from generic pointer space */
4470 /*-----------------------------------------------------------------*/
4472 genGenPointerSet (operand * right, operand * result, iCode * ic, iCode *pi)
4476 sym_link *retype = getSpec (operandType (right));
4479 aopOp (result, ic, FALSE);
4481 /* if the operand is already in dptr
4482 then we do nothing else we move the value to dptr */
4483 if (AOP_ISZ(AOP(result))) {
4487 getFreePtr(ic,&aop,FALSE,TRUE);
4488 if (isRegPair(AOP(result))) {
4489 emitcode ("movw", "r30,%s", aopGet (AOP (result), 0));
4491 emitcode ("mov", "r30,%s", aopGet (AOP (result), 0));
4492 emitcode ("mov", "r31,%s", aopGet (AOP (result), 1));
4494 emitcode ("mov", "r24,%s", aopGet (AOP (result), 2));
4498 /* so Z register now contains the address */
4499 aopOp (right, ic, FALSE);
4501 /* if bit then unpack */
4502 if (IS_BITVAR (retype))
4503 genUnpackBits (result, "Z", GPOINTER);
4505 size = AOP_SIZE (right);
4509 char *l = aopGet(AOP (right), offset++);
4513 emitcode ("call", "__gptrput_pi");
4515 emitcode ("call", "__gptrput");
4519 /* now some housekeeping stuff */
4521 /* we had to allocate for this iCode */
4523 if (isRegPair(AOP(result))) {
4524 emitcode ("movw", "%s,r30", aopGet (AOP (result), 0));
4526 emitcode ("mov", "%s,r30", aopGet (AOP (result), 0));
4527 emitcode ("mov", "%s,r31", aopGet (AOP (result), 1));
4530 freeAsmop (NULL, aop, ic, TRUE);
4533 /* we did not allocate which means left
4534 already in a pointer register, then
4535 if size > 0 && this could be used again
4536 we have to point it back to where it
4538 if ((AOP_SIZE (right) > 1 &&
4539 !OP_SYMBOL (result)->remat &&
4540 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) && !pi) {
4541 int size = AOP_SIZE (right) - 1;
4542 emitcode ("sbiw", "r30,%d",size);
4545 if (pi) pi->generated = 1;
4546 freeAsmop (right, NULL, ic, TRUE);
4547 freeAsmop (result, NULL, ic, TRUE);
4550 /*-----------------------------------------------------------------*/
4551 /* genPointerSet - stores the value into a pointer location */
4552 /*-----------------------------------------------------------------*/
4554 genPointerSet (iCode * ic, iCode *pi)
4556 operand *right, *result;
4557 sym_link *type, *etype;
4560 right = IC_RIGHT (ic);
4561 result = IC_RESULT (ic);
4563 /* depending on the type of pointer we need to
4564 move it to the correct pointer register */
4565 type = operandType (result);
4566 etype = getSpec (type);
4567 /* if left is of type of pointer then it is simple */
4568 if (IS_PTR (type) && !IS_FUNC (type->next)) {
4569 p_type = DCL_TYPE (type);
4572 /* we have to go by the storage class */
4573 p_type = PTR_TYPE (SPEC_OCLS (etype));
4577 /* now that we have the pointer type we assign
4578 the pointer values */
4585 genMemPointerSet (right, result, ic, pi);
4589 genGenPointerSet (right, result, ic, pi);
4593 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4594 "genPointerSet: illegal pointer type");
4599 /*-----------------------------------------------------------------*/
4600 /* genIfx - generate code for Ifx statement */
4601 /*-----------------------------------------------------------------*/
4603 genIfx (iCode * ic, iCode * popIc)
4605 operand *cond = IC_COND (ic);
4610 aopOp (cond, ic, FALSE);
4612 /* get the value into acc */
4613 if (AOP_SIZE(cond) == 1 && AOP_ISHIGHREG(AOP(cond),0)) {
4614 cname = aopGet(AOP(cond),0);
4616 toBoolean (cond, "r24", 0);
4620 /* the result is now in the accumulator */
4621 freeAsmop (cond, NULL, ic, TRUE);
4623 /* if there was something to be popped then do it */
4626 emitcode("cpi","%s,0",cname);
4627 } else if (!tob) emitcode("cpi","%s,0",cname);
4629 lbl = newiTempLabel(NULL);
4631 emitcode ("breq","L%05d",lbl->key);
4632 emitcode ("jmp","L%05d",IC_TRUE(ic)->key);
4633 emitcode ("","L%05d:",lbl->key);
4635 emitcode ("brne","L%05d",lbl->key);
4636 emitcode ("jmp","L%05d",IC_FALSE(ic)->key);
4637 emitcode ("","L%05d:",lbl->key);
4642 /*-----------------------------------------------------------------*/
4643 /* genAddrOf - generates code for address of */
4644 /*-----------------------------------------------------------------*/
4646 genAddrOf (iCode * ic)
4648 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
4651 aopOp (IC_RESULT (ic), ic, FALSE);
4652 assert(AOP_SIZE(IC_RESULT(ic)) >= 2);
4653 /* if the operand is on the stack then we
4654 need to get the stack offset of this
4657 /* if it has an offset then we need to compute it */
4659 if (allHigh(AOP(IC_RESULT(ic)))) {
4660 if (isRegPair (AOP(IC_RESULT(ic)))) {
4661 emitcode ("movw","%s,r28",aopGet(AOP(IC_RESULT(ic)),0));
4663 emitcode ("mov","%s,r28",aopGet(AOP(IC_RESULT(ic)),0));
4664 emitcode ("mov","%s,r29",aopGet(AOP(IC_RESULT(ic)),1));
4666 if (sym->stack < 0) {
4667 emitcode("subi","%s,<(%d)",aopGet(AOP(IC_RESULT(ic)),0),-sym->stack);
4668 emitcode("sbci","%s,>(%d)",aopGet(AOP(IC_RESULT(ic)),1),-sym->stack);
4670 emitcode("subi","%s,<(-%d)",aopGet(AOP(IC_RESULT(ic)),0),sym->stack);
4671 emitcode("sbci","%s,>(-%d)",aopGet(AOP(IC_RESULT(ic)),1),sym->stack);
4674 emitcode("movw","r24,r28");
4675 if (sym->stack > -63 && sym->stack < 63) {
4677 emitcode("sbiw","r24,%d",-sym->stack);
4679 emitcode("sbiw","r24,%d",sym->stack);
4681 if (sym->stack < 0) {
4682 emitcode("subi","r24,<(%d)",-sym->stack);
4683 emitcode("sbci","r25,>(%d)",-sym->stack);
4685 emitcode("subi","r24,<(-%d)",sym->stack);
4686 emitcode("sbci","r25,>(-%d)",sym->stack);
4690 aopPut(AOP(IC_RESULT(ic)),"r24",0);
4691 aopPut(AOP(IC_RESULT(ic)),"r25",1);
4695 aopPut(AOP(IC_RESULT(ic)),"r28",0);
4696 aopPut(AOP(IC_RESULT(ic)),"r29",1);
4698 /* fill the result with zero */
4699 size = AOP_SIZE (IC_RESULT (ic)) - 2;
4702 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
4708 /* object not on stack then we need the name */
4709 size = AOP_SIZE (IC_RESULT (ic));
4713 char s[SDCC_NAME_MAX];
4715 sprintf (s, ">(%s)", sym->rname);
4717 sprintf (s, "<(%s)", sym->rname);
4718 aopPut (AOP (IC_RESULT (ic)), s, offset++);
4722 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4726 /*-----------------------------------------------------------------*/
4727 /* genFarFarAssign - assignment when both are in far space */
4728 /*-----------------------------------------------------------------*/
4730 genFarFarAssign (operand * result, operand * right, iCode * ic)
4732 int size = AOP_SIZE (right);
4735 /* first push the right side on to the stack */
4737 l = aopGet (AOP (right), offset++);
4739 emitcode ("push", "acc");
4742 freeAsmop (right, NULL, ic, FALSE);
4743 /* now assign DPTR to result */
4744 aopOp (result, ic, FALSE);
4745 size = AOP_SIZE (result);
4747 emitcode ("pop", "acc");
4748 aopPut (AOP (result), "a", --offset);
4750 freeAsmop (result, NULL, ic, FALSE);
4754 /*-----------------------------------------------------------------*/
4755 /* genAssign - generate code for assignment */
4756 /*-----------------------------------------------------------------*/
4758 genAssign (iCode * ic)
4760 operand *result, *right;
4762 unsigned long lit = 0L;
4764 result = IC_RESULT (ic);
4765 right = IC_RIGHT (ic);
4767 /* if they are the same */
4768 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4771 aopOp (right, ic, FALSE);
4773 /* special case both in far space */
4774 if (AOP_TYPE (right) == AOP_DPTR &&
4775 IS_TRUE_SYMOP (result) && isOperandInFarSpace (result)) {
4777 genFarFarAssign (result, right, ic);
4781 aopOp (result, ic, TRUE);
4783 /* if they are the same registers */
4784 if (sameRegs (AOP (right), AOP (result)))
4787 /* if the result is a bit */
4788 if (AOP_TYPE (result) == AOP_CRY) {
4790 /* if the right size is a literal then
4791 we know what the value is */
4792 if (AOP_TYPE (right) == AOP_LIT) {
4793 if (((int) operandLitValue (right)))
4794 aopPut (AOP (result), one, 0);
4796 aopPut (AOP (result), zero, 0);
4800 /* the right is also a bit variable */
4801 if (AOP_TYPE (right) == AOP_CRY) {
4802 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4803 aopPut (AOP (result), "c", 0);
4808 toBoolean (right, "", 0);
4809 aopPut (AOP (result), "a", 0);
4813 /* bit variables done */
4815 size = AOP_SIZE (result);
4817 if (AOP_TYPE (right) == AOP_LIT)
4819 (unsigned long) floatFromVal (AOP (right)->aopu.
4821 if ((size > 1) && (AOP_TYPE (result) != AOP_REG)
4822 && (AOP_TYPE (right) == AOP_LIT)
4823 && !IS_FLOAT (operandType (right)) && (lit < 256L)) {
4824 emitcode ("clr", "a");
4826 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) ==
4827 0) aopPut (AOP (result), "a", size);
4829 aopPut (AOP (result),
4830 aopGet (AOP (right), size), size);
4835 aopPut (AOP (result),
4836 aopGet (AOP (right), offset), offset);
4842 freeAsmop (right, NULL, ic, FALSE);
4843 freeAsmop (result, NULL, ic, TRUE);
4846 /*-----------------------------------------------------------------*/
4847 /* genJumpTab - genrates code for jump table */
4848 /*-----------------------------------------------------------------*/
4850 genJumpTab (iCode * ic)
4855 aopOp (IC_JTCOND (ic), ic, FALSE);
4856 /* get the condition into accumulator */
4857 l = aopGet (AOP (IC_JTCOND (ic)), 0);
4859 /* multiply by three */
4860 emitcode ("add", "a,acc");
4861 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0));
4862 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
4864 jtab = newiTempLabel (NULL);
4865 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
4866 emitcode ("jmp", "@a+dptr");
4867 emitcode ("", "%05d$:", jtab->key + 100);
4868 /* now generate the jump labels */
4869 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
4870 jtab = setNextItem (IC_JTLABELS (ic)))
4871 emitcode ("ljmp", "%05d$", jtab->key + 100);
4875 /*-----------------------------------------------------------------*/
4876 /* genCast - gen code for casting */
4877 /*-----------------------------------------------------------------*/
4879 genCast (iCode * ic)
4881 operand *result = IC_RESULT (ic);
4882 sym_link *ctype = operandType (IC_LEFT (ic));
4883 sym_link *rtype = operandType (IC_RIGHT (ic));
4884 operand *right = IC_RIGHT (ic);
4887 /* if they are equivalent then do nothing */
4888 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4891 aopOp (right, ic, FALSE);
4892 aopOp (result, ic, FALSE);
4894 /* if the result is a bit */
4895 if (AOP_TYPE (result) == AOP_CRY) {
4896 /* if the right size is a literal then
4897 we know what the value is */
4898 if (AOP_TYPE (right) == AOP_LIT) {
4899 if (((int) operandLitValue (right)))
4900 aopPut (AOP (result), one, 0);
4902 aopPut (AOP (result), zero, 0);
4907 /* the right is also a bit variable */
4908 if (AOP_TYPE (right) == AOP_CRY) {
4909 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4910 aopPut (AOP (result), "c", 0);
4915 toBoolean (right, "", 0);
4916 aopPut (AOP (result), "a", 0);
4920 /* if they are the same size : or less */
4921 if (AOP_SIZE (result) <= AOP_SIZE (right)) {
4923 /* if they are in the same place */
4924 if (sameRegs (AOP (right), AOP (result)))
4927 /* if they in different places then copy */
4928 size = AOP_SIZE (result);
4931 aopPut (AOP (result),
4932 aopGet (AOP (right), offset), offset);
4939 /* if the result is of type pointer */
4940 if (IS_PTR (ctype)) {
4943 sym_link *type = operandType (right);
4944 sym_link *etype = getSpec (type);
4946 /* pointer to generic pointer */
4947 if (IS_GENPTR (ctype)) {
4951 p_type = DCL_TYPE (type);
4953 /* we have to go by the storage class */
4954 p_type = PTR_TYPE (SPEC_OCLS (etype));
4957 /* the first two bytes are known */
4958 size = GPTRSIZE - 1;
4961 aopPut (AOP (result),
4962 aopGet (AOP (right), offset), offset);
4965 /* the last byte depending on type */
4982 /* this should never happen */
4983 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4984 "got unknown pointer type");
4987 aopPut (AOP (result), l, GPTRSIZE - 1);
4991 /* just copy the pointers */
4992 size = AOP_SIZE (result);
4995 aopPut (AOP (result),
4996 aopGet (AOP (right), offset), offset);
5002 /* so we now know that the size of destination is greater
5003 than the size of the source */
5004 /* we move to result for the size of source */
5005 size = AOP_SIZE (right);
5008 aopPut (AOP (result), aopGet (AOP (right), offset), offset);
5012 /* now depending on the sign of the source && destination */
5013 size = AOP_SIZE (result) - AOP_SIZE (right);
5014 /* if unsigned or not an integral type */
5015 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype)) {
5017 aopPut (AOP (result), zero, offset++);
5020 /* we need to extend the sign :{ */
5021 // PENDING: Does nothing on avr
5023 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1);
5026 emitcode ("rlc", "a");
5027 emitcode ("subb", "a,acc");
5029 aopPut (AOP (result), "a", offset++);
5032 /* we are done hurray !!!! */
5035 freeAsmop (right, NULL, ic, TRUE);
5036 freeAsmop (result, NULL, ic, TRUE);
5040 /*-----------------------------------------------------------------*/
5041 /* genDjnz - generate decrement & jump if not zero instrucion */
5042 /*-----------------------------------------------------------------*/
5044 genDjnz (iCode * ic, iCode * ifx)
5050 /* if the if condition has a false label
5051 then we cannot save */
5055 /* if the minus is not of the form
5057 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
5058 !IS_OP_LITERAL (IC_RIGHT (ic)))
5061 if (operandLitValue (IC_RIGHT (ic)) != 1)
5064 /* if the size of this greater than one then no
5066 if (getSize (operandType (IC_RESULT (ic))) > 1)
5069 /* otherwise we can save BIG */
5070 lbl = newiTempLabel (NULL);
5071 lbl1 = newiTempLabel (NULL);
5073 aopOp (IC_RESULT (ic), ic, FALSE);
5075 if (IS_AOP_PREG (IC_RESULT (ic))) {
5076 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0));
5077 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0));
5078 emitcode ("jnz", "%05d$", lbl->key + 100);
5081 emitcode ("djnz", "%s,%05d$",
5082 aopGet (AOP (IC_RESULT (ic)), 0), lbl->key + 100);
5084 emitcode ("sjmp", "%05d$", lbl1->key + 100);
5085 emitcode ("", "%05d$:", lbl->key + 100);
5086 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5087 emitcode ("", "%05d$:", lbl1->key + 100);
5089 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5094 static char *recvregs[8] = {
5095 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23"
5098 static int recvCnt = 0;
5100 /*-----------------------------------------------------------------*/
5101 /* genReceive - generate code for a receive iCode */
5102 /*-----------------------------------------------------------------*/
5104 genReceive (iCode * ic)
5106 int size, offset = 0;
5107 aopOp (IC_RESULT (ic), ic, FALSE);
5108 size = AOP_SIZE (IC_RESULT (ic));
5110 aopPut (AOP (IC_RESULT (ic)), recvregs[recvCnt++], offset);
5113 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5116 /*-----------------------------------------------------------------*/
5117 /* gen51Code - generate code for 8051 based controllers */
5118 /*-----------------------------------------------------------------*/
5120 genAVRCode (iCode * lic)
5125 lineHead = lineCurr = NULL;
5127 /* print the allocation information */
5129 printAllocInfo (currFunc, codeOutFile);
5130 /* if debug information required */
5131 /* if (options.debug && currFunc) { */
5133 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
5135 /* emitcode ("", ".type %s,@function", currFunc->name); */
5138 /* stack pointer name */
5142 for (ic = lic; ic; ic = ic->next) {
5144 if (cln != ic->lineno) {
5145 if (options.debug) {
5147 emitcode ("", "C$%s$%d$%d$%d ==.",
5148 FileBaseName (ic->filename),
5149 ic->lineno, ic->level, ic->block);
5152 emitcode (";", "%s %d", ic->filename, ic->lineno);
5155 /* if the result is marked as
5156 spilt and rematerializable or code for
5157 this has already been generated then
5159 if (resultRemat (ic) || ic->generated)
5162 /* depending on the operation */
5181 /* IPOP happens only when trying to restore a
5182 spilt live range, if there is an ifx statement
5183 following this pop then the if statement might
5184 be using some of the registers being popped which
5185 would destory the contents of the register so
5186 we need to check for this condition and handle it */
5188 ic->next->op == IFX &&
5189 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
5190 genIfx (ic->next, ic);
5208 genEndFunction (ic);
5228 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
5245 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
5249 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
5253 genCmpLe (ic, ifxForOp (IC_RESULT (ic), ic));
5257 genCmpGe (ic, ifxForOp (IC_RESULT (ic), ic));
5261 genCmpNe (ic, ifxForOp (IC_RESULT (ic), ic));
5265 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
5277 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
5281 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
5285 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
5312 case GET_VALUE_AT_ADDRESS:
5313 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
5317 if (POINTER_SET (ic))
5318 genPointerSet (ic, hasInc(IC_RESULT(ic),ic));
5344 addSet (&_G.sendSet, ic);
5353 /* now we are ready to call the
5354 peep hole optimizer */
5355 if (!options.nopeep)
5356 peepHole (&lineHead);
5358 /* now do the actual printing */
5359 printLine (lineHead, codeOutFile);