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>
40 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
41 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
42 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
48 #include "SDCCpeeph.h"
52 char *aopLiteral (value * val, int offset);
55 /* this is the down and dirty file with all kinds of
56 kludgy & hacky stuff. This is what it is all about
57 CODE GENERATION for a specific MCU . some of the
58 routines may be reusable, will have to see */
60 static char *zero = "0x00";
61 static char *one = "0x01";
64 char *fReturnAVR[] = { "r16", "r17", "r18", "r19" };
65 unsigned fAVRReturnSize = 4; /* shared with ralloc.c */
66 char **fAVRReturn = fReturnAVR;
67 static char *larray[4] = { "lo8", "hi8", "hlo8", "hhi8" };
71 static short rbank = -1;
72 static char *tscr[4] = { "r0", "r1", "r24", "r25" };
73 static unsigned char SLMask[] = { 0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
74 0xE0, 0xC0, 0x80, 0x00
76 static unsigned char SRMask[] = { 0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
77 0x07, 0x03, 0x01, 0x00
92 extern int avr_ptrRegReq;
94 extern FILE *codeOutFile;
95 #define RESULTONSTACK(x) \
96 (IC_RESULT(x) && IC_RESULT(x)->aop && \
97 IC_RESULT(x)->aop->type == AOP_STK )
99 #define MOVR0(x) if (strcmp(x,"r0")) emitcode("mov","r0,%s",x);
100 #define MOVR24(x) if (strcmp(x,"r24")) emitcode("mov","r24,%s",x);
101 #define AOP_ISHIGHREG(a,n) (a->type == AOP_REG && a->aopu.aop_reg[n] && a->aopu.aop_reg[n]->rIdx >= R16_IDX)
102 #define CLRC emitcode("clc","")
103 #define SETC emitcode("stc","")
105 #define IS_REGIDX(a,r) (a->type == AOP_REG && a->aopu.aop_reg[0]->rIdx == r)
107 static lineNode *lineHead = NULL;
108 static lineNode *lineCurr = NULL;
117 /*-----------------------------------------------------------------*/
118 /* reAdjustPreg - points a register back to where it should */
119 /*-----------------------------------------------------------------*/
121 reAdjustPreg (asmop * aop)
126 if ((size = aop->size) <= 1)
132 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name, size);
138 /*-----------------------------------------------------------------*/
139 /* outBitC - output a bit C */
140 /*-----------------------------------------------------------------*/
142 outBitC (operand * result)
144 emitcode ("clr", "r0");
145 emitcode ("rol", "r0");
149 /*-----------------------------------------------------------------*/
150 /* inExcludeList - return 1 if the string is in exclude Reg list */
151 /*-----------------------------------------------------------------*/
153 inExcludeList (char *s)
157 if (options.excludeRegs[i] &&
158 STRCASECMP (options.excludeRegs[i], "none") == 0)
161 for (i = 0; options.excludeRegs[i]; i++) {
162 if (options.excludeRegs[i] &&
163 STRCASECMP (s, options.excludeRegs[i]) == 0)
169 /*-----------------------------------------------------------------*/
170 /* findLabelBackwards: walks back through the iCode chain looking */
171 /* for the given label. Returns number of iCode instructions */
172 /* between that label and given ic. */
173 /* Returns zero if label not found. */
174 /*-----------------------------------------------------------------*/
176 findLabelBackwards (iCode * ic, int key)
184 if (ic->op == LABEL && IC_LABEL (ic)->key == key) {
185 /* printf("findLabelBackwards = %d\n", count); */
193 /*-----------------------------------------------------------------*/
194 /* addSign - complete with sign */
195 /*-----------------------------------------------------------------*/
197 addSign (operand * result, int offset, int sign)
199 int size = (getDataSize (result) - offset);
202 emitcode ("rlc", "a");
203 emitcode ("subb", "a,acc");
205 aopPut (AOP (result), "a", offset++);
209 aopPut (AOP (result), zero, offset++);
213 /*-----------------------------------------------------------------*/
214 /* isLiteralBit - test if lit == 2^n */
215 /*-----------------------------------------------------------------*/
217 isLiteralBit (unsigned long lit)
219 unsigned long pw[32] = { 1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
220 0x100L, 0x200L, 0x400L, 0x800L,
221 0x1000L, 0x2000L, 0x4000L, 0x8000L,
222 0x10000L, 0x20000L, 0x40000L, 0x80000L,
223 0x100000L, 0x200000L, 0x400000L, 0x800000L,
224 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
225 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L
229 for (idx = 0; idx < 32; idx++)
234 #endif // End Unused code section
236 /*-----------------------------------------------------------------*/
237 /* emitcode - writes the code into a file : for now it is simple */
238 /*-----------------------------------------------------------------*/
240 emitcode (char *inst, char *fmt, ...)
243 char lb[INITIAL_INLINEASM];
250 sprintf (lb, "%s\t", inst);
252 sprintf (lb, "%s", inst);
253 vsprintf (lb + (strlen (lb)), fmt, ap);
256 vsprintf (lb, fmt, ap);
258 while (isspace (*lbp))
262 lineCurr = (lineCurr ?
263 connectLine (lineCurr, newLineNode (lb)) :
264 (lineHead = newLineNode (lb)));
265 lineCurr->isInline = _G.inLine;
266 lineCurr->isDebug = _G.debugLine;
270 /*-----------------------------------------------------------------*/
271 /* hasInc - operand is incremented before any other use */
272 /*-----------------------------------------------------------------*/
274 hasInc (operand *op, iCode *ic)
276 sym_link *type = operandType(op);
277 sym_link *retype = getSpec (type);
278 iCode *lic = ic->next;
281 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
282 isize = getSize(type->next);
284 /* if operand of the form op = op + <sizeof *op> */
285 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
286 isOperandEqual(IC_RESULT(lic),op) &&
287 isOperandLiteral(IC_RIGHT(lic)) &&
288 operandLitValue(IC_RIGHT(lic)) == isize) {
291 /* if the operand used or deffed */
292 if (bitVectBitValue(ic->uses,op->key) || ((unsigned) ic->defKey == op->key)) {
300 /*-----------------------------------------------------------------*/
301 /* getFreePtr - returns X or Z whichever is free or can be pushed */
302 /*-----------------------------------------------------------------*/
304 getFreePtr (iCode * ic, asmop ** aopp, bool result, bool zonly)
306 bool xiu = FALSE, ziu = FALSE;
307 bool xou = FALSE, zou = FALSE;
309 /* the logic: if x & z used in the instruction
310 then we are in trouble otherwise */
312 /* first check if x & z are used by this
313 instruction, in which case we are in trouble */
314 if ((xiu = bitVectBitValue (ic->rUsed, X_IDX)) &&
315 (ziu = bitVectBitValue (ic->rUsed, Z_IDX))) {
319 xou = bitVectBitValue (ic->rMask, X_IDX);
320 zou = bitVectBitValue (ic->rMask, Z_IDX);
322 /* if no usage of Z then return it */
324 ic->rUsed = bitVectSetBit (ic->rUsed, Z_IDX);
325 (*aopp)->type = AOP_Z;
327 (*aopp)->aop_ptr2 = avr_regWithIdx (R31_IDX);
328 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R30_IDX);
331 /* if no usage of X then return it */
332 if (!xiu && !xou && !zonly) {
333 ic->rUsed = bitVectSetBit (ic->rUsed, X_IDX);
334 (*aopp)->type = AOP_X;
336 (*aopp)->aop_ptr2 = avr_regWithIdx (R27_IDX);
337 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R26_IDX);
340 /* if z not used then */
343 /* push it if not already pushed */
345 emitcode ("push", "%s",
346 avr_regWithIdx (R30_IDX)->dname);
347 emitcode ("push", "%s",
348 avr_regWithIdx (R31_IDX)->dname);
352 ic->rUsed = bitVectSetBit (ic->rUsed, Z_IDX);
353 (*aopp)->type = AOP_Z;
354 (*aopp)->aop_ptr2 = avr_regWithIdx (R31_IDX);
355 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R30_IDX);
358 /* now we know they both have usage */
359 /* if x not used in this instruction */
360 if (!xiu && !zonly) {
361 /* push it if not already pushed */
363 emitcode ("push", "%s",
364 avr_regWithIdx (R26_IDX)->dname);
365 emitcode ("push", "%s",
366 avr_regWithIdx (R27_IDX)->dname);
370 ic->rUsed = bitVectSetBit (ic->rUsed, X_IDX);
371 (*aopp)->type = AOP_X;
373 (*aopp)->aop_ptr2 = avr_regWithIdx (R27_IDX);
374 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R26_IDX);
379 /* I said end of world but not quite end of world yet */
380 /* if this is a result then we can push it on the stack */
382 (*aopp)->type = AOP_STK;
386 /* other wise this is true end of the world */
387 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
388 "getFreePtr should never reach here");
392 /*-----------------------------------------------------------------*/
393 /* newAsmop - creates a new asmOp */
394 /*-----------------------------------------------------------------*/
396 newAsmop (short type)
400 aop = Safe_calloc (1, sizeof (asmop));
405 /*-----------------------------------------------------------------*/
406 /* pointerCode - returns the code for a pointer type */
407 /*-----------------------------------------------------------------*/
409 pointerCode (sym_link * etype)
412 return PTR_TYPE (SPEC_OCLS (etype));
416 /*-----------------------------------------------------------------*/
417 /* aopForSym - for a true symbol */
418 /*-----------------------------------------------------------------*/
420 aopForSym (iCode * ic, symbol * sym, bool result)
423 memmap *space = SPEC_OCLS (sym->etype);
425 /* if already has one */
429 /* assign depending on the storage class */
430 /* if it is on the stack */
432 sym->aop = aop = newAsmop (0);
433 aop->size = getSize (sym->type);
435 /* we can use std / ldd instruction */
437 && (sym->stack + getSize (sym->type) - 1) <= 63) {
438 aop->type = AOP_STK_D;
439 aop->aopu.aop_stk = sym->stack;
443 /* otherwise get a free pointer register X/Z */
444 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result, FALSE);
446 /* now assign the address of the variable to
447 the pointer register */
448 if (aop->type != AOP_STK) {
449 emitcode ("movw", "%s,r28", aop->aopu.aop_ptr->name);
450 if (sym->stack < 0) {
451 if ((sym->stack - _G.nRegsSaved) > -63) {
452 emitcode ("sbiw", "%s,0x%02x",
453 aop->aopu.aop_ptr->name,
458 emitcode ("subi", "%s,lo8(%d)",
459 aop->aopu.aop_ptr->name,
460 sym->stack - _G.nRegsSaved);
461 emitcode ("sbci", "%s,hi8(%d)",
463 sym->stack - _G.nRegsSaved);
467 if (sym->stack <= 63) {
468 emitcode ("adiw", "%s,0x%02x",
469 aop->aopu.aop_ptr->name,
473 emitcode ("subi", "%s,lo8(-%d)",
474 aop->aopu.aop_ptr->name,
476 emitcode ("sbci", "%s,hi8(-%d)",
485 /* if in bit space */
486 if (IN_BITSPACE (space)) {
487 sym->aop = aop = newAsmop (AOP_CRY);
488 aop->aopu.aop_dir = sym->rname;
489 aop->size = getSize (sym->type);
492 /* if it is in direct space */
493 if (IN_DIRSPACE (space)) {
494 sym->aop = aop = newAsmop (AOP_DIR);
495 aop->aopu.aop_dir = sym->rname;
496 aop->size = getSize (sym->type);
500 /* special case for a function */
501 if (IS_FUNC (sym->type)) {
502 sym->aop = aop = newAsmop (AOP_IMMD);
503 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
504 strcpy (aop->aopu.aop_immd, sym->rname);
505 aop->size = FPTRSIZE;
509 /* only remaining is code / eeprom which will need pointer reg */
510 /* if it is in code space */
512 sym->aop = aop = newAsmop (0);
514 if (IN_CODESPACE (space))
517 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result, aop->code);
518 aop->size = getSize (sym->type);
519 emitcode ("ldi", "%s,lo8(%s)", aop->aopu.aop_ptr->name, sym->rname);
520 emitcode ("ldi", "%s,hi8(%s)", aop->aop_ptr2);
525 /*-----------------------------------------------------------------*/
526 /* aopForRemat - rematerialzes an object */
527 /*-----------------------------------------------------------------*/
529 aopForRemat (symbol * sym)
531 iCode *ic = sym->rematiCode;
532 asmop *aop = newAsmop (AOP_IMMD);
537 val += (int) operandLitValue (IC_RIGHT (ic));
538 else if (ic->op == '-')
539 val -= (int) operandLitValue (IC_RIGHT (ic));
543 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
547 sprintf (buffer, "(%s %c 0x%04x)",
548 OP_SYMBOL (IC_LEFT (ic))->rname,
549 val >= 0 ? '+' : '-', abs (val) & 0xffff);
551 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
553 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
554 strcpy (aop->aopu.aop_immd, buffer);
558 /*-----------------------------------------------------------------*/
559 /* regsInCommon - two operands have some registers in common */
560 /*-----------------------------------------------------------------*/
562 regsInCommon (operand * op1, operand * op2)
567 /* if they have registers in common */
568 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
571 sym1 = OP_SYMBOL (op1);
572 sym2 = OP_SYMBOL (op2);
574 if (sym1->nRegs == 0 || sym2->nRegs == 0)
577 for (i = 0; i < sym1->nRegs; i++) {
582 for (j = 0; j < sym2->nRegs; j++) {
586 if (sym2->regs[j] == sym1->regs[i])
594 /*-----------------------------------------------------------------*/
595 /* operandsEqu - equivalent */
596 /*-----------------------------------------------------------------*/
598 operandsEqu (operand * op1, operand * op2)
602 /* if they not symbols */
603 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
606 sym1 = OP_SYMBOL (op1);
607 sym2 = OP_SYMBOL (op2);
609 /* if both are itemps & one is spilt
610 and the other is not then false */
611 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
612 sym1->isspilt != sym2->isspilt) return FALSE;
614 /* if they are the same */
618 if (strcmp (sym1->rname, sym2->rname) == 0)
622 /* if left is a tmp & right is not */
623 if (IS_ITEMP (op1) &&
624 !IS_ITEMP (op2) && sym1->isspilt && (sym1->usl.spillLoc == sym2))
627 if (IS_ITEMP (op2) &&
629 sym2->isspilt && sym1->level > 0 && (sym2->usl.spillLoc == sym1))
635 /*-----------------------------------------------------------------*/
636 /* sameRegs - two asmops have the same registers */
637 /*-----------------------------------------------------------------*/
639 sameRegs (asmop * aop1, asmop * aop2)
646 if (aop1->type != AOP_REG || aop2->type != AOP_REG)
649 if (aop1->size != aop2->size)
652 for (i = 0; i < aop1->size; i++)
653 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
659 /*-----------------------------------------------------------------*/
660 /* isRegPair - for size 2 if this operand has a register pair */
661 /*-----------------------------------------------------------------*/
663 isRegPair (asmop * aop)
665 if (!aop || aop->size < 2)
667 if (aop->type == AOP_X || aop->type == AOP_Z)
669 if (aop->type != AOP_REG)
671 if ( ((aop->aopu.aop_reg[1]->rIdx - aop->aopu.aop_reg[0]->rIdx) == 1) &&
672 (aop->aopu.aop_reg[0]->rIdx & 1) == 0)
678 /*-----------------------------------------------------------------*/
679 /* aopOp - allocates an asmop for an operand : */
680 /*-----------------------------------------------------------------*/
682 aopOp (operand * op, iCode * ic, bool result)
691 /* if this a literal */
692 if (IS_OP_LITERAL (op)) {
693 op->aop = aop = newAsmop (AOP_LIT);
694 aop->aopu.aop_lit = op->operand.valOperand;
695 aop->size = getSize (operandType (op));
699 /* if already has a asmop then continue */
703 /* if the underlying symbol has a aop */
704 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop) {
705 op->aop = OP_SYMBOL (op)->aop;
709 /* if this is a true symbol */
710 if (IS_TRUE_SYMOP (op)) {
711 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
715 /* this is a temporary : this has
721 e) can be a return use only */
723 sym = OP_SYMBOL (op);
726 /* if the type is a conditional */
727 if (sym->regType & REG_CND) {
728 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
733 /* if it is spilt then two situations
735 b) has a spill location */
736 if (sym->isspilt || sym->nRegs == 0) {
738 /* rematerialize it NOW */
740 sym->aop = op->aop = aop = aopForRemat (sym);
741 aop->size = getSize (sym->type);
746 assert ("ACC_USE cannot happen in AVR\n");
751 aop = op->aop = sym->aop = newAsmop (AOP_STR);
752 aop->size = getSize (sym->type);
753 for (i = 0; i < (int) fAVRReturnSize; i++)
754 aop->aopu.aop_str[i] = fAVRReturn[i];
758 /* else spill location */
759 sym->aop = op->aop = aop =
760 aopForSym (ic, sym->usl.spillLoc, result);
761 aop->size = getSize (sym->type);
765 /* must be in a register */
766 sym->aop = op->aop = aop = newAsmop (AOP_REG);
767 aop->size = sym->nRegs;
768 for (i = 0; i < sym->nRegs; i++)
769 aop->aopu.aop_reg[i] = sym->regs[i];
772 /*-----------------------------------------------------------------*/
773 /* freeAsmop - free up the asmop given to an operand */
774 /*----------------------------------------------------------------*/
776 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
793 /* depending on the asmop type only three cases need work AOP_RO
794 , AOP_R1 && AOP_STK */
799 emitcode ("pop", "r26");
800 emitcode ("pop", "r27");
804 bitVectUnSetBit (ic->rUsed, X_IDX);
810 emitcode ("pop", "r30");
811 emitcode ("pop", "r31");
815 bitVectUnSetBit (ic->rUsed, Z_IDX);
821 int stk = aop->aopu.aop_stk + aop->size;
822 bitVectUnSetBit (ic->rUsed, X_IDX);
823 bitVectUnSetBit (ic->rUsed, Z_IDX);
825 getFreePtr (ic, &aop, FALSE, 0);
827 emitcode ("movw", "%s,r28");
829 if (stk <= 63 && stk > 0) {
830 emitcode ("adiw", "%s,0x%02x",
831 aop->aopu.aop_ptr->name,
835 emitcode ("subi", "%s,lo8(%d)",
836 aop->aopu.aop_ptr->name,
838 emitcode ("sbci", "%s,hi8(%d)",
845 emitcode ("pop", "r24");
846 emitcode ("st", "-%s,r24",
847 aop->type == AOP_X ? "X" : "Z");
852 freeAsmop (op, NULL, ic, TRUE);
854 emitcode ("pop", "r26");
855 emitcode ("pop", "r27");
860 emitcode ("pop", "r30");
861 emitcode ("pop", "r31");
868 /* all other cases just dealloc */
872 OP_SYMBOL (op)->aop = NULL;
873 /* if the symbol has a spill */
875 SPIL_LOC (op)->aop = NULL;
880 /*-----------------------------------------------------------------*/
881 /* aopGet - for fetching value of the aop */
882 /*-----------------------------------------------------------------*/
884 aopGet (asmop * aop, int offset)
889 /* offset is greater than
891 if (offset > (aop->size - 1) && aop->type != AOP_LIT)
894 /* depending on type */
898 if (offset > aop->coff) {
899 emitcode ("adiw", "%s,%d", aop->aopu.aop_ptr->name,
903 if (offset < aop->coff) {
904 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name,
909 emitcode ("ld", "%s,x",
910 (rs = ((offset & 1) ? "r25" : "r24")));
915 if (offset > aop->coff) {
916 emitcode ("adiw", "r30,%d",
920 emitcode ("sbiw", "r30,%d",
923 emitcode ("lpm", "%s,z",
924 (rs = ((offset & 1) ? "r25" : "r24")));
928 if (offset > aop->coff) {
929 emitcode ("ldd", "%s,z+%d",
931 ((offset & 1) ? "r25" : "r24")),
935 emitcode ("sbiw", "%s,%d",
936 aop->aopu.aop_ptr->name,
939 emitcode ("ld", "%s,z",
941 ((offset & 1) ? "r25" : "r24")));
948 emitcode ("lds", "%s,(%s)+%d",
949 (rs = ((offset & 1) ? "r25" : "r24")),
950 aop->aopu.aop_immd, offset);
954 emitcode ("lds", "%s,(%s)+%d",
955 (rs = ((offset & 1) ? "r25" : "r24")),
956 aop->aopu.aop_dir, offset);
960 return aop->aopu.aop_reg[offset]->name;
963 assert ("cannot be in bit space AOP_CRY\n");
967 s = aopLiteral (aop->aopu.aop_lit, offset);
968 emitcode ("ldi", "%s,lo8(%s)",
969 (rs = ((offset & 1) ? "r24" : "r25")), s);
974 return aop->aopu.aop_str[offset];
977 emitcode ("ldd", "%s,Y+%d",
978 (rs = ((offset & 1) ? "r25" : "r24")),
979 aop->aopu.aop_stk + offset);
983 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
984 "aopget got unsupported aop->type");
988 /*-----------------------------------------------------------------*/
989 /* aopPut - puts a string for a aop */
990 /*-----------------------------------------------------------------*/
992 aopPut (asmop * aop, char *s, int offset)
996 if (aop->size && offset > (aop->size - 1)) {
997 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
998 "aopPut got offset > aop->size");
1002 /* will assign value to value */
1003 /* depending on where it is ofcourse */
1004 switch (aop->type) {
1007 sprintf (d, "(%s)+%d", aop->aopu.aop_dir, offset);
1010 sprintf (d, "%s", aop->aopu.aop_dir);
1013 emitcode ("sts", "%s,%s", d, s);
1017 if (toupper (*s) != 'R') {
1019 emitcode ("clr", "%s",
1020 aop->aopu.aop_reg[offset]->name);
1023 emitcode ("ldi", "r25,%s", s);
1024 emitcode ("mov", "%s,r35",
1025 aop->aopu.aop_reg[offset]->name);
1029 if (strcmp (aop->aopu.aop_reg[offset]->name, s)) {
1030 emitcode ("mov", "%s,%s",
1031 aop->aopu.aop_reg[offset]->name, s);
1037 if (offset > aop->coff) {
1038 emitcode ("adiw", "%s,%d", aop->aopu.aop_ptr->name,
1039 offset - aop->coff);
1042 if (offset < aop->coff) {
1043 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name,
1044 aop->coff - offset);
1048 emitcode ("st", "x,%s", s);
1053 if (offset > aop->coff) {
1054 emitcode ("adiw", "r30,%d",
1055 offset - aop->coff);
1058 emitcode ("sbiw", "r30,%d",
1059 aop->coff - offset);
1061 emitcode ("lpm", "%s,z", s);
1064 /* we can use lds */
1065 if (offset > aop->coff) {
1066 emitcode ("sdd", "z+%d,%s",
1067 offset - aop->coff, s);
1070 emitcode ("sbiw", "%s,%d",
1071 aop->aopu.aop_ptr->name,
1072 aop->coff - offset);
1074 emitcode ("ld", "%s,z", s);
1080 emitcode ("push", "%s", s);
1084 /* if used only for a condition code check */
1085 assert (toupper (*s) == 'R');
1087 emitcode ("xrl", "r0,r0");
1088 emitcode ("cpi", "%s,0", s);
1091 emitcode ("cpc", "r0,%s", s);
1097 if (strcmp (aop->aopu.aop_str[offset], s))
1098 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset],
1103 emitcode ("std", "y+%d,%s", offset, s);
1107 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1108 "aopPut got unsupported aop->type");
1114 #define AOP(op) op->aop
1115 #define AOP_TYPE(op) AOP(op)->type
1116 #define AOP_SIZE(op) AOP(op)->size
1117 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_X || \
1118 AOP_TYPE(x) == AOP_Z))
1119 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1120 ((x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R27_IDX)) || \
1121 (x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R31_IDX)) )))
1122 #define AOP_ISX(x) (x && (x->type == AOP_REG && \
1123 ((x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R27_IDX)))))
1124 #define AOP_ISZ(x) (x && (x->type == AOP_REG && \
1125 ((x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R31_IDX)))))
1127 /*-----------------------------------------------------------------*/
1128 /* genNotFloat - generates not for float operations */
1129 /*-----------------------------------------------------------------*/
1131 genNotFloat (operand * op, operand * res)
1137 /* we will put 127 in the first byte of
1139 aopPut (AOP (res), "127", 0);
1140 size = AOP_SIZE (op) - 1;
1143 l = aopGet (op->aop, offset++);
1147 emitcode ("or", "R0,%s", aopGet (op->aop, offset++));
1149 tlbl = newiTempLabel (NULL);
1151 tlbl = newiTempLabel (NULL);
1152 aopPut (res->aop, zero, 1);
1153 emitcode ("cpi", "r0,0");
1154 emitcode ("breq", "L%05d", tlbl->key);
1155 aopPut (res->aop, one, 1);
1156 emitcode ("", "L%05d:", tlbl->key);
1158 size = res->aop->size - 2;
1160 /* put zeros in the rest */
1162 aopPut (res->aop, zero, offset++);
1165 /*-----------------------------------------------------------------*/
1166 /* opIsGptr: returns non-zero if the passed operand is */
1167 /* a generic pointer type. */
1168 /*-----------------------------------------------------------------*/
1170 opIsGptr (operand * op)
1172 sym_link *type = operandType (op);
1174 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type)) {
1180 /*-----------------------------------------------------------------*/
1181 /* getDataSize - get the operand data size */
1182 /*-----------------------------------------------------------------*/
1184 getDataSize (operand * op)
1187 size = AOP_SIZE (op);
1188 if (size == GPTRSIZE) {
1189 sym_link *type = operandType (op);
1190 if (IS_GENPTR (type)) {
1191 /* generic pointer; arithmetic operations
1192 * should ignore the high byte (pointer type).
1200 /*-----------------------------------------------------------------*/
1201 /* outAcc - output Acc */
1202 /*-----------------------------------------------------------------*/
1204 outAcc (operand * result)
1207 size = getDataSize (result);
1209 aopPut (AOP (result), "r0", 0);
1212 /* unsigned or positive */
1214 aopPut (AOP (result), zero, offset++);
1219 /*-----------------------------------------------------------------*/
1220 /* toBoolean - emit code for orl a,operator(sizeop) */
1221 /*-----------------------------------------------------------------*/
1223 toBoolean (operand * oper, char *r, bool clr)
1225 int size = AOP_SIZE (oper);
1228 emitcode ("clr", "%s", r);
1230 emitcode ("or", "%s,%s", r, aopGet (AOP (oper), offset++));
1234 /*-----------------------------------------------------------------*/
1235 /* genNot - generate code for ! operation */
1236 /*-----------------------------------------------------------------*/
1241 sym_link *optype = operandType (IC_LEFT (ic));
1242 int size, offset = 1;
1244 /* assign asmOps to operand & result */
1245 aopOp (IC_LEFT (ic), ic, FALSE);
1246 aopOp (IC_RESULT (ic), ic, TRUE);
1248 /* if type float then do float */
1249 if (IS_FLOAT (optype)) {
1250 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1253 emitcode ("clr", "r24");
1254 tlbl = newiTempLabel (NULL);
1255 size = AOP_SIZE (IC_LEFT (ic));
1258 emitcode ("cpse", "%s,r24", aopGet (AOP (IC_LEFT (ic)), 0));
1263 emitcode ("cpc", "%s,r24",
1264 aopGet (AOP (IC_LEFT (ic)),
1267 emitcode ("cpi", "%s,0",
1268 aopGet (AOP (IC_LEFT (ic)),
1272 emitcode ("bne", "L%05d", tlbl->key);
1274 emitcode ("ldi", "r24,1");
1275 emitcode ("", "L%05d:", tlbl->key);
1276 aopPut (AOP (IC_RESULT (ic)), "r24", 0);
1277 size = AOP_SIZE (IC_RESULT (ic)) - 1;
1280 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
1284 /* release the aops */
1285 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1286 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1290 /*-----------------------------------------------------------------*/
1291 /* genCpl - generate code for complement */
1292 /*-----------------------------------------------------------------*/
1300 /* assign asmOps to operand & result */
1301 aopOp (IC_LEFT (ic), ic, FALSE);
1302 aopOp (IC_RESULT (ic), ic, TRUE);
1303 samer = sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)));
1304 size = AOP_SIZE (IC_RESULT (ic));
1306 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
1308 emitcode ("com", "%s", l);
1311 aopPut (AOP (IC_RESULT (ic)), l, offset);
1312 emitcode ("com", "%s",
1313 aopGet (AOP (IC_RESULT (ic)), offset));
1318 /* release the aops */
1319 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1320 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1323 /*-----------------------------------------------------------------*/
1324 /* genUminusFloat - unary minus for floating points */
1325 /*-----------------------------------------------------------------*/
1327 genUminusFloat (operand * op, operand * result)
1329 int size, offset = 0;
1331 /* for this we just need to flip the
1332 first it then copy the rest in place */
1333 size = AOP_SIZE (op) - 1;
1334 l = aopGet (AOP (op), 3);
1336 emitcode ("ldi", "r24,0x80");
1337 if (sameRegs (AOP (op), AOP (result))) {
1338 emitcode ("eor", "%s,r24", l);
1341 aopPut (AOP (result), l, 3);
1342 emitcode ("eor", "%s,r24", aopGet (AOP (result), 3));
1345 aopPut (AOP (result), aopGet (AOP (op), offset), offset);
1350 /*-----------------------------------------------------------------*/
1351 /* genUminus - unary minus code generation */
1352 /*-----------------------------------------------------------------*/
1354 genUminus (iCode * ic)
1357 sym_link *optype, *rtype;
1361 aopOp (IC_LEFT (ic), ic, FALSE);
1362 aopOp (IC_RESULT (ic), ic, TRUE);
1364 optype = operandType (IC_LEFT (ic));
1365 rtype = operandType (IC_RESULT (ic));
1367 /* if float then do float stuff */
1368 if (IS_FLOAT (optype)) {
1369 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1373 /* otherwise subtract from zero */
1374 size = AOP_SIZE (IC_LEFT (ic));
1376 samer = sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)));
1379 emitcode ("neg", "%s",
1380 aopGet (AOP (IC_LEFT (ic)), 0));
1383 aopPut (AOP (IC_RESULT (ic)),
1384 aopGet (AOP (IC_LEFT (ic)), 0), 0);
1385 emitcode ("neg", "%s",
1386 aopGet (AOP (IC_RESULT (ic)), 0));
1392 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
1394 aopPut (AOP (IC_RESULT (ic)), l, offset);
1395 l = aopGet (AOP (IC_RESULT (ic)), offset);
1398 emitcode ("com", "%s", l);
1400 emitcode ("neg", "%s", l);
1403 size = AOP_SIZE (IC_LEFT (ic)) - 1;
1406 emitcode ("sbci", "%s,lo8(-1)",
1407 aopGet (AOP (IC_RESULT (ic)), offset++));
1411 /* if any remaining bytes in the result */
1412 /* we just need to propagate the sign */
1413 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic))))) {
1414 symbol *tlbl = newiTempLabel (NULL);
1415 emitcode ("clr", "r0");
1416 emitcode ("brcc", "L%05d", tlbl->key);
1417 emitcode ("com", "r0");
1418 emitcode ("", "L%05d:", tlbl->key);
1420 aopPut (AOP (IC_RESULT (ic)), "r0", offset++);
1424 /* release the aops */
1425 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1426 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1429 /*-----------------------------------------------------------------*/
1430 /* assignResultValue - */
1431 /*-----------------------------------------------------------------*/
1433 assignResultValue (operand * oper)
1436 int size = AOP_SIZE (oper);
1438 aopPut (AOP (oper), fAVRReturn[offset], offset);
1443 /*-----------------------------------------------------------------*/
1444 /* saveZreg - if indirect call then save z-pointer register */
1445 /*-----------------------------------------------------------------*/
1447 saveZreg (iCode * ic)
1449 /* only if live accross this call */
1450 if (ic->regsSaved == 0 &&
1451 (bitVectBitValue (ic->rMask, R30_IDX) ||
1452 bitVectBitValue (ic->rMask, R31_IDX))) {
1454 emitcode ("push", "r30");
1455 emitcode ("push", "r31");
1459 /*-----------------------------------------------------------------*/
1460 /* popZreg - restore values of zreg */
1461 /*-----------------------------------------------------------------*/
1463 popZreg (iCode * ic)
1465 if (ic->regsSaved) {
1466 emitcode ("pop", "r31");
1467 emitcode ("pop", "r30");
1471 /*-----------------------------------------------------------------*/
1472 /* genIpush - genrate code for pushing this gets a little complex */
1473 /*-----------------------------------------------------------------*/
1475 genIpush (iCode * ic)
1477 int size, offset = 0;
1481 if (!ic->parmPush) {
1482 /* and the item is spilt then do nothing */
1483 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1488 for (lic = ic->next; lic; lic = lic->next)
1489 if (lic->op == PCALL)
1495 /* this is a paramter push */
1496 aopOp (IC_LEFT (ic), ic, FALSE);
1497 size = AOP_SIZE (IC_LEFT (ic));
1499 l = aopGet (AOP (IC_LEFT (ic)), offset++);
1500 emitcode ("push", "%s", l);
1503 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1506 /*-----------------------------------------------------------------*/
1507 /* genIpop - recover the registers: can happen only for spilling */
1508 /*-----------------------------------------------------------------*/
1510 genIpop (iCode * ic)
1515 /* if the temp was not pushed then */
1516 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1519 aopOp (IC_LEFT (ic), ic, FALSE);
1520 size = AOP_SIZE (IC_LEFT (ic));
1521 offset = (size - 1);
1523 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--));
1525 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1528 /*-----------------------------------------------------------------*/
1529 /* genCall - generates a call statement */
1530 /*-----------------------------------------------------------------*/
1532 genCall (iCode * ic)
1535 /* if send set is not empty the assign */
1539 for (sic = setFirstItem (_G.sendSet); sic;
1540 sic = setNextItem (_G.sendSet)) {
1541 int size, offset = 0;
1542 aopOp (IC_LEFT (sic), sic, FALSE);
1543 size = AOP_SIZE (IC_LEFT (sic));
1546 aopGet (AOP (IC_LEFT (sic)), offset);
1548 sprintf (buffer, "r%d", rnum++);
1550 emitcode ("mov", "%s,%s", b, l);
1553 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1558 emitcode ("call", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1559 OP_SYMBOL (IC_LEFT (ic))->rname :
1560 OP_SYMBOL (IC_LEFT (ic))->name));
1562 /* if we need assign a result value */
1563 if ((IS_ITEMP (IC_RESULT (ic)) &&
1564 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1565 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1566 IS_TRUE_SYMOP (IC_RESULT (ic))) {
1568 aopOp (IC_RESULT (ic), ic, FALSE);
1569 assignResultValue (IC_RESULT (ic));
1570 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1573 /* adjust the stack for parameters if required */
1574 if (ic->parmBytes) {
1575 if (ic->parmBytes > 63) {
1576 emitcode ("sbiw", "r28,%d", ic->parmBytes);
1579 emitcode ("subi", "r28,lo8(%d)",
1581 emitcode ("sbci", "r29,hi8(%d)",
1588 /*-----------------------------------------------------------------*/
1589 /* genPcall - generates a call by pointer statement */
1590 /*-----------------------------------------------------------------*/
1592 genPcall (iCode * ic)
1598 aopOp (IC_LEFT (ic), ic, FALSE);
1599 emitcode ("mov", "r30", aopGet (AOP (IC_LEFT (ic)), 0));
1600 emitcode ("mov", "r31", aopGet (AOP (IC_RIGHT (ic)), 0));
1601 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1603 /* if send set is not empty the assign */
1607 for (sic = setFirstItem (_G.sendSet); sic;
1608 sic = setNextItem (_G.sendSet)) {
1609 int size, offset = 0;
1610 aopOp (IC_LEFT (sic), sic, FALSE);
1611 size = AOP_SIZE (IC_LEFT (sic));
1614 aopGet (AOP (IC_LEFT (sic)), offset);
1616 sprintf (b, "r%d", rnum++);
1618 emitcode ("mov", "%s,%s", b, l);
1621 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1626 emitcode ("icall", "");
1628 /* if we need assign a result value */
1629 if ((IS_ITEMP (IC_RESULT (ic)) &&
1630 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1631 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1632 IS_TRUE_SYMOP (IC_RESULT (ic))) {
1634 aopOp (IC_RESULT (ic), ic, FALSE);
1636 assignResultValue (IC_RESULT (ic));
1637 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1640 /* adjust the stack for parameters if
1642 if (ic->parmBytes) {
1644 if (ic->parmBytes > 3) {
1645 emitcode ("mov", "a,%s", spname);
1646 emitcode ("add", "a,#0x%02x",
1647 (-ic->parmBytes) & 0xff);
1648 emitcode ("mov", "%s,a", spname);
1651 for (i = 0; i < ic->parmBytes; i++)
1652 emitcode ("dec", "%s", spname);
1656 /* adjust the stack for parameters if required */
1657 if (ic->parmBytes) {
1658 if (ic->parmBytes > 63) {
1659 emitcode ("sbiw", "r28,%d", ic->parmBytes);
1662 emitcode ("subi", "r28,lo8(%d)",
1664 emitcode ("sbci", "r29,hi8(%d)",
1672 /*-----------------------------------------------------------------*/
1673 /* resultRemat - result is rematerializable */
1674 /*-----------------------------------------------------------------*/
1676 resultRemat (iCode * ic)
1678 if (SKIP_IC (ic) || ic->op == IFX)
1681 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic))) {
1682 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
1683 if (sym->remat && !POINTER_SET (ic))
1690 #if defined(__BORLANDC__) || defined(_MSC_VER)
1691 #define STRCASECMP stricmp
1693 #define STRCASECMP strcasecmp
1696 /*-----------------------------------------------------------------*/
1697 /* genFunction - generated code for function entry */
1698 /*-----------------------------------------------------------------*/
1700 genFunction (iCode * ic)
1707 /* create the function header */
1708 emitcode (";", "-----------------------------------------");
1709 emitcode (";", " function %s",
1710 (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
1711 emitcode (";", "-----------------------------------------");
1713 emitcode ("", "%s:", sym->rname);
1714 fetype = getSpec (operandType (IC_LEFT (ic)));
1716 /* if critical function then turn interrupts off */
1717 if (SPEC_CRTCL (fetype))
1718 emitcode ("cli", "");
1720 if (IS_ISR (sym->etype)) {
1723 /* save the preserved registers that are used in this function */
1724 for (i = R2_IDX; i <= R15_IDX; i++) {
1725 if (bitVectBitValue (sym->regsUsed, i)) {
1727 emitcode ("push", "%s", avr_regWithIdx (i)->name);
1730 /* now for the pointer registers */
1731 if (bitVectBitValue (sym->regsUsed, R26_IDX)) {
1733 emitcode ("push", "r26");
1735 if (bitVectBitValue (sym->regsUsed, R27_IDX)) {
1737 emitcode ("push", "r27");
1739 if (bitVectBitValue (sym->regsUsed, R30_IDX)) {
1741 emitcode ("push", "r30");
1743 if (bitVectBitValue (sym->regsUsed, R31_IDX)) {
1745 emitcode ("push", "r31");
1747 /* adjust the stack for the function */
1749 emitcode ("push", "r28");
1750 emitcode ("push", "r29");
1751 emitcode ("in", "r28,__SP_L__");
1752 emitcode ("in", "r29,__SP_H__");
1753 if (sym->stack <= 63) {
1754 emitcode ("sbiw", "r28,%d", sym->stack);
1757 emitcode ("subi", "r28,lo8(%d)", sym->stack);
1758 emitcode ("sbci", "r29,hi8(%d)", sym->stack);
1760 emitcode ("out", "__SP_L__,r28");
1761 emitcode ("out", "__SP_H__,r29");
1765 /*-----------------------------------------------------------------*/
1766 /* genEndFunction - generates epilogue for functions */
1767 /*-----------------------------------------------------------------*/
1769 genEndFunction (iCode * ic)
1771 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
1774 /* restore stack pointer */
1776 if (sym->stack <= 63) {
1777 emitcode ("adiw", "r28,%d", sym->stack);
1780 emitcode ("subi", "r28,lo8(-%d)", sym->stack);
1781 emitcode ("sbci", "r29,hi8(-%d)", sym->stack);
1783 emitcode ("out", "__SP_L__,r28");
1784 emitcode ("out", "__SP_H__,r29");
1786 /* pop frame pointer */
1787 emitcode ("pop", "r29");
1788 emitcode ("pop", "r28");
1790 /* restore preserved registers */
1791 if (bitVectBitValue (sym->regsUsed, R31_IDX)) {
1793 emitcode ("pop", "r31");
1795 if (bitVectBitValue (sym->regsUsed, R30_IDX)) {
1797 emitcode ("pop", "r30");
1799 if (bitVectBitValue (sym->regsUsed, R27_IDX)) {
1801 emitcode ("pop", "r27");
1803 if (bitVectBitValue (sym->regsUsed, R26_IDX)) {
1805 emitcode ("pop", "r26");
1807 for (i = R15_IDX; i >= R2_IDX; i--) {
1808 if (bitVectBitValue (sym->regsUsed, i)) {
1810 emitcode ("pop", "%s", avr_regWithIdx (i)->name);
1814 if (SPEC_CRTCL (sym->etype))
1815 emitcode ("sti", "");
1817 if (IS_ISR (sym->etype)) {
1818 emitcode ("rti", "");
1821 emitcode ("ret", "");
1826 /*-----------------------------------------------------------------*/
1827 /* genRet - generate code for return statement */
1828 /*-----------------------------------------------------------------*/
1832 int size, offset = 0;
1834 /* if we have no return value then
1835 just generate the "ret" */
1839 /* we have something to return then
1840 move the return value into place */
1841 aopOp (IC_LEFT (ic), ic, FALSE);
1842 size = AOP_SIZE (IC_LEFT (ic));
1845 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) {
1846 emitcode ("ldi", "%s,%s(%d)", fAVRReturn[offset],
1848 (int) floatFromVal (AOP (IC_LEFT (ic))->
1849 aopu.aop_lit), offset);
1853 l = aopGet (AOP (IC_LEFT (ic)), offset);
1854 if (strcmp (fAVRReturn[offset], l))
1855 emitcode ("mov", "%s,%s", fAVRReturn[offset],
1861 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1864 /* generate a jump to the return label
1865 if the next is not the return statement */
1866 if (!(ic->next && ic->next->op == LABEL &&
1867 IC_LABEL (ic->next) == returnLabel))
1869 emitcode ("rjmp", "L%05d", returnLabel->key);
1873 /*-----------------------------------------------------------------*/
1874 /* genLabel - generates a label */
1875 /*-----------------------------------------------------------------*/
1877 genLabel (iCode * ic)
1879 /* special case never generate */
1880 if (IC_LABEL (ic) == entryLabel)
1883 emitcode ("", "L%05d:", IC_LABEL (ic)->key);
1886 /*-----------------------------------------------------------------*/
1887 /* genGoto - generates a ljmp */
1888 /*-----------------------------------------------------------------*/
1890 genGoto (iCode * ic)
1892 emitcode ("rjmp", "L%05d", (IC_LABEL (ic)->key + 100));
1895 /*-----------------------------------------------------------------*/
1896 /* genPlusIncr :- does addition with increment if possible */
1897 /*-----------------------------------------------------------------*/
1899 genPlusIncr (iCode * ic)
1901 unsigned int icount;
1903 /* will try to generate an increment */
1904 /* if the right side is not a literal
1906 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
1910 (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.
1913 /* if the sizes are greater than 2 or they are not the same regs
1915 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1918 /* so we know LEFT & RESULT in the same registers and add
1920 /* for short & char types */
1921 if (AOP_SIZE (IC_RESULT (ic)) < 2) {
1923 emitcode ("inc", "%s",
1924 aopGet (AOP (IC_LEFT (ic)), 0));
1927 emitcode ("subi", "%s,lo8(%d)",
1928 aopGet (AOP (IC_LEFT (ic)), 0), 0-icount);
1932 if (AOP_SIZE (IC_RESULT (ic)) <= 3) {
1933 /* if register pair and starts with 26/30 then adiw */
1934 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0
1936 && (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX)
1937 || IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX))) {
1938 emitcode ("adiw", "%s,%d",
1939 aopGet (AOP (IC_RESULT (ic)), 0), icount);
1944 emitcode ("subi", "%s,lo8(%d)",
1945 aopGet (AOP (IC_RESULT (ic)), 0), 0-icount);
1946 emitcode ("sbci", "%s,hi8(%d)",
1947 aopGet (AOP (IC_RESULT (ic)), 1), 0-icount);
1951 /* for 32 bit longs */
1952 emitcode ("subi", "%s,lo8(%d)", aopGet (AOP (IC_RESULT (ic)), 0),
1954 emitcode ("sbci", "%s,hi8(%d)", aopGet (AOP (IC_RESULT (ic)), 1),
1956 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2),
1958 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3),
1964 /* This is the pure and virtuous version of this code.
1965 * I'm pretty certain it's right, but not enough to toss the old
1969 adjustArithmeticResult (iCode * ic)
1971 if (opIsGptr (IC_RESULT (ic)) &&
1972 opIsGptr (IC_LEFT (ic)) &&
1973 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)))) {
1974 aopPut (AOP (IC_RESULT (ic)),
1975 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1),
1979 if (opIsGptr (IC_RESULT (ic)) &&
1980 opIsGptr (IC_RIGHT (ic)) &&
1981 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)))) {
1982 aopPut (AOP (IC_RESULT (ic)),
1983 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1),
1987 if (opIsGptr (IC_RESULT (ic)) &&
1988 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
1989 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
1990 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
1991 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)))) {
1993 sprintf (buffer, "%d",
1994 pointerCode (getSpec (operandType (IC_LEFT (ic)))));
1995 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
1999 /*-----------------------------------------------------------------*/
2000 /* genPlus - generates code for addition */
2001 /*-----------------------------------------------------------------*/
2003 genPlus (iCode * ic)
2005 int size, offset = 0;
2009 /* special cases :- */
2011 aopOp (IC_LEFT (ic), ic, FALSE);
2012 aopOp (IC_RIGHT (ic), ic, FALSE);
2013 aopOp (IC_RESULT (ic), ic, TRUE);
2015 /* if I can do an increment instead
2016 of add then GOOD for ME */
2017 if (genPlusIncr (ic) == TRUE)
2020 size = getDataSize (IC_RESULT (ic));
2021 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2025 aopPut (AOP (IC_RESULT (ic)),
2026 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2028 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
2035 emitcode (l, "%s,%s",
2036 aopGet (AOP (IC_RESULT (ic)), offset),
2037 aopGet (AOP (IC_RIGHT (ic)), offset));
2045 emitcode (l, "%s,%s(-%d)",
2046 aopGet (AOP (IC_RESULT (ic)), offset),
2048 (int) floatFromVal (AOP (IC_RIGHT (ic))->
2054 adjustArithmeticResult (ic);
2057 freeAsmop (IC_LEFT (ic), NULL, ic,
2058 (RESULTONSTACK (ic) ? FALSE : TRUE));
2059 freeAsmop (IC_RIGHT (ic), NULL, ic,
2060 (RESULTONSTACK (ic) ? FALSE : TRUE));
2061 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2064 /*-----------------------------------------------------------------*/
2065 /* genMinusDec :- does subtraction with deccrement if possible */
2066 /*-----------------------------------------------------------------*/
2068 genMinusDec (iCode * ic)
2070 unsigned int icount;
2072 /* will try to generate an increment */
2073 /* if the right side is not a literal
2075 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2079 (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.
2082 /* if the sizes are greater than 2 or they are not the same regs
2084 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic))))
2087 /* so we know LEFT & RESULT in the same registers and add
2089 /* for short & char types */
2090 if (AOP_SIZE (IC_RESULT (ic)) < 2) {
2092 emitcode ("dec", "%s",
2093 aopGet (AOP (IC_LEFT (ic)), 0));
2096 emitcode ("subi", "%s,lo8(%d)",
2097 aopGet (AOP (IC_LEFT (ic)), 0), icount);
2101 if (AOP_SIZE (IC_RESULT (ic)) <= 3) {
2102 /* if register pair and starts with 26/30 then adiw */
2103 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0
2105 && (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX)
2106 || IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX))) {
2107 emitcode ("sbiw", "%s,%d",
2108 aopGet (AOP (IC_RESULT (ic)), 0), icount);
2113 emitcode ("subi", "%s,lo8(%d)",
2114 aopGet (AOP (IC_RESULT (ic)), 0), icount);
2115 emitcode ("sbci", "%s,hi8(%d)",
2116 aopGet (AOP (IC_RESULT (ic)), 1), icount);
2119 /* for 32 bit longs */
2120 emitcode ("subi", "%s,lo8(%d)", aopGet (AOP (IC_RESULT (ic)), 0),
2122 emitcode ("sbci", "%s,hi8(%d)", aopGet (AOP (IC_RESULT (ic)), 1),
2124 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2),
2126 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3),
2132 /*-----------------------------------------------------------------*/
2133 /* genMinus - generates code for subtraction */
2134 /*-----------------------------------------------------------------*/
2136 genMinus (iCode * ic)
2138 int size, offset = 0, samer;
2141 aopOp (IC_LEFT (ic), ic, FALSE);
2142 aopOp (IC_RIGHT (ic), ic, FALSE);
2143 aopOp (IC_RESULT (ic), ic, TRUE);
2145 /* if I can do an decrement instead
2146 of subtract then GOOD for ME */
2147 if (genMinusDec (ic) == TRUE)
2150 size = getDataSize (IC_RESULT (ic));
2151 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2154 aopPut (AOP (IC_RESULT (ic)),
2155 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2157 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
2164 emitcode (l, "%s,%s",
2165 aopGet (AOP (IC_RESULT (ic)), offset),
2166 aopGet (AOP (IC_RIGHT (ic)), offset));
2174 emitcode (l, "%s,%s(%d)",
2175 aopGet (AOP (IC_RESULT (ic)), offset),
2177 (int) floatFromVal (AOP (IC_RIGHT (ic))->
2183 adjustArithmeticResult (ic);
2186 freeAsmop (IC_LEFT (ic), NULL, ic,
2187 (RESULTONSTACK (ic) ? FALSE : TRUE));
2188 freeAsmop (IC_RIGHT (ic), NULL, ic,
2189 (RESULTONSTACK (ic) ? FALSE : TRUE));
2190 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2193 /*-----------------------------------------------------------------*/
2194 /* genMultOneByte : 8 bit multiplication & division */
2195 /*-----------------------------------------------------------------*/
2197 genMultOneByte (operand * left, operand * right, operand * result)
2199 sym_link *opetype = operandType (result);
2203 /* (if two literals, the value is computed before) */
2204 /* if one literal, literal on the right */
2205 if (AOP_TYPE (left) == AOP_LIT) {
2211 size = AOP_SIZE (result);
2213 if (SPEC_USIGN (opetype)) {
2214 emitcode ("mul", "%s,%s", aopGet (AOP (left), 0),
2215 aopGet (AOP (right), 0));
2218 emitcode ("muls", "%s,%s", aopGet (AOP (left), 0),
2219 aopGet (AOP (right), 0));
2221 aopPut (AOP (result), "r0", 0);
2223 aopPut (AOP (result), "r1", 1);
2226 if (SPEC_USIGN (opetype)) {
2228 aopPut (AOP (result), zero, offset++);
2233 lbl = newiTempLabel (NULL);
2234 emitcode ("ldi", "r24,0");
2235 emitcode ("brcc", "L%05d", lbl->key);
2236 emitcode ("ldi", "r24,lo8(-1)");
2237 emitcode ("", "L%05d:", lbl->key);
2239 aopPut (AOP (result), "r24",
2247 /*-----------------------------------------------------------------*/
2248 /* genMult - generates code for multiplication */
2249 /*-----------------------------------------------------------------*/
2251 genMult (iCode * ic)
2253 operand *left = IC_LEFT (ic);
2254 operand *right = IC_RIGHT (ic);
2255 operand *result = IC_RESULT (ic);
2257 /* assign the amsops */
2258 aopOp (left, ic, FALSE);
2259 aopOp (right, ic, FALSE);
2260 aopOp (result, ic, TRUE);
2262 /* if both are of size == 1 */
2263 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1) {
2264 genMultOneByte (left, right, result);
2268 /* should have been converted to function call */
2272 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2273 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2274 freeAsmop (result, NULL, ic, TRUE);
2277 /*-----------------------------------------------------------------*/
2278 /* genDiv - generates code for division */
2279 /*-----------------------------------------------------------------*/
2283 /* should have been converted to function call */
2287 /*-----------------------------------------------------------------*/
2288 /* genMod - generates code for division */
2289 /*-----------------------------------------------------------------*/
2293 /* should have been converted to function call */
2305 /*-----------------------------------------------------------------*/
2306 /* revavrcnd - reverse a conditional for avr */
2307 /*-----------------------------------------------------------------*/
2309 revavrcnd (int type)
2321 for (i = 0; i < (sizeof (rar) / sizeof (rar[0])); i++) {
2322 if (rar[i].type == type)
2323 return rar[i].rtype;
2324 if (rar[i].rtype == type)
2327 assert (1); /* cannot happen */
2328 return 0; /* makes the compiler happy */
2331 static char *br_name[4] = { "breq", "brne", "brlt", "brge" };
2332 static char *br_uname[4] = { "breq", "brne", "brlo", "brcc" };
2334 /*-----------------------------------------------------------------*/
2335 /* genBranch - generate the branch instruction */
2336 /*-----------------------------------------------------------------*/
2338 genBranch (iCode * ifx, int br_type, int sign)
2340 int tj = (IC_TRUE (ifx) ? 1 : 0);
2342 if (tj) { /* if true jump */
2343 char *nm = (sign ? br_name[br_type] : br_uname[br_type]);
2344 emitcode (nm, "L%05d", IC_TRUE (ifx)->key);
2346 else { /* if false jump */
2347 int rtype = revavrcnd (br_type);
2348 char *nm = (sign ? br_name[rtype] : br_uname[rtype]);
2349 emitcode (nm, "L%05d", IC_FALSE (ifx)->key);
2354 /*-----------------------------------------------------------------*/
2355 /* genCmp - compare & jump */
2356 /*-----------------------------------------------------------------*/
2358 genCmp (iCode * ic, iCode * ifx, int br_type)
2360 operand *left, *right, *result;
2361 sym_link *letype, *retype;
2363 int sign, size, offset = 0;
2365 left = IC_LEFT (ic);
2366 right = IC_RIGHT (ic);
2367 result = IC_RESULT (ic);
2369 letype = getSpec (operandType (left));
2370 retype = getSpec (operandType (right));
2371 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
2373 /* assign the amsops */
2374 aopOp (left, ic, FALSE);
2375 aopOp (right, ic, FALSE);
2376 aopOp (result, ic, TRUE);
2377 size = AOP_SIZE (left);
2381 if (AOP_TYPE (right) == AOP_LIT) {
2382 emitcode ("cpi", "%s,lo8(%d)",
2383 aopGet (AOP (left), 0),
2385 floatFromVal (AOP (IC_RIGHT (ic))->
2387 genBranch (ifx, br_type, sign);
2389 else { /* right != literal */
2390 emitcode ("cp", "%s,%s",
2391 aopGet (AOP (left), 0),
2392 aopGet (AOP (right), 0));
2393 genBranch (ifx, br_type, sign);
2396 else { /* size != 1 */
2399 emitcode ("cp", "%s,%s",
2400 aopGet (AOP (left), 0),
2401 aopGet (AOP (right), 0));
2403 emitcode ("cpc", "%s,%s",
2404 aopGet (AOP (left), offset),
2405 aopGet (AOP (right),
2409 genBranch (ifx, br_type, sign);
2413 emitcode ("clr", "r0");
2416 emitcode ("cp", "%s,%s",
2417 aopGet (AOP (left), 0),
2418 aopGet (AOP (right), 0));
2420 emitcode ("cpc", "%s,%s",
2421 aopGet (AOP (left), offset),
2422 aopGet (AOP (right), offset));
2425 lbl = newiTempLabel (NULL);
2426 br_type = revavrcnd (br_type);
2428 emitcode (br_uname[br_type], "L%05d", lbl->key);
2430 emitcode (br_name[br_type], "L%05d", lbl->key);
2431 emitcode ("inc", "r0");
2432 emitcode ("", "L%05d:", lbl->key);
2433 aopPut (AOP (result), "r0", 0);
2434 size = AOP_SIZE (result) - 1;
2437 aopPut (AOP (result), zero, offset++);
2440 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2441 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2442 freeAsmop (result, NULL, ic, TRUE);
2445 /*-----------------------------------------------------------------*/
2446 /* genCmpGt :- greater than comparison */
2447 /*-----------------------------------------------------------------*/
2449 genCmpGt (iCode * ic, iCode * ifx)
2451 /* should have transformed by the parser */
2455 /*-----------------------------------------------------------------*/
2456 /* genCmpLt - less than comparisons */
2457 /*-----------------------------------------------------------------*/
2459 genCmpLt (iCode * ic, iCode * ifx)
2461 genCmp (ic, ifx, AVR_LT);
2464 /*-----------------------------------------------------------------*/
2465 /* genCmpEq - generates code for equal to */
2466 /*-----------------------------------------------------------------*/
2468 genCmpEq (iCode * ic, iCode * ifx)
2470 genCmp (ic, ifx, AVR_EQ);
2473 /*-----------------------------------------------------------------*/
2474 /* genCmpNe - generates code for not equal to */
2475 /*-----------------------------------------------------------------*/
2477 genCmpNe (iCode * ic, iCode * ifx)
2479 genCmp (ic, ifx, AVR_NE);
2482 /*-----------------------------------------------------------------*/
2483 /* genCmpGe - generates code for greater than equal to */
2484 /*-----------------------------------------------------------------*/
2486 genCmpGe (iCode * ic, iCode * ifx)
2488 genCmp (ic, ifx, AVR_GE);
2491 /*-----------------------------------------------------------------*/
2492 /* genCmpLe - generates code for less than equal to */
2493 /*-----------------------------------------------------------------*/
2495 genCmpLe (iCode * ic, iCode * ifx)
2497 operand *left = IC_LEFT (ic);
2498 operand *right = IC_RIGHT (ic);
2500 IC_RIGHT (ic) = left;
2501 IC_LEFT (ic) = right;
2502 genCmp (ic, ifx, AVR_GE);
2505 /*-----------------------------------------------------------------*/
2506 /* ifxForOp - returns the icode containing the ifx for operand */
2507 /*-----------------------------------------------------------------*/
2509 ifxForOp (operand * op, iCode * ic)
2511 /* if true symbol then needs to be assigned */
2512 if (IS_TRUE_SYMOP (op))
2515 /* if this has register type condition and
2516 the next instruction is ifx with the same operand
2517 and live to of the operand is upto the ifx only then */
2519 ic->next->op == IFX &&
2520 IC_COND (ic->next)->key == op->key &&
2521 OP_SYMBOL (op)->liveTo <= ic->next->seq) return ic->next;
2526 /*-----------------------------------------------------------------*/
2527 /* genAndOp - for && operation */
2528 /*-----------------------------------------------------------------*/
2530 genAndOp (iCode * ic)
2532 operand *left, *right, *result;
2536 /* note here that && operations that are in an
2537 if statement are taken away by backPatchLabels
2538 only those used in arthmetic operations remain */
2539 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2540 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2541 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
2543 tlbl = newiTempLabel (NULL);
2544 toBoolean (left, "r0", TRUE);
2545 toBoolean (right, "r1", TRUE);
2546 emitcode ("and", "r0,r1");
2547 emitcode ("ldi", "r24,1");
2548 emitcode ("breq", "L%05d", tlbl->key);
2549 emitcode ("dec", "r24");
2550 emitcode ("", "L%05d:", tlbl->key);
2551 aopPut (AOP (result), "r24", 0);
2552 size = AOP_SIZE (result) - 1;
2555 aopPut (AOP (result), zero, offset++);
2557 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2558 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2559 freeAsmop (result, NULL, ic, TRUE);
2563 /*-----------------------------------------------------------------*/
2564 /* genOrOp - for || operation */
2565 /*-----------------------------------------------------------------*/
2567 genOrOp (iCode * ic)
2569 operand *left, *right, *result;
2573 /* note here that || operations that are in an
2574 if statement are taken away by backPatchLabels
2575 only those used in arthmetic operations remain */
2576 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2577 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2578 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
2580 tlbl = newiTempLabel (NULL);
2581 toBoolean (left, "r0", TRUE);
2582 toBoolean (right, "r0", FALSE);
2583 emitcode ("ldi", "r24,1");
2584 emitcode ("breq", "L%05d", tlbl->key);
2585 emitcode ("dec", "r24");
2586 emitcode ("", "L%05d:", tlbl->key);
2587 aopPut (AOP (result), "r24", 0);
2588 size = AOP_SIZE (result) - 1;
2591 aopPut (AOP (result), zero, offset++);
2593 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2594 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2595 freeAsmop (result, NULL, ic, TRUE);
2599 AVR_AND = 0, AVR_OR, AVR_XOR
2601 static char *bopnames_lit[] = { "andi", "ori" };
2602 static char *bopnames[] = { "and", "or", "eor" };
2603 /*-----------------------------------------------------------------*/
2604 /* genBitWise - generate bitwise operations */
2605 /*-----------------------------------------------------------------*/
2607 genBitWise (iCode * ic, iCode * ifx, int bitop)
2609 operand *left, *right, *result;
2610 int size, offset = 0;
2615 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2616 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2617 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
2619 size = AOP_SIZE (left);
2621 if (ifx) { /* used only for jumps */
2622 if (AOP_TYPE (right) == AOP_LIT &&
2623 (bitop == AVR_AND || bitop == AVR_OR)) {
2625 (int) floatFromVal (AOP (right)->aopu.
2627 int p2 = powof2 (lit);
2628 if (bitop == AVR_AND && p2) { /* right side is a power of 2 */
2629 l = aopGet (AOP (left), p2 / 8);
2630 if (IC_TRUE (ifx)) {
2631 emitcode ("sbrc", "%s,%d", l,
2633 emitcode ("rjmp", "L%05d",
2634 IC_TRUE (ifx)->key);
2637 emitcode ("sbrs", "%s,%d", l,
2639 emitcode ("rjmp", "L%05d",
2640 IC_FALSE (ifx)->key);
2643 else { /* right not power of two */
2644 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2646 if (eh && AOP_ISHIGHREG(AOP(IC_LEFT(ic)),0)) {
2647 emitcode (bopnames_lit[bitop],
2649 aopGet (AOP (IC_LEFT (ic)), 0), lit);
2652 MOVR24 (aopGet (AOP (IC_LEFT (ic)), 0));
2653 emitcode (bopnames_lit[bitop], "r24,lo8(%d)", lit);
2655 lbl = newiTempLabel (NULL);
2656 if (IC_TRUE (ifx)) {
2657 emitcode ("breq", "L%05d", lbl->key);
2658 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2661 emitcode ("brne", "L%05d", lbl->key);
2662 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)-> key);
2664 emitcode ("", "L%05d:", lbl->key);
2666 else if (size == 2) {
2667 emitcode ("mov", "r24,%s", aopGet (AOP (IC_LEFT (ic)), 0));
2668 emitcode ("mov", "r25,%s", aopGet (AOP (IC_LEFT (ic)), 1));
2669 emitcode (bopnames_lit[bitop], "r24,lo8(%d)", lit);
2670 emitcode (bopnames_lit[bitop], "r25,hi8(%d)", lit);
2671 emitcode ("sbiw", "r24,0");
2672 lbl = newiTempLabel (NULL);
2673 if (IC_TRUE (ifx)) {
2674 emitcode ("breq", "L%05d", lbl->key);
2675 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2678 emitcode ("brne", "L%05d", lbl->key);
2679 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2681 emitcode ("", "L%05d:", lbl->key);
2684 lbl = newiTempLabel (NULL);
2685 lbl1 = newiTempLabel (NULL);
2687 if (eh && AOP_ISHIGHREG(AOP(IC_LEFT(ic)),offset)) {
2688 emitcode (bopnames_lit [bitop], "%s,lo8(%d)",
2689 aopGet (AOP (IC_LEFT (ic)), offset),
2693 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
2695 emitcode ("andi", "r24,lo8(%d)", lit);
2697 emitcode ("brne", "L%05d", lbl->key);
2702 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)-> key);
2704 emitcode ("rjmp", "L%05d", lbl1->key);
2705 emitcode ("", "L%05d:", lbl->key);
2708 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2709 emitcode ("", "L%05d:", lbl1->key);
2714 else { /* right is not a literal */
2715 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2716 int reh = OP_SYMBOL (right)->liveTo <= ic->seq;
2719 emitcode (bopnames[bitop], "%s,%s", aopGet (AOP (IC_LEFT (ic)), 0),
2720 aopGet (AOP (IC_RIGHT (ic)), 0));
2723 emitcode (bopnames[bitop], "%s,%s",
2724 aopGet (AOP (IC_RIGHT (ic)), 0),
2725 aopGet (AOP (IC_LEFT (ic)), 0));
2728 MOVR0 (aopGet (AOP (IC_LEFT (ic)), 0));
2729 emitcode (bopnames[bitop], "r0,%s",
2730 aopGet (AOP (IC_RIGHT (ic)), 0));
2732 lbl = newiTempLabel (NULL);
2733 if (IC_TRUE (ifx)) {
2734 emitcode ("breq", "L%05d", lbl->key);
2735 emitcode ("rjmp", "L%05d",
2736 IC_TRUE (ifx)->key);
2739 emitcode ("brne", "L%05d", lbl->key);
2740 emitcode ("rjmp", "L%05d",
2741 IC_FALSE (ifx)->key);
2743 emitcode ("", "L%05d:", lbl->key);
2745 else if (size == 2) {
2746 emitcode ("mov", "r24,%s",
2747 aopGet (AOP (IC_LEFT (ic)), 0));
2748 emitcode ("mov", "r25,%s",
2749 aopGet (AOP (IC_LEFT (ic)), 1));
2750 emitcode (bopnames[bitop], "r24,%s",
2751 aopGet (AOP (IC_RIGHT (ic)), 0));
2752 emitcode (bopnames[bitop], "r25,%s",
2753 aopGet (AOP (IC_RIGHT (ic)), 1));
2754 emitcode ("sbiw", "r24,0");
2755 lbl = newiTempLabel (NULL);
2756 if (IC_TRUE (ifx)) {
2757 emitcode ("breq", "L%05d", lbl->key);
2758 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2761 emitcode ("brne", "L%05d", lbl->key);
2762 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2764 emitcode ("", "L%05d:", lbl->key);
2767 lbl = newiTempLabel (NULL);
2768 lbl1 = newiTempLabel (NULL);
2771 emitcode (bopnames[bitop], "%s,%s",
2772 aopGet (AOP (IC_LEFT (ic)), offset),
2773 aopGet (AOP (IC_RIGHT (ic)), offset));
2776 emitcode (bopnames[bitop], "%s,%s",
2777 aopGet (AOP (IC_RIGHT (ic)), offset),
2778 aopGet (AOP (IC_LEFT (ic)), offset));
2781 MOVR0 (aopGet (AOP (IC_LEFT (ic)), offset));
2782 emitcode (bopnames[bitop], "r0,%s",
2783 aopGet (AOP (IC_RIGHT (ic)), offset));
2785 emitcode ("brne", "L%05d", lbl->key);
2790 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2792 emitcode ("rjmp", "L%05d", lbl1->key);
2793 emitcode ("", "L%05d:", lbl->key);
2796 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2797 emitcode ("", "L%05d:", lbl1->key);
2804 /* result needs to go a register */
2805 samerl = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2806 samerr = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)));
2808 if (AOP_TYPE (right) == AOP_LIT) {
2810 (int) floatFromVal (AOP (right)->aopu.
2812 if (((lit >> (8 * offset)) & 0xff) == 0) {
2813 if (bitop == AVR_AND) {
2814 aopPut (AOP (result), zero, offset++);
2817 else if (bitop == AVR_OR) {
2819 aopPut (AOP (result),
2829 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT &&
2830 AOP_ISHIGHREG(AOP(IC_LEFT(ic)),offset) &&
2831 (bitop == AVR_AND || bitop == AVR_OR)) {
2832 emitcode (bopnames_lit[bitop], "%s,%s(%d)",
2833 aopGet (AOP (IC_LEFT (ic)), offset),
2835 (int) floatFromVal (AOP (right)-> aopu.aop_lit));
2838 emitcode (bopnames[bitop], "%s,%s",
2839 aopGet (AOP (IC_LEFT (ic)), offset),
2840 aopGet (AOP (IC_RIGHT (ic)), offset));
2844 emitcode (bopnames[bitop], "%s,%s",
2845 aopGet (AOP (IC_RIGHT (ic)), offset),
2846 aopGet (AOP (IC_LEFT (ic)), offset));
2849 aopPut (AOP (IC_RESULT (ic)),
2850 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2851 emitcode (bopnames[bitop],
2852 aopGet (AOP (IC_RESULT (ic)), offset),
2853 aopGet (AOP (IC_RIGHT (ic)), offset));
2858 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2859 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2860 freeAsmop (result, NULL, ic, TRUE);
2863 /*-----------------------------------------------------------------*/
2864 /* genAnd - code for and */
2865 /*-----------------------------------------------------------------*/
2867 genAnd (iCode * ic, iCode * ifx)
2869 genBitWise (ic, ifx, AVR_AND);
2872 /*-----------------------------------------------------------------*/
2873 /* genOr - code for or */
2874 /*-----------------------------------------------------------------*/
2876 genOr (iCode * ic, iCode * ifx)
2878 genBitWise (ic, ifx, AVR_OR);
2881 /*-----------------------------------------------------------------*/
2882 /* genXor - code for xclusive or */
2883 /*-----------------------------------------------------------------*/
2885 genXor (iCode * ic, iCode * ifx)
2887 genBitWise (ic, ifx, AVR_XOR);
2890 /*-----------------------------------------------------------------*/
2891 /* genInline - write the inline code out */
2892 /*-----------------------------------------------------------------*/
2894 genInline (iCode * ic)
2896 char *buffer, *bp, *bp1;
2898 _G.inLine += (!options.asmpeep);
2900 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
2901 strcpy (buffer, IC_INLINE (ic));
2903 /* emit each line as a code */
2924 /* emitcode("",buffer); */
2925 _G.inLine -= (!options.asmpeep);
2928 /*-----------------------------------------------------------------*/
2929 /* genRotC - rotate right/left with carry , lr = 1 rotate right */
2930 /*-----------------------------------------------------------------*/
2932 genRotC (iCode * ic, int lr)
2934 operand *left, *result;
2935 int size, offset = 0;
2937 /* rotate right with carry */
2938 left = IC_LEFT (ic);
2939 result = IC_RESULT (ic);
2940 aopOp (left, ic, FALSE);
2941 aopOp (result, ic, FALSE);
2943 /* move it to the result */
2944 size = AOP_SIZE (result);
2945 if (!sameRegs (AOP (left), AOP (result))) {
2948 aopPut (AOP (result),
2949 aopGet (AOP (left), offset), offset);
2952 size = AOP_SIZE (result);
2960 emitcode ("sbrc", "%s,%d", aopGet (AOP (result), offset),
2962 emitcode ("sec", "");
2965 emitcode ((lr ? "ror" : "rol"), "%s",
2966 aopGet (AOP (result), offset));
2972 freeAsmop (left, NULL, ic, TRUE);
2973 freeAsmop (result, NULL, ic, TRUE);
2976 /*-----------------------------------------------------------------*/
2977 /* genRRC - rotate right with carry */
2978 /*-----------------------------------------------------------------*/
2985 /*-----------------------------------------------------------------*/
2986 /* genRLC - generate code for rotate left with carry */
2987 /*-----------------------------------------------------------------*/
2994 /*-----------------------------------------------------------------*/
2995 /* genGetHbit - generates code get highest order bit */
2996 /*-----------------------------------------------------------------*/
2998 genGetHbit (iCode * ic)
3000 operand *left, *result;
3003 left = IC_LEFT (ic);
3004 result = IC_RESULT (ic);
3005 aopOp (left, ic, FALSE);
3006 aopOp (result, ic, FALSE);
3008 size = AOP_SIZE (result);
3009 if (!sameRegs (AOP (left), AOP (result))) {
3010 emitcode ("clr", "%s", aopGet (AOP (result), size - 1));
3011 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3012 emitcode ("subi", "%s,lo8(-1)",
3013 aopGet (AOP (result), size - 1));
3016 emitcode ("clr", "r0");
3017 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3018 emitcode ("subi", "r0,lo8(-1)");
3019 aopPut (AOP (result), "r0", 0);
3024 emitcode ("clr", aopGet (AOP (result), offset++));
3026 freeAsmop (left, NULL, ic, TRUE);
3027 freeAsmop (result, NULL, ic, TRUE);
3030 /*-----------------------------------------------------------------*/
3031 /* genShiftLeftLit - shift left by a known amount */
3032 /*-----------------------------------------------------------------*/
3034 genShiftLeftLit (iCode * ic)
3036 operand *left, *right, *result;
3037 int size, shCount, offset = 0;
3040 right = IC_RIGHT (ic);
3041 left = IC_LEFT (ic);
3042 result = IC_RESULT (ic);
3044 aopOp (left, ic, FALSE);
3045 aopOp (result, ic, FALSE);
3046 size = AOP_SIZE (result);
3047 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3049 if (shCount > (size * 8 - 1)) {
3051 aopPut (AOP (result), zero, offset++);
3056 if (!sameRegs (AOP (left), AOP (result)))
3057 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3059 if (AOP_ISHIGHREG(AOP(result),0)) {
3060 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3061 emitcode ("andi", "%s,0xf0");
3063 emitcode ("ldi","r24,0xf0");
3064 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3065 emitcode ("and", "%s,r24");
3070 emitcode ("add", "%s,%s", aopGet (AOP (result), 0),
3071 aopGet (AOP (result), 0));
3075 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3078 if (shCount >= 12) {
3079 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3080 aopPut (AOP (result), zero, 0);
3081 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3082 if (AOP_ISHIGHREG(AOP(result),1)) {
3083 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3085 emitcode ("ldi","r24,0xf0");
3086 emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
3092 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3093 aopPut (AOP (result), zero, 0);
3099 if (!sameRegs (AOP (left), AOP (result))) {
3100 aopPut (AOP (result), aopGet (AOP (left), 0),
3102 aopPut (AOP (result), aopGet (AOP (left), 1),
3105 emitcode ("mov", "r24,%s", aopGet (AOP (result), 0));
3106 emitcode ("andi", "r24,0x0f");
3107 if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
3108 emitcode("ldi","r25,0xf0");
3110 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3111 if (AOP_ISHIGHREG(AOP(result),0)) {
3112 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 0));
3114 emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
3116 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3117 if (AOP_ISHIGHREG(AOP(result),1)) {
3118 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3120 emitcode ("and", "%s,r25", aopGet (AOP (result), 1));
3122 emitcode ("or", "%s,r24", aopGet (AOP (result), 1));
3124 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3125 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3128 if (!lByteZ && !sameRegs (AOP (result), AOP (left))
3132 aopPut (AOP (result),
3133 aopGet (AOP (left), offset), offset);
3139 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3142 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3143 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3148 assert ("shifting generic pointer ?\n");
3151 /* 32 bits we do only byte boundaries */
3152 if (shCount >= 24) {
3153 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3154 aopPut (AOP (result), zero, 2);
3155 aopPut (AOP (result), zero, 1);
3156 aopPut (AOP (result), zero, 0);
3160 if (shCount >= 16) {
3161 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3162 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3163 aopPut (AOP (result), zero, 1);
3164 aopPut (AOP (result), zero, 0);
3169 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3170 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3171 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3172 aopPut (AOP (result), zero, 0);
3176 if (!lByteZ && !sameRegs (AOP (left), AOP (right))) {
3179 aopPut (AOP (result),
3180 aopGet (AOP (left), offset), offset);
3184 size = AOP_SIZE (result);
3190 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3191 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3192 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3193 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3198 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3199 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3200 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3205 emitcode ("lsl", "%s", aopGet (AOP (result), 2));
3206 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3211 emitcode ("lsl", "%s", aopGet (AOP (result), 3));
3219 freeAsmop (left, NULL, ic, TRUE);
3220 freeAsmop (right, NULL, ic, TRUE);
3221 freeAsmop (result, NULL, ic, TRUE);
3224 /*-----------------------------------------------------------------*/
3225 /* genLeftShift - generates code for left shifting */
3226 /*-----------------------------------------------------------------*/
3228 genLeftShift (iCode * ic)
3230 operand *left, *right, *result;
3234 right = IC_RIGHT (ic);
3235 left = IC_LEFT (ic);
3236 result = IC_RESULT (ic);
3238 aopOp (right, ic, FALSE);
3240 if (AOP_TYPE (right) == AOP_LIT) {
3241 genShiftLeftLit (ic);
3246 aopOp (left, ic, FALSE);
3247 aopOp (result, ic, FALSE);
3248 size = AOP_SIZE (result);
3250 if (AOP_SIZE (right) > 1) {
3251 if (isRegPair (AOP (right))) {
3252 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3255 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3256 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3260 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3262 if (!sameRegs (AOP (left), AOP (result))) {
3264 aopPut (AOP (result), aopGet (AOP (left), offset),
3268 size = AOP_SIZE (result);
3270 tlbl = newiTempLabel (NULL);
3271 emitcode ("", "L%05d:", tlbl->key);
3275 emitcode ("rol", "%s", aopGet (AOP (result), offset));
3277 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3280 if (AOP_SIZE (right) > 1)
3281 emitcode ("sbiw", "r24,1");
3283 emitcode ("dec", "r24");
3284 emitcode ("brne", "L%05d", tlbl->key);
3286 freeAsmop (left, NULL, ic, TRUE);
3287 freeAsmop (right, NULL, ic, TRUE);
3288 freeAsmop (result, NULL, ic, TRUE);
3291 /*-----------------------------------------------------------------*/
3292 /* genShiftRightLit - generate for right shift with known count */
3293 /*-----------------------------------------------------------------*/
3295 genShiftRightLit (iCode * ic)
3297 operand *left = IC_LEFT (ic)
3298 , *right = IC_RIGHT (ic)
3299 , *result = IC_RESULT (ic);
3300 int size, shCount, offset = 0;
3302 sym_link *letype = getSpec (operandType (left));
3303 int sign = !SPEC_USIGN (letype);
3305 right = IC_RIGHT (ic);
3306 left = IC_LEFT (ic);
3307 result = IC_RESULT (ic);
3309 aopOp (left, ic, FALSE);
3310 aopOp (result, ic, FALSE);
3311 size = AOP_SIZE (result);
3312 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3314 /* if signed then give up and use a loop to shift */
3317 if (!sameRegs (AOP (left), AOP (result))) {
3319 aopPut (AOP (result),
3320 aopGet (AOP (left), offset), offset);
3323 size = size = AOP_SIZE (result);
3326 /* be as economical as possible */
3331 size = AOP_SIZE (result);
3333 if (offset == (size - 1))
3334 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3336 emitcode ("lsr", "%s", aopGet (AOP (result), offset));
3342 emitcode ("ldi", "r24,lo8(%d)", shCount);
3343 tlbl = newiTempLabel (NULL);
3344 emitcode ("", "L%05d:", tlbl->key);
3347 if (offset == (size - 1))
3348 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3350 emitcode ("lsr", "%s", aopGet (AOP (result), offset));
3353 emitcode ("dec", "r24");
3354 emitcode ("brne", "L%05d", tlbl->key);
3358 if (shCount > (size * 8 - 1)) {
3360 aopPut (AOP (result), zero, offset++);
3363 /* for unsigned we can much more efficient */
3366 if (!sameRegs (AOP (left), AOP (result)))
3367 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3369 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3370 if (AOP_ISHIGHREG(AOP(result),0)) {
3371 emitcode ("andi", "%s,0x0f",aopGet(AOP(result),0));
3373 emitcode ("ldi","r24,0x0f");
3374 emitcode ("and", "%s,r24",aopGet(AOP(result),0));
3379 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3382 if (shCount >= 12) {
3383 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3384 aopPut (AOP (result), zero, 1);
3385 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3386 if (AOP_ISHIGHREG(AOP(result),0)) {
3387 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3389 emitcode ("ldi","r24,0x0f");
3390 emitcode ("and", "%s,r24",aopGet(AOP(result),0));
3396 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3397 aopPut (AOP (result), zero, 1);
3403 if (!sameRegs (AOP (left), AOP (result))) {
3404 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3405 aopPut (AOP (result), aopGet (AOP (left), 1), 1);
3407 if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
3408 emitcode("ldi","r25,0x0f");
3410 emitcode ("mov", "r24,%s", aopGet (AOP (result), 1));
3411 emitcode ("andi", "r24,0xf0");
3412 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3413 if (AOP_ISHIGHREG(AOP(result),0)) {
3414 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3416 emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
3418 emitcode ("or", "%s,r24", aopGet (AOP (result), 0));
3419 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3420 if (AOP_ISHIGHREG(AOP(result),1)) {
3421 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 1));
3423 emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
3426 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3427 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3431 if (!hByteZ && !sameRegs (AOP (result), AOP (left))
3435 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3441 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3444 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3445 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3451 assert ("shifting generic pointer ?\n");
3454 /* 32 bits we do only byte boundaries */
3455 if (shCount >= 24) {
3456 aopPut (AOP (result), aopGet (AOP (left), 3), 0);
3457 aopPut (AOP (result), zero, 1);
3458 aopPut (AOP (result), zero, 2);
3459 aopPut (AOP (result), zero, 3);
3463 if (shCount >= 16) {
3464 aopPut (AOP (result), aopGet (AOP (left), 3), 1);
3465 aopPut (AOP (result), aopGet (AOP (left), 2), 0);
3466 aopPut (AOP (result), zero, 2);
3467 aopPut (AOP (result), zero, 3);
3472 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3473 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3474 aopPut (AOP (result), aopGet (AOP (left), 3), 2);
3475 aopPut (AOP (result), zero, 3);
3479 if (!hByteZ && !sameRegs (AOP (left), AOP (right))) {
3482 aopPut (AOP (result),
3483 aopGet (AOP (left), offset), offset);
3487 size = AOP_SIZE (result);
3493 emitcode ("lsr", "%s", aopGet (AOP (result), 3));
3494 emitcode ("ror", "%s", aopGet (AOP (result), 2));
3495 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3496 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3501 emitcode ("lsr", "%s", aopGet (AOP (result), 2));
3502 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3503 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3508 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3509 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3514 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3521 freeAsmop (left, NULL, ic, TRUE);
3522 freeAsmop (right, NULL, ic, TRUE);
3523 freeAsmop (result, NULL, ic, TRUE);
3526 /*-----------------------------------------------------------------*/
3527 /* genRightShift - generate code for right shifting */
3528 /*-----------------------------------------------------------------*/
3530 genRightShift (iCode * ic)
3532 operand *right, *left, *result;
3535 int sign = 0, first = 1;
3538 aopOp (right = IC_RIGHT (ic), ic, FALSE);
3540 if (AOP_TYPE (right) == AOP_LIT) {
3541 genShiftRightLit (ic);
3545 if (AOP_SIZE (right) > 1) {
3546 if (isRegPair (AOP (right))) {
3547 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3550 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3551 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3555 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3557 aopOp (left = IC_LEFT (ic), ic, FALSE);
3558 aopOp (result = IC_RESULT (ic), ic, FALSE);
3559 size = AOP_SIZE (result);
3560 tlbl = newiTempLabel (NULL);
3561 emitcode ("", "L%05d:", tlbl->key);
3563 letype = getSpec (operandType (left));
3564 sign = !SPEC_USIGN (letype);
3565 if (!sameRegs (AOP (left), AOP (result))) {
3567 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3570 size = AOP_SIZE (result);
3572 size = AOP_SIZE (result);
3576 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3578 emitcode ("lsr", "%s", aopGet (AOP (result), offset));
3582 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3585 if (AOP_SIZE (right) > 1)
3586 emitcode ("sbiw", "r24,1");
3588 emitcode ("dec", "r24");
3589 emitcode ("brne", "L%05d", tlbl->key);
3591 freeAsmop (left, NULL, ic, TRUE);
3592 freeAsmop (result, NULL, ic, TRUE);
3595 /*-----------------------------------------------------------------*/
3596 /* RRsh - shift right rn by known count */
3597 /*-----------------------------------------------------------------*/
3599 RRsh (int shCount,int reg)
3601 shCount &= 0x0007; // shCount : 0..7
3607 emitcode ("lsr", "r%d",reg);
3610 emitcode ("lsr", "r%d",reg);
3611 emitcode ("lsr", "r%d",reg);
3614 emitcode ("swap", "r%d",reg);
3615 emitcode ("lsl", "r%d",reg);
3618 emitcode ("swap", "r%d",reg);
3621 emitcode ("swap", "r%d",reg);
3622 emitcode ("lsr", "r%d",reg);
3625 emitcode ("swap","r%d",reg);
3626 emitcode ("lsr", "r%d",reg);
3627 emitcode ("lsr", "r%d",reg);
3630 emitcode ("swap","r%d",reg);
3631 emitcode ("lsr", "r%d",reg);
3632 emitcode ("lsr", "r%d",reg);
3633 emitcode ("lsr", "r%d",reg);
3638 /*-----------------------------------------------------------------*/
3639 /* RLsh - shift left rn by known count */
3640 /*-----------------------------------------------------------------*/
3642 RLsh (int shCount, int reg)
3644 shCount &= 0x0007; // shCount : 0..7
3650 emitcode ("lsl", "r%d",reg);
3653 emitcode ("lsl", "r%d",reg);
3654 emitcode ("lsl", "r%d",reg);
3657 emitcode ("swap","r%d",reg);
3658 emitcode ("lsr", "r%d",reg);
3661 emitcode ("swap", "r%d",reg);
3664 emitcode ("swap","r%d",reg);
3665 emitcode ("lsl", "r%d",reg);
3668 emitcode ("swap","r%d",reg);
3669 emitcode ("lsl", "r%d",reg);
3670 emitcode ("lsl", "r%d",reg);
3673 emitcode ("swap","r%d",reg);
3674 emitcode ("lsl", "r%d",reg);
3675 emitcode ("lsl", "r%d",reg);
3676 emitcode ("lsl", "r%d",reg);
3681 /*-----------------------------------------------------------------*/
3682 /* genUnpackBits - generates code for unpacking bits */
3683 /*-----------------------------------------------------------------*/
3685 genUnpackBits (operand * result, char *rname, int ptype)
3693 etype = getSpec (operandType (result));
3694 rsize = getSize (operandType (result));
3695 /* read the first byte */
3702 emitcode ("ld", "r24,%s+", rname);
3706 emitcode ("lpm", "r24,%s+", rname);
3710 emitcode ("call","__gptrget_pi");
3711 emitcode ("mov","r24,r0");
3715 rlen = SPEC_BLEN (etype);
3717 /* if we have bitdisplacement then it fits */
3718 /* into this byte completely or if length is */
3719 /* less than a byte */
3720 if ((shCnt = SPEC_BSTR (etype)) || (SPEC_BLEN (etype) <= 8)) {
3722 /* shift right acc */
3725 emitcode ("andi", "r24,lo(0x%x)",
3726 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
3727 aopPut (AOP (result), "r24", offset++);
3731 /* bit field did not fit in a byte */
3732 aopPut (AOP (result), "r24", offset++);
3742 emitcode ("ld", "r24,%s+");
3746 emitcode ("lpm", "r24,%s+");
3750 emitcode ("call", "__gptrget_pi");
3755 /* if we are done */
3759 aopPut (AOP (result), "r24", offset++);
3764 aopPut (AOP (result), "r24", offset++);
3768 if (offset < rsize) {
3771 aopPut (AOP (result), zero, offset++);
3776 /*-----------------------------------------------------------------*/
3777 /* genDataPointerGet - generates code when ptr offset is known */
3778 /*-----------------------------------------------------------------*/
3780 genDataPointerGet (operand * left, operand * result, iCode * ic)
3784 int size, offset = 0;
3785 aopOp (result, ic, TRUE);
3787 /* get the string representation of the name */
3788 l = aopGet (AOP (left), 0);
3789 size = AOP_SIZE (result);
3792 sprintf (buffer, "(%s + %d)", l, offset);
3794 sprintf (buffer, "%s", l);
3795 emitcode ("lds", "%s,%s", aopGet (AOP (result), offset++),
3799 freeAsmop (left, NULL, ic, TRUE);
3800 freeAsmop (result, NULL, ic, TRUE);
3803 /*-----------------------------------------------------------------*/
3804 /* genNearPointerGet - emitcode for near pointer fetch */
3805 /*-----------------------------------------------------------------*/
3807 genMemPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
3812 char *rname, *frname = NULL;
3813 sym_link *rtype, *retype;
3814 sym_link *ltype = operandType (left);
3816 rtype = operandType (result);
3817 retype = getSpec (rtype);
3819 aopOp (left, ic, FALSE);
3821 /* if left is rematerialisable and
3822 result is not bit variable type and
3823 the left is pointer to data space i.e
3824 lower 128 bytes of space */
3825 if (AOP_TYPE (left) == AOP_IMMD &&
3826 !IS_BITVAR (retype) && DCL_TYPE (ltype) == POINTER) {
3827 genDataPointerGet (left, result, ic);
3831 /* if the value is already in a pointer register
3832 then don't need anything more */
3833 if (!AOP_INPREG (AOP (left))) {
3834 /* otherwise get a free pointer register */
3836 preg = getFreePtr (ic, &aop, FALSE, 0);
3837 if (isRegPair (AOP (left) )) {
3838 emitcode ("movw", "%s,%s",
3839 aop->aopu.aop_ptr->name,
3840 aopGet(AOP(left),0));
3842 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
3843 aopGet (AOP (left), 0));
3844 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
3845 aopGet (AOP (left), 1));
3851 frname = aopGet(aop,0);
3855 } else if (AOP_ISZ(aop)) {
3858 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
3859 "pointer not in correct register");
3863 aopOp (result, ic, FALSE);
3865 /* if bitfield then unpack the bits */
3866 if (IS_BITVAR (retype))
3867 genUnpackBits (result, rname, POINTER);
3869 /* we have can just get the values */
3870 int size = AOP_SIZE (result);
3875 emitcode ("ld","%s,%s+",aopGet(AOP(result),offset), rname);
3877 emitcode ("ld","%s,%s",aopGet(AOP(result),offset), rname);
3882 /* now some housekeeping stuff */
3884 /* we had to allocate for this iCode */
3886 if (isRegPair (AOP (left) )) {
3887 emitcode ("movw", "%s,%s",
3888 aopGet (AOP(left),0),
3889 aop->aopu.aop_ptr->name);
3891 emitcode ("mov", "%s,%s",
3892 aopGet (AOP (left), 0),
3893 aop->aopu.aop_ptr->name);
3894 emitcode ("mov", "%s,%s",
3895 aopGet (AOP (left), 1),
3896 aop->aop_ptr2->name);
3899 freeAsmop (NULL, aop, ic, TRUE);
3902 /* we did not allocate which means left
3903 already in a pointer register, then
3904 if size > 0 && this could be used again
3905 we have to point it back to where it
3907 if ((AOP_SIZE (result) > 1 &&
3908 !OP_SYMBOL (left)->remat &&
3909 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) && !pi) {
3910 int size = AOP_SIZE (result) - 1;
3911 emitcode ("sbiw", "%s,%d",frname,size);
3916 if (pi) pi->generated = 1;
3917 freeAsmop (left, NULL, ic, TRUE);
3918 freeAsmop (result, NULL, ic, TRUE);
3922 /*-----------------------------------------------------------------*/
3923 /* genCodePointerGet - gget value from code space */
3924 /*-----------------------------------------------------------------*/
3926 genCodePointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
3929 sym_link *retype = getSpec (operandType (result));
3933 aopOp (left, ic, FALSE);
3935 /* if the operand is already in Z register
3936 then we do nothing else we move the value to Z register */
3937 if (AOP_ISZ(AOP(left))) {
3941 getFreePtr(ic,&aop,FALSE,TRUE);
3942 if (isRegPair(AOP (left))) {
3943 emitcode ("movw","r30,%s",aopGet (AOP (left), 0));
3945 emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
3946 emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
3951 aopOp (result, ic, FALSE);
3953 /* if bit then unpack */
3954 if (IS_BITVAR (retype))
3955 genUnpackBits (result, "Z", CPOINTER);
3957 size = AOP_SIZE (result);
3962 emitcode ("lpm","%s,Z+",aopGet(AOP(result),offset++));
3964 emitcode ("lpm","%s,Z",aopGet(AOP(result),offset++));
3969 /* now some housekeeping stuff */
3971 /* we had to allocate for this iCode */
3973 if (isRegPair(AOP (left))) {
3974 emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
3976 emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
3977 emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
3980 freeAsmop (NULL, aop, ic, TRUE);
3983 /* we did not allocate which means left
3984 already in a pointer register, then
3985 if size > 0 && this could be used again
3986 we have to point it back to where it
3988 if ((AOP_SIZE (result) > 1 &&
3989 !OP_SYMBOL (left)->remat &&
3990 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) &&
3992 int size = AOP_SIZE (result) - 1;
3993 emitcode ("sbiw", "r30,%d",size);
3998 if (pi) pi->generated=1;
3999 freeAsmop (left, NULL, ic, TRUE);
4000 freeAsmop (result, NULL, ic, TRUE);
4004 /*-----------------------------------------------------------------*/
4005 /* genGenPointerGet - gget value from generic pointer space */
4006 /*-----------------------------------------------------------------*/
4008 genGenPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
4012 sym_link *retype = getSpec (operandType (result));
4015 aopOp (left, ic, FALSE);
4017 /* if the operand is already in dptr
4018 then we do nothing else we move the value to dptr */
4019 if (AOP_ISZ(AOP(left))) {
4023 getFreePtr(ic,&aop,FALSE,TRUE);
4024 if (isRegPair(AOP(left))) {
4025 emitcode ("movw", "r30,%s", aopGet (AOP (left), 0));
4027 emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
4028 emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
4030 emitcode ("mov", "r24,%s", aopGet (AOP (left), 2));
4034 /* so Z register now contains the address */
4036 aopOp (result, ic, FALSE);
4038 /* if bit then unpack */
4039 if (IS_BITVAR (retype))
4040 genUnpackBits (result, "Z", GPOINTER);
4042 size = AOP_SIZE (result);
4047 emitcode ("call", "__gptrget_pi");
4049 emitcode ("call", "__gptrget");
4050 aopPut (AOP (result), "r0", offset++);
4055 /* now some housekeeping stuff */
4057 /* we had to allocate for this iCode */
4059 if (isRegPair(AOP (left))) {
4060 emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
4062 emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
4063 emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
4066 freeAsmop (NULL, aop, ic, TRUE);
4069 /* we did not allocate which means left
4070 already in a pointer register, then
4071 if size > 0 && this could be used again
4072 we have to point it back to where it
4074 if ((AOP_SIZE (result) > 1 &&
4075 !OP_SYMBOL (left)->remat &&
4076 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) &&
4078 int size = AOP_SIZE (result) - 1;
4079 emitcode ("sbiw", "r30,%d",size);
4082 if (pi) pi->generated=1;
4083 freeAsmop (left, NULL, ic, TRUE);
4084 freeAsmop (result, NULL, ic, TRUE);
4087 /*-----------------------------------------------------------------*/
4088 /* genPointerGet - generate code for pointer get */
4089 /*-----------------------------------------------------------------*/
4091 genPointerGet (iCode * ic, iCode *pi)
4093 operand *left, *result;
4094 sym_link *type, *etype;
4097 left = IC_LEFT (ic);
4098 result = IC_RESULT (ic);
4100 /* depending on the type of pointer we need to
4101 move it to the correct pointer register */
4102 type = operandType (left);
4103 etype = getSpec (type);
4104 /* if left is of type of pointer then it is simple */
4105 if (IS_PTR (type) && !IS_FUNC (type->next))
4106 p_type = DCL_TYPE (type);
4108 /* we have to go by the storage class */
4109 p_type = PTR_TYPE (SPEC_OCLS (etype));
4114 /* now that we have the pointer type we assign
4115 the pointer values */
4122 genMemPointerGet (left, result, ic, pi);
4126 genCodePointerGet (left, result, ic, pi);
4130 genGenPointerGet (left, result, ic, pi);
4136 /*-----------------------------------------------------------------*/
4137 /* genPackBits - generates code for packed bit storage */
4138 /*-----------------------------------------------------------------*/
4140 genPackBits (sym_link * etype,
4142 char *rname, int p_type)
4150 blen = SPEC_BLEN (etype);
4151 bstr = SPEC_BSTR (etype);
4153 l = aopGet (AOP (right), offset++);
4156 /* if the bit lenth is less than or */
4157 /* it exactly fits a byte then */
4158 if (SPEC_BLEN (etype) <= 8) {
4159 shCount = SPEC_BSTR (etype);
4161 /* shift left acc */
4164 if (SPEC_BLEN (etype) < 8) { /* if smaller than a byte */
4171 emitcode ("ld", "r1,%s",rname);
4175 emitcode ("push", "r1");
4176 emitcode ("push", "r24");
4177 emitcode ("call", "__gptrget");
4178 emitcode ("pop", "r1");
4179 emitcode ("mov","r24,r0");
4183 emitcode ("andi", "r24,#0x%02x", (unsigned char)
4184 ((unsigned char) (0xFF << (blen + bstr)) |
4185 (unsigned char) (0xFF >> (8 - bstr))));
4186 emitcode ("or", "r24,r1");
4187 if (p_type == GPOINTER)
4188 emitcode ("pop", "r1");
4197 emitcode("st","%s+,r24");
4201 emitcode("mov","r0,r24");
4202 emitcode ("call", "__gptrput_pi");
4207 if (SPEC_BLEN (etype) <= 8)
4210 rLen = SPEC_BLEN (etype);
4212 /* now generate for lengths greater than one byte */
4215 l = aopGet (AOP (right), offset++);
4226 emitcode ("st", "%s+,%s",rname,l);
4231 emitcode ("lcall", "__gptrput_pi");
4238 /* last last was not complete */
4240 /* save the byte & read byte */
4246 emitcode ("st","%s+,r24",rname);
4249 emitcode ("push", "r1");
4250 emitcode ("push", "r24");
4251 emitcode ("lcall", "__gptrget");
4252 emitcode ("mov","r24,r0");
4253 emitcode ("pop", "r1");
4257 emitcode ("andi", "r24,0x%02x", (((unsigned char) -1 << rLen) & 0xff));
4258 emitcode ("or", "r24,r1");
4261 if (p_type == GPOINTER)
4262 emitcode ("pop", "r1");
4270 emitcode ("st", "%s,r24", rname);
4274 emitcode ("mov","r0,r24");
4275 emitcode ("call", "__gptrput");
4280 /*-----------------------------------------------------------------*/
4281 /* genDataPointerSet - remat pointer to data space */
4282 /*-----------------------------------------------------------------*/
4284 genDataPointerSet (operand * right, operand * result, iCode * ic)
4286 int size, offset = 0;
4287 char *l, buffer[256];
4289 aopOp (right, ic, FALSE);
4291 l = aopGet (AOP (result), 0);
4292 size = AOP_SIZE (right);
4295 sprintf (buffer, "(%s + %d)", l, offset);
4297 sprintf (buffer, "%s", l);
4298 emitcode ("sts", "%s,%s", buffer,
4299 aopGet (AOP (right), offset++));
4302 freeAsmop (right, NULL, ic, TRUE);
4303 freeAsmop (result, NULL, ic, TRUE);
4306 /*-----------------------------------------------------------------*/
4307 /* genNearPointerSet - emitcode for near pointer put */
4308 /*-----------------------------------------------------------------*/
4310 genMemPointerSet (operand * right, operand * result, iCode * ic, iCode *pi)
4313 char *frname = NULL, *rname, *l;
4316 sym_link *ptype = operandType (result);
4318 retype = getSpec (operandType (right));
4320 aopOp (result, ic, FALSE);
4322 /* if the result is rematerializable &
4323 in data space & not a bit variable */
4324 if (AOP_TYPE (result) == AOP_IMMD &&
4325 DCL_TYPE (ptype) == POINTER && !IS_BITVAR (retype)) {
4326 genDataPointerSet (right, result, ic);
4329 if (!AOP_INPREG(AOP(result))) {
4330 /* otherwise get a free pointer register */
4332 getFreePtr (ic, &aop, FALSE, 0);
4333 if (isRegPair (AOP (result) )) {
4334 emitcode ("movw", "%s,%s",aop->aopu.aop_ptr->name,
4335 aopGet(AOP (result), 0));
4337 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
4338 aopGet (AOP (result), 0));
4339 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
4340 aopGet (AOP (result), 1));
4345 frname = aopGet(aop,0);
4348 aopOp (right, ic, FALSE);
4351 } else if (AOP_ISZ(aop)) {
4354 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4355 "pointer not in correct register");
4358 /* if bitfield then unpack the bits */
4359 if (IS_BITVAR (retype))
4360 genPackBits (retype, right, rname, POINTER);
4362 /* we have can just get the values */
4363 int size = AOP_SIZE (right);
4367 l = aopGet (AOP (right), offset);
4369 emitcode ("st", "%s+,%s", rname,l);
4371 emitcode ("st", "%s,%s", rname,l);
4376 /* now some housekeeping stuff */
4378 /* we had to allocate for this iCode */
4380 if (isRegPair (AOP (result) )) {
4381 emitcode ("movw", "%s,%s",
4382 aopGet(AOP(result),0),
4383 aop->aopu.aop_ptr->name);
4385 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
4386 aopGet (AOP (result), 0));
4387 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
4388 aopGet (AOP (result), 1));
4391 freeAsmop (NULL, aop, ic, TRUE);
4394 /* we did not allocate which means left
4395 already in a pointer register, then
4396 if size > 0 && this could be used again
4397 we have to point it back to where it
4399 if ((AOP_SIZE (right) > 1 &&
4400 !OP_SYMBOL (result)->remat &&
4401 (OP_SYMBOL (right)->liveTo > ic->seq || ic->depth)) && !pi) {
4402 int size = AOP_SIZE (right) - 1;
4403 emitcode ("sbiw", "%s,%d",frname,size);
4408 if (pi) pi->generated = 1;
4409 freeAsmop (result, NULL, ic, TRUE);
4410 freeAsmop (right, NULL, ic, TRUE);
4413 /*-----------------------------------------------------------------*/
4414 /* genGenPointerSet - set value from generic pointer space */
4415 /*-----------------------------------------------------------------*/
4417 genGenPointerSet (operand * right, operand * result, iCode * ic, iCode *pi)
4421 sym_link *retype = getSpec (operandType (right));
4424 aopOp (result, ic, FALSE);
4426 /* if the operand is already in dptr
4427 then we do nothing else we move the value to dptr */
4428 if (AOP_ISZ(AOP(result))) {
4432 getFreePtr(ic,&aop,FALSE,TRUE);
4433 if (isRegPair(AOP(result))) {
4434 emitcode ("movw", "r30,%s", aopGet (AOP (result), 0));
4436 emitcode ("mov", "r30,%s", aopGet (AOP (result), 0));
4437 emitcode ("mov", "r31,%s", aopGet (AOP (result), 1));
4439 emitcode ("mov", "r24,%s", aopGet (AOP (result), 2));
4443 /* so Z register now contains the address */
4444 aopOp (right, ic, FALSE);
4446 /* if bit then unpack */
4447 if (IS_BITVAR (retype))
4448 genUnpackBits (result, "Z", GPOINTER);
4450 size = AOP_SIZE (right);
4454 char *l = aopGet(AOP (right), offset++);
4458 emitcode ("call", "__gptrput_pi");
4460 emitcode ("call", "__gptrput");
4464 /* now some housekeeping stuff */
4466 /* we had to allocate for this iCode */
4468 if (isRegPair(AOP(result))) {
4469 emitcode ("movw", "%s,r30", aopGet (AOP (result), 0));
4471 emitcode ("mov", "%s,r30", aopGet (AOP (result), 0));
4472 emitcode ("mov", "%s,r31", aopGet (AOP (result), 1));
4475 freeAsmop (NULL, aop, ic, TRUE);
4478 /* we did not allocate which means left
4479 already in a pointer register, then
4480 if size > 0 && this could be used again
4481 we have to point it back to where it
4483 if ((AOP_SIZE (right) > 1 &&
4484 !OP_SYMBOL (result)->remat &&
4485 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) && !pi) {
4486 int size = AOP_SIZE (right) - 1;
4487 emitcode ("sbiw", "r30,%d",size);
4490 if (pi) pi->generated = 1;
4491 freeAsmop (right, NULL, ic, TRUE);
4492 freeAsmop (result, NULL, ic, TRUE);
4495 /*-----------------------------------------------------------------*/
4496 /* genPointerSet - stores the value into a pointer location */
4497 /*-----------------------------------------------------------------*/
4499 genPointerSet (iCode * ic, iCode *pi)
4501 operand *right, *result;
4502 sym_link *type, *etype;
4505 right = IC_RIGHT (ic);
4506 result = IC_RESULT (ic);
4508 /* depending on the type of pointer we need to
4509 move it to the correct pointer register */
4510 type = operandType (result);
4511 etype = getSpec (type);
4512 /* if left is of type of pointer then it is simple */
4513 if (IS_PTR (type) && !IS_FUNC (type->next)) {
4514 p_type = DCL_TYPE (type);
4517 /* we have to go by the storage class */
4518 p_type = PTR_TYPE (SPEC_OCLS (etype));
4522 /* now that we have the pointer type we assign
4523 the pointer values */
4530 genMemPointerSet (right, result, ic, pi);
4534 genGenPointerSet (right, result, ic, pi);
4540 /*-----------------------------------------------------------------*/
4541 /* genIfx - generate code for Ifx statement */
4542 /*-----------------------------------------------------------------*/
4544 genIfx (iCode * ic, iCode * popIc)
4546 operand *cond = IC_COND (ic);
4550 aopOp (cond, ic, FALSE);
4552 /* get the value into acc */
4553 if (AOP_SIZE(cond) == 1 && AOP_ISHIGHREG(AOP(cond),0)) {
4554 cname = aopGet(AOP(cond),0);
4556 toBoolean (cond, "r24", 1);
4559 /* the result is now in the accumulator */
4560 freeAsmop (cond, NULL, ic, TRUE);
4562 /* if there was something to be popped then do it */
4566 emitcode("cpi","%s,0",cname);
4567 lbl = newiTempLabel(NULL);
4569 emitcode ("brne","L%05d",lbl->key);
4570 emitcode ("jmp","L%05d",IC_TRUE(ic)->key);
4571 emitcode ("","L%05d:",lbl->key);
4573 emitcode ("breq","L%05d",lbl->key);
4574 emitcode ("jmp","L%05d",IC_FALSE(ic)->key);
4575 emitcode ("","L%05d:",lbl->key);
4580 /*-----------------------------------------------------------------*/
4581 /* genAddrOf - generates code for address of */
4582 /*-----------------------------------------------------------------*/
4584 genAddrOf (iCode * ic)
4586 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
4589 aopOp (IC_RESULT (ic), ic, FALSE);
4591 /* if the operand is on the stack then we
4592 need to get the stack offset of this
4595 /* if it has an offset then we need to compute it */
4597 emitcode ("mov", "a,_bp");
4598 emitcode ("add", "a,#0x%02x",
4599 ((char) sym->stack & 0xff));
4600 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4603 /* we can just move _bp */
4604 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
4606 /* fill the result with zero */
4607 size = AOP_SIZE (IC_RESULT (ic)) - 2;
4610 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
4616 /* object not on stack then we need the name */
4617 size = AOP_SIZE (IC_RESULT (ic));
4621 char s[SDCC_NAME_MAX];
4623 sprintf (s, "(%s >> %d)", sym->rname, offset * 8);
4625 sprintf (s, "%s", sym->rname);
4626 aopPut (AOP (IC_RESULT (ic)), s, offset++);
4630 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4634 /*-----------------------------------------------------------------*/
4635 /* genFarFarAssign - assignment when both are in far space */
4636 /*-----------------------------------------------------------------*/
4638 genFarFarAssign (operand * result, operand * right, iCode * ic)
4640 int size = AOP_SIZE (right);
4643 /* first push the right side on to the stack */
4645 l = aopGet (AOP (right), offset++);
4647 emitcode ("push", "acc");
4650 freeAsmop (right, NULL, ic, FALSE);
4651 /* now assign DPTR to result */
4652 aopOp (result, ic, FALSE);
4653 size = AOP_SIZE (result);
4655 emitcode ("pop", "acc");
4656 aopPut (AOP (result), "a", --offset);
4658 freeAsmop (result, NULL, ic, FALSE);
4662 /*-----------------------------------------------------------------*/
4663 /* genAssign - generate code for assignment */
4664 /*-----------------------------------------------------------------*/
4666 genAssign (iCode * ic)
4668 operand *result, *right;
4670 unsigned long lit = 0L;
4672 result = IC_RESULT (ic);
4673 right = IC_RIGHT (ic);
4675 /* if they are the same */
4676 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4679 aopOp (right, ic, FALSE);
4681 /* special case both in far space */
4682 if (AOP_TYPE (right) == AOP_DPTR &&
4683 IS_TRUE_SYMOP (result) && isOperandInFarSpace (result)) {
4685 genFarFarAssign (result, right, ic);
4689 aopOp (result, ic, TRUE);
4691 /* if they are the same registers */
4692 if (sameRegs (AOP (right), AOP (result)))
4695 /* if the result is a bit */
4696 if (AOP_TYPE (result) == AOP_CRY) {
4698 /* if the right size is a literal then
4699 we know what the value is */
4700 if (AOP_TYPE (right) == AOP_LIT) {
4701 if (((int) operandLitValue (right)))
4702 aopPut (AOP (result), one, 0);
4704 aopPut (AOP (result), zero, 0);
4708 /* the right is also a bit variable */
4709 if (AOP_TYPE (right) == AOP_CRY) {
4710 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4711 aopPut (AOP (result), "c", 0);
4716 toBoolean (right, "", 0);
4717 aopPut (AOP (result), "a", 0);
4721 /* bit variables done */
4723 size = AOP_SIZE (result);
4725 if (AOP_TYPE (right) == AOP_LIT)
4727 (unsigned long) floatFromVal (AOP (right)->aopu.
4729 if ((size > 1) && (AOP_TYPE (result) != AOP_REG)
4730 && (AOP_TYPE (right) == AOP_LIT)
4731 && !IS_FLOAT (operandType (right)) && (lit < 256L)) {
4732 emitcode ("clr", "a");
4734 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) ==
4735 0) aopPut (AOP (result), "a", size);
4737 aopPut (AOP (result),
4738 aopGet (AOP (right), size), size);
4743 aopPut (AOP (result),
4744 aopGet (AOP (right), offset), offset);
4750 freeAsmop (right, NULL, ic, FALSE);
4751 freeAsmop (result, NULL, ic, TRUE);
4754 /*-----------------------------------------------------------------*/
4755 /* genJumpTab - genrates code for jump table */
4756 /*-----------------------------------------------------------------*/
4758 genJumpTab (iCode * ic)
4763 aopOp (IC_JTCOND (ic), ic, FALSE);
4764 /* get the condition into accumulator */
4765 l = aopGet (AOP (IC_JTCOND (ic)), 0);
4767 /* multiply by three */
4768 emitcode ("add", "a,acc");
4769 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0));
4770 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
4772 jtab = newiTempLabel (NULL);
4773 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
4774 emitcode ("jmp", "@a+dptr");
4775 emitcode ("", "%05d$:", jtab->key + 100);
4776 /* now generate the jump labels */
4777 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
4778 jtab = setNextItem (IC_JTLABELS (ic)))
4779 emitcode ("ljmp", "%05d$", jtab->key + 100);
4783 /*-----------------------------------------------------------------*/
4784 /* genCast - gen code for casting */
4785 /*-----------------------------------------------------------------*/
4787 genCast (iCode * ic)
4789 operand *result = IC_RESULT (ic);
4790 sym_link *ctype = operandType (IC_LEFT (ic));
4791 sym_link *rtype = operandType (IC_RIGHT (ic));
4792 operand *right = IC_RIGHT (ic);
4795 /* if they are equivalent then do nothing */
4796 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4799 aopOp (right, ic, FALSE);
4800 aopOp (result, ic, FALSE);
4802 /* if the result is a bit */
4803 if (AOP_TYPE (result) == AOP_CRY) {
4804 /* if the right size is a literal then
4805 we know what the value is */
4806 if (AOP_TYPE (right) == AOP_LIT) {
4807 if (((int) operandLitValue (right)))
4808 aopPut (AOP (result), one, 0);
4810 aopPut (AOP (result), zero, 0);
4815 /* the right is also a bit variable */
4816 if (AOP_TYPE (right) == AOP_CRY) {
4817 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4818 aopPut (AOP (result), "c", 0);
4823 toBoolean (right, "", 0);
4824 aopPut (AOP (result), "a", 0);
4828 /* if they are the same size : or less */
4829 if (AOP_SIZE (result) <= AOP_SIZE (right)) {
4831 /* if they are in the same place */
4832 if (sameRegs (AOP (right), AOP (result)))
4835 /* if they in different places then copy */
4836 size = AOP_SIZE (result);
4839 aopPut (AOP (result),
4840 aopGet (AOP (right), offset), offset);
4847 /* if the result is of type pointer */
4848 if (IS_PTR (ctype)) {
4851 sym_link *type = operandType (right);
4852 sym_link *etype = getSpec (type);
4854 /* pointer to generic pointer */
4855 if (IS_GENPTR (ctype)) {
4859 p_type = DCL_TYPE (type);
4861 /* we have to go by the storage class */
4862 p_type = PTR_TYPE (SPEC_OCLS (etype));
4865 /* the first two bytes are known */
4866 size = GPTRSIZE - 1;
4869 aopPut (AOP (result),
4870 aopGet (AOP (right), offset), offset);
4873 /* the last byte depending on type */
4890 /* this should never happen */
4891 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4892 "got unknown pointer type");
4895 aopPut (AOP (result), l, GPTRSIZE - 1);
4899 /* just copy the pointers */
4900 size = AOP_SIZE (result);
4903 aopPut (AOP (result),
4904 aopGet (AOP (right), offset), offset);
4910 /* so we now know that the size of destination is greater
4911 than the size of the source */
4912 /* we move to result for the size of source */
4913 size = AOP_SIZE (right);
4916 aopPut (AOP (result), aopGet (AOP (right), offset), offset);
4920 /* now depending on the sign of the source && destination */
4921 size = AOP_SIZE (result) - AOP_SIZE (right);
4922 /* if unsigned or not an integral type */
4923 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype)) {
4925 aopPut (AOP (result), zero, offset++);
4928 /* we need to extend the sign :{ */
4929 // PENDING: Does nothing on avr
4931 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1);
4934 emitcode ("rlc", "a");
4935 emitcode ("subb", "a,acc");
4937 aopPut (AOP (result), "a", offset++);
4940 /* we are done hurray !!!! */
4943 freeAsmop (right, NULL, ic, TRUE);
4944 freeAsmop (result, NULL, ic, TRUE);
4948 /*-----------------------------------------------------------------*/
4949 /* genDjnz - generate decrement & jump if not zero instrucion */
4950 /*-----------------------------------------------------------------*/
4952 genDjnz (iCode * ic, iCode * ifx)
4958 /* if the if condition has a false label
4959 then we cannot save */
4963 /* if the minus is not of the form
4965 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
4966 !IS_OP_LITERAL (IC_RIGHT (ic)))
4969 if (operandLitValue (IC_RIGHT (ic)) != 1)
4972 /* if the size of this greater than one then no
4974 if (getSize (operandType (IC_RESULT (ic))) > 1)
4977 /* otherwise we can save BIG */
4978 lbl = newiTempLabel (NULL);
4979 lbl1 = newiTempLabel (NULL);
4981 aopOp (IC_RESULT (ic), ic, FALSE);
4983 if (IS_AOP_PREG (IC_RESULT (ic))) {
4984 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0));
4985 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0));
4986 emitcode ("jnz", "%05d$", lbl->key + 100);
4989 emitcode ("djnz", "%s,%05d$",
4990 aopGet (AOP (IC_RESULT (ic)), 0), lbl->key + 100);
4992 emitcode ("sjmp", "%05d$", lbl1->key + 100);
4993 emitcode ("", "%05d$:", lbl->key + 100);
4994 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4995 emitcode ("", "%05d$:", lbl1->key + 100);
4997 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5002 static char *recvregs[8] = {
5003 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23"
5006 static int recvCnt = 0;
5008 /*-----------------------------------------------------------------*/
5009 /* genReceive - generate code for a receive iCode */
5010 /*-----------------------------------------------------------------*/
5012 genReceive (iCode * ic)
5014 int size, offset = 0;
5015 aopOp (IC_RESULT (ic), ic, FALSE);
5016 size = AOP_SIZE (IC_RESULT (ic));
5018 aopPut (AOP (IC_RESULT (ic)), recvregs[recvCnt++], offset);
5021 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5024 /*-----------------------------------------------------------------*/
5025 /* gen51Code - generate code for 8051 based controllers */
5026 /*-----------------------------------------------------------------*/
5028 genAVRCode (iCode * lic)
5033 lineHead = lineCurr = NULL;
5035 /* print the allocation information */
5037 printAllocInfo (currFunc, codeOutFile);
5038 /* if debug information required */
5039 /* if (options.debug && currFunc) { */
5041 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
5043 emitcode ("", ".type %s,@function", currFunc->name);
5046 /* stack pointer name */
5050 for (ic = lic; ic; ic = ic->next) {
5052 if (cln != ic->lineno) {
5053 if (options.debug) {
5055 emitcode ("", "C$%s$%d$%d$%d ==.",
5056 FileBaseName (ic->filename),
5057 ic->lineno, ic->level, ic->block);
5060 emitcode (";", "%s %d", ic->filename, ic->lineno);
5063 /* if the result is marked as
5064 spilt and rematerializable or code for
5065 this has already been generated then
5067 if (resultRemat (ic) || ic->generated)
5070 /* depending on the operation */
5089 /* IPOP happens only when trying to restore a
5090 spilt live range, if there is an ifx statement
5091 following this pop then the if statement might
5092 be using some of the registers being popped which
5093 would destory the contents of the register so
5094 we need to check for this condition and handle it */
5096 ic->next->op == IFX &&
5097 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
5098 genIfx (ic->next, ic);
5116 genEndFunction (ic);
5136 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
5153 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
5157 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
5161 genCmpLe (ic, ifxForOp (IC_RESULT (ic), ic));
5165 genCmpGe (ic, ifxForOp (IC_RESULT (ic), ic));
5169 genCmpNe (ic, ifxForOp (IC_RESULT (ic), ic));
5173 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
5185 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
5189 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
5193 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
5220 case GET_VALUE_AT_ADDRESS:
5221 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
5225 if (POINTER_SET (ic))
5226 genPointerSet (ic, hasInc(IC_RESULT(ic),ic));
5252 addSet (&_G.sendSet, ic);
5261 /* now we are ready to call the
5262 peep hole optimizer */
5263 if (!options.nopeep)
5264 peepHole (&lineHead);
5266 /* now do the actual printing */
5267 printLine (lineHead, codeOutFile);