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) && !defined(__MINGW32__) && !defined(__CYGWIN__)
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++)
235 /*-----------------------------------------------------------------*/
236 /* outAcc - output Acc */
237 /*-----------------------------------------------------------------*/
239 outAcc (operand * result)
242 size = getDataSize (result);
244 aopPut (AOP (result), "r0", 0);
247 /* unsigned or positive */
249 aopPut (AOP (result), zero, offset++);
254 #endif // End Unused code section
256 /*-----------------------------------------------------------------*/
257 /* emitcode - writes the code into a file : for now it is simple */
258 /*-----------------------------------------------------------------*/
260 emitcode (char *inst, char *fmt, ...)
263 char lb[INITIAL_INLINEASM];
270 sprintf (lb, "%s\t", inst);
272 sprintf (lb, "%s", inst);
273 vsprintf (lb + (strlen (lb)), fmt, ap);
276 vsprintf (lb, fmt, ap);
278 while (isspace (*lbp))
282 lineCurr = (lineCurr ?
283 connectLine (lineCurr, newLineNode (lb)) :
284 (lineHead = newLineNode (lb)));
285 lineCurr->isInline = _G.inLine;
286 lineCurr->isDebug = _G.debugLine;
290 /*-----------------------------------------------------------------*/
291 /* hasInc - operand is incremented before any other use */
292 /*-----------------------------------------------------------------*/
294 hasInc (operand *op, iCode *ic)
296 sym_link *type = operandType(op);
297 sym_link *retype = getSpec (type);
298 iCode *lic = ic->next;
301 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
302 isize = getSize(type->next);
304 /* if operand of the form op = op + <sizeof *op> */
305 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
306 isOperandEqual(IC_RESULT(lic),op) &&
307 isOperandLiteral(IC_RIGHT(lic)) &&
308 operandLitValue(IC_RIGHT(lic)) == isize) {
311 /* if the operand used or deffed */
312 if (bitVectBitValue(ic->uses,op->key) || ((unsigned) ic->defKey == op->key)) {
320 /*-----------------------------------------------------------------*/
321 /* getFreePtr - returns X or Z whichever is free or can be pushed */
322 /*-----------------------------------------------------------------*/
324 getFreePtr (iCode * ic, asmop ** aopp, bool result, bool zonly)
326 bool xiu = FALSE, ziu = FALSE;
327 bool xou = FALSE, zou = FALSE;
329 /* the logic: if x & z used in the instruction
330 then we are in trouble otherwise */
332 /* first check if x & z are used by this
333 instruction, in which case we are in trouble */
334 if ((xiu = bitVectBitValue (ic->rUsed, X_IDX)) &&
335 (ziu = bitVectBitValue (ic->rUsed, Z_IDX))) {
339 xou = bitVectBitValue (ic->rMask, X_IDX);
340 zou = bitVectBitValue (ic->rMask, Z_IDX);
342 /* if no usage of Z then return it */
344 ic->rUsed = bitVectSetBit (ic->rUsed, Z_IDX);
345 (*aopp)->type = AOP_Z;
347 (*aopp)->aop_ptr2 = avr_regWithIdx (R31_IDX);
348 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R30_IDX);
351 /* if no usage of X then return it */
352 if (!xiu && !xou && !zonly) {
353 ic->rUsed = bitVectSetBit (ic->rUsed, X_IDX);
354 (*aopp)->type = AOP_X;
356 (*aopp)->aop_ptr2 = avr_regWithIdx (R27_IDX);
357 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R26_IDX);
360 /* if z not used then */
363 /* push it if not already pushed */
365 emitcode ("push", "%s",
366 avr_regWithIdx (R30_IDX)->dname);
367 emitcode ("push", "%s",
368 avr_regWithIdx (R31_IDX)->dname);
372 ic->rUsed = bitVectSetBit (ic->rUsed, Z_IDX);
373 (*aopp)->type = AOP_Z;
374 (*aopp)->aop_ptr2 = avr_regWithIdx (R31_IDX);
375 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R30_IDX);
378 /* now we know they both have usage */
379 /* if x not used in this instruction */
380 if (!xiu && !zonly) {
381 /* push it if not already pushed */
383 emitcode ("push", "%s",
384 avr_regWithIdx (R26_IDX)->dname);
385 emitcode ("push", "%s",
386 avr_regWithIdx (R27_IDX)->dname);
390 ic->rUsed = bitVectSetBit (ic->rUsed, X_IDX);
391 (*aopp)->type = AOP_X;
393 (*aopp)->aop_ptr2 = avr_regWithIdx (R27_IDX);
394 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R26_IDX);
399 /* I said end of world but not quite end of world yet */
400 /* if this is a result then we can push it on the stack */
402 (*aopp)->type = AOP_STK;
406 /* other wise this is true end of the world */
407 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
408 "getFreePtr should never reach here");
412 /*-----------------------------------------------------------------*/
413 /* newAsmop - creates a new asmOp */
414 /*-----------------------------------------------------------------*/
416 newAsmop (short type)
420 aop = Safe_calloc (1, sizeof (asmop));
425 /*-----------------------------------------------------------------*/
426 /* pointerCode - returns the code for a pointer type */
427 /*-----------------------------------------------------------------*/
429 pointerCode (sym_link * etype)
432 return PTR_TYPE (SPEC_OCLS (etype));
436 /*-----------------------------------------------------------------*/
437 /* aopForSym - for a true symbol */
438 /*-----------------------------------------------------------------*/
440 aopForSym (iCode * ic, symbol * sym, bool result)
443 memmap *space = SPEC_OCLS (sym->etype);
445 /* if already has one */
449 /* assign depending on the storage class */
450 /* if it is on the stack */
452 sym->aop = aop = newAsmop (0);
453 aop->size = getSize (sym->type);
455 /* we can use std / ldd instruction */
457 && (sym->stack + getSize (sym->type) - 1) <= 63) {
458 aop->type = AOP_STK_D;
459 aop->aopu.aop_stk = sym->stack;
463 /* otherwise get a free pointer register X/Z */
464 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result, FALSE);
466 /* now assign the address of the variable to
467 the pointer register */
468 if (aop->type != AOP_STK) {
469 emitcode ("movw", "%s,r28", aop->aopu.aop_ptr->name);
470 if (sym->stack < 0) {
471 if ((sym->stack - _G.nRegsSaved) > -63) {
472 emitcode ("sbiw", "%s,0x%02x",
473 aop->aopu.aop_ptr->name,
478 emitcode ("subi", "%s,(%d & 0xff)",
479 aop->aopu.aop_ptr->name,
480 sym->stack - _G.nRegsSaved);
481 emitcode ("sbci", "%s,((%d >> 8) & 0xff)",
483 sym->stack - _G.nRegsSaved);
487 if (sym->stack <= 63) {
488 emitcode ("adiw", "%s,0x%02x",
489 aop->aopu.aop_ptr->name,
493 emitcode ("subi", "%s,((-%d) & 0xff)",
494 aop->aopu.aop_ptr->name,
496 emitcode ("sbci", "%s,(((-%d) >> 8) & 0xff))",
505 /* if in bit space */
506 if (IN_BITSPACE (space)) {
507 sym->aop = aop = newAsmop (AOP_CRY);
508 aop->aopu.aop_dir = sym->rname;
509 aop->size = getSize (sym->type);
512 /* if it is in direct space */
513 if (IN_DIRSPACE (space)) {
514 sym->aop = aop = newAsmop (AOP_DIR);
515 aop->aopu.aop_dir = sym->rname;
516 aop->size = getSize (sym->type);
520 /* special case for a function */
521 if (IS_FUNC (sym->type)) {
522 sym->aop = aop = newAsmop (AOP_IMMD);
523 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
524 strcpy (aop->aopu.aop_immd, sym->rname);
525 aop->size = FPTRSIZE;
529 /* only remaining is code / eeprom which will need pointer reg */
530 /* if it is in code space */
532 sym->aop = aop = newAsmop (0);
534 if (IN_CODESPACE (space))
537 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result, aop->code);
538 aop->size = getSize (sym->type);
539 emitcode ("ldi", "%s,lo8(%s)", aop->aopu.aop_ptr->name, sym->rname);
540 emitcode ("ldi", "%s,hi8(%s)", aop->aop_ptr2);
545 /*-----------------------------------------------------------------*/
546 /* aopForRemat - rematerialzes an object */
547 /*-----------------------------------------------------------------*/
549 aopForRemat (symbol * sym)
551 iCode *ic = sym->rematiCode;
552 asmop *aop = newAsmop (AOP_IMMD);
557 val += (int) operandLitValue (IC_RIGHT (ic));
558 else if (ic->op == '-')
559 val -= (int) operandLitValue (IC_RIGHT (ic));
563 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
567 sprintf (buffer, "(%s %c 0x%04x)",
568 OP_SYMBOL (IC_LEFT (ic))->rname,
569 val >= 0 ? '+' : '-', abs (val) & 0xffff);
571 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
573 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
574 strcpy (aop->aopu.aop_immd, buffer);
578 /*-----------------------------------------------------------------*/
579 /* regsInCommon - two operands have some registers in common */
580 /*-----------------------------------------------------------------*/
582 regsInCommon (operand * op1, operand * op2)
587 /* if they have registers in common */
588 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
591 sym1 = OP_SYMBOL (op1);
592 sym2 = OP_SYMBOL (op2);
594 if (sym1->nRegs == 0 || sym2->nRegs == 0)
597 for (i = 0; i < sym1->nRegs; i++) {
602 for (j = 0; j < sym2->nRegs; j++) {
606 if (sym2->regs[j] == sym1->regs[i])
614 /*-----------------------------------------------------------------*/
615 /* operandsEqu - equivalent */
616 /*-----------------------------------------------------------------*/
618 operandsEqu (operand * op1, operand * op2)
622 /* if they not symbols */
623 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
626 sym1 = OP_SYMBOL (op1);
627 sym2 = OP_SYMBOL (op2);
629 /* if both are itemps & one is spilt
630 and the other is not then false */
631 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
632 sym1->isspilt != sym2->isspilt) return FALSE;
634 /* if they are the same */
638 if (strcmp (sym1->rname, sym2->rname) == 0)
642 /* if left is a tmp & right is not */
643 if (IS_ITEMP (op1) &&
644 !IS_ITEMP (op2) && sym1->isspilt && (sym1->usl.spillLoc == sym2))
647 if (IS_ITEMP (op2) &&
649 sym2->isspilt && sym1->level > 0 && (sym2->usl.spillLoc == sym1))
655 /*-----------------------------------------------------------------*/
656 /* sameRegs - two asmops have the same registers */
657 /*-----------------------------------------------------------------*/
659 sameRegs (asmop * aop1, asmop * aop2)
666 if (aop1->type != AOP_REG || aop2->type != AOP_REG)
669 if (aop1->size != aop2->size)
672 for (i = 0; i < aop1->size; i++)
673 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
679 /*-----------------------------------------------------------------*/
680 /* isRegPair - for size 2 if this operand has a register pair */
681 /*-----------------------------------------------------------------*/
683 isRegPair (asmop * aop)
685 if (!aop || aop->size < 2)
687 if (aop->type == AOP_X || aop->type == AOP_Z)
689 if (aop->type != AOP_REG)
691 if ( ((aop->aopu.aop_reg[1]->rIdx - aop->aopu.aop_reg[0]->rIdx) == 1) &&
692 (aop->aopu.aop_reg[0]->rIdx & 1) == 0)
698 /*-----------------------------------------------------------------*/
699 /* aopOp - allocates an asmop for an operand : */
700 /*-----------------------------------------------------------------*/
702 aopOp (operand * op, iCode * ic, bool result)
711 /* if this a literal */
712 if (IS_OP_LITERAL (op)) {
713 op->aop = aop = newAsmop (AOP_LIT);
714 aop->aopu.aop_lit = op->operand.valOperand;
715 aop->size = getSize (operandType (op));
719 /* if already has a asmop then continue */
723 /* if the underlying symbol has a aop */
724 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop) {
725 op->aop = OP_SYMBOL (op)->aop;
729 /* if this is a true symbol */
730 if (IS_TRUE_SYMOP (op)) {
731 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
735 /* this is a temporary : this has
741 e) can be a return use only */
743 sym = OP_SYMBOL (op);
746 /* if the type is a conditional */
747 if (sym->regType & REG_CND) {
748 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
753 /* if it is spilt then two situations
755 b) has a spill location */
756 if (sym->isspilt || sym->nRegs == 0) {
758 /* rematerialize it NOW */
760 sym->aop = op->aop = aop = aopForRemat (sym);
761 aop->size = getSize (sym->type);
766 assert ("ACC_USE cannot happen in AVR\n");
771 aop = op->aop = sym->aop = newAsmop (AOP_STR);
772 aop->size = getSize (sym->type);
773 for (i = 0; i < (int) fAVRReturnSize; i++)
774 aop->aopu.aop_str[i] = fAVRReturn[i];
778 /* else spill location */
779 sym->aop = op->aop = aop =
780 aopForSym (ic, sym->usl.spillLoc, result);
781 aop->size = getSize (sym->type);
785 /* must be in a register */
786 sym->aop = op->aop = aop = newAsmop (AOP_REG);
787 aop->size = sym->nRegs;
788 for (i = 0; i < sym->nRegs; i++)
789 aop->aopu.aop_reg[i] = sym->regs[i];
792 /*-----------------------------------------------------------------*/
793 /* freeAsmop - free up the asmop given to an operand */
794 /*----------------------------------------------------------------*/
796 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
813 /* depending on the asmop type only three cases need work AOP_RO
814 , AOP_R1 && AOP_STK */
819 emitcode ("pop", "r26");
820 emitcode ("pop", "r27");
824 bitVectUnSetBit (ic->rUsed, X_IDX);
830 emitcode ("pop", "r30");
831 emitcode ("pop", "r31");
835 bitVectUnSetBit (ic->rUsed, Z_IDX);
841 int stk = aop->aopu.aop_stk + aop->size;
842 bitVectUnSetBit (ic->rUsed, X_IDX);
843 bitVectUnSetBit (ic->rUsed, Z_IDX);
845 getFreePtr (ic, &aop, FALSE, 0);
847 emitcode ("movw", "%s,r28");
849 if (stk <= 63 && stk > 0) {
850 emitcode ("adiw", "%s,0x%02x",
851 aop->aopu.aop_ptr->name,
855 emitcode ("subi", "%s,lo8(%d)",
856 aop->aopu.aop_ptr->name,
858 emitcode ("sbci", "%s,hi8(%d)",
865 emitcode ("pop", "r24");
866 emitcode ("st", "-%s,r24",
867 aop->type == AOP_X ? "X" : "Z");
872 freeAsmop (op, NULL, ic, TRUE);
874 emitcode ("pop", "r26");
875 emitcode ("pop", "r27");
880 emitcode ("pop", "r30");
881 emitcode ("pop", "r31");
888 /* all other cases just dealloc */
892 OP_SYMBOL (op)->aop = NULL;
893 /* if the symbol has a spill */
895 SPIL_LOC (op)->aop = NULL;
900 /*-----------------------------------------------------------------*/
901 /* aopGet - for fetching value of the aop */
902 /*-----------------------------------------------------------------*/
904 aopGet (asmop * aop, int offset)
909 /* offset is greater than
911 if (offset > (aop->size - 1) && aop->type != AOP_LIT)
914 /* depending on type */
918 if (offset > aop->coff) {
919 emitcode ("adiw", "%s,%d", aop->aopu.aop_ptr->name,
923 if (offset < aop->coff) {
924 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name,
929 emitcode ("ld", "%s,x",
930 (rs = ((offset & 1) ? "r25" : "r24")));
935 if (offset > aop->coff) {
936 emitcode ("adiw", "r30,%d",
940 emitcode ("sbiw", "r30,%d",
943 emitcode ("lpm", "%s,z",
944 (rs = ((offset & 1) ? "r25" : "r24")));
948 if (offset > aop->coff) {
949 emitcode ("ldd", "%s,z+%d",
951 ((offset & 1) ? "r25" : "r24")),
955 emitcode ("sbiw", "%s,%d",
956 aop->aopu.aop_ptr->name,
959 emitcode ("ld", "%s,z",
961 ((offset & 1) ? "r25" : "r24")));
968 emitcode ("lds", "%s,(%s)+%d",
969 (rs = ((offset & 1) ? "r25" : "r24")),
970 aop->aopu.aop_immd, offset);
974 emitcode ("lds", "%s,(%s)+%d",
975 (rs = ((offset & 1) ? "r25" : "r24")),
976 aop->aopu.aop_dir, offset);
980 return aop->aopu.aop_reg[offset]->name;
983 assert ("cannot be in bit space AOP_CRY\n");
987 s = aopLiteral (aop->aopu.aop_lit, offset);
988 emitcode ("ldi", "%s,lo8(%s)",
989 (rs = ((offset & 1) ? "r24" : "r25")), s);
994 return aop->aopu.aop_str[offset];
997 emitcode ("ldd", "%s,Y+%d",
998 (rs = ((offset & 1) ? "r25" : "r24")),
999 aop->aopu.aop_stk + offset);
1003 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1004 "aopget got unsupported aop->type");
1008 /*-----------------------------------------------------------------*/
1009 /* aopPut - puts a string for a aop */
1010 /*-----------------------------------------------------------------*/
1012 aopPut (asmop * aop, char *s, int offset)
1016 if (aop->size && offset > (aop->size - 1)) {
1017 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1018 "aopPut got offset > aop->size");
1022 /* will assign value to value */
1023 /* depending on where it is ofcourse */
1024 switch (aop->type) {
1027 sprintf (d, "(%s)+%d", aop->aopu.aop_dir, offset);
1030 sprintf (d, "%s", aop->aopu.aop_dir);
1033 emitcode ("sts", "%s,%s", d, s);
1037 if (toupper (*s) != 'R') {
1039 emitcode ("clr", "%s",
1040 aop->aopu.aop_reg[offset]->name);
1043 emitcode ("ldi", "r25,%s", s);
1044 emitcode ("mov", "%s,r35",
1045 aop->aopu.aop_reg[offset]->name);
1049 if (strcmp (aop->aopu.aop_reg[offset]->name, s)) {
1050 emitcode ("mov", "%s,%s",
1051 aop->aopu.aop_reg[offset]->name, s);
1057 if (offset > aop->coff) {
1058 emitcode ("adiw", "%s,%d", aop->aopu.aop_ptr->name,
1059 offset - aop->coff);
1062 if (offset < aop->coff) {
1063 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name,
1064 aop->coff - offset);
1068 emitcode ("st", "x,%s", s);
1073 if (offset > aop->coff) {
1074 emitcode ("adiw", "r30,%d",
1075 offset - aop->coff);
1078 emitcode ("sbiw", "r30,%d",
1079 aop->coff - offset);
1081 emitcode ("lpm", "%s,z", s);
1084 /* we can use lds */
1085 if (offset > aop->coff) {
1086 emitcode ("sdd", "z+%d,%s",
1087 offset - aop->coff, s);
1090 emitcode ("sbiw", "%s,%d",
1091 aop->aopu.aop_ptr->name,
1092 aop->coff - offset);
1094 emitcode ("ld", "%s,z", s);
1100 emitcode ("push", "%s", s);
1104 /* if used only for a condition code check */
1105 assert (toupper (*s) == 'R');
1107 emitcode ("xrl", "r0,r0");
1108 emitcode ("cpi", "%s,0", s);
1111 emitcode ("cpc", "r0,%s", s);
1117 if (strcmp (aop->aopu.aop_str[offset], s))
1118 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset],
1123 emitcode ("std", "y+%d,%s", offset, s);
1127 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1128 "aopPut got unsupported aop->type");
1134 #define AOP(op) op->aop
1135 #define AOP_TYPE(op) AOP(op)->type
1136 #define AOP_SIZE(op) AOP(op)->size
1137 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_X || \
1138 AOP_TYPE(x) == AOP_Z))
1139 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1140 ((x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R27_IDX)) || \
1141 (x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R31_IDX)) )))
1142 #define AOP_ISX(x) (x && (x->type == AOP_REG && \
1143 ((x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R27_IDX)))))
1144 #define AOP_ISZ(x) (x && (x->type == AOP_REG && \
1145 ((x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R31_IDX)))))
1147 /*-----------------------------------------------------------------*/
1148 /* genNotFloat - generates not for float operations */
1149 /*-----------------------------------------------------------------*/
1151 genNotFloat (operand * op, operand * res)
1157 /* we will put 127 in the first byte of
1159 aopPut (AOP (res), "127", 0);
1160 size = AOP_SIZE (op) - 1;
1163 l = aopGet (op->aop, offset++);
1167 emitcode ("or", "R0,%s", aopGet (op->aop, offset++));
1169 tlbl = newiTempLabel (NULL);
1171 tlbl = newiTempLabel (NULL);
1172 aopPut (res->aop, zero, 1);
1173 emitcode ("cpi", "r0,0");
1174 emitcode ("breq", "L%05d", tlbl->key);
1175 aopPut (res->aop, one, 1);
1176 emitcode ("", "L%05d:", tlbl->key);
1178 size = res->aop->size - 2;
1180 /* put zeros in the rest */
1182 aopPut (res->aop, zero, offset++);
1185 /*-----------------------------------------------------------------*/
1186 /* opIsGptr: returns non-zero if the passed operand is */
1187 /* a generic pointer type. */
1188 /*-----------------------------------------------------------------*/
1190 opIsGptr (operand * op)
1192 sym_link *type = operandType (op);
1194 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type)) {
1200 /*-----------------------------------------------------------------*/
1201 /* getDataSize - get the operand data size */
1202 /*-----------------------------------------------------------------*/
1204 getDataSize (operand * op)
1207 size = AOP_SIZE (op);
1208 if (size == GPTRSIZE) {
1209 sym_link *type = operandType (op);
1210 if (IS_GENPTR (type)) {
1211 /* generic pointer; arithmetic operations
1212 * should ignore the high byte (pointer type).
1220 /*-----------------------------------------------------------------*/
1221 /* toBoolean - emit code for orl a,operator(sizeop) */
1222 /*-----------------------------------------------------------------*/
1224 toBoolean (operand * oper, char *r, bool clr)
1226 int size = AOP_SIZE (oper);
1229 emitcode ("clr", "%s", r);
1231 emitcode ("or", "%s,%s", r, aopGet (AOP (oper), offset++));
1234 emitcode("mov","%s,%s",r,aopGet (AOP (oper), offset++));
1235 if (size) while (size--) emitcode ("or", "%s,%s", r, aopGet (AOP (oper), offset++));
1240 /*-----------------------------------------------------------------*/
1241 /* genNot - generate code for ! operation */
1242 /*-----------------------------------------------------------------*/
1247 sym_link *optype = operandType (IC_LEFT (ic));
1248 int size, offset = 1;
1250 /* assign asmOps to operand & result */
1251 aopOp (IC_LEFT (ic), ic, FALSE);
1252 aopOp (IC_RESULT (ic), ic, TRUE);
1254 /* if type float then do float */
1255 if (IS_FLOAT (optype)) {
1256 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1259 emitcode ("clr", "r24");
1260 tlbl = newiTempLabel (NULL);
1261 size = AOP_SIZE (IC_LEFT (ic));
1264 emitcode ("cpse", "%s,r24", aopGet (AOP (IC_LEFT (ic)), 0));
1269 emitcode ("cpc", "%s,r24",
1270 aopGet (AOP (IC_LEFT (ic)),
1273 emitcode ("cpi", "%s,0",
1274 aopGet (AOP (IC_LEFT (ic)),
1278 emitcode ("bne", "L%05d", tlbl->key);
1280 emitcode ("ldi", "r24,1");
1281 emitcode ("", "L%05d:", tlbl->key);
1282 aopPut (AOP (IC_RESULT (ic)), "r24", 0);
1283 size = AOP_SIZE (IC_RESULT (ic)) - 1;
1286 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
1290 /* release the aops */
1291 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1292 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1296 /*-----------------------------------------------------------------*/
1297 /* genCpl - generate code for complement */
1298 /*-----------------------------------------------------------------*/
1306 /* assign asmOps to operand & result */
1307 aopOp (IC_LEFT (ic), ic, FALSE);
1308 aopOp (IC_RESULT (ic), ic, TRUE);
1309 samer = sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)));
1310 size = AOP_SIZE (IC_RESULT (ic));
1312 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
1314 emitcode ("com", "%s", l);
1317 aopPut (AOP (IC_RESULT (ic)), l, offset);
1318 emitcode ("com", "%s",
1319 aopGet (AOP (IC_RESULT (ic)), offset));
1324 /* release the aops */
1325 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1326 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1329 /*-----------------------------------------------------------------*/
1330 /* genUminusFloat - unary minus for floating points */
1331 /*-----------------------------------------------------------------*/
1333 genUminusFloat (operand * op, operand * result)
1335 int size, offset = 0;
1337 /* for this we just need to flip the
1338 first it then copy the rest in place */
1339 size = AOP_SIZE (op) - 1;
1340 l = aopGet (AOP (op), 3);
1342 emitcode ("ldi", "r24,0x80");
1343 if (sameRegs (AOP (op), AOP (result))) {
1344 emitcode ("eor", "%s,r24", l);
1347 aopPut (AOP (result), l, 3);
1348 emitcode ("eor", "%s,r24", aopGet (AOP (result), 3));
1351 aopPut (AOP (result), aopGet (AOP (op), offset), offset);
1356 /*-----------------------------------------------------------------*/
1357 /* genUminus - unary minus code generation */
1358 /*-----------------------------------------------------------------*/
1360 genUminus (iCode * ic)
1363 sym_link *optype, *rtype;
1367 aopOp (IC_LEFT (ic), ic, FALSE);
1368 aopOp (IC_RESULT (ic), ic, TRUE);
1370 optype = operandType (IC_LEFT (ic));
1371 rtype = operandType (IC_RESULT (ic));
1373 /* if float then do float stuff */
1374 if (IS_FLOAT (optype)) {
1375 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1379 /* otherwise subtract from zero */
1380 size = AOP_SIZE (IC_LEFT (ic));
1382 samer = sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)));
1385 emitcode ("neg", "%s",
1386 aopGet (AOP (IC_LEFT (ic)), 0));
1389 aopPut (AOP (IC_RESULT (ic)),
1390 aopGet (AOP (IC_LEFT (ic)), 0), 0);
1391 emitcode ("neg", "%s",
1392 aopGet (AOP (IC_RESULT (ic)), 0));
1398 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
1400 aopPut (AOP (IC_RESULT (ic)), l, offset);
1401 l = aopGet (AOP (IC_RESULT (ic)), offset);
1404 emitcode ("com", "%s", l);
1406 emitcode ("neg", "%s", l);
1409 size = AOP_SIZE (IC_LEFT (ic)) - 1;
1412 emitcode ("sbci", "%s,lo8(-1)",
1413 aopGet (AOP (IC_RESULT (ic)), offset++));
1417 /* if any remaining bytes in the result */
1418 /* we just need to propagate the sign */
1419 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic))))) {
1420 symbol *tlbl = newiTempLabel (NULL);
1421 emitcode ("clr", "r0");
1422 emitcode ("brcc", "L%05d", tlbl->key);
1423 emitcode ("com", "r0");
1424 emitcode ("", "L%05d:", tlbl->key);
1426 aopPut (AOP (IC_RESULT (ic)), "r0", offset++);
1430 /* release the aops */
1431 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1432 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1435 /*-----------------------------------------------------------------*/
1436 /* assignResultValue - */
1437 /*-----------------------------------------------------------------*/
1439 assignResultValue (operand * oper)
1442 int size = AOP_SIZE (oper);
1444 aopPut (AOP (oper), fAVRReturn[offset], offset);
1449 /*-----------------------------------------------------------------*/
1450 /* saveZreg - if indirect call then save z-pointer register */
1451 /*-----------------------------------------------------------------*/
1453 saveZreg (iCode * ic)
1455 /* only if live accross this call */
1456 if (ic->regsSaved == 0 &&
1457 (bitVectBitValue (ic->rMask, R30_IDX) ||
1458 bitVectBitValue (ic->rMask, R31_IDX))) {
1460 emitcode ("push", "r30");
1461 emitcode ("push", "r31");
1465 /*-----------------------------------------------------------------*/
1466 /* popZreg - restore values of zreg */
1467 /*-----------------------------------------------------------------*/
1469 popZreg (iCode * ic)
1471 if (ic->regsSaved) {
1472 emitcode ("pop", "r31");
1473 emitcode ("pop", "r30");
1477 /*-----------------------------------------------------------------*/
1478 /* genIpush - genrate code for pushing this gets a little complex */
1479 /*-----------------------------------------------------------------*/
1481 genIpush (iCode * ic)
1483 int size, offset = 0;
1487 if (!ic->parmPush) {
1488 /* and the item is spilt then do nothing */
1489 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1494 for (lic = ic->next; lic; lic = lic->next)
1495 if (lic->op == PCALL)
1501 /* this is a paramter push */
1502 aopOp (IC_LEFT (ic), ic, FALSE);
1503 size = AOP_SIZE (IC_LEFT (ic));
1505 l = aopGet (AOP (IC_LEFT (ic)), offset++);
1506 emitcode ("push", "%s", l);
1509 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1512 /*-----------------------------------------------------------------*/
1513 /* genIpop - recover the registers: can happen only for spilling */
1514 /*-----------------------------------------------------------------*/
1516 genIpop (iCode * ic)
1521 /* if the temp was not pushed then */
1522 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1525 aopOp (IC_LEFT (ic), ic, FALSE);
1526 size = AOP_SIZE (IC_LEFT (ic));
1527 offset = (size - 1);
1529 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--));
1531 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1534 /*-----------------------------------------------------------------*/
1535 /* genCall - generates a call statement */
1536 /*-----------------------------------------------------------------*/
1538 genCall (iCode * ic)
1541 /* if send set is not empty the assign */
1545 for (sic = setFirstItem (_G.sendSet); sic;
1546 sic = setNextItem (_G.sendSet)) {
1547 int size, offset = 0;
1548 aopOp (IC_LEFT (sic), sic, FALSE);
1549 size = AOP_SIZE (IC_LEFT (sic));
1552 aopGet (AOP (IC_LEFT (sic)), offset);
1554 sprintf (buffer, "r%d", rnum++);
1556 emitcode ("mov", "%s,%s", b, l);
1559 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1564 emitcode ("call", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1565 OP_SYMBOL (IC_LEFT (ic))->rname :
1566 OP_SYMBOL (IC_LEFT (ic))->name));
1568 /* if we need assign a result value */
1569 if ((IS_ITEMP (IC_RESULT (ic)) &&
1570 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1571 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1572 IS_TRUE_SYMOP (IC_RESULT (ic))) {
1574 aopOp (IC_RESULT (ic), ic, FALSE);
1575 assignResultValue (IC_RESULT (ic));
1576 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1579 /* adjust the stack for parameters if required */
1580 if (ic->parmBytes) {
1581 if (ic->parmBytes > 63) {
1582 emitcode ("sbiw", "r28,%d", ic->parmBytes);
1585 emitcode ("subi", "r28,lo8(%d)",
1587 emitcode ("sbci", "r29,hi8(%d)",
1594 /*-----------------------------------------------------------------*/
1595 /* genPcall - generates a call by pointer statement */
1596 /*-----------------------------------------------------------------*/
1598 genPcall (iCode * ic)
1604 aopOp (IC_LEFT (ic), ic, FALSE);
1605 emitcode ("mov", "r30", aopGet (AOP (IC_LEFT (ic)), 0));
1606 emitcode ("mov", "r31", aopGet (AOP (IC_RIGHT (ic)), 0));
1607 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1609 /* if send set is not empty the assign */
1613 for (sic = setFirstItem (_G.sendSet); sic;
1614 sic = setNextItem (_G.sendSet)) {
1615 int size, offset = 0;
1616 aopOp (IC_LEFT (sic), sic, FALSE);
1617 size = AOP_SIZE (IC_LEFT (sic));
1620 aopGet (AOP (IC_LEFT (sic)), offset);
1622 sprintf (b, "r%d", rnum++);
1624 emitcode ("mov", "%s,%s", b, l);
1627 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1632 emitcode ("icall", "");
1634 /* if we need assign a result value */
1635 if ((IS_ITEMP (IC_RESULT (ic)) &&
1636 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1637 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1638 IS_TRUE_SYMOP (IC_RESULT (ic))) {
1640 aopOp (IC_RESULT (ic), ic, FALSE);
1642 assignResultValue (IC_RESULT (ic));
1643 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1646 /* adjust the stack for parameters if
1648 if (ic->parmBytes) {
1650 if (ic->parmBytes > 3) {
1651 emitcode ("mov", "a,%s", spname);
1652 emitcode ("add", "a,#0x%02x",
1653 (-ic->parmBytes) & 0xff);
1654 emitcode ("mov", "%s,a", spname);
1657 for (i = 0; i < ic->parmBytes; i++)
1658 emitcode ("dec", "%s", spname);
1662 /* adjust the stack for parameters if required */
1663 if (ic->parmBytes) {
1664 if (ic->parmBytes > 63) {
1665 emitcode ("sbiw", "r28,%d", ic->parmBytes);
1668 emitcode ("subi", "r28,lo8(%d)",
1670 emitcode ("sbci", "r29,hi8(%d)",
1678 /*-----------------------------------------------------------------*/
1679 /* resultRemat - result is rematerializable */
1680 /*-----------------------------------------------------------------*/
1682 resultRemat (iCode * ic)
1684 if (SKIP_IC (ic) || ic->op == IFX)
1687 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic))) {
1688 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
1689 if (sym->remat && !POINTER_SET (ic))
1696 #if defined(__BORLANDC__) || defined(_MSC_VER)
1697 #define STRCASECMP stricmp
1699 #define STRCASECMP strcasecmp
1702 /*-----------------------------------------------------------------*/
1703 /* genFunction - generated code for function entry */
1704 /*-----------------------------------------------------------------*/
1706 genFunction (iCode * ic)
1713 /* create the function header */
1714 emitcode (";", "-----------------------------------------");
1715 emitcode (";", " function %s",
1716 (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
1717 emitcode (";", "-----------------------------------------");
1719 emitcode ("", "%s:", sym->rname);
1720 fetype = getSpec (operandType (IC_LEFT (ic)));
1722 /* if critical function then turn interrupts off */
1723 if (SPEC_CRTCL (fetype))
1724 emitcode ("cli", "");
1726 if (IS_ISR (sym->etype)) {
1729 /* save the preserved registers that are used in this function */
1730 for (i = R2_IDX; i <= R15_IDX; i++) {
1731 if (bitVectBitValue (sym->regsUsed, i)) {
1733 emitcode ("push", "%s", avr_regWithIdx (i)->name);
1736 /* now for the pointer registers */
1737 if (bitVectBitValue (sym->regsUsed, R26_IDX)) {
1739 emitcode ("push", "r26");
1741 if (bitVectBitValue (sym->regsUsed, R27_IDX)) {
1743 emitcode ("push", "r27");
1745 if (bitVectBitValue (sym->regsUsed, R30_IDX)) {
1747 emitcode ("push", "r30");
1749 if (bitVectBitValue (sym->regsUsed, R31_IDX)) {
1751 emitcode ("push", "r31");
1753 /* adjust the stack for the function */
1755 emitcode ("push", "r28");
1756 emitcode ("push", "r29");
1757 emitcode ("in", "r28,__SP_L__");
1758 emitcode ("in", "r29,__SP_H__");
1759 if (sym->stack <= 63) {
1760 emitcode ("sbiw", "r28,%d", sym->stack);
1763 emitcode ("subi", "r28,lo8(%d)", sym->stack);
1764 emitcode ("sbci", "r29,hi8(%d)", sym->stack);
1766 emitcode ("out", "__SP_L__,r28");
1767 emitcode ("out", "__SP_H__,r29");
1771 /*-----------------------------------------------------------------*/
1772 /* genEndFunction - generates epilogue for functions */
1773 /*-----------------------------------------------------------------*/
1775 genEndFunction (iCode * ic)
1777 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
1780 /* restore stack pointer */
1782 if (sym->stack <= 63) {
1783 emitcode ("adiw", "r28,%d", sym->stack);
1786 emitcode ("subi", "r28,lo8(-%d)", sym->stack);
1787 emitcode ("sbci", "r29,hi8(-%d)", sym->stack);
1789 emitcode ("out", "__SP_L__,r28");
1790 emitcode ("out", "__SP_H__,r29");
1792 /* pop frame pointer */
1793 emitcode ("pop", "r29");
1794 emitcode ("pop", "r28");
1796 /* restore preserved registers */
1797 if (bitVectBitValue (sym->regsUsed, R31_IDX)) {
1799 emitcode ("pop", "r31");
1801 if (bitVectBitValue (sym->regsUsed, R30_IDX)) {
1803 emitcode ("pop", "r30");
1805 if (bitVectBitValue (sym->regsUsed, R27_IDX)) {
1807 emitcode ("pop", "r27");
1809 if (bitVectBitValue (sym->regsUsed, R26_IDX)) {
1811 emitcode ("pop", "r26");
1813 for (i = R15_IDX; i >= R2_IDX; i--) {
1814 if (bitVectBitValue (sym->regsUsed, i)) {
1816 emitcode ("pop", "%s", avr_regWithIdx (i)->name);
1820 if (SPEC_CRTCL (sym->etype))
1821 emitcode ("sti", "");
1823 if (IS_ISR (sym->etype)) {
1824 emitcode ("rti", "");
1827 emitcode ("ret", "");
1832 /*-----------------------------------------------------------------*/
1833 /* genRet - generate code for return statement */
1834 /*-----------------------------------------------------------------*/
1838 int size, offset = 0;
1840 /* if we have no return value then
1841 just generate the "ret" */
1845 /* we have something to return then
1846 move the return value into place */
1847 aopOp (IC_LEFT (ic), ic, FALSE);
1848 size = AOP_SIZE (IC_LEFT (ic));
1851 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) {
1852 emitcode ("ldi", "%s,%s(%d)", fAVRReturn[offset],
1854 (int) floatFromVal (AOP (IC_LEFT (ic))->
1855 aopu.aop_lit), offset);
1859 l = aopGet (AOP (IC_LEFT (ic)), offset);
1860 if (strcmp (fAVRReturn[offset], l))
1861 emitcode ("mov", "%s,%s", fAVRReturn[offset],
1867 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1870 /* generate a jump to the return label
1871 if the next is not the return statement */
1872 if (!(ic->next && ic->next->op == LABEL &&
1873 IC_LABEL (ic->next) == returnLabel))
1875 emitcode ("rjmp", "L%05d", returnLabel->key);
1879 /*-----------------------------------------------------------------*/
1880 /* genLabel - generates a label */
1881 /*-----------------------------------------------------------------*/
1883 genLabel (iCode * ic)
1885 /* special case never generate */
1886 if (IC_LABEL (ic) == entryLabel)
1889 emitcode ("", "L%05d:", IC_LABEL (ic)->key);
1892 /*-----------------------------------------------------------------*/
1893 /* genGoto - generates a ljmp */
1894 /*-----------------------------------------------------------------*/
1896 genGoto (iCode * ic)
1898 emitcode ("rjmp", "L%05d", (IC_LABEL (ic)->key));
1901 /*-----------------------------------------------------------------*/
1902 /* genPlusIncr :- does addition with increment if possible */
1903 /*-----------------------------------------------------------------*/
1905 genPlusIncr (iCode * ic)
1907 unsigned int icount;
1909 /* will try to generate an increment */
1910 /* if the right side is not a literal
1912 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
1916 (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.
1919 /* if the sizes are greater than 2 or they are not the same regs
1921 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1924 /* so we know LEFT & RESULT in the same registers and add
1926 /* for short & char types */
1927 if (AOP_SIZE (IC_RESULT (ic)) < 2) {
1929 emitcode ("inc", "%s",
1930 aopGet (AOP (IC_LEFT (ic)), 0));
1933 emitcode ("subi", "%s,lo8(%d)",
1934 aopGet (AOP (IC_LEFT (ic)), 0), 0-icount);
1938 if (AOP_SIZE (IC_RESULT (ic)) <= 3) {
1939 /* if register pair and starts with 26/30 then adiw */
1940 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0
1942 && (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX)
1943 || IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX))) {
1944 emitcode ("adiw", "%s,%d",
1945 aopGet (AOP (IC_RESULT (ic)), 0), icount);
1950 emitcode ("subi", "%s,lo8(%d)",
1951 aopGet (AOP (IC_RESULT (ic)), 0), 0-icount);
1952 emitcode ("sbci", "%s,hi8(%d)",
1953 aopGet (AOP (IC_RESULT (ic)), 1), 0-icount);
1957 /* for 32 bit longs */
1958 emitcode ("subi", "%s,lo8(%d)", aopGet (AOP (IC_RESULT (ic)), 0),
1960 emitcode ("sbci", "%s,hi8(%d)", aopGet (AOP (IC_RESULT (ic)), 1),
1962 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2),
1964 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3),
1970 /* This is the pure and virtuous version of this code.
1971 * I'm pretty certain it's right, but not enough to toss the old
1975 adjustArithmeticResult (iCode * ic)
1977 if (opIsGptr (IC_RESULT (ic)) &&
1978 opIsGptr (IC_LEFT (ic)) &&
1979 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)))) {
1980 aopPut (AOP (IC_RESULT (ic)),
1981 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1),
1985 if (opIsGptr (IC_RESULT (ic)) &&
1986 opIsGptr (IC_RIGHT (ic)) &&
1987 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)))) {
1988 aopPut (AOP (IC_RESULT (ic)),
1989 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1),
1993 if (opIsGptr (IC_RESULT (ic)) &&
1994 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
1995 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
1996 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
1997 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)))) {
1999 sprintf (buffer, "%d",
2000 pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2001 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2005 /*-----------------------------------------------------------------*/
2006 /* genPlus - generates code for addition */
2007 /*-----------------------------------------------------------------*/
2009 genPlus (iCode * ic)
2011 int size, offset = 0;
2015 /* special cases :- */
2017 aopOp (IC_LEFT (ic), ic, FALSE);
2018 aopOp (IC_RIGHT (ic), ic, FALSE);
2019 aopOp (IC_RESULT (ic), ic, TRUE);
2021 /* if I can do an increment instead
2022 of add then GOOD for ME */
2023 if (genPlusIncr (ic) == TRUE)
2026 size = getDataSize (IC_RESULT (ic));
2027 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2031 aopPut (AOP (IC_RESULT (ic)),
2032 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2034 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
2041 emitcode (l, "%s,%s",
2042 aopGet (AOP (IC_RESULT (ic)), offset),
2043 aopGet (AOP (IC_RIGHT (ic)), offset));
2051 emitcode (l, "%s,%s(-%d)",
2052 aopGet (AOP (IC_RESULT (ic)), offset),
2054 (int) floatFromVal (AOP (IC_RIGHT (ic))->
2060 adjustArithmeticResult (ic);
2063 freeAsmop (IC_LEFT (ic), NULL, ic,
2064 (RESULTONSTACK (ic) ? FALSE : TRUE));
2065 freeAsmop (IC_RIGHT (ic), NULL, ic,
2066 (RESULTONSTACK (ic) ? FALSE : TRUE));
2067 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2070 /*-----------------------------------------------------------------*/
2071 /* genMinusDec :- does subtraction with deccrement if possible */
2072 /*-----------------------------------------------------------------*/
2074 genMinusDec (iCode * ic)
2076 unsigned int icount;
2078 /* will try to generate an increment */
2079 /* if the right side is not a literal
2081 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2085 (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.
2088 /* if the sizes are greater than 2 or they are not the same regs
2090 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic))))
2093 /* so we know LEFT & RESULT in the same registers and add
2095 /* for short & char types */
2096 if (AOP_SIZE (IC_RESULT (ic)) < 2) {
2098 emitcode ("dec", "%s",
2099 aopGet (AOP (IC_LEFT (ic)), 0));
2102 emitcode ("subi", "%s,lo8(%d)",
2103 aopGet (AOP (IC_LEFT (ic)), 0), icount);
2107 if (AOP_SIZE (IC_RESULT (ic)) <= 3) {
2108 /* if register pair and starts with 26/30 then adiw */
2109 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0
2111 && (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX)
2112 || IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX))) {
2113 emitcode ("sbiw", "%s,%d",
2114 aopGet (AOP (IC_RESULT (ic)), 0), icount);
2119 emitcode ("subi", "%s,lo8(%d)",
2120 aopGet (AOP (IC_RESULT (ic)), 0), icount);
2121 emitcode ("sbci", "%s,hi8(%d)",
2122 aopGet (AOP (IC_RESULT (ic)), 1), icount);
2125 /* for 32 bit longs */
2126 emitcode ("subi", "%s,lo8(%d)", aopGet (AOP (IC_RESULT (ic)), 0),
2128 emitcode ("sbci", "%s,hi8(%d)", aopGet (AOP (IC_RESULT (ic)), 1),
2130 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2),
2132 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3),
2138 /*-----------------------------------------------------------------*/
2139 /* genMinus - generates code for subtraction */
2140 /*-----------------------------------------------------------------*/
2142 genMinus (iCode * ic)
2144 int size, offset = 0, samer;
2147 aopOp (IC_LEFT (ic), ic, FALSE);
2148 aopOp (IC_RIGHT (ic), ic, FALSE);
2149 aopOp (IC_RESULT (ic), ic, TRUE);
2151 /* if I can do an decrement instead
2152 of subtract then GOOD for ME */
2153 if (genMinusDec (ic) == TRUE)
2156 size = getDataSize (IC_RESULT (ic));
2157 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2160 aopPut (AOP (IC_RESULT (ic)),
2161 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2163 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
2170 emitcode (l, "%s,%s",
2171 aopGet (AOP (IC_RESULT (ic)), offset),
2172 aopGet (AOP (IC_RIGHT (ic)), offset));
2180 emitcode (l, "%s,%s(%d)",
2181 aopGet (AOP (IC_RESULT (ic)), offset),
2183 (int) floatFromVal (AOP (IC_RIGHT (ic))->
2189 adjustArithmeticResult (ic);
2192 freeAsmop (IC_LEFT (ic), NULL, ic,
2193 (RESULTONSTACK (ic) ? FALSE : TRUE));
2194 freeAsmop (IC_RIGHT (ic), NULL, ic,
2195 (RESULTONSTACK (ic) ? FALSE : TRUE));
2196 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2199 /*-----------------------------------------------------------------*/
2200 /* genMultOneByte : 8 bit multiplication & division */
2201 /*-----------------------------------------------------------------*/
2203 genMultOneByte (operand * left, operand * right, operand * result)
2205 sym_link *opetype = operandType (result);
2209 /* (if two literals, the value is computed before) */
2210 /* if one literal, literal on the right */
2211 if (AOP_TYPE (left) == AOP_LIT) {
2217 size = AOP_SIZE (result);
2219 if (SPEC_USIGN (opetype)) {
2220 emitcode ("mul", "%s,%s", aopGet (AOP (left), 0),
2221 aopGet (AOP (right), 0));
2224 emitcode ("muls", "%s,%s", aopGet (AOP (left), 0),
2225 aopGet (AOP (right), 0));
2227 aopPut (AOP (result), "r0", 0);
2229 aopPut (AOP (result), "r1", 1);
2232 if (SPEC_USIGN (opetype)) {
2234 aopPut (AOP (result), zero, offset++);
2239 lbl = newiTempLabel (NULL);
2240 emitcode ("ldi", "r24,0");
2241 emitcode ("brcc", "L%05d", lbl->key);
2242 emitcode ("ldi", "r24,lo8(-1)");
2243 emitcode ("", "L%05d:", lbl->key);
2245 aopPut (AOP (result), "r24",
2253 /*-----------------------------------------------------------------*/
2254 /* genMult - generates code for multiplication */
2255 /*-----------------------------------------------------------------*/
2257 genMult (iCode * ic)
2259 operand *left = IC_LEFT (ic);
2260 operand *right = IC_RIGHT (ic);
2261 operand *result = IC_RESULT (ic);
2263 /* assign the amsops */
2264 aopOp (left, ic, FALSE);
2265 aopOp (right, ic, FALSE);
2266 aopOp (result, ic, TRUE);
2268 /* if both are of size == 1 */
2269 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1) {
2270 genMultOneByte (left, right, result);
2274 /* should have been converted to function call */
2278 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2279 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2280 freeAsmop (result, NULL, ic, TRUE);
2283 /*-----------------------------------------------------------------*/
2284 /* genDiv - generates code for division */
2285 /*-----------------------------------------------------------------*/
2289 /* should have been converted to function call */
2293 /*-----------------------------------------------------------------*/
2294 /* genMod - generates code for division */
2295 /*-----------------------------------------------------------------*/
2299 /* should have been converted to function call */
2311 /*-----------------------------------------------------------------*/
2312 /* revavrcnd - reverse a conditional for avr */
2313 /*-----------------------------------------------------------------*/
2315 revavrcnd (int type)
2327 for (i = 0; i < (sizeof (rar) / sizeof (rar[0])); i++) {
2328 if (rar[i].type == type)
2329 return rar[i].rtype;
2330 if (rar[i].rtype == type)
2333 assert (1); /* cannot happen */
2334 return 0; /* makes the compiler happy */
2337 static char *br_name[4] = { "breq", "brne", "brlt", "brge" };
2338 static char *br_uname[4] = { "breq", "brne", "brlo", "brcc" };
2340 /*-----------------------------------------------------------------*/
2341 /* genBranch - generate the branch instruction */
2342 /*-----------------------------------------------------------------*/
2344 genBranch (iCode * ifx, int br_type, int sign)
2346 int tj = (IC_TRUE (ifx) ? 1 : 0);
2348 if (tj) { /* if true jump */
2349 char *nm = (sign ? br_name[br_type] : br_uname[br_type]);
2350 emitcode (nm, "L%05d", IC_TRUE (ifx)->key);
2352 else { /* if false jump */
2353 int rtype = revavrcnd (br_type);
2354 char *nm = (sign ? br_name[rtype] : br_uname[rtype]);
2355 emitcode (nm, "L%05d", IC_FALSE (ifx)->key);
2360 /*-----------------------------------------------------------------*/
2361 /* genCmp - compare & jump */
2362 /*-----------------------------------------------------------------*/
2364 genCmp (iCode * ic, iCode * ifx, int br_type)
2366 operand *left, *right, *result;
2367 sym_link *letype, *retype;
2369 int sign, size, offset = 0;
2371 left = IC_LEFT (ic);
2372 right = IC_RIGHT (ic);
2373 result = IC_RESULT (ic);
2375 letype = getSpec (operandType (left));
2376 retype = getSpec (operandType (right));
2377 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
2379 /* assign the amsops */
2380 aopOp (left, ic, FALSE);
2381 aopOp (right, ic, FALSE);
2382 aopOp (result, ic, TRUE);
2383 size = AOP_SIZE (left);
2387 if (AOP_TYPE (right) == AOP_LIT) {
2388 emitcode ("cpi", "%s,lo8(%d)",
2389 aopGet (AOP (left), 0),
2391 floatFromVal (AOP (IC_RIGHT (ic))->
2393 genBranch (ifx, br_type, sign);
2395 else { /* right != literal */
2396 emitcode ("cp", "%s,%s",
2397 aopGet (AOP (left), 0),
2398 aopGet (AOP (right), 0));
2399 genBranch (ifx, br_type, sign);
2402 else { /* size != 1 */
2405 emitcode ("cp", "%s,%s",
2406 aopGet (AOP (left), 0),
2407 aopGet (AOP (right), 0));
2409 emitcode ("cpc", "%s,%s",
2410 aopGet (AOP (left), offset),
2411 aopGet (AOP (right),
2415 genBranch (ifx, br_type, sign);
2419 emitcode ("clr", "r0");
2422 emitcode ("cp", "%s,%s",
2423 aopGet (AOP (left), 0),
2424 aopGet (AOP (right), 0));
2426 emitcode ("cpc", "%s,%s",
2427 aopGet (AOP (left), offset),
2428 aopGet (AOP (right), offset));
2431 lbl = newiTempLabel (NULL);
2432 br_type = revavrcnd (br_type);
2434 emitcode (br_uname[br_type], "L%05d", lbl->key);
2436 emitcode (br_name[br_type], "L%05d", lbl->key);
2437 emitcode ("inc", "r0");
2438 emitcode ("", "L%05d:", lbl->key);
2439 aopPut (AOP (result), "r0", 0);
2440 size = AOP_SIZE (result) - 1;
2443 aopPut (AOP (result), zero, offset++);
2446 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2447 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2448 freeAsmop (result, NULL, ic, TRUE);
2451 /*-----------------------------------------------------------------*/
2452 /* genCmpGt :- greater than comparison */
2453 /*-----------------------------------------------------------------*/
2455 genCmpGt (iCode * ic, iCode * ifx)
2457 /* should have transformed by the parser */
2461 /*-----------------------------------------------------------------*/
2462 /* genCmpLt - less than comparisons */
2463 /*-----------------------------------------------------------------*/
2465 genCmpLt (iCode * ic, iCode * ifx)
2467 genCmp (ic, ifx, AVR_LT);
2470 /*-----------------------------------------------------------------*/
2471 /* genCmpEq - generates code for equal to */
2472 /*-----------------------------------------------------------------*/
2474 genCmpEq (iCode * ic, iCode * ifx)
2476 genCmp (ic, ifx, AVR_EQ);
2479 /*-----------------------------------------------------------------*/
2480 /* genCmpNe - generates code for not equal to */
2481 /*-----------------------------------------------------------------*/
2483 genCmpNe (iCode * ic, iCode * ifx)
2485 genCmp (ic, ifx, AVR_NE);
2488 /*-----------------------------------------------------------------*/
2489 /* genCmpGe - generates code for greater than equal to */
2490 /*-----------------------------------------------------------------*/
2492 genCmpGe (iCode * ic, iCode * ifx)
2494 genCmp (ic, ifx, AVR_GE);
2497 /*-----------------------------------------------------------------*/
2498 /* genCmpLe - generates code for less than equal to */
2499 /*-----------------------------------------------------------------*/
2501 genCmpLe (iCode * ic, iCode * ifx)
2503 operand *left = IC_LEFT (ic);
2504 operand *right = IC_RIGHT (ic);
2506 IC_RIGHT (ic) = left;
2507 IC_LEFT (ic) = right;
2508 genCmp (ic, ifx, AVR_GE);
2511 /*-----------------------------------------------------------------*/
2512 /* ifxForOp - returns the icode containing the ifx for operand */
2513 /*-----------------------------------------------------------------*/
2515 ifxForOp (operand * op, iCode * ic)
2517 /* if true symbol then needs to be assigned */
2518 if (IS_TRUE_SYMOP (op))
2521 /* if this has register type condition and
2522 the next instruction is ifx with the same operand
2523 and live to of the operand is upto the ifx only then */
2525 ic->next->op == IFX &&
2526 IC_COND (ic->next)->key == op->key &&
2527 OP_SYMBOL (op)->liveTo <= ic->next->seq) return ic->next;
2532 /*-----------------------------------------------------------------*/
2533 /* genAndOp - for && operation */
2534 /*-----------------------------------------------------------------*/
2536 genAndOp (iCode * ic)
2538 operand *left, *right, *result;
2542 /* note here that && operations that are in an
2543 if statement are taken away by backPatchLabels
2544 only those used in arthmetic operations remain */
2545 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2546 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2547 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
2549 tlbl = newiTempLabel (NULL);
2550 toBoolean (left, "r0", TRUE);
2551 toBoolean (right, "r1", TRUE);
2552 emitcode ("and", "r0,r1");
2553 emitcode ("ldi", "r24,1");
2554 emitcode ("breq", "L%05d", tlbl->key);
2555 emitcode ("dec", "r24");
2556 emitcode ("", "L%05d:", tlbl->key);
2557 aopPut (AOP (result), "r24", 0);
2558 size = AOP_SIZE (result) - 1;
2561 aopPut (AOP (result), zero, offset++);
2563 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2564 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2565 freeAsmop (result, NULL, ic, TRUE);
2569 /*-----------------------------------------------------------------*/
2570 /* genOrOp - for || operation */
2571 /*-----------------------------------------------------------------*/
2573 genOrOp (iCode * ic)
2575 operand *left, *right, *result;
2579 /* note here that || operations that are in an
2580 if statement are taken away by backPatchLabels
2581 only those used in arthmetic operations remain */
2582 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2583 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2584 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
2586 tlbl = newiTempLabel (NULL);
2587 toBoolean (left, "r0", TRUE);
2588 toBoolean (right, "r0", FALSE);
2589 emitcode ("ldi", "r24,1");
2590 emitcode ("breq", "L%05d", tlbl->key);
2591 emitcode ("dec", "r24");
2592 emitcode ("", "L%05d:", tlbl->key);
2593 aopPut (AOP (result), "r24", 0);
2594 size = AOP_SIZE (result) - 1;
2597 aopPut (AOP (result), zero, offset++);
2599 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2600 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2601 freeAsmop (result, NULL, ic, TRUE);
2605 AVR_AND = 0, AVR_OR, AVR_XOR
2607 static char *bopnames_lit[] = { "andi", "ori" };
2608 static char *bopnames[] = { "and", "or", "eor" };
2609 /*-----------------------------------------------------------------*/
2610 /* genBitWise - generate bitwise operations */
2611 /*-----------------------------------------------------------------*/
2613 genBitWise (iCode * ic, iCode * ifx, int bitop)
2615 operand *left, *right, *result;
2616 int size, offset = 0;
2621 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2622 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2623 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
2625 size = AOP_SIZE (left);
2627 if (ifx) { /* used only for jumps */
2628 if (AOP_TYPE (right) == AOP_LIT &&
2629 (bitop == AVR_AND || bitop == AVR_OR)) {
2631 (int) floatFromVal (AOP (right)->aopu.
2633 int p2 = powof2 (lit);
2634 if (bitop == AVR_AND && p2) { /* right side is a power of 2 */
2635 l = aopGet (AOP (left), p2 / 8);
2636 if (IC_TRUE (ifx)) {
2637 emitcode ("sbrc", "%s,%d", l,
2639 emitcode ("rjmp", "L%05d",
2640 IC_TRUE (ifx)->key);
2643 emitcode ("sbrs", "%s,%d", l,
2645 emitcode ("rjmp", "L%05d",
2646 IC_FALSE (ifx)->key);
2649 else { /* right not power of two */
2650 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2652 if (eh && AOP_ISHIGHREG(AOP(IC_LEFT(ic)),0)) {
2653 emitcode (bopnames_lit[bitop],
2655 aopGet (AOP (IC_LEFT (ic)), 0), lit);
2658 MOVR24 (aopGet (AOP (IC_LEFT (ic)), 0));
2659 emitcode (bopnames_lit[bitop], "r24,lo8(%d)", lit);
2661 lbl = newiTempLabel (NULL);
2662 if (IC_TRUE (ifx)) {
2663 emitcode ("breq", "L%05d", lbl->key);
2664 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2667 emitcode ("brne", "L%05d", lbl->key);
2668 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)-> key);
2670 emitcode ("", "L%05d:", lbl->key);
2672 else if (size == 2) {
2673 emitcode ("mov", "r24,%s", aopGet (AOP (IC_LEFT (ic)), 0));
2674 emitcode ("mov", "r25,%s", aopGet (AOP (IC_LEFT (ic)), 1));
2675 emitcode (bopnames_lit[bitop], "r24,lo8(%d)", lit);
2676 emitcode (bopnames_lit[bitop], "r25,hi8(%d)", lit);
2677 emitcode ("sbiw", "r24,0");
2678 lbl = newiTempLabel (NULL);
2679 if (IC_TRUE (ifx)) {
2680 emitcode ("breq", "L%05d", lbl->key);
2681 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2684 emitcode ("brne", "L%05d", lbl->key);
2685 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2687 emitcode ("", "L%05d:", lbl->key);
2690 lbl = newiTempLabel (NULL);
2691 lbl1 = newiTempLabel (NULL);
2693 if (eh && AOP_ISHIGHREG(AOP(IC_LEFT(ic)),offset)) {
2694 emitcode (bopnames_lit [bitop], "%s,lo8(%d)",
2695 aopGet (AOP (IC_LEFT (ic)), offset),
2699 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
2701 emitcode ("andi", "r24,lo8(%d)", lit);
2703 emitcode ("brne", "L%05d", lbl->key);
2708 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)-> key);
2710 emitcode ("rjmp", "L%05d", lbl1->key);
2711 emitcode ("", "L%05d:", lbl->key);
2714 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2715 emitcode ("", "L%05d:", lbl1->key);
2720 else { /* right is not a literal */
2721 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2722 int reh = OP_SYMBOL (right)->liveTo <= ic->seq;
2725 emitcode (bopnames[bitop], "%s,%s", aopGet (AOP (IC_LEFT (ic)), 0),
2726 aopGet (AOP (IC_RIGHT (ic)), 0));
2729 emitcode (bopnames[bitop], "%s,%s",
2730 aopGet (AOP (IC_RIGHT (ic)), 0),
2731 aopGet (AOP (IC_LEFT (ic)), 0));
2734 MOVR0 (aopGet (AOP (IC_LEFT (ic)), 0));
2735 emitcode (bopnames[bitop], "r0,%s",
2736 aopGet (AOP (IC_RIGHT (ic)), 0));
2738 lbl = newiTempLabel (NULL);
2739 if (IC_TRUE (ifx)) {
2740 emitcode ("breq", "L%05d", lbl->key);
2741 emitcode ("rjmp", "L%05d",
2742 IC_TRUE (ifx)->key);
2745 emitcode ("brne", "L%05d", lbl->key);
2746 emitcode ("rjmp", "L%05d",
2747 IC_FALSE (ifx)->key);
2749 emitcode ("", "L%05d:", lbl->key);
2751 else if (size == 2) {
2752 emitcode ("mov", "r24,%s",
2753 aopGet (AOP (IC_LEFT (ic)), 0));
2754 emitcode ("mov", "r25,%s",
2755 aopGet (AOP (IC_LEFT (ic)), 1));
2756 emitcode (bopnames[bitop], "r24,%s",
2757 aopGet (AOP (IC_RIGHT (ic)), 0));
2758 emitcode (bopnames[bitop], "r25,%s",
2759 aopGet (AOP (IC_RIGHT (ic)), 1));
2760 emitcode ("sbiw", "r24,0");
2761 lbl = newiTempLabel (NULL);
2762 if (IC_TRUE (ifx)) {
2763 emitcode ("breq", "L%05d", lbl->key);
2764 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2767 emitcode ("brne", "L%05d", lbl->key);
2768 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2770 emitcode ("", "L%05d:", lbl->key);
2773 lbl = newiTempLabel (NULL);
2774 lbl1 = newiTempLabel (NULL);
2777 emitcode (bopnames[bitop], "%s,%s",
2778 aopGet (AOP (IC_LEFT (ic)), offset),
2779 aopGet (AOP (IC_RIGHT (ic)), offset));
2782 emitcode (bopnames[bitop], "%s,%s",
2783 aopGet (AOP (IC_RIGHT (ic)), offset),
2784 aopGet (AOP (IC_LEFT (ic)), offset));
2787 MOVR0 (aopGet (AOP (IC_LEFT (ic)), offset));
2788 emitcode (bopnames[bitop], "r0,%s",
2789 aopGet (AOP (IC_RIGHT (ic)), offset));
2791 emitcode ("brne", "L%05d", lbl->key);
2796 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2798 emitcode ("rjmp", "L%05d", lbl1->key);
2799 emitcode ("", "L%05d:", lbl->key);
2802 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2803 emitcode ("", "L%05d:", lbl1->key);
2810 /* result needs to go a register */
2811 samerl = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2812 samerr = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)));
2814 if (AOP_TYPE (right) == AOP_LIT) {
2816 (int) floatFromVal (AOP (right)->aopu.
2818 if (((lit >> (8 * offset)) & 0xff) == 0) {
2819 if (bitop == AVR_AND) {
2820 aopPut (AOP (result), zero, offset++);
2823 else if (bitop == AVR_OR) {
2825 aopPut (AOP (result),
2835 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT &&
2836 AOP_ISHIGHREG(AOP(IC_LEFT(ic)),offset) &&
2837 (bitop == AVR_AND || bitop == AVR_OR)) {
2838 emitcode (bopnames_lit[bitop], "%s,%s(%d)",
2839 aopGet (AOP (IC_LEFT (ic)), offset),
2841 (int) floatFromVal (AOP (right)-> aopu.aop_lit));
2844 emitcode (bopnames[bitop], "%s,%s",
2845 aopGet (AOP (IC_LEFT (ic)), offset),
2846 aopGet (AOP (IC_RIGHT (ic)), offset));
2850 emitcode (bopnames[bitop], "%s,%s",
2851 aopGet (AOP (IC_RIGHT (ic)), offset),
2852 aopGet (AOP (IC_LEFT (ic)), offset));
2855 aopPut (AOP (IC_RESULT (ic)),
2856 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2857 emitcode (bopnames[bitop],
2858 aopGet (AOP (IC_RESULT (ic)), offset),
2859 aopGet (AOP (IC_RIGHT (ic)), offset));
2864 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2865 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2866 freeAsmop (result, NULL, ic, TRUE);
2869 /*-----------------------------------------------------------------*/
2870 /* genAnd - code for and */
2871 /*-----------------------------------------------------------------*/
2873 genAnd (iCode * ic, iCode * ifx)
2875 genBitWise (ic, ifx, AVR_AND);
2878 /*-----------------------------------------------------------------*/
2879 /* genOr - code for or */
2880 /*-----------------------------------------------------------------*/
2882 genOr (iCode * ic, iCode * ifx)
2884 genBitWise (ic, ifx, AVR_OR);
2887 /*-----------------------------------------------------------------*/
2888 /* genXor - code for xclusive or */
2889 /*-----------------------------------------------------------------*/
2891 genXor (iCode * ic, iCode * ifx)
2893 genBitWise (ic, ifx, AVR_XOR);
2896 /*-----------------------------------------------------------------*/
2897 /* genInline - write the inline code out */
2898 /*-----------------------------------------------------------------*/
2900 genInline (iCode * ic)
2902 char *buffer, *bp, *bp1;
2904 _G.inLine += (!options.asmpeep);
2906 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
2907 strcpy (buffer, IC_INLINE (ic));
2909 /* emit each line as a code */
2930 /* emitcode("",buffer); */
2931 _G.inLine -= (!options.asmpeep);
2934 /*-----------------------------------------------------------------*/
2935 /* genRotC - rotate right/left with carry , lr = 1 rotate right */
2936 /*-----------------------------------------------------------------*/
2938 genRotC (iCode * ic, int lr)
2940 operand *left, *result;
2941 int size, offset = 0;
2943 /* rotate right with carry */
2944 left = IC_LEFT (ic);
2945 result = IC_RESULT (ic);
2946 aopOp (left, ic, FALSE);
2947 aopOp (result, ic, FALSE);
2949 /* move it to the result */
2950 size = AOP_SIZE (result);
2951 if (!sameRegs (AOP (left), AOP (result))) {
2954 aopPut (AOP (result),
2955 aopGet (AOP (left), offset), offset);
2958 size = AOP_SIZE (result);
2966 emitcode ("sbrc", "%s,%d", aopGet (AOP (result), offset),
2968 emitcode ("sec", "");
2971 emitcode ((lr ? "ror" : "rol"), "%s",
2972 aopGet (AOP (result), offset));
2978 freeAsmop (left, NULL, ic, TRUE);
2979 freeAsmop (result, NULL, ic, TRUE);
2982 /*-----------------------------------------------------------------*/
2983 /* genRRC - rotate right with carry */
2984 /*-----------------------------------------------------------------*/
2991 /*-----------------------------------------------------------------*/
2992 /* genRLC - generate code for rotate left with carry */
2993 /*-----------------------------------------------------------------*/
3000 /*-----------------------------------------------------------------*/
3001 /* genGetHbit - generates code get highest order bit */
3002 /*-----------------------------------------------------------------*/
3004 genGetHbit (iCode * ic)
3006 operand *left, *result;
3009 left = IC_LEFT (ic);
3010 result = IC_RESULT (ic);
3011 aopOp (left, ic, FALSE);
3012 aopOp (result, ic, FALSE);
3014 size = AOP_SIZE (result);
3015 if (!sameRegs (AOP (left), AOP (result))) {
3016 emitcode ("clr", "%s", aopGet (AOP (result), size - 1));
3017 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3018 emitcode ("subi", "%s,lo8(-1)",
3019 aopGet (AOP (result), size - 1));
3022 emitcode ("clr", "r0");
3023 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3024 emitcode ("subi", "r0,lo8(-1)");
3025 aopPut (AOP (result), "r0", 0);
3030 emitcode ("clr", aopGet (AOP (result), offset++));
3032 freeAsmop (left, NULL, ic, TRUE);
3033 freeAsmop (result, NULL, ic, TRUE);
3036 /*-----------------------------------------------------------------*/
3037 /* genShiftLeftLit - shift left by a known amount */
3038 /*-----------------------------------------------------------------*/
3040 genShiftLeftLit (iCode * ic)
3042 operand *left, *right, *result;
3043 int size, shCount, offset = 0;
3046 right = IC_RIGHT (ic);
3047 left = IC_LEFT (ic);
3048 result = IC_RESULT (ic);
3050 aopOp (left, ic, FALSE);
3051 aopOp (result, ic, FALSE);
3052 size = AOP_SIZE (result);
3053 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3055 if (shCount > (size * 8 - 1)) {
3057 aopPut (AOP (result), zero, offset++);
3062 if (!sameRegs (AOP (left), AOP (result)))
3063 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3065 if (AOP_ISHIGHREG(AOP(result),0)) {
3066 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3067 emitcode ("andi", "%s,0xf0");
3069 emitcode ("ldi","r24,0xf0");
3070 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3071 emitcode ("and", "%s,r24");
3076 emitcode ("add", "%s,%s", aopGet (AOP (result), 0),
3077 aopGet (AOP (result), 0));
3081 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3084 if (shCount >= 12) {
3085 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3086 aopPut (AOP (result), zero, 0);
3087 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3088 if (AOP_ISHIGHREG(AOP(result),1)) {
3089 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3091 emitcode ("ldi","r24,0xf0");
3092 emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
3098 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3099 aopPut (AOP (result), zero, 0);
3105 if (!sameRegs (AOP (left), AOP (result))) {
3106 aopPut (AOP (result), aopGet (AOP (left), 0),
3108 aopPut (AOP (result), aopGet (AOP (left), 1),
3111 emitcode ("mov", "r24,%s", aopGet (AOP (result), 0));
3112 emitcode ("andi", "r24,0x0f");
3113 if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
3114 emitcode("ldi","r25,0xf0");
3116 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3117 if (AOP_ISHIGHREG(AOP(result),0)) {
3118 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 0));
3120 emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
3122 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3123 if (AOP_ISHIGHREG(AOP(result),1)) {
3124 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3126 emitcode ("and", "%s,r25", aopGet (AOP (result), 1));
3128 emitcode ("or", "%s,r24", aopGet (AOP (result), 1));
3130 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3131 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3134 if (!lByteZ && !sameRegs (AOP (result), AOP (left))
3138 aopPut (AOP (result),
3139 aopGet (AOP (left), offset), offset);
3145 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3148 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3149 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3154 assert ("shifting generic pointer ?\n");
3157 /* 32 bits we do only byte boundaries */
3158 if (shCount >= 24) {
3159 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3160 aopPut (AOP (result), zero, 2);
3161 aopPut (AOP (result), zero, 1);
3162 aopPut (AOP (result), zero, 0);
3166 if (shCount >= 16) {
3167 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3168 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3169 aopPut (AOP (result), zero, 1);
3170 aopPut (AOP (result), zero, 0);
3175 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3176 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3177 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3178 aopPut (AOP (result), zero, 0);
3182 if (!lByteZ && !sameRegs (AOP (left), AOP (right))) {
3185 aopPut (AOP (result),
3186 aopGet (AOP (left), offset), offset);
3190 size = AOP_SIZE (result);
3196 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3197 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3198 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3199 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3204 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3205 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3206 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3211 emitcode ("lsl", "%s", aopGet (AOP (result), 2));
3212 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3217 emitcode ("lsl", "%s", aopGet (AOP (result), 3));
3225 freeAsmop (left, NULL, ic, TRUE);
3226 freeAsmop (right, NULL, ic, TRUE);
3227 freeAsmop (result, NULL, ic, TRUE);
3230 /*-----------------------------------------------------------------*/
3231 /* genLeftShift - generates code for left shifting */
3232 /*-----------------------------------------------------------------*/
3234 genLeftShift (iCode * ic)
3236 operand *left, *right, *result;
3240 right = IC_RIGHT (ic);
3241 left = IC_LEFT (ic);
3242 result = IC_RESULT (ic);
3244 aopOp (right, ic, FALSE);
3246 if (AOP_TYPE (right) == AOP_LIT) {
3247 genShiftLeftLit (ic);
3252 aopOp (left, ic, FALSE);
3253 aopOp (result, ic, FALSE);
3254 size = AOP_SIZE (result);
3256 if (AOP_SIZE (right) > 1) {
3257 if (isRegPair (AOP (right))) {
3258 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3261 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3262 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3266 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3268 if (!sameRegs (AOP (left), AOP (result))) {
3270 aopPut (AOP (result), aopGet (AOP (left), offset),
3274 size = AOP_SIZE (result);
3276 tlbl = newiTempLabel (NULL);
3277 emitcode ("", "L%05d:", tlbl->key);
3281 emitcode ("rol", "%s", aopGet (AOP (result), offset));
3283 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3286 if (AOP_SIZE (right) > 1)
3287 emitcode ("sbiw", "r24,1");
3289 emitcode ("dec", "r24");
3290 emitcode ("brne", "L%05d", tlbl->key);
3292 freeAsmop (left, NULL, ic, TRUE);
3293 freeAsmop (right, NULL, ic, TRUE);
3294 freeAsmop (result, NULL, ic, TRUE);
3297 /*-----------------------------------------------------------------*/
3298 /* genShiftRightLit - generate for right shift with known count */
3299 /*-----------------------------------------------------------------*/
3301 genShiftRightLit (iCode * ic)
3303 operand *left = IC_LEFT (ic)
3304 , *right = IC_RIGHT (ic)
3305 , *result = IC_RESULT (ic);
3306 int size, shCount, offset = 0;
3308 sym_link *letype = getSpec (operandType (left));
3309 int sign = !SPEC_USIGN (letype);
3311 right = IC_RIGHT (ic);
3312 left = IC_LEFT (ic);
3313 result = IC_RESULT (ic);
3315 aopOp (left, ic, FALSE);
3316 aopOp (result, ic, FALSE);
3317 size = AOP_SIZE (result);
3318 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3320 /* if signed then give up and use a loop to shift */
3323 if (!sameRegs (AOP (left), AOP (result))) {
3325 aopPut (AOP (result),
3326 aopGet (AOP (left), offset), offset);
3329 size = AOP_SIZE (result);
3332 /* be as economical as possible */
3335 size = AOP_SIZE (result);
3338 /* highest order byte */
3339 if (offset == (AOP_SIZE(result)-1))
3340 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3342 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3348 emitcode ("ldi", "r24,lo8(%d)", shCount);
3349 tlbl = newiTempLabel (NULL);
3350 emitcode ("", "L%05d:", tlbl->key);
3353 if (offset == (AOP_SIZE(result) - 1))
3354 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3356 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3359 emitcode ("dec", "r24");
3360 emitcode ("brne", "L%05d", tlbl->key);
3364 if (shCount > (size * 8 - 1)) {
3366 aopPut (AOP (result), zero, offset++);
3369 /* for unsigned we can much more efficient */
3372 if (!sameRegs (AOP (left), AOP (result)))
3373 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3375 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3376 if (AOP_ISHIGHREG(AOP(result),0)) {
3377 emitcode ("andi", "%s,0x0f",aopGet(AOP(result),0));
3379 emitcode ("ldi","r24,0x0f");
3380 emitcode ("and", "%s,r24",aopGet(AOP(result),0));
3385 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3388 if (shCount >= 12) {
3389 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3390 aopPut (AOP (result), zero, 1);
3391 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3392 if (AOP_ISHIGHREG(AOP(result),0)) {
3393 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3395 emitcode ("ldi","r24,0x0f");
3396 emitcode ("and", "%s,r24",aopGet(AOP(result),0));
3402 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3403 aopPut (AOP (result), zero, 1);
3409 if (!sameRegs (AOP (left), AOP (result))) {
3410 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3411 aopPut (AOP (result), aopGet (AOP (left), 1), 1);
3413 if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
3414 emitcode("ldi","r25,0x0f");
3416 emitcode ("mov", "r24,%s", aopGet (AOP (result), 1));
3417 emitcode ("andi", "r24,0xf0");
3418 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3419 if (AOP_ISHIGHREG(AOP(result),0)) {
3420 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3422 emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
3424 emitcode ("or", "%s,r24", aopGet (AOP (result), 0));
3425 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3426 if (AOP_ISHIGHREG(AOP(result),1)) {
3427 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 1));
3429 emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
3432 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3433 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3437 if (!hByteZ && !sameRegs (AOP (result), AOP (left))
3441 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3447 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3450 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3451 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3457 assert ("shifting generic pointer ?\n");
3460 /* 32 bits we do only byte boundaries */
3461 if (shCount >= 24) {
3462 aopPut (AOP (result), aopGet (AOP (left), 3), 0);
3463 aopPut (AOP (result), zero, 1);
3464 aopPut (AOP (result), zero, 2);
3465 aopPut (AOP (result), zero, 3);
3469 if (shCount >= 16) {
3470 aopPut (AOP (result), aopGet (AOP (left), 3), 1);
3471 aopPut (AOP (result), aopGet (AOP (left), 2), 0);
3472 aopPut (AOP (result), zero, 2);
3473 aopPut (AOP (result), zero, 3);
3478 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3479 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3480 aopPut (AOP (result), aopGet (AOP (left), 3), 2);
3481 aopPut (AOP (result), zero, 3);
3485 if (!hByteZ && !sameRegs (AOP (left), AOP (right))) {
3488 aopPut (AOP (result),
3489 aopGet (AOP (left), offset), offset);
3493 size = AOP_SIZE (result);
3499 emitcode ("lsr", "%s", aopGet (AOP (result), 3));
3500 emitcode ("ror", "%s", aopGet (AOP (result), 2));
3501 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3502 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3507 emitcode ("lsr", "%s", aopGet (AOP (result), 2));
3508 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3509 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3514 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3515 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3520 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3527 freeAsmop (left, NULL, ic, TRUE);
3528 freeAsmop (right, NULL, ic, TRUE);
3529 freeAsmop (result, NULL, ic, TRUE);
3532 /*-----------------------------------------------------------------*/
3533 /* genRightShift - generate code for right shifting */
3534 /*-----------------------------------------------------------------*/
3536 genRightShift (iCode * ic)
3538 operand *right, *left, *result;
3541 int sign = 0, first = 1;
3544 aopOp (right = IC_RIGHT (ic), ic, FALSE);
3546 if (AOP_TYPE (right) == AOP_LIT) {
3547 genShiftRightLit (ic);
3551 if (AOP_SIZE (right) > 1) {
3552 if (isRegPair (AOP (right))) {
3553 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3556 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3557 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3561 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3563 aopOp (left = IC_LEFT (ic), ic, FALSE);
3564 aopOp (result = IC_RESULT (ic), ic, FALSE);
3565 size = AOP_SIZE (result);
3566 tlbl = newiTempLabel (NULL);
3567 emitcode ("", "L%05d:", tlbl->key);
3569 letype = getSpec (operandType (left));
3570 sign = !SPEC_USIGN (letype);
3571 if (!sameRegs (AOP (left), AOP (result))) {
3573 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3576 size = AOP_SIZE (result);
3578 size = AOP_SIZE (result);
3582 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3584 emitcode ("lsr", "%s", aopGet (AOP (result), offset));
3588 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3591 if (AOP_SIZE (right) > 1)
3592 emitcode ("sbiw", "r24,1");
3594 emitcode ("dec", "r24");
3595 emitcode ("brne", "L%05d", tlbl->key);
3597 freeAsmop (left, NULL, ic, TRUE);
3598 freeAsmop (result, NULL, ic, TRUE);
3601 /*-----------------------------------------------------------------*/
3602 /* RRsh - shift right rn by known count */
3603 /*-----------------------------------------------------------------*/
3605 RRsh (int shCount,int reg)
3607 shCount &= 0x0007; // shCount : 0..7
3613 emitcode ("lsr", "r%d",reg);
3616 emitcode ("lsr", "r%d",reg);
3617 emitcode ("lsr", "r%d",reg);
3620 emitcode ("swap", "r%d",reg);
3621 emitcode ("lsl", "r%d",reg);
3624 emitcode ("swap", "r%d",reg);
3627 emitcode ("swap", "r%d",reg);
3628 emitcode ("lsr", "r%d",reg);
3631 emitcode ("swap","r%d",reg);
3632 emitcode ("lsr", "r%d",reg);
3633 emitcode ("lsr", "r%d",reg);
3636 emitcode ("swap","r%d",reg);
3637 emitcode ("lsr", "r%d",reg);
3638 emitcode ("lsr", "r%d",reg);
3639 emitcode ("lsr", "r%d",reg);
3644 /*-----------------------------------------------------------------*/
3645 /* RLsh - shift left rn by known count */
3646 /*-----------------------------------------------------------------*/
3648 RLsh (int shCount, int reg)
3650 shCount &= 0x0007; // shCount : 0..7
3656 emitcode ("lsl", "r%d",reg);
3659 emitcode ("lsl", "r%d",reg);
3660 emitcode ("lsl", "r%d",reg);
3663 emitcode ("swap","r%d",reg);
3664 emitcode ("lsr", "r%d",reg);
3667 emitcode ("swap", "r%d",reg);
3670 emitcode ("swap","r%d",reg);
3671 emitcode ("lsl", "r%d",reg);
3674 emitcode ("swap","r%d",reg);
3675 emitcode ("lsl", "r%d",reg);
3676 emitcode ("lsl", "r%d",reg);
3679 emitcode ("swap","r%d",reg);
3680 emitcode ("lsl", "r%d",reg);
3681 emitcode ("lsl", "r%d",reg);
3682 emitcode ("lsl", "r%d",reg);
3687 /*-----------------------------------------------------------------*/
3688 /* genUnpackBits - generates code for unpacking bits */
3689 /*-----------------------------------------------------------------*/
3691 genUnpackBits (operand * result, char *rname, int ptype)
3699 etype = getSpec (operandType (result));
3700 rsize = getSize (operandType (result));
3701 /* read the first byte */
3708 emitcode ("ld", "r24,%s+", rname);
3712 emitcode ("lpm", "r24,%s+", rname);
3716 emitcode ("call","__gptrget_pi");
3717 emitcode ("mov","r24,r0");
3721 rlen = SPEC_BLEN (etype);
3723 /* if we have bitdisplacement then it fits */
3724 /* into this byte completely or if length is */
3725 /* less than a byte */
3726 if ((shCnt = SPEC_BSTR (etype)) || (SPEC_BLEN (etype) <= 8)) {
3728 /* shift right acc */
3731 emitcode ("andi", "r24,lo(0x%x)",
3732 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
3733 aopPut (AOP (result), "r24", offset++);
3737 /* bit field did not fit in a byte */
3738 aopPut (AOP (result), "r24", offset++);
3748 emitcode ("ld", "r24,%s+");
3752 emitcode ("lpm", "r24,%s+");
3756 emitcode ("call", "__gptrget_pi");
3761 /* if we are done */
3765 aopPut (AOP (result), "r24", offset++);
3770 aopPut (AOP (result), "r24", offset++);
3774 if (offset < rsize) {
3777 aopPut (AOP (result), zero, offset++);
3782 /*-----------------------------------------------------------------*/
3783 /* genDataPointerGet - generates code when ptr offset is known */
3784 /*-----------------------------------------------------------------*/
3786 genDataPointerGet (operand * left, operand * result, iCode * ic)
3790 int size, offset = 0;
3791 aopOp (result, ic, TRUE);
3793 /* get the string representation of the name */
3794 l = aopGet (AOP (left), 0);
3795 size = AOP_SIZE (result);
3798 sprintf (buffer, "(%s + %d)", l, offset);
3800 sprintf (buffer, "%s", l);
3801 emitcode ("lds", "%s,%s", aopGet (AOP (result), offset++),
3805 freeAsmop (left, NULL, ic, TRUE);
3806 freeAsmop (result, NULL, ic, TRUE);
3809 /*-----------------------------------------------------------------*/
3810 /* genNearPointerGet - emitcode for near pointer fetch */
3811 /*-----------------------------------------------------------------*/
3813 genMemPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
3818 char *rname, *frname = NULL;
3819 sym_link *rtype, *retype;
3820 sym_link *ltype = operandType (left);
3822 rtype = operandType (result);
3823 retype = getSpec (rtype);
3825 aopOp (left, ic, FALSE);
3827 /* if left is rematerialisable and
3828 result is not bit variable type and
3829 the left is pointer to data space i.e
3830 lower 128 bytes of space */
3831 if (AOP_TYPE (left) == AOP_IMMD &&
3832 !IS_BITVAR (retype) && DCL_TYPE (ltype) == POINTER) {
3833 genDataPointerGet (left, result, ic);
3837 /* if the value is already in a pointer register
3838 then don't need anything more */
3839 if (!AOP_INPREG (AOP (left))) {
3840 /* otherwise get a free pointer register */
3842 preg = getFreePtr (ic, &aop, FALSE, 0);
3843 if (isRegPair (AOP (left) )) {
3844 emitcode ("movw", "%s,%s",
3845 aop->aopu.aop_ptr->name,
3846 aopGet(AOP(left),0));
3848 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
3849 aopGet (AOP (left), 0));
3850 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
3851 aopGet (AOP (left), 1));
3857 frname = aopGet(aop,0);
3861 } else if (AOP_ISZ(aop)) {
3864 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
3865 "pointer not in correct register");
3869 aopOp (result, ic, FALSE);
3871 /* if bitfield then unpack the bits */
3872 if (IS_BITVAR (retype))
3873 genUnpackBits (result, rname, POINTER);
3875 /* we have can just get the values */
3876 int size = AOP_SIZE (result);
3881 emitcode ("ld","%s,%s+",aopGet(AOP(result),offset), rname);
3883 emitcode ("ld","%s,%s",aopGet(AOP(result),offset), rname);
3888 /* now some housekeeping stuff */
3890 /* we had to allocate for this iCode */
3892 if (isRegPair (AOP (left) )) {
3893 emitcode ("movw", "%s,%s",
3894 aopGet (AOP(left),0),
3895 aop->aopu.aop_ptr->name);
3897 emitcode ("mov", "%s,%s",
3898 aopGet (AOP (left), 0),
3899 aop->aopu.aop_ptr->name);
3900 emitcode ("mov", "%s,%s",
3901 aopGet (AOP (left), 1),
3902 aop->aop_ptr2->name);
3905 freeAsmop (NULL, aop, ic, TRUE);
3908 /* we did not allocate which means left
3909 already in a pointer register, then
3910 if size > 0 && this could be used again
3911 we have to point it back to where it
3913 if ((AOP_SIZE (result) > 1 &&
3914 !OP_SYMBOL (left)->remat &&
3915 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) && !pi) {
3916 int size = AOP_SIZE (result) - 1;
3917 emitcode ("sbiw", "%s,%d",frname,size);
3922 if (pi) pi->generated = 1;
3923 freeAsmop (left, NULL, ic, TRUE);
3924 freeAsmop (result, NULL, ic, TRUE);
3928 /*-----------------------------------------------------------------*/
3929 /* genCodePointerGet - gget value from code space */
3930 /*-----------------------------------------------------------------*/
3932 genCodePointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
3935 sym_link *retype = getSpec (operandType (result));
3939 aopOp (left, ic, FALSE);
3941 /* if the operand is already in Z register
3942 then we do nothing else we move the value to Z register */
3943 if (AOP_ISZ(AOP(left))) {
3947 getFreePtr(ic,&aop,FALSE,TRUE);
3948 if (isRegPair(AOP (left))) {
3949 emitcode ("movw","r30,%s",aopGet (AOP (left), 0));
3951 emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
3952 emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
3957 aopOp (result, ic, FALSE);
3959 /* if bit then unpack */
3960 if (IS_BITVAR (retype))
3961 genUnpackBits (result, "Z", CPOINTER);
3963 size = AOP_SIZE (result);
3968 emitcode ("lpm","%s,Z+",aopGet(AOP(result),offset++));
3970 emitcode ("lpm","%s,Z",aopGet(AOP(result),offset++));
3975 /* now some housekeeping stuff */
3977 /* we had to allocate for this iCode */
3979 if (isRegPair(AOP (left))) {
3980 emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
3982 emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
3983 emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
3986 freeAsmop (NULL, aop, ic, TRUE);
3989 /* we did not allocate which means left
3990 already in a pointer register, then
3991 if size > 0 && this could be used again
3992 we have to point it back to where it
3994 if ((AOP_SIZE (result) > 1 &&
3995 !OP_SYMBOL (left)->remat &&
3996 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) &&
3998 int size = AOP_SIZE (result) - 1;
3999 emitcode ("sbiw", "r30,%d",size);
4004 if (pi) pi->generated=1;
4005 freeAsmop (left, NULL, ic, TRUE);
4006 freeAsmop (result, NULL, ic, TRUE);
4010 /*-----------------------------------------------------------------*/
4011 /* genGenPointerGet - gget value from generic pointer space */
4012 /*-----------------------------------------------------------------*/
4014 genGenPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
4018 sym_link *retype = getSpec (operandType (result));
4021 aopOp (left, ic, FALSE);
4023 /* if the operand is already in dptr
4024 then we do nothing else we move the value to dptr */
4025 if (AOP_ISZ(AOP(left))) {
4029 getFreePtr(ic,&aop,FALSE,TRUE);
4030 if (isRegPair(AOP(left))) {
4031 emitcode ("movw", "r30,%s", aopGet (AOP (left), 0));
4033 emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
4034 emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
4036 emitcode ("mov", "r24,%s", aopGet (AOP (left), 2));
4040 /* so Z register now contains the address */
4042 aopOp (result, ic, FALSE);
4044 /* if bit then unpack */
4045 if (IS_BITVAR (retype))
4046 genUnpackBits (result, "Z", GPOINTER);
4048 size = AOP_SIZE (result);
4053 emitcode ("call", "__gptrget_pi");
4055 emitcode ("call", "__gptrget");
4056 aopPut (AOP (result), "r0", offset++);
4061 /* now some housekeeping stuff */
4063 /* we had to allocate for this iCode */
4065 if (isRegPair(AOP (left))) {
4066 emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
4068 emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
4069 emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
4072 freeAsmop (NULL, aop, ic, TRUE);
4075 /* we did not allocate which means left
4076 already in a pointer register, then
4077 if size > 0 && this could be used again
4078 we have to point it back to where it
4080 if ((AOP_SIZE (result) > 1 &&
4081 !OP_SYMBOL (left)->remat &&
4082 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) &&
4084 int size = AOP_SIZE (result) - 1;
4085 emitcode ("sbiw", "r30,%d",size);
4088 if (pi) pi->generated=1;
4089 freeAsmop (left, NULL, ic, TRUE);
4090 freeAsmop (result, NULL, ic, TRUE);
4093 /*-----------------------------------------------------------------*/
4094 /* genPointerGet - generate code for pointer get */
4095 /*-----------------------------------------------------------------*/
4097 genPointerGet (iCode * ic, iCode *pi)
4099 operand *left, *result;
4100 sym_link *type, *etype;
4103 left = IC_LEFT (ic);
4104 result = IC_RESULT (ic);
4106 /* depending on the type of pointer we need to
4107 move it to the correct pointer register */
4108 type = operandType (left);
4109 etype = getSpec (type);
4110 /* if left is of type of pointer then it is simple */
4111 if (IS_PTR (type) && !IS_FUNC (type->next))
4112 p_type = DCL_TYPE (type);
4114 /* we have to go by the storage class */
4115 p_type = PTR_TYPE (SPEC_OCLS (etype));
4120 /* now that we have the pointer type we assign
4121 the pointer values */
4128 genMemPointerGet (left, result, ic, pi);
4132 genCodePointerGet (left, result, ic, pi);
4136 genGenPointerGet (left, result, ic, pi);
4142 /*-----------------------------------------------------------------*/
4143 /* genPackBits - generates code for packed bit storage */
4144 /*-----------------------------------------------------------------*/
4146 genPackBits (sym_link * etype,
4148 char *rname, int p_type)
4156 blen = SPEC_BLEN (etype);
4157 bstr = SPEC_BSTR (etype);
4159 l = aopGet (AOP (right), offset++);
4162 /* if the bit lenth is less than or */
4163 /* it exactly fits a byte then */
4164 if (SPEC_BLEN (etype) <= 8) {
4165 shCount = SPEC_BSTR (etype);
4167 /* shift left acc */
4170 if (SPEC_BLEN (etype) < 8) { /* if smaller than a byte */
4177 emitcode ("ld", "r1,%s",rname);
4181 emitcode ("push", "r1");
4182 emitcode ("push", "r24");
4183 emitcode ("call", "__gptrget");
4184 emitcode ("pop", "r1");
4185 emitcode ("mov","r24,r0");
4189 emitcode ("andi", "r24,#0x%02x", (unsigned char)
4190 ((unsigned char) (0xFF << (blen + bstr)) |
4191 (unsigned char) (0xFF >> (8 - bstr))));
4192 emitcode ("or", "r24,r1");
4193 if (p_type == GPOINTER)
4194 emitcode ("pop", "r1");
4203 emitcode("st","%s+,r24");
4207 emitcode("mov","r0,r24");
4208 emitcode ("call", "__gptrput_pi");
4213 if (SPEC_BLEN (etype) <= 8)
4216 rLen = SPEC_BLEN (etype);
4218 /* now generate for lengths greater than one byte */
4221 l = aopGet (AOP (right), offset++);
4232 emitcode ("st", "%s+,%s",rname,l);
4237 emitcode ("lcall", "__gptrput_pi");
4244 /* last last was not complete */
4246 /* save the byte & read byte */
4252 emitcode ("st","%s+,r24",rname);
4255 emitcode ("push", "r1");
4256 emitcode ("push", "r24");
4257 emitcode ("lcall", "__gptrget");
4258 emitcode ("mov","r24,r0");
4259 emitcode ("pop", "r1");
4263 emitcode ("andi", "r24,0x%02x", (((unsigned char) -1 << rLen) & 0xff));
4264 emitcode ("or", "r24,r1");
4267 if (p_type == GPOINTER)
4268 emitcode ("pop", "r1");
4276 emitcode ("st", "%s,r24", rname);
4280 emitcode ("mov","r0,r24");
4281 emitcode ("call", "__gptrput");
4286 /*-----------------------------------------------------------------*/
4287 /* genDataPointerSet - remat pointer to data space */
4288 /*-----------------------------------------------------------------*/
4290 genDataPointerSet (operand * right, operand * result, iCode * ic)
4292 int size, offset = 0;
4293 char *l, buffer[256];
4295 aopOp (right, ic, FALSE);
4297 l = aopGet (AOP (result), 0);
4298 size = AOP_SIZE (right);
4301 sprintf (buffer, "(%s + %d)", l, offset);
4303 sprintf (buffer, "%s", l);
4304 emitcode ("sts", "%s,%s", buffer,
4305 aopGet (AOP (right), offset++));
4308 freeAsmop (right, NULL, ic, TRUE);
4309 freeAsmop (result, NULL, ic, TRUE);
4312 /*-----------------------------------------------------------------*/
4313 /* genNearPointerSet - emitcode for near pointer put */
4314 /*-----------------------------------------------------------------*/
4316 genMemPointerSet (operand * right, operand * result, iCode * ic, iCode *pi)
4319 char *frname = NULL, *rname, *l;
4322 sym_link *ptype = operandType (result);
4324 retype = getSpec (operandType (right));
4326 aopOp (result, ic, FALSE);
4328 /* if the result is rematerializable &
4329 in data space & not a bit variable */
4330 if (AOP_TYPE (result) == AOP_IMMD &&
4331 DCL_TYPE (ptype) == POINTER && !IS_BITVAR (retype)) {
4332 genDataPointerSet (right, result, ic);
4335 if (!AOP_INPREG(AOP(result))) {
4336 /* otherwise get a free pointer register */
4338 getFreePtr (ic, &aop, FALSE, 0);
4339 if (isRegPair (AOP (result) )) {
4340 emitcode ("movw", "%s,%s",aop->aopu.aop_ptr->name,
4341 aopGet(AOP (result), 0));
4343 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
4344 aopGet (AOP (result), 0));
4345 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
4346 aopGet (AOP (result), 1));
4351 frname = aopGet(aop,0);
4354 aopOp (right, ic, FALSE);
4357 } else if (AOP_ISZ(aop)) {
4360 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4361 "pointer not in correct register");
4364 /* if bitfield then unpack the bits */
4365 if (IS_BITVAR (retype))
4366 genPackBits (retype, right, rname, POINTER);
4368 /* we have can just get the values */
4369 int size = AOP_SIZE (right);
4373 l = aopGet (AOP (right), offset);
4375 emitcode ("st", "%s+,%s", rname,l);
4377 emitcode ("st", "%s,%s", rname,l);
4382 /* now some housekeeping stuff */
4384 /* we had to allocate for this iCode */
4386 if (isRegPair (AOP (result) )) {
4387 emitcode ("movw", "%s,%s",
4388 aopGet(AOP(result),0),
4389 aop->aopu.aop_ptr->name);
4391 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
4392 aopGet (AOP (result), 0));
4393 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
4394 aopGet (AOP (result), 1));
4397 freeAsmop (NULL, aop, ic, TRUE);
4400 /* we did not allocate which means left
4401 already in a pointer register, then
4402 if size > 0 && this could be used again
4403 we have to point it back to where it
4405 if ((AOP_SIZE (right) > 1 &&
4406 !OP_SYMBOL (result)->remat &&
4407 (OP_SYMBOL (right)->liveTo > ic->seq || ic->depth)) && !pi) {
4408 int size = AOP_SIZE (right) - 1;
4409 emitcode ("sbiw", "%s,%d",frname,size);
4414 if (pi) pi->generated = 1;
4415 freeAsmop (result, NULL, ic, TRUE);
4416 freeAsmop (right, NULL, ic, TRUE);
4419 /*-----------------------------------------------------------------*/
4420 /* genGenPointerSet - set value from generic pointer space */
4421 /*-----------------------------------------------------------------*/
4423 genGenPointerSet (operand * right, operand * result, iCode * ic, iCode *pi)
4427 sym_link *retype = getSpec (operandType (right));
4430 aopOp (result, ic, FALSE);
4432 /* if the operand is already in dptr
4433 then we do nothing else we move the value to dptr */
4434 if (AOP_ISZ(AOP(result))) {
4438 getFreePtr(ic,&aop,FALSE,TRUE);
4439 if (isRegPair(AOP(result))) {
4440 emitcode ("movw", "r30,%s", aopGet (AOP (result), 0));
4442 emitcode ("mov", "r30,%s", aopGet (AOP (result), 0));
4443 emitcode ("mov", "r31,%s", aopGet (AOP (result), 1));
4445 emitcode ("mov", "r24,%s", aopGet (AOP (result), 2));
4449 /* so Z register now contains the address */
4450 aopOp (right, ic, FALSE);
4452 /* if bit then unpack */
4453 if (IS_BITVAR (retype))
4454 genUnpackBits (result, "Z", GPOINTER);
4456 size = AOP_SIZE (right);
4460 char *l = aopGet(AOP (right), offset++);
4464 emitcode ("call", "__gptrput_pi");
4466 emitcode ("call", "__gptrput");
4470 /* now some housekeeping stuff */
4472 /* we had to allocate for this iCode */
4474 if (isRegPair(AOP(result))) {
4475 emitcode ("movw", "%s,r30", aopGet (AOP (result), 0));
4477 emitcode ("mov", "%s,r30", aopGet (AOP (result), 0));
4478 emitcode ("mov", "%s,r31", aopGet (AOP (result), 1));
4481 freeAsmop (NULL, aop, ic, TRUE);
4484 /* we did not allocate which means left
4485 already in a pointer register, then
4486 if size > 0 && this could be used again
4487 we have to point it back to where it
4489 if ((AOP_SIZE (right) > 1 &&
4490 !OP_SYMBOL (result)->remat &&
4491 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) && !pi) {
4492 int size = AOP_SIZE (right) - 1;
4493 emitcode ("sbiw", "r30,%d",size);
4496 if (pi) pi->generated = 1;
4497 freeAsmop (right, NULL, ic, TRUE);
4498 freeAsmop (result, NULL, ic, TRUE);
4501 /*-----------------------------------------------------------------*/
4502 /* genPointerSet - stores the value into a pointer location */
4503 /*-----------------------------------------------------------------*/
4505 genPointerSet (iCode * ic, iCode *pi)
4507 operand *right, *result;
4508 sym_link *type, *etype;
4511 right = IC_RIGHT (ic);
4512 result = IC_RESULT (ic);
4514 /* depending on the type of pointer we need to
4515 move it to the correct pointer register */
4516 type = operandType (result);
4517 etype = getSpec (type);
4518 /* if left is of type of pointer then it is simple */
4519 if (IS_PTR (type) && !IS_FUNC (type->next)) {
4520 p_type = DCL_TYPE (type);
4523 /* we have to go by the storage class */
4524 p_type = PTR_TYPE (SPEC_OCLS (etype));
4528 /* now that we have the pointer type we assign
4529 the pointer values */
4536 genMemPointerSet (right, result, ic, pi);
4540 genGenPointerSet (right, result, ic, pi);
4546 /*-----------------------------------------------------------------*/
4547 /* genIfx - generate code for Ifx statement */
4548 /*-----------------------------------------------------------------*/
4550 genIfx (iCode * ic, iCode * popIc)
4552 operand *cond = IC_COND (ic);
4557 aopOp (cond, ic, FALSE);
4559 /* get the value into acc */
4560 if (AOP_SIZE(cond) == 1 && AOP_ISHIGHREG(AOP(cond),0)) {
4561 cname = aopGet(AOP(cond),0);
4563 toBoolean (cond, "r24", 0);
4567 /* the result is now in the accumulator */
4568 freeAsmop (cond, NULL, ic, TRUE);
4570 /* if there was something to be popped then do it */
4573 emitcode("cpi","%s,0",cname);
4574 } else if (!tob) emitcode("cpi","%s,0",cname);
4576 lbl = newiTempLabel(NULL);
4579 emitcode ("breq","L%05d",lbl->key);
4581 emitcode ("brne","L%05d",lbl->key);
4582 emitcode ("jmp","L%05d",IC_TRUE(ic)->key);
4583 emitcode ("","L%05d:",lbl->key);
4586 emitcode ("brne","L%05d",lbl->key);
4588 emitcode ("breq","L%05d",lbl->key);
4589 emitcode ("jmp","L%05d",IC_FALSE(ic)->key);
4590 emitcode ("","L%05d:",lbl->key);
4595 /*-----------------------------------------------------------------*/
4596 /* genAddrOf - generates code for address of */
4597 /*-----------------------------------------------------------------*/
4599 genAddrOf (iCode * ic)
4601 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
4604 aopOp (IC_RESULT (ic), ic, FALSE);
4606 /* if the operand is on the stack then we
4607 need to get the stack offset of this
4610 /* if it has an offset then we need to compute it */
4612 emitcode ("mov", "a,_bp");
4613 emitcode ("add", "a,#0x%02x",
4614 ((char) sym->stack & 0xff));
4615 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4618 /* we can just move _bp */
4619 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
4621 /* fill the result with zero */
4622 size = AOP_SIZE (IC_RESULT (ic)) - 2;
4625 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
4631 /* object not on stack then we need the name */
4632 size = AOP_SIZE (IC_RESULT (ic));
4636 char s[SDCC_NAME_MAX];
4638 sprintf (s, "(%s >> %d)", sym->rname, offset * 8);
4640 sprintf (s, "%s", sym->rname);
4641 aopPut (AOP (IC_RESULT (ic)), s, offset++);
4645 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4649 /*-----------------------------------------------------------------*/
4650 /* genFarFarAssign - assignment when both are in far space */
4651 /*-----------------------------------------------------------------*/
4653 genFarFarAssign (operand * result, operand * right, iCode * ic)
4655 int size = AOP_SIZE (right);
4658 /* first push the right side on to the stack */
4660 l = aopGet (AOP (right), offset++);
4662 emitcode ("push", "acc");
4665 freeAsmop (right, NULL, ic, FALSE);
4666 /* now assign DPTR to result */
4667 aopOp (result, ic, FALSE);
4668 size = AOP_SIZE (result);
4670 emitcode ("pop", "acc");
4671 aopPut (AOP (result), "a", --offset);
4673 freeAsmop (result, NULL, ic, FALSE);
4677 /*-----------------------------------------------------------------*/
4678 /* genAssign - generate code for assignment */
4679 /*-----------------------------------------------------------------*/
4681 genAssign (iCode * ic)
4683 operand *result, *right;
4685 unsigned long lit = 0L;
4687 result = IC_RESULT (ic);
4688 right = IC_RIGHT (ic);
4690 /* if they are the same */
4691 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4694 aopOp (right, ic, FALSE);
4696 /* special case both in far space */
4697 if (AOP_TYPE (right) == AOP_DPTR &&
4698 IS_TRUE_SYMOP (result) && isOperandInFarSpace (result)) {
4700 genFarFarAssign (result, right, ic);
4704 aopOp (result, ic, TRUE);
4706 /* if they are the same registers */
4707 if (sameRegs (AOP (right), AOP (result)))
4710 /* if the result is a bit */
4711 if (AOP_TYPE (result) == AOP_CRY) {
4713 /* if the right size is a literal then
4714 we know what the value is */
4715 if (AOP_TYPE (right) == AOP_LIT) {
4716 if (((int) operandLitValue (right)))
4717 aopPut (AOP (result), one, 0);
4719 aopPut (AOP (result), zero, 0);
4723 /* the right is also a bit variable */
4724 if (AOP_TYPE (right) == AOP_CRY) {
4725 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4726 aopPut (AOP (result), "c", 0);
4731 toBoolean (right, "", 0);
4732 aopPut (AOP (result), "a", 0);
4736 /* bit variables done */
4738 size = AOP_SIZE (result);
4740 if (AOP_TYPE (right) == AOP_LIT)
4742 (unsigned long) floatFromVal (AOP (right)->aopu.
4744 if ((size > 1) && (AOP_TYPE (result) != AOP_REG)
4745 && (AOP_TYPE (right) == AOP_LIT)
4746 && !IS_FLOAT (operandType (right)) && (lit < 256L)) {
4747 emitcode ("clr", "a");
4749 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) ==
4750 0) aopPut (AOP (result), "a", size);
4752 aopPut (AOP (result),
4753 aopGet (AOP (right), size), size);
4758 aopPut (AOP (result),
4759 aopGet (AOP (right), offset), offset);
4765 freeAsmop (right, NULL, ic, FALSE);
4766 freeAsmop (result, NULL, ic, TRUE);
4769 /*-----------------------------------------------------------------*/
4770 /* genJumpTab - genrates code for jump table */
4771 /*-----------------------------------------------------------------*/
4773 genJumpTab (iCode * ic)
4778 aopOp (IC_JTCOND (ic), ic, FALSE);
4779 /* get the condition into accumulator */
4780 l = aopGet (AOP (IC_JTCOND (ic)), 0);
4782 /* multiply by three */
4783 emitcode ("add", "a,acc");
4784 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0));
4785 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
4787 jtab = newiTempLabel (NULL);
4788 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
4789 emitcode ("jmp", "@a+dptr");
4790 emitcode ("", "%05d$:", jtab->key + 100);
4791 /* now generate the jump labels */
4792 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
4793 jtab = setNextItem (IC_JTLABELS (ic)))
4794 emitcode ("ljmp", "%05d$", jtab->key + 100);
4798 /*-----------------------------------------------------------------*/
4799 /* genCast - gen code for casting */
4800 /*-----------------------------------------------------------------*/
4802 genCast (iCode * ic)
4804 operand *result = IC_RESULT (ic);
4805 sym_link *ctype = operandType (IC_LEFT (ic));
4806 sym_link *rtype = operandType (IC_RIGHT (ic));
4807 operand *right = IC_RIGHT (ic);
4810 /* if they are equivalent then do nothing */
4811 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4814 aopOp (right, ic, FALSE);
4815 aopOp (result, ic, FALSE);
4817 /* if the result is a bit */
4818 if (AOP_TYPE (result) == AOP_CRY) {
4819 /* if the right size is a literal then
4820 we know what the value is */
4821 if (AOP_TYPE (right) == AOP_LIT) {
4822 if (((int) operandLitValue (right)))
4823 aopPut (AOP (result), one, 0);
4825 aopPut (AOP (result), zero, 0);
4830 /* the right is also a bit variable */
4831 if (AOP_TYPE (right) == AOP_CRY) {
4832 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4833 aopPut (AOP (result), "c", 0);
4838 toBoolean (right, "", 0);
4839 aopPut (AOP (result), "a", 0);
4843 /* if they are the same size : or less */
4844 if (AOP_SIZE (result) <= AOP_SIZE (right)) {
4846 /* if they are in the same place */
4847 if (sameRegs (AOP (right), AOP (result)))
4850 /* if they in different places then copy */
4851 size = AOP_SIZE (result);
4854 aopPut (AOP (result),
4855 aopGet (AOP (right), offset), offset);
4862 /* if the result is of type pointer */
4863 if (IS_PTR (ctype)) {
4866 sym_link *type = operandType (right);
4867 sym_link *etype = getSpec (type);
4869 /* pointer to generic pointer */
4870 if (IS_GENPTR (ctype)) {
4874 p_type = DCL_TYPE (type);
4876 /* we have to go by the storage class */
4877 p_type = PTR_TYPE (SPEC_OCLS (etype));
4880 /* the first two bytes are known */
4881 size = GPTRSIZE - 1;
4884 aopPut (AOP (result),
4885 aopGet (AOP (right), offset), offset);
4888 /* the last byte depending on type */
4905 /* this should never happen */
4906 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4907 "got unknown pointer type");
4910 aopPut (AOP (result), l, GPTRSIZE - 1);
4914 /* just copy the pointers */
4915 size = AOP_SIZE (result);
4918 aopPut (AOP (result),
4919 aopGet (AOP (right), offset), offset);
4925 /* so we now know that the size of destination is greater
4926 than the size of the source */
4927 /* we move to result for the size of source */
4928 size = AOP_SIZE (right);
4931 aopPut (AOP (result), aopGet (AOP (right), offset), offset);
4935 /* now depending on the sign of the source && destination */
4936 size = AOP_SIZE (result) - AOP_SIZE (right);
4937 /* if unsigned or not an integral type */
4938 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype)) {
4940 aopPut (AOP (result), zero, offset++);
4943 /* we need to extend the sign :{ */
4944 // PENDING: Does nothing on avr
4946 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1);
4949 emitcode ("rlc", "a");
4950 emitcode ("subb", "a,acc");
4952 aopPut (AOP (result), "a", offset++);
4955 /* we are done hurray !!!! */
4958 freeAsmop (right, NULL, ic, TRUE);
4959 freeAsmop (result, NULL, ic, TRUE);
4963 /*-----------------------------------------------------------------*/
4964 /* genDjnz - generate decrement & jump if not zero instrucion */
4965 /*-----------------------------------------------------------------*/
4967 genDjnz (iCode * ic, iCode * ifx)
4973 /* if the if condition has a false label
4974 then we cannot save */
4978 /* if the minus is not of the form
4980 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
4981 !IS_OP_LITERAL (IC_RIGHT (ic)))
4984 if (operandLitValue (IC_RIGHT (ic)) != 1)
4987 /* if the size of this greater than one then no
4989 if (getSize (operandType (IC_RESULT (ic))) > 1)
4992 /* otherwise we can save BIG */
4993 lbl = newiTempLabel (NULL);
4994 lbl1 = newiTempLabel (NULL);
4996 aopOp (IC_RESULT (ic), ic, FALSE);
4998 if (IS_AOP_PREG (IC_RESULT (ic))) {
4999 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0));
5000 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0));
5001 emitcode ("jnz", "%05d$", lbl->key + 100);
5004 emitcode ("djnz", "%s,%05d$",
5005 aopGet (AOP (IC_RESULT (ic)), 0), lbl->key + 100);
5007 emitcode ("sjmp", "%05d$", lbl1->key + 100);
5008 emitcode ("", "%05d$:", lbl->key + 100);
5009 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5010 emitcode ("", "%05d$:", lbl1->key + 100);
5012 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5017 static char *recvregs[8] = {
5018 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23"
5021 static int recvCnt = 0;
5023 /*-----------------------------------------------------------------*/
5024 /* genReceive - generate code for a receive iCode */
5025 /*-----------------------------------------------------------------*/
5027 genReceive (iCode * ic)
5029 int size, offset = 0;
5030 aopOp (IC_RESULT (ic), ic, FALSE);
5031 size = AOP_SIZE (IC_RESULT (ic));
5033 aopPut (AOP (IC_RESULT (ic)), recvregs[recvCnt++], offset);
5036 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5039 /*-----------------------------------------------------------------*/
5040 /* gen51Code - generate code for 8051 based controllers */
5041 /*-----------------------------------------------------------------*/
5043 genAVRCode (iCode * lic)
5048 lineHead = lineCurr = NULL;
5050 /* print the allocation information */
5052 printAllocInfo (currFunc, codeOutFile);
5053 /* if debug information required */
5054 /* if (options.debug && currFunc) { */
5056 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
5058 /* emitcode ("", ".type %s,@function", currFunc->name); */
5061 /* stack pointer name */
5065 for (ic = lic; ic; ic = ic->next) {
5067 if (cln != ic->lineno) {
5068 if (options.debug) {
5070 emitcode ("", "C$%s$%d$%d$%d ==.",
5071 FileBaseName (ic->filename),
5072 ic->lineno, ic->level, ic->block);
5075 emitcode (";", "%s %d", ic->filename, ic->lineno);
5078 /* if the result is marked as
5079 spilt and rematerializable or code for
5080 this has already been generated then
5082 if (resultRemat (ic) || ic->generated)
5085 /* depending on the operation */
5104 /* IPOP happens only when trying to restore a
5105 spilt live range, if there is an ifx statement
5106 following this pop then the if statement might
5107 be using some of the registers being popped which
5108 would destory the contents of the register so
5109 we need to check for this condition and handle it */
5111 ic->next->op == IFX &&
5112 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
5113 genIfx (ic->next, ic);
5131 genEndFunction (ic);
5151 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
5168 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
5172 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
5176 genCmpLe (ic, ifxForOp (IC_RESULT (ic), ic));
5180 genCmpGe (ic, ifxForOp (IC_RESULT (ic), ic));
5184 genCmpNe (ic, ifxForOp (IC_RESULT (ic), ic));
5188 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
5200 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
5204 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
5208 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
5235 case GET_VALUE_AT_ADDRESS:
5236 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
5240 if (POINTER_SET (ic))
5241 genPointerSet (ic, hasInc(IC_RESULT(ic),ic));
5267 addSet (&_G.sendSet, ic);
5276 /* now we are ready to call the
5277 peep hole optimizer */
5278 if (!options.nopeep)
5279 peepHole (&lineHead);
5281 /* now do the actual printing */
5282 printLine (lineHead, codeOutFile);