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(OP_USES(op),lic->key) || ((unsigned) lic->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)",
479 aop->aopu.aop_ptr->name,
480 sym->stack - _G.nRegsSaved);
481 emitcode ("sbci", "%s,>(%d)",
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)",
494 aop->aopu.aop_ptr->name,
496 emitcode ("sbci", "%s,>(-%d)",
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,<(%s)", aop->aopu.aop_ptr->name, sym->rname);
540 emitcode ("ldi", "%s,>(%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,<(%d)",
856 aop->aopu.aop_ptr->name,
858 emitcode ("sbci", "%s,>(%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,<(%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,0xff",
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,<(%d)",
1587 emitcode ("sbci", "r29,>(%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,<(%d)",
1670 emitcode ("sbci", "r29,>(%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,<(%d)", sym->stack);
1764 emitcode ("sbci", "r29,>(%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,<(-%d)", sym->stack);
1787 emitcode ("sbci", "r29,>(-%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;
1910 /* will try to generate an increment */
1911 /* if the right side is not a literal
1913 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
1916 icount = (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 if (AOP_ISHIGHREG( AOP (IC_LEFT (ic)),0)) {
1934 emitcode ("subi", "%s,<(%d)",
1935 aopGet (AOP (IC_LEFT (ic)), 0), 0-icount);
1940 for (offset = 0 ; offset < AOP_SIZE(IC_RESULT(ic)) ; offset++) {
1941 if (!(AOP_ISHIGHREG(AOP(IC_RESULT(ic)),offset))) return FALSE;
1944 if (AOP_SIZE (IC_RESULT (ic)) <= 3) {
1945 /* if register pair and starts with 26/30 then adiw */
1946 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0
1948 && (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX) ||
1949 IS_REGIDX (AOP (IC_RESULT (ic)), R24_IDX) ||
1950 IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX))) {
1951 emitcode ("adiw", "%s,%d",
1952 aopGet (AOP (IC_RESULT (ic)), 0), icount);
1957 emitcode ("subi", "%s,<(%d)",
1958 aopGet (AOP (IC_RESULT (ic)), 0), 0-icount);
1959 emitcode ("sbci", "%s,>(%d)",
1960 aopGet (AOP (IC_RESULT (ic)), 1), 0-icount);
1964 /* for 32 bit longs */
1965 emitcode ("subi", "%s,<(%d)", aopGet (AOP (IC_RESULT (ic)), 0),
1967 emitcode ("sbci", "%s,>(%d)", aopGet (AOP (IC_RESULT (ic)), 1),
1969 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2),
1971 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3),
1977 /* This is the pure and virtuous version of this code.
1978 * I'm pretty certain it's right, but not enough to toss the old
1982 adjustArithmeticResult (iCode * ic)
1984 if (opIsGptr (IC_RESULT (ic)) &&
1985 opIsGptr (IC_LEFT (ic)) &&
1986 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)))) {
1987 aopPut (AOP (IC_RESULT (ic)),
1988 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1),
1992 if (opIsGptr (IC_RESULT (ic)) &&
1993 opIsGptr (IC_RIGHT (ic)) &&
1994 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)))) {
1995 aopPut (AOP (IC_RESULT (ic)),
1996 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1),
2000 if (opIsGptr (IC_RESULT (ic)) &&
2001 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2002 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2003 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2004 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)))) {
2006 sprintf (buffer, "%d",
2007 pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2008 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2012 /*-----------------------------------------------------------------*/
2013 /* genPlus - generates code for addition */
2014 /*-----------------------------------------------------------------*/
2016 genPlus (iCode * ic)
2018 int size, offset = 0;
2022 /* special cases :- */
2024 aopOp (IC_LEFT (ic), ic, FALSE);
2025 aopOp (IC_RIGHT (ic), ic, FALSE);
2026 aopOp (IC_RESULT (ic), ic, TRUE);
2028 /* if I can do an increment instead
2029 of add then GOOD for ME */
2030 if (genPlusIncr (ic) == TRUE)
2033 size = getDataSize (IC_RESULT (ic));
2034 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2038 aopPut (AOP (IC_RESULT (ic)),
2039 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2041 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
2048 emitcode (l, "%s,%s",
2049 aopGet (AOP (IC_RESULT (ic)), offset),
2050 aopGet (AOP (IC_RIGHT (ic)), offset));
2053 if (AOP_ISHIGHREG( AOP( IC_RESULT(ic)),offset)) {
2059 emitcode (l, "%s,%s(-%d)",
2060 aopGet (AOP (IC_RESULT (ic)), offset),
2062 (int) floatFromVal (AOP (IC_RIGHT (ic))->
2070 emitcode (l, "%s,%s",
2071 aopGet (AOP (IC_RESULT (ic)), offset),
2072 aopGet (AOP (IC_RIGHT (ic)), offset));
2078 adjustArithmeticResult (ic);
2081 freeAsmop (IC_LEFT (ic), NULL, ic,
2082 (RESULTONSTACK (ic) ? FALSE : TRUE));
2083 freeAsmop (IC_RIGHT (ic), NULL, ic,
2084 (RESULTONSTACK (ic) ? FALSE : TRUE));
2085 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2088 /*-----------------------------------------------------------------*/
2089 /* genMinusDec :- does subtraction with deccrement if possible */
2090 /*-----------------------------------------------------------------*/
2092 genMinusDec (iCode * ic)
2094 unsigned int icount;
2097 /* will try to generate an increment */
2098 /* if the right side is not a literal
2100 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2104 (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.
2107 /* if the sizes are greater than 2 or they are not the same regs
2109 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic))))
2112 /* so we know LEFT & RESULT in the same registers and add
2114 /* for short & char types */
2115 if (AOP_SIZE (IC_RESULT (ic)) < 2) {
2117 emitcode ("dec", "%s",
2118 aopGet (AOP (IC_LEFT (ic)), 0));
2121 if (AOP_ISHIGHREG( AOP ( IC_LEFT(ic)),0)) {
2122 emitcode ("subi", "%s,<(%d)",
2123 aopGet (AOP (IC_LEFT (ic)), 0), icount);
2128 for (offset = 0 ; offset < AOP_SIZE(IC_RESULT(ic)) ; offset++) {
2129 if (!(AOP_ISHIGHREG(AOP(IC_RESULT(ic)),offset))) return FALSE;
2132 if (AOP_SIZE (IC_RESULT (ic)) <= 3) {
2133 /* if register pair and starts with 26/30 then adiw */
2134 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0
2136 && (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX) ||
2137 IS_REGIDX (AOP (IC_RESULT (ic)), R24_IDX) ||
2138 IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX))) {
2139 emitcode ("sbiw", "%s,%d",
2140 aopGet (AOP (IC_RESULT (ic)), 0), icount);
2145 emitcode ("subi", "%s,<(%d)",
2146 aopGet (AOP (IC_RESULT (ic)), 0), icount);
2147 emitcode ("sbci", "%s,>(%d)",
2148 aopGet (AOP (IC_RESULT (ic)), 1), icount);
2151 /* for 32 bit longs */
2152 emitcode ("subi", "%s,<(%d)", aopGet (AOP (IC_RESULT (ic)), 0),
2154 emitcode ("sbci", "%s,>(%d)", aopGet (AOP (IC_RESULT (ic)), 1),
2156 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2),
2158 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3),
2164 /*-----------------------------------------------------------------*/
2165 /* genMinus - generates code for subtraction */
2166 /*-----------------------------------------------------------------*/
2168 genMinus (iCode * ic)
2170 int size, offset = 0, samer;
2173 aopOp (IC_LEFT (ic), ic, FALSE);
2174 aopOp (IC_RIGHT (ic), ic, FALSE);
2175 aopOp (IC_RESULT (ic), ic, TRUE);
2177 /* if I can do an decrement instead
2178 of subtract then GOOD for ME */
2179 if (genMinusDec (ic) == TRUE)
2182 size = getDataSize (IC_RESULT (ic));
2183 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2186 aopPut (AOP (IC_RESULT (ic)),
2187 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2189 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
2196 emitcode (l, "%s,%s",
2197 aopGet (AOP (IC_RESULT (ic)), offset),
2198 aopGet (AOP (IC_RIGHT (ic)), offset));
2201 if (AOP_ISHIGHREG(AOP (IC_RESULT (ic)),offset)) {
2207 emitcode (l, "%s,%s(%d)",
2208 aopGet (AOP (IC_RESULT (ic)), offset),
2210 (int) floatFromVal (AOP (IC_RIGHT (ic))->
2218 emitcode (l, "%s,%s",
2219 aopGet (AOP (IC_RESULT (ic)), offset),
2220 aopGet (AOP (IC_RIGHT (ic)), offset));
2226 adjustArithmeticResult (ic);
2229 freeAsmop (IC_LEFT (ic), NULL, ic,
2230 (RESULTONSTACK (ic) ? FALSE : TRUE));
2231 freeAsmop (IC_RIGHT (ic), NULL, ic,
2232 (RESULTONSTACK (ic) ? FALSE : TRUE));
2233 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2236 /*-----------------------------------------------------------------*/
2237 /* genMultOneByte : 8 bit multiplication & division */
2238 /*-----------------------------------------------------------------*/
2240 genMultOneByte (operand * left, operand * right, operand * result)
2242 sym_link *opetype = operandType (result);
2246 /* (if two literals, the value is computed before) */
2247 /* if one literal, literal on the right */
2248 if (AOP_TYPE (left) == AOP_LIT) {
2254 size = AOP_SIZE (result);
2256 if (SPEC_USIGN (opetype)) {
2257 emitcode ("mul", "%s,%s", aopGet (AOP (left), 0),
2258 aopGet (AOP (right), 0));
2261 emitcode ("muls", "%s,%s", aopGet (AOP (left), 0),
2262 aopGet (AOP (right), 0));
2264 aopPut (AOP (result), "r0", 0);
2266 aopPut (AOP (result), "r1", 1);
2269 if (SPEC_USIGN (opetype)) {
2271 aopPut (AOP (result), zero, offset++);
2276 lbl = newiTempLabel (NULL);
2277 emitcode ("ldi", "r24,0");
2278 emitcode ("brcc", "L%05d", lbl->key);
2279 emitcode ("ldi", "r24,0xff)");
2280 emitcode ("", "L%05d:", lbl->key);
2282 aopPut (AOP (result), "r24",
2290 /*-----------------------------------------------------------------*/
2291 /* genMult - generates code for multiplication */
2292 /*-----------------------------------------------------------------*/
2294 genMult (iCode * ic)
2296 operand *left = IC_LEFT (ic);
2297 operand *right = IC_RIGHT (ic);
2298 operand *result = IC_RESULT (ic);
2300 /* assign the amsops */
2301 aopOp (left, ic, FALSE);
2302 aopOp (right, ic, FALSE);
2303 aopOp (result, ic, TRUE);
2305 /* if both are of size == 1 */
2306 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1) {
2307 genMultOneByte (left, right, result);
2311 /* should have been converted to function call */
2315 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2316 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2317 freeAsmop (result, NULL, ic, TRUE);
2320 /*-----------------------------------------------------------------*/
2321 /* genDiv - generates code for division */
2322 /*-----------------------------------------------------------------*/
2326 /* should have been converted to function call */
2330 /*-----------------------------------------------------------------*/
2331 /* genMod - generates code for division */
2332 /*-----------------------------------------------------------------*/
2336 /* should have been converted to function call */
2348 /*-----------------------------------------------------------------*/
2349 /* revavrcnd - reverse a conditional for avr */
2350 /*-----------------------------------------------------------------*/
2352 revavrcnd (int type)
2364 for (i = 0; i < (sizeof (rar) / sizeof (rar[0])); i++) {
2365 if (rar[i].type == type)
2366 return rar[i].rtype;
2367 if (rar[i].rtype == type)
2370 assert (1); /* cannot happen */
2371 return 0; /* makes the compiler happy */
2374 static char *br_name[4] = { "breq", "brne", "brlt", "brge" };
2375 static char *br_uname[4] = { "breq", "brne", "brlo", "brcc" };
2377 /*-----------------------------------------------------------------*/
2378 /* genBranch - generate the branch instruction */
2379 /*-----------------------------------------------------------------*/
2381 genBranch (iCode * ifx, int br_type, int sign)
2383 int tj = (IC_TRUE (ifx) ? 1 : 0);
2385 if (tj) { /* if true jump */
2386 char *nm = (sign ? br_name[br_type] : br_uname[br_type]);
2387 emitcode (nm, "L%05d", IC_TRUE (ifx)->key);
2389 else { /* if false jump */
2390 int rtype = revavrcnd (br_type);
2391 char *nm = (sign ? br_name[rtype] : br_uname[rtype]);
2392 emitcode (nm, "L%05d", IC_FALSE (ifx)->key);
2397 /*-----------------------------------------------------------------*/
2398 /* genCmp - compare & jump */
2399 /*-----------------------------------------------------------------*/
2401 genCmp (iCode * ic, iCode * ifx, int br_type)
2403 operand *left, *right, *result;
2404 sym_link *letype, *retype;
2406 int sign, size, offset = 0;
2408 left = IC_LEFT (ic);
2409 right = IC_RIGHT (ic);
2410 result = IC_RESULT (ic);
2412 letype = getSpec (operandType (left));
2413 retype = getSpec (operandType (right));
2414 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
2416 /* assign the amsops */
2417 aopOp (left, ic, FALSE);
2418 aopOp (right, ic, FALSE);
2419 aopOp (result, ic, TRUE);
2420 size = AOP_SIZE (left);
2424 if (AOP_TYPE (right) == AOP_LIT) {
2425 emitcode ("cpi", "%s,<(%d)",
2426 aopGet (AOP (left), 0),
2428 floatFromVal (AOP (IC_RIGHT (ic))->
2430 genBranch (ifx, br_type, sign);
2432 else { /* right != literal */
2433 emitcode ("cp", "%s,%s",
2434 aopGet (AOP (left), 0),
2435 aopGet (AOP (right), 0));
2436 genBranch (ifx, br_type, sign);
2439 else { /* size != 1 */
2442 emitcode ("cp", "%s,%s",
2443 aopGet (AOP (left), 0),
2444 aopGet (AOP (right), 0));
2446 emitcode ("cpc", "%s,%s",
2447 aopGet (AOP (left), offset),
2448 aopGet (AOP (right),
2452 genBranch (ifx, br_type, sign);
2456 emitcode ("clr", "r0");
2459 emitcode ("cp", "%s,%s",
2460 aopGet (AOP (left), 0),
2461 aopGet (AOP (right), 0));
2463 emitcode ("cpc", "%s,%s",
2464 aopGet (AOP (left), offset),
2465 aopGet (AOP (right), offset));
2468 lbl = newiTempLabel (NULL);
2469 br_type = revavrcnd (br_type);
2471 emitcode (br_uname[br_type], "L%05d", lbl->key);
2473 emitcode (br_name[br_type], "L%05d", lbl->key);
2474 emitcode ("inc", "r0");
2475 emitcode ("", "L%05d:", lbl->key);
2476 aopPut (AOP (result), "r0", 0);
2477 size = AOP_SIZE (result) - 1;
2480 aopPut (AOP (result), zero, offset++);
2483 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2484 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2485 freeAsmop (result, NULL, ic, TRUE);
2488 /*-----------------------------------------------------------------*/
2489 /* genCmpGt :- greater than comparison */
2490 /*-----------------------------------------------------------------*/
2492 genCmpGt (iCode * ic, iCode * ifx)
2494 /* should have transformed by the parser */
2498 /*-----------------------------------------------------------------*/
2499 /* genCmpLt - less than comparisons */
2500 /*-----------------------------------------------------------------*/
2502 genCmpLt (iCode * ic, iCode * ifx)
2504 genCmp (ic, ifx, AVR_LT);
2507 /*-----------------------------------------------------------------*/
2508 /* genCmpEq - generates code for equal to */
2509 /*-----------------------------------------------------------------*/
2511 genCmpEq (iCode * ic, iCode * ifx)
2513 genCmp (ic, ifx, AVR_EQ);
2516 /*-----------------------------------------------------------------*/
2517 /* genCmpNe - generates code for not equal to */
2518 /*-----------------------------------------------------------------*/
2520 genCmpNe (iCode * ic, iCode * ifx)
2522 genCmp (ic, ifx, AVR_NE);
2525 /*-----------------------------------------------------------------*/
2526 /* genCmpGe - generates code for greater than equal to */
2527 /*-----------------------------------------------------------------*/
2529 genCmpGe (iCode * ic, iCode * ifx)
2531 genCmp (ic, ifx, AVR_GE);
2534 /*-----------------------------------------------------------------*/
2535 /* genCmpLe - generates code for less than equal to */
2536 /*-----------------------------------------------------------------*/
2538 genCmpLe (iCode * ic, iCode * ifx)
2540 operand *left = IC_LEFT (ic);
2541 operand *right = IC_RIGHT (ic);
2543 IC_RIGHT (ic) = left;
2544 IC_LEFT (ic) = right;
2545 genCmp (ic, ifx, AVR_GE);
2548 /*-----------------------------------------------------------------*/
2549 /* ifxForOp - returns the icode containing the ifx for operand */
2550 /*-----------------------------------------------------------------*/
2552 ifxForOp (operand * op, iCode * ic)
2554 /* if true symbol then needs to be assigned */
2555 if (IS_TRUE_SYMOP (op))
2558 /* if this has register type condition and
2559 the next instruction is ifx with the same operand
2560 and live to of the operand is upto the ifx only then */
2562 ic->next->op == IFX &&
2563 IC_COND (ic->next)->key == op->key &&
2564 OP_SYMBOL (op)->liveTo <= ic->next->seq) return ic->next;
2569 /*-----------------------------------------------------------------*/
2570 /* genAndOp - for && operation */
2571 /*-----------------------------------------------------------------*/
2573 genAndOp (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, "r1", TRUE);
2589 emitcode ("and", "r0,r1");
2590 emitcode ("ldi", "r24,1");
2591 emitcode ("breq", "L%05d", tlbl->key);
2592 emitcode ("dec", "r24");
2593 emitcode ("", "L%05d:", tlbl->key);
2594 aopPut (AOP (result), "r24", 0);
2595 size = AOP_SIZE (result) - 1;
2598 aopPut (AOP (result), zero, offset++);
2600 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2601 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2602 freeAsmop (result, NULL, ic, TRUE);
2606 /*-----------------------------------------------------------------*/
2607 /* genOrOp - for || operation */
2608 /*-----------------------------------------------------------------*/
2610 genOrOp (iCode * ic)
2612 operand *left, *right, *result;
2616 /* note here that || operations that are in an
2617 if statement are taken away by backPatchLabels
2618 only those used in arthmetic operations remain */
2619 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2620 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2621 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
2623 tlbl = newiTempLabel (NULL);
2624 toBoolean (left, "r0", TRUE);
2625 toBoolean (right, "r0", FALSE);
2626 emitcode ("ldi", "r24,1");
2627 emitcode ("breq", "L%05d", tlbl->key);
2628 emitcode ("dec", "r24");
2629 emitcode ("", "L%05d:", tlbl->key);
2630 aopPut (AOP (result), "r24", 0);
2631 size = AOP_SIZE (result) - 1;
2634 aopPut (AOP (result), zero, offset++);
2636 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2637 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2638 freeAsmop (result, NULL, ic, TRUE);
2642 AVR_AND = 0, AVR_OR, AVR_XOR
2644 static char *bopnames_lit[] = { "andi", "ori" };
2645 static char *bopnames[] = { "and", "or", "eor" };
2646 /*-----------------------------------------------------------------*/
2647 /* genBitWise - generate bitwise operations */
2648 /*-----------------------------------------------------------------*/
2650 genBitWise (iCode * ic, iCode * ifx, int bitop)
2652 operand *left, *right, *result;
2653 int size, offset = 0;
2658 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2659 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2660 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
2662 size = AOP_SIZE (left);
2664 if (ifx) { /* used only for jumps */
2665 if (AOP_TYPE (right) == AOP_LIT &&
2666 (bitop == AVR_AND || bitop == AVR_OR)) {
2668 (int) floatFromVal (AOP (right)->aopu.
2670 int p2 = powof2 (lit);
2671 if (bitop == AVR_AND && p2) { /* right side is a power of 2 */
2672 l = aopGet (AOP (left), p2 / 8);
2673 if (IC_TRUE (ifx)) {
2674 emitcode ("sbrc", "%s,%d", l,
2676 emitcode ("rjmp", "L%05d",
2677 IC_TRUE (ifx)->key);
2680 emitcode ("sbrs", "%s,%d", l,
2682 emitcode ("rjmp", "L%05d",
2683 IC_FALSE (ifx)->key);
2686 else { /* right not power of two */
2687 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2689 if (eh && AOP_ISHIGHREG(AOP(IC_LEFT(ic)),0)) {
2690 emitcode (bopnames_lit[bitop],
2692 aopGet (AOP (IC_LEFT (ic)), 0), lit);
2695 MOVR24 (aopGet (AOP (IC_LEFT (ic)), 0));
2696 emitcode (bopnames_lit[bitop], "r24,<(%d)", lit);
2698 lbl = newiTempLabel (NULL);
2699 if (IC_TRUE (ifx)) {
2700 emitcode ("breq", "L%05d", lbl->key);
2701 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2704 emitcode ("brne", "L%05d", lbl->key);
2705 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)-> key);
2707 emitcode ("", "L%05d:", lbl->key);
2709 else if (size == 2) {
2710 emitcode ("mov", "r24,%s", aopGet (AOP (IC_LEFT (ic)), 0));
2711 emitcode ("mov", "r25,%s", aopGet (AOP (IC_LEFT (ic)), 1));
2712 emitcode (bopnames_lit[bitop], "r24,<(%d)", lit);
2713 emitcode (bopnames_lit[bitop], "r25,>(%d)", lit);
2714 emitcode ("sbiw", "r24,0");
2715 lbl = newiTempLabel (NULL);
2716 if (IC_TRUE (ifx)) {
2717 emitcode ("breq", "L%05d", lbl->key);
2718 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2721 emitcode ("brne", "L%05d", lbl->key);
2722 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2724 emitcode ("", "L%05d:", lbl->key);
2727 lbl = newiTempLabel (NULL);
2728 lbl1 = newiTempLabel (NULL);
2730 if (eh && AOP_ISHIGHREG(AOP(IC_LEFT(ic)),offset)) {
2731 emitcode (bopnames_lit [bitop], "%s,<(%d)",
2732 aopGet (AOP (IC_LEFT (ic)), offset),
2736 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
2738 emitcode ("andi", "r24,<(%d)", lit);
2740 emitcode ("brne", "L%05d", lbl->key);
2745 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)-> key);
2747 emitcode ("rjmp", "L%05d", lbl1->key);
2748 emitcode ("", "L%05d:", lbl->key);
2751 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2752 emitcode ("", "L%05d:", lbl1->key);
2757 else { /* right is not a literal */
2758 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2759 int reh = OP_SYMBOL (right)->liveTo <= ic->seq;
2762 emitcode (bopnames[bitop], "%s,%s", aopGet (AOP (IC_LEFT (ic)), 0),
2763 aopGet (AOP (IC_RIGHT (ic)), 0));
2766 emitcode (bopnames[bitop], "%s,%s",
2767 aopGet (AOP (IC_RIGHT (ic)), 0),
2768 aopGet (AOP (IC_LEFT (ic)), 0));
2771 MOVR0 (aopGet (AOP (IC_LEFT (ic)), 0));
2772 emitcode (bopnames[bitop], "r0,%s",
2773 aopGet (AOP (IC_RIGHT (ic)), 0));
2775 lbl = newiTempLabel (NULL);
2776 if (IC_TRUE (ifx)) {
2777 emitcode ("breq", "L%05d", lbl->key);
2778 emitcode ("rjmp", "L%05d",
2779 IC_TRUE (ifx)->key);
2782 emitcode ("brne", "L%05d", lbl->key);
2783 emitcode ("rjmp", "L%05d",
2784 IC_FALSE (ifx)->key);
2786 emitcode ("", "L%05d:", lbl->key);
2788 else if (size == 2) {
2789 emitcode ("mov", "r24,%s",
2790 aopGet (AOP (IC_LEFT (ic)), 0));
2791 emitcode ("mov", "r25,%s",
2792 aopGet (AOP (IC_LEFT (ic)), 1));
2793 emitcode (bopnames[bitop], "r24,%s",
2794 aopGet (AOP (IC_RIGHT (ic)), 0));
2795 emitcode (bopnames[bitop], "r25,%s",
2796 aopGet (AOP (IC_RIGHT (ic)), 1));
2797 emitcode ("sbiw", "r24,0");
2798 lbl = newiTempLabel (NULL);
2799 if (IC_TRUE (ifx)) {
2800 emitcode ("breq", "L%05d", lbl->key);
2801 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2804 emitcode ("brne", "L%05d", lbl->key);
2805 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2807 emitcode ("", "L%05d:", lbl->key);
2810 lbl = newiTempLabel (NULL);
2811 lbl1 = newiTempLabel (NULL);
2814 emitcode (bopnames[bitop], "%s,%s",
2815 aopGet (AOP (IC_LEFT (ic)), offset),
2816 aopGet (AOP (IC_RIGHT (ic)), offset));
2819 emitcode (bopnames[bitop], "%s,%s",
2820 aopGet (AOP (IC_RIGHT (ic)), offset),
2821 aopGet (AOP (IC_LEFT (ic)), offset));
2824 MOVR0 (aopGet (AOP (IC_LEFT (ic)), offset));
2825 emitcode (bopnames[bitop], "r0,%s",
2826 aopGet (AOP (IC_RIGHT (ic)), offset));
2828 emitcode ("brne", "L%05d", lbl->key);
2833 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2835 emitcode ("rjmp", "L%05d", lbl1->key);
2836 emitcode ("", "L%05d:", lbl->key);
2839 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2840 emitcode ("", "L%05d:", lbl1->key);
2847 /* result needs to go a register */
2848 samerl = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2849 samerr = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)));
2851 if (AOP_TYPE (right) == AOP_LIT) {
2853 (int) floatFromVal (AOP (right)->aopu.
2855 if (((lit >> (8 * offset)) & 0xff) == 0) {
2856 if (bitop == AVR_AND) {
2857 aopPut (AOP (result), zero, offset++);
2860 else if (bitop == AVR_OR) {
2862 aopPut (AOP (result),
2872 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT &&
2873 AOP_ISHIGHREG(AOP(IC_LEFT(ic)),offset) &&
2874 (bitop == AVR_AND || bitop == AVR_OR)) {
2875 emitcode (bopnames_lit[bitop], "%s,%s(%d)",
2876 aopGet (AOP (IC_LEFT (ic)), offset),
2878 (int) floatFromVal (AOP (right)-> aopu.aop_lit));
2881 emitcode (bopnames[bitop], "%s,%s",
2882 aopGet (AOP (IC_LEFT (ic)), offset),
2883 aopGet (AOP (IC_RIGHT (ic)), offset));
2887 emitcode (bopnames[bitop], "%s,%s",
2888 aopGet (AOP (IC_RIGHT (ic)), offset),
2889 aopGet (AOP (IC_LEFT (ic)), offset));
2892 aopPut (AOP (IC_RESULT (ic)),
2893 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2894 emitcode (bopnames[bitop],
2895 aopGet (AOP (IC_RESULT (ic)), offset),
2896 aopGet (AOP (IC_RIGHT (ic)), offset));
2901 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2902 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2903 freeAsmop (result, NULL, ic, TRUE);
2906 /*-----------------------------------------------------------------*/
2907 /* genAnd - code for and */
2908 /*-----------------------------------------------------------------*/
2910 genAnd (iCode * ic, iCode * ifx)
2912 genBitWise (ic, ifx, AVR_AND);
2915 /*-----------------------------------------------------------------*/
2916 /* genOr - code for or */
2917 /*-----------------------------------------------------------------*/
2919 genOr (iCode * ic, iCode * ifx)
2921 genBitWise (ic, ifx, AVR_OR);
2924 /*-----------------------------------------------------------------*/
2925 /* genXor - code for xclusive or */
2926 /*-----------------------------------------------------------------*/
2928 genXor (iCode * ic, iCode * ifx)
2930 genBitWise (ic, ifx, AVR_XOR);
2933 /*-----------------------------------------------------------------*/
2934 /* genInline - write the inline code out */
2935 /*-----------------------------------------------------------------*/
2937 genInline (iCode * ic)
2939 char *buffer, *bp, *bp1;
2941 _G.inLine += (!options.asmpeep);
2943 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
2944 strcpy (buffer, IC_INLINE (ic));
2946 /* emit each line as a code */
2967 /* emitcode("",buffer); */
2968 _G.inLine -= (!options.asmpeep);
2971 /*-----------------------------------------------------------------*/
2972 /* genRotC - rotate right/left with carry , lr = 1 rotate right */
2973 /*-----------------------------------------------------------------*/
2975 genRotC (iCode * ic, int lr)
2977 operand *left, *result;
2978 int size, offset = 0;
2980 /* rotate right with carry */
2981 left = IC_LEFT (ic);
2982 result = IC_RESULT (ic);
2983 aopOp (left, ic, FALSE);
2984 aopOp (result, ic, FALSE);
2986 /* move it to the result */
2987 size = AOP_SIZE (result);
2988 if (!sameRegs (AOP (left), AOP (result))) {
2991 aopPut (AOP (result),
2992 aopGet (AOP (left), offset), offset);
2995 size = AOP_SIZE (result);
3003 emitcode ("sbrc", "%s,%d", aopGet (AOP (result), offset),
3005 emitcode ("sec", "");
3008 emitcode ((lr ? "ror" : "rol"), "%s",
3009 aopGet (AOP (result), offset));
3015 freeAsmop (left, NULL, ic, TRUE);
3016 freeAsmop (result, NULL, ic, TRUE);
3019 /*-----------------------------------------------------------------*/
3020 /* genRRC - rotate right with carry */
3021 /*-----------------------------------------------------------------*/
3028 /*-----------------------------------------------------------------*/
3029 /* genRLC - generate code for rotate left with carry */
3030 /*-----------------------------------------------------------------*/
3037 /*-----------------------------------------------------------------*/
3038 /* genGetHbit - generates code get highest order bit */
3039 /*-----------------------------------------------------------------*/
3041 genGetHbit (iCode * ic)
3043 operand *left, *result;
3046 left = IC_LEFT (ic);
3047 result = IC_RESULT (ic);
3048 aopOp (left, ic, FALSE);
3049 aopOp (result, ic, FALSE);
3051 size = AOP_SIZE (result);
3052 if (!sameRegs (AOP (left), AOP (result))) {
3053 emitcode ("clr", "%s", aopGet (AOP (result), size - 1));
3054 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3055 emitcode ("subi", "%s,<(-1)",
3056 aopGet (AOP (result), size - 1));
3059 emitcode ("clr", "r0");
3060 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3061 emitcode ("subi", "r0,<(-1)");
3062 aopPut (AOP (result), "r0", 0);
3067 emitcode ("clr", aopGet (AOP (result), offset++));
3069 freeAsmop (left, NULL, ic, TRUE);
3070 freeAsmop (result, NULL, ic, TRUE);
3073 /*-----------------------------------------------------------------*/
3074 /* genShiftLeftLit - shift left by a known amount */
3075 /*-----------------------------------------------------------------*/
3077 genShiftLeftLit (iCode * ic)
3079 operand *left, *right, *result;
3080 int size, shCount, offset = 0;
3083 right = IC_RIGHT (ic);
3084 left = IC_LEFT (ic);
3085 result = IC_RESULT (ic);
3087 aopOp (left, ic, FALSE);
3088 aopOp (result, ic, FALSE);
3089 size = AOP_SIZE (result);
3090 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3092 if (shCount > (size * 8 - 1)) {
3094 aopPut (AOP (result), zero, offset++);
3099 if (!sameRegs (AOP (left), AOP (result)))
3100 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3102 if (AOP_ISHIGHREG(AOP(result),0)) {
3103 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3104 emitcode ("andi", "%s,0xf0");
3106 emitcode ("ldi","r24,0xf0");
3107 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3108 emitcode ("and", "%s,r24");
3113 emitcode ("add", "%s,%s", aopGet (AOP (result), 0),
3114 aopGet (AOP (result), 0));
3118 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3121 if (shCount >= 12) {
3122 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3123 aopPut (AOP (result), zero, 0);
3124 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3125 if (AOP_ISHIGHREG(AOP(result),1)) {
3126 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3128 emitcode ("ldi","r24,0xf0");
3129 emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
3135 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3136 aopPut (AOP (result), zero, 0);
3142 if (!sameRegs (AOP (left), AOP (result))) {
3143 aopPut (AOP (result), aopGet (AOP (left), 0),
3145 aopPut (AOP (result), aopGet (AOP (left), 1),
3148 emitcode ("mov", "r24,%s", aopGet (AOP (result), 0));
3149 emitcode ("andi", "r24,0x0f");
3150 if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
3151 emitcode("ldi","r25,0xf0");
3153 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3154 if (AOP_ISHIGHREG(AOP(result),0)) {
3155 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 0));
3157 emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
3159 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3160 if (AOP_ISHIGHREG(AOP(result),1)) {
3161 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3163 emitcode ("and", "%s,r25", aopGet (AOP (result), 1));
3165 emitcode ("or", "%s,r24", aopGet (AOP (result), 1));
3167 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3168 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3171 if (!lByteZ && !sameRegs (AOP (result), AOP (left))
3175 aopPut (AOP (result),
3176 aopGet (AOP (left), offset), offset);
3182 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3185 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3186 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3191 assert ("shifting generic pointer ?\n");
3194 /* 32 bits we do only byte boundaries */
3195 if (shCount >= 24) {
3196 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3197 aopPut (AOP (result), zero, 2);
3198 aopPut (AOP (result), zero, 1);
3199 aopPut (AOP (result), zero, 0);
3203 if (shCount >= 16) {
3204 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3205 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3206 aopPut (AOP (result), zero, 1);
3207 aopPut (AOP (result), zero, 0);
3212 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3213 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3214 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3215 aopPut (AOP (result), zero, 0);
3219 if (!lByteZ && !sameRegs (AOP (left), AOP (right))) {
3222 aopPut (AOP (result),
3223 aopGet (AOP (left), offset), offset);
3227 size = AOP_SIZE (result);
3233 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3234 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3235 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3236 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3241 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3242 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3243 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3248 emitcode ("lsl", "%s", aopGet (AOP (result), 2));
3249 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3254 emitcode ("lsl", "%s", aopGet (AOP (result), 3));
3262 freeAsmop (left, NULL, ic, TRUE);
3263 freeAsmop (right, NULL, ic, TRUE);
3264 freeAsmop (result, NULL, ic, TRUE);
3267 /*-----------------------------------------------------------------*/
3268 /* genLeftShift - generates code for left shifting */
3269 /*-----------------------------------------------------------------*/
3271 genLeftShift (iCode * ic)
3273 operand *left, *right, *result;
3277 right = IC_RIGHT (ic);
3278 left = IC_LEFT (ic);
3279 result = IC_RESULT (ic);
3281 aopOp (right, ic, FALSE);
3283 if (AOP_TYPE (right) == AOP_LIT) {
3284 genShiftLeftLit (ic);
3289 aopOp (left, ic, FALSE);
3290 aopOp (result, ic, FALSE);
3291 size = AOP_SIZE (result);
3293 if (AOP_SIZE (right) > 1) {
3294 if (isRegPair (AOP (right))) {
3295 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3298 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3299 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3303 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3305 if (!sameRegs (AOP (left), AOP (result))) {
3307 aopPut (AOP (result), aopGet (AOP (left), offset),
3311 size = AOP_SIZE (result);
3313 tlbl = newiTempLabel (NULL);
3314 emitcode ("", "L%05d:", tlbl->key);
3318 emitcode ("rol", "%s", aopGet (AOP (result), offset));
3320 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3323 if (AOP_SIZE (right) > 1)
3324 emitcode ("sbiw", "r24,1");
3326 emitcode ("dec", "r24");
3327 emitcode ("brne", "L%05d", tlbl->key);
3329 freeAsmop (left, NULL, ic, TRUE);
3330 freeAsmop (right, NULL, ic, TRUE);
3331 freeAsmop (result, NULL, ic, TRUE);
3334 /*-----------------------------------------------------------------*/
3335 /* genShiftRightLit - generate for right shift with known count */
3336 /*-----------------------------------------------------------------*/
3338 genShiftRightLit (iCode * ic)
3340 operand *left = IC_LEFT (ic)
3341 , *right = IC_RIGHT (ic)
3342 , *result = IC_RESULT (ic);
3343 int size, shCount, offset = 0;
3345 sym_link *letype = getSpec (operandType (left));
3346 int sign = !SPEC_USIGN (letype);
3348 right = IC_RIGHT (ic);
3349 left = IC_LEFT (ic);
3350 result = IC_RESULT (ic);
3352 aopOp (left, ic, FALSE);
3353 aopOp (result, ic, FALSE);
3354 size = AOP_SIZE (result);
3355 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3357 /* if signed then give up and use a loop to shift */
3360 if (!sameRegs (AOP (left), AOP (result))) {
3362 aopPut (AOP (result),
3363 aopGet (AOP (left), offset), offset);
3366 size = AOP_SIZE (result);
3369 /* be as economical as possible */
3372 size = AOP_SIZE (result);
3375 /* highest order byte */
3376 if (offset == (AOP_SIZE(result)-1))
3377 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3379 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3385 emitcode ("ldi", "r24,<(%d)", shCount);
3386 tlbl = newiTempLabel (NULL);
3387 emitcode ("", "L%05d:", tlbl->key);
3390 if (offset == (AOP_SIZE(result) - 1))
3391 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3393 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3396 emitcode ("dec", "r24");
3397 emitcode ("brne", "L%05d", tlbl->key);
3401 if (shCount > (size * 8 - 1)) {
3403 aopPut (AOP (result), zero, offset++);
3406 /* for unsigned we can much more efficient */
3409 if (!sameRegs (AOP (left), AOP (result)))
3410 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3412 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3413 if (AOP_ISHIGHREG(AOP(result),0)) {
3414 emitcode ("andi", "%s,0x0f",aopGet(AOP(result),0));
3416 emitcode ("ldi","r24,0x0f");
3417 emitcode ("and", "%s,r24",aopGet(AOP(result),0));
3422 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3425 if (shCount >= 12) {
3426 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3427 aopPut (AOP (result), zero, 1);
3428 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3429 if (AOP_ISHIGHREG(AOP(result),0)) {
3430 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3432 emitcode ("ldi","r24,0x0f");
3433 emitcode ("and", "%s,r24",aopGet(AOP(result),0));
3439 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3440 aopPut (AOP (result), zero, 1);
3446 if (!sameRegs (AOP (left), AOP (result))) {
3447 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3448 aopPut (AOP (result), aopGet (AOP (left), 1), 1);
3450 if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
3451 emitcode("ldi","r25,0x0f");
3453 emitcode ("mov", "r24,%s", aopGet (AOP (result), 1));
3454 emitcode ("andi", "r24,0xf0");
3455 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3456 if (AOP_ISHIGHREG(AOP(result),0)) {
3457 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3459 emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
3461 emitcode ("or", "%s,r24", aopGet (AOP (result), 0));
3462 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3463 if (AOP_ISHIGHREG(AOP(result),1)) {
3464 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 1));
3466 emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
3469 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3470 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3474 if (!hByteZ && !sameRegs (AOP (result), AOP (left))
3478 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3484 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3487 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3488 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3494 assert ("shifting generic pointer ?\n");
3497 /* 32 bits we do only byte boundaries */
3498 if (shCount >= 24) {
3499 aopPut (AOP (result), aopGet (AOP (left), 3), 0);
3500 aopPut (AOP (result), zero, 1);
3501 aopPut (AOP (result), zero, 2);
3502 aopPut (AOP (result), zero, 3);
3506 if (shCount >= 16) {
3507 aopPut (AOP (result), aopGet (AOP (left), 3), 1);
3508 aopPut (AOP (result), aopGet (AOP (left), 2), 0);
3509 aopPut (AOP (result), zero, 2);
3510 aopPut (AOP (result), zero, 3);
3515 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3516 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3517 aopPut (AOP (result), aopGet (AOP (left), 3), 2);
3518 aopPut (AOP (result), zero, 3);
3522 if (!hByteZ && !sameRegs (AOP (left), AOP (right))) {
3525 aopPut (AOP (result),
3526 aopGet (AOP (left), offset), offset);
3530 size = AOP_SIZE (result);
3536 emitcode ("lsr", "%s", aopGet (AOP (result), 3));
3537 emitcode ("ror", "%s", aopGet (AOP (result), 2));
3538 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3539 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3544 emitcode ("lsr", "%s", aopGet (AOP (result), 2));
3545 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3546 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3551 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3552 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3557 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3564 freeAsmop (left, NULL, ic, TRUE);
3565 freeAsmop (right, NULL, ic, TRUE);
3566 freeAsmop (result, NULL, ic, TRUE);
3569 /*-----------------------------------------------------------------*/
3570 /* genRightShift - generate code for right shifting */
3571 /*-----------------------------------------------------------------*/
3573 genRightShift (iCode * ic)
3575 operand *right, *left, *result;
3578 int sign = 0, first = 1;
3581 aopOp (right = IC_RIGHT (ic), ic, FALSE);
3583 if (AOP_TYPE (right) == AOP_LIT) {
3584 genShiftRightLit (ic);
3588 if (AOP_SIZE (right) > 1) {
3589 if (isRegPair (AOP (right))) {
3590 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3593 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3594 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3598 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3600 aopOp (left = IC_LEFT (ic), ic, FALSE);
3601 aopOp (result = IC_RESULT (ic), ic, FALSE);
3602 size = AOP_SIZE (result);
3603 tlbl = newiTempLabel (NULL);
3604 emitcode ("", "L%05d:", tlbl->key);
3606 letype = getSpec (operandType (left));
3607 sign = !SPEC_USIGN (letype);
3608 if (!sameRegs (AOP (left), AOP (result))) {
3610 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3613 size = AOP_SIZE (result);
3615 size = AOP_SIZE (result);
3619 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3621 emitcode ("lsr", "%s", aopGet (AOP (result), offset));
3625 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3628 if (AOP_SIZE (right) > 1)
3629 emitcode ("sbiw", "r24,1");
3631 emitcode ("dec", "r24");
3632 emitcode ("brne", "L%05d", tlbl->key);
3634 freeAsmop (left, NULL, ic, TRUE);
3635 freeAsmop (result, NULL, ic, TRUE);
3638 /*-----------------------------------------------------------------*/
3639 /* RRsh - shift right rn by known count */
3640 /*-----------------------------------------------------------------*/
3642 RRsh (int shCount,int reg)
3644 shCount &= 0x0007; // shCount : 0..7
3650 emitcode ("lsr", "r%d",reg);
3653 emitcode ("lsr", "r%d",reg);
3654 emitcode ("lsr", "r%d",reg);
3657 emitcode ("swap", "r%d",reg);
3658 emitcode ("lsl", "r%d",reg);
3661 emitcode ("swap", "r%d",reg);
3664 emitcode ("swap", "r%d",reg);
3665 emitcode ("lsr", "r%d",reg);
3668 emitcode ("swap","r%d",reg);
3669 emitcode ("lsr", "r%d",reg);
3670 emitcode ("lsr", "r%d",reg);
3673 emitcode ("swap","r%d",reg);
3674 emitcode ("lsr", "r%d",reg);
3675 emitcode ("lsr", "r%d",reg);
3676 emitcode ("lsr", "r%d",reg);
3681 /*-----------------------------------------------------------------*/
3682 /* RLsh - shift left rn by known count */
3683 /*-----------------------------------------------------------------*/
3685 RLsh (int shCount, int reg)
3687 shCount &= 0x0007; // shCount : 0..7
3693 emitcode ("lsl", "r%d",reg);
3696 emitcode ("lsl", "r%d",reg);
3697 emitcode ("lsl", "r%d",reg);
3700 emitcode ("swap","r%d",reg);
3701 emitcode ("lsr", "r%d",reg);
3704 emitcode ("swap", "r%d",reg);
3707 emitcode ("swap","r%d",reg);
3708 emitcode ("lsl", "r%d",reg);
3711 emitcode ("swap","r%d",reg);
3712 emitcode ("lsl", "r%d",reg);
3713 emitcode ("lsl", "r%d",reg);
3716 emitcode ("swap","r%d",reg);
3717 emitcode ("lsl", "r%d",reg);
3718 emitcode ("lsl", "r%d",reg);
3719 emitcode ("lsl", "r%d",reg);
3724 /*-----------------------------------------------------------------*/
3725 /* genUnpackBits - generates code for unpacking bits */
3726 /*-----------------------------------------------------------------*/
3728 genUnpackBits (operand * result, char *rname, int ptype)
3736 etype = getSpec (operandType (result));
3737 rsize = getSize (operandType (result));
3738 /* read the first byte */
3745 emitcode ("ld", "r24,%s+", rname);
3749 emitcode ("lpm", "r24,%s+", rname);
3753 emitcode ("call","__gptrget_pi");
3754 emitcode ("mov","r24,r0");
3758 rlen = SPEC_BLEN (etype);
3760 /* if we have bitdisplacement then it fits */
3761 /* into this byte completely or if length is */
3762 /* less than a byte */
3763 if ((shCnt = SPEC_BSTR (etype)) || (SPEC_BLEN (etype) <= 8)) {
3765 /* shift right acc */
3768 emitcode ("andi", "r24,lo(0x%x)",
3769 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
3770 aopPut (AOP (result), "r24", offset++);
3774 /* bit field did not fit in a byte */
3775 aopPut (AOP (result), "r24", offset++);
3785 emitcode ("ld", "r24,%s+");
3789 emitcode ("lpm", "r24,%s+");
3793 emitcode ("call", "__gptrget_pi");
3798 /* if we are done */
3802 aopPut (AOP (result), "r24", offset++);
3807 aopPut (AOP (result), "r24", offset++);
3811 if (offset < rsize) {
3814 aopPut (AOP (result), zero, offset++);
3819 /*-----------------------------------------------------------------*/
3820 /* genDataPointerGet - generates code when ptr offset is known */
3821 /*-----------------------------------------------------------------*/
3823 genDataPointerGet (operand * left, operand * result, iCode * ic)
3827 int size, offset = 0;
3828 aopOp (result, ic, TRUE);
3830 /* get the string representation of the name */
3831 l = aopGet (AOP (left), 0);
3832 size = AOP_SIZE (result);
3835 sprintf (buffer, "(%s + %d)", l, offset);
3837 sprintf (buffer, "%s", l);
3838 emitcode ("lds", "%s,%s", aopGet (AOP (result), offset++),
3842 freeAsmop (left, NULL, ic, TRUE);
3843 freeAsmop (result, NULL, ic, TRUE);
3846 /*-----------------------------------------------------------------*/
3847 /* genNearPointerGet - emitcode for near pointer fetch */
3848 /*-----------------------------------------------------------------*/
3850 genMemPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
3855 char *rname, *frname = NULL;
3856 sym_link *rtype, *retype;
3857 sym_link *ltype = operandType (left);
3859 rtype = operandType (result);
3860 retype = getSpec (rtype);
3862 aopOp (left, ic, FALSE);
3864 /* if left is rematerialisable and
3865 result is not bit variable type and
3866 the left is pointer to data space i.e
3867 lower 128 bytes of space */
3868 if (AOP_TYPE (left) == AOP_IMMD &&
3869 !IS_BITVAR (retype) && DCL_TYPE (ltype) == POINTER) {
3870 genDataPointerGet (left, result, ic);
3874 /* if the value is already in a pointer register
3875 then don't need anything more */
3876 if (!AOP_INPREG (AOP (left))) {
3877 /* otherwise get a free pointer register */
3879 preg = getFreePtr (ic, &aop, FALSE, 0);
3880 if (isRegPair (AOP (left) )) {
3881 emitcode ("movw", "%s,%s",
3882 aop->aopu.aop_ptr->name,
3883 aopGet(AOP(left),0));
3885 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
3886 aopGet (AOP (left), 0));
3887 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
3888 aopGet (AOP (left), 1));
3894 frname = aopGet(aop,0);
3898 } else if (AOP_ISZ(aop)) {
3901 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
3902 "pointer not in correct register");
3906 aopOp (result, ic, FALSE);
3908 /* if bitfield then unpack the bits */
3909 if (IS_BITVAR (retype))
3910 genUnpackBits (result, rname, POINTER);
3912 /* we have can just get the values */
3913 int size = AOP_SIZE (result);
3918 emitcode ("ld","%s,%s+",aopGet(AOP(result),offset), rname);
3920 emitcode ("ld","%s,%s",aopGet(AOP(result),offset), rname);
3925 /* now some housekeeping stuff */
3927 /* we had to allocate for this iCode */
3929 if (isRegPair (AOP (left) )) {
3930 emitcode ("movw", "%s,%s",
3931 aopGet (AOP(left),0),
3932 aop->aopu.aop_ptr->name);
3934 emitcode ("mov", "%s,%s",
3935 aopGet (AOP (left), 0),
3936 aop->aopu.aop_ptr->name);
3937 emitcode ("mov", "%s,%s",
3938 aopGet (AOP (left), 1),
3939 aop->aop_ptr2->name);
3942 freeAsmop (NULL, aop, ic, TRUE);
3945 /* we did not allocate which means left
3946 already in a pointer register, then
3947 if size > 0 && this could be used again
3948 we have to point it back to where it
3950 if ((AOP_SIZE (result) > 1 &&
3951 !OP_SYMBOL (left)->remat &&
3952 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) && !pi) {
3953 int size = AOP_SIZE (result) - 1;
3954 emitcode ("sbiw", "%s,%d",frname,size);
3959 if (pi) pi->generated = 1;
3960 freeAsmop (left, NULL, ic, TRUE);
3961 freeAsmop (result, NULL, ic, TRUE);
3965 /*-----------------------------------------------------------------*/
3966 /* genCodePointerGet - gget value from code space */
3967 /*-----------------------------------------------------------------*/
3969 genCodePointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
3972 sym_link *retype = getSpec (operandType (result));
3976 aopOp (left, ic, FALSE);
3978 /* if the operand is already in Z register
3979 then we do nothing else we move the value to Z register */
3980 if (AOP_ISZ(AOP(left))) {
3984 getFreePtr(ic,&aop,FALSE,TRUE);
3985 if (isRegPair(AOP (left))) {
3986 emitcode ("movw","r30,%s",aopGet (AOP (left), 0));
3988 emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
3989 emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
3994 aopOp (result, ic, FALSE);
3996 /* if bit then unpack */
3997 if (IS_BITVAR (retype))
3998 genUnpackBits (result, "Z", CPOINTER);
4000 size = AOP_SIZE (result);
4005 emitcode ("lpm","%s,Z+",aopGet(AOP(result),offset++));
4007 emitcode ("lpm","%s,Z",aopGet(AOP(result),offset++));
4012 /* now some housekeeping stuff */
4014 /* we had to allocate for this iCode */
4016 if (isRegPair(AOP (left))) {
4017 emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
4019 emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
4020 emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
4023 freeAsmop (NULL, aop, ic, TRUE);
4026 /* we did not allocate which means left
4027 already in a pointer register, then
4028 if size > 0 && this could be used again
4029 we have to point it back to where it
4031 if ((AOP_SIZE (result) > 1 &&
4032 !OP_SYMBOL (left)->remat &&
4033 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) &&
4035 int size = AOP_SIZE (result) - 1;
4036 emitcode ("sbiw", "r30,%d",size);
4041 if (pi) pi->generated=1;
4042 freeAsmop (left, NULL, ic, TRUE);
4043 freeAsmop (result, NULL, ic, TRUE);
4047 /*-----------------------------------------------------------------*/
4048 /* genGenPointerGet - gget value from generic pointer space */
4049 /*-----------------------------------------------------------------*/
4051 genGenPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
4055 sym_link *retype = getSpec (operandType (result));
4058 aopOp (left, ic, FALSE);
4060 /* if the operand is already in dptr
4061 then we do nothing else we move the value to dptr */
4062 if (AOP_ISZ(AOP(left))) {
4066 getFreePtr(ic,&aop,FALSE,TRUE);
4067 if (isRegPair(AOP(left))) {
4068 emitcode ("movw", "r30,%s", aopGet (AOP (left), 0));
4070 emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
4071 emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
4073 emitcode ("mov", "r24,%s", aopGet (AOP (left), 2));
4077 /* so Z register now contains the address */
4079 aopOp (result, ic, FALSE);
4081 /* if bit then unpack */
4082 if (IS_BITVAR (retype))
4083 genUnpackBits (result, "Z", GPOINTER);
4085 size = AOP_SIZE (result);
4090 emitcode ("call", "__gptrget_pi");
4092 emitcode ("call", "__gptrget");
4093 aopPut (AOP (result), "r0", offset++);
4098 /* now some housekeeping stuff */
4100 /* we had to allocate for this iCode */
4102 if (isRegPair(AOP (left))) {
4103 emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
4105 emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
4106 emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
4109 freeAsmop (NULL, aop, ic, TRUE);
4112 /* we did not allocate which means left
4113 already in a pointer register, then
4114 if size > 0 && this could be used again
4115 we have to point it back to where it
4117 if ((AOP_SIZE (result) > 1 &&
4118 !OP_SYMBOL (left)->remat &&
4119 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) &&
4121 int size = AOP_SIZE (result) - 1;
4122 emitcode ("sbiw", "r30,%d",size);
4125 if (pi) pi->generated=1;
4126 freeAsmop (left, NULL, ic, TRUE);
4127 freeAsmop (result, NULL, ic, TRUE);
4130 /*-----------------------------------------------------------------*/
4131 /* genPointerGet - generate code for pointer get */
4132 /*-----------------------------------------------------------------*/
4134 genPointerGet (iCode * ic, iCode *pi)
4136 operand *left, *result;
4137 sym_link *type, *etype;
4140 left = IC_LEFT (ic);
4141 result = IC_RESULT (ic);
4143 /* depending on the type of pointer we need to
4144 move it to the correct pointer register */
4145 type = operandType (left);
4146 etype = getSpec (type);
4147 /* if left is of type of pointer then it is simple */
4148 if (IS_PTR (type) && !IS_FUNC (type->next))
4149 p_type = DCL_TYPE (type);
4151 /* we have to go by the storage class */
4152 p_type = PTR_TYPE (SPEC_OCLS (etype));
4157 /* now that we have the pointer type we assign
4158 the pointer values */
4165 genMemPointerGet (left, result, ic, pi);
4169 genCodePointerGet (left, result, ic, pi);
4173 genGenPointerGet (left, result, ic, pi);
4179 /*-----------------------------------------------------------------*/
4180 /* genPackBits - generates code for packed bit storage */
4181 /*-----------------------------------------------------------------*/
4183 genPackBits (sym_link * etype,
4185 char *rname, int p_type)
4193 blen = SPEC_BLEN (etype);
4194 bstr = SPEC_BSTR (etype);
4196 l = aopGet (AOP (right), offset++);
4199 /* if the bit lenth is less than or */
4200 /* it exactly fits a byte then */
4201 if (SPEC_BLEN (etype) <= 8) {
4202 shCount = SPEC_BSTR (etype);
4204 /* shift left acc */
4207 if (SPEC_BLEN (etype) < 8) { /* if smaller than a byte */
4214 emitcode ("ld", "r1,%s",rname);
4218 emitcode ("push", "r1");
4219 emitcode ("push", "r24");
4220 emitcode ("call", "__gptrget");
4221 emitcode ("pop", "r1");
4222 emitcode ("mov","r24,r0");
4226 emitcode ("andi", "r24,#0x%02x", (unsigned char)
4227 ((unsigned char) (0xFF << (blen + bstr)) |
4228 (unsigned char) (0xFF >> (8 - bstr))));
4229 emitcode ("or", "r24,r1");
4230 if (p_type == GPOINTER)
4231 emitcode ("pop", "r1");
4240 emitcode("st","%s+,r24");
4244 emitcode("mov","r0,r24");
4245 emitcode ("call", "__gptrput_pi");
4250 if (SPEC_BLEN (etype) <= 8)
4253 rLen = SPEC_BLEN (etype);
4255 /* now generate for lengths greater than one byte */
4258 l = aopGet (AOP (right), offset++);
4269 emitcode ("st", "%s+,%s",rname,l);
4274 emitcode ("lcall", "__gptrput_pi");
4281 /* last last was not complete */
4283 /* save the byte & read byte */
4289 emitcode ("st","%s+,r24",rname);
4292 emitcode ("push", "r1");
4293 emitcode ("push", "r24");
4294 emitcode ("lcall", "__gptrget");
4295 emitcode ("mov","r24,r0");
4296 emitcode ("pop", "r1");
4300 emitcode ("andi", "r24,0x%02x", (((unsigned char) -1 << rLen) & 0xff));
4301 emitcode ("or", "r24,r1");
4304 if (p_type == GPOINTER)
4305 emitcode ("pop", "r1");
4313 emitcode ("st", "%s,r24", rname);
4317 emitcode ("mov","r0,r24");
4318 emitcode ("call", "__gptrput");
4323 /*-----------------------------------------------------------------*/
4324 /* genDataPointerSet - remat pointer to data space */
4325 /*-----------------------------------------------------------------*/
4327 genDataPointerSet (operand * right, operand * result, iCode * ic)
4329 int size, offset = 0;
4330 char *l, buffer[256];
4332 aopOp (right, ic, FALSE);
4334 l = aopGet (AOP (result), 0);
4335 size = AOP_SIZE (right);
4338 sprintf (buffer, "(%s + %d)", l, offset);
4340 sprintf (buffer, "%s", l);
4341 emitcode ("sts", "%s,%s", buffer,
4342 aopGet (AOP (right), offset++));
4345 freeAsmop (right, NULL, ic, TRUE);
4346 freeAsmop (result, NULL, ic, TRUE);
4349 /*-----------------------------------------------------------------*/
4350 /* genNearPointerSet - emitcode for near pointer put */
4351 /*-----------------------------------------------------------------*/
4353 genMemPointerSet (operand * right, operand * result, iCode * ic, iCode *pi)
4356 char *frname = NULL, *rname, *l;
4359 sym_link *ptype = operandType (result);
4361 retype = getSpec (operandType (right));
4363 aopOp (result, ic, FALSE);
4365 /* if the result is rematerializable &
4366 in data space & not a bit variable */
4367 if (AOP_TYPE (result) == AOP_IMMD &&
4368 DCL_TYPE (ptype) == POINTER && !IS_BITVAR (retype)) {
4369 genDataPointerSet (right, result, ic);
4372 if (!AOP_INPREG(AOP(result))) {
4373 /* otherwise get a free pointer register */
4375 getFreePtr (ic, &aop, FALSE, 0);
4376 if (isRegPair (AOP (result) )) {
4377 emitcode ("movw", "%s,%s",aop->aopu.aop_ptr->name,
4378 aopGet(AOP (result), 0));
4380 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
4381 aopGet (AOP (result), 0));
4382 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
4383 aopGet (AOP (result), 1));
4388 frname = aopGet(aop,0);
4391 aopOp (right, ic, FALSE);
4394 } else if (AOP_ISZ(aop)) {
4397 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4398 "pointer not in correct register");
4401 /* if bitfield then unpack the bits */
4402 if (IS_BITVAR (retype))
4403 genPackBits (retype, right, rname, POINTER);
4405 /* we have can just get the values */
4406 int size = AOP_SIZE (right);
4410 l = aopGet (AOP (right), offset);
4412 emitcode ("st", "%s+,%s", rname,l);
4414 emitcode ("st", "%s,%s", rname,l);
4419 /* now some housekeeping stuff */
4421 /* we had to allocate for this iCode */
4423 if (isRegPair (AOP (result) )) {
4424 emitcode ("movw", "%s,%s",
4425 aopGet(AOP(result),0),
4426 aop->aopu.aop_ptr->name);
4428 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
4429 aopGet (AOP (result), 0));
4430 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
4431 aopGet (AOP (result), 1));
4434 freeAsmop (NULL, aop, ic, TRUE);
4437 /* we did not allocate which means left
4438 already in a pointer register, then
4439 if size > 0 && this could be used again
4440 we have to point it back to where it
4442 if ((AOP_SIZE (right) > 1 &&
4443 !OP_SYMBOL (result)->remat &&
4444 (OP_SYMBOL (right)->liveTo > ic->seq || ic->depth)) && !pi) {
4445 int size = AOP_SIZE (right) - 1;
4446 emitcode ("sbiw", "%s,%d",frname,size);
4451 if (pi) pi->generated = 1;
4452 freeAsmop (result, NULL, ic, TRUE);
4453 freeAsmop (right, NULL, ic, TRUE);
4456 /*-----------------------------------------------------------------*/
4457 /* genGenPointerSet - set value from generic pointer space */
4458 /*-----------------------------------------------------------------*/
4460 genGenPointerSet (operand * right, operand * result, iCode * ic, iCode *pi)
4464 sym_link *retype = getSpec (operandType (right));
4467 aopOp (result, ic, FALSE);
4469 /* if the operand is already in dptr
4470 then we do nothing else we move the value to dptr */
4471 if (AOP_ISZ(AOP(result))) {
4475 getFreePtr(ic,&aop,FALSE,TRUE);
4476 if (isRegPair(AOP(result))) {
4477 emitcode ("movw", "r30,%s", aopGet (AOP (result), 0));
4479 emitcode ("mov", "r30,%s", aopGet (AOP (result), 0));
4480 emitcode ("mov", "r31,%s", aopGet (AOP (result), 1));
4482 emitcode ("mov", "r24,%s", aopGet (AOP (result), 2));
4486 /* so Z register now contains the address */
4487 aopOp (right, ic, FALSE);
4489 /* if bit then unpack */
4490 if (IS_BITVAR (retype))
4491 genUnpackBits (result, "Z", GPOINTER);
4493 size = AOP_SIZE (right);
4497 char *l = aopGet(AOP (right), offset++);
4501 emitcode ("call", "__gptrput_pi");
4503 emitcode ("call", "__gptrput");
4507 /* now some housekeeping stuff */
4509 /* we had to allocate for this iCode */
4511 if (isRegPair(AOP(result))) {
4512 emitcode ("movw", "%s,r30", aopGet (AOP (result), 0));
4514 emitcode ("mov", "%s,r30", aopGet (AOP (result), 0));
4515 emitcode ("mov", "%s,r31", aopGet (AOP (result), 1));
4518 freeAsmop (NULL, aop, ic, TRUE);
4521 /* we did not allocate which means left
4522 already in a pointer register, then
4523 if size > 0 && this could be used again
4524 we have to point it back to where it
4526 if ((AOP_SIZE (right) > 1 &&
4527 !OP_SYMBOL (result)->remat &&
4528 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) && !pi) {
4529 int size = AOP_SIZE (right) - 1;
4530 emitcode ("sbiw", "r30,%d",size);
4533 if (pi) pi->generated = 1;
4534 freeAsmop (right, NULL, ic, TRUE);
4535 freeAsmop (result, NULL, ic, TRUE);
4538 /*-----------------------------------------------------------------*/
4539 /* genPointerSet - stores the value into a pointer location */
4540 /*-----------------------------------------------------------------*/
4542 genPointerSet (iCode * ic, iCode *pi)
4544 operand *right, *result;
4545 sym_link *type, *etype;
4548 right = IC_RIGHT (ic);
4549 result = IC_RESULT (ic);
4551 /* depending on the type of pointer we need to
4552 move it to the correct pointer register */
4553 type = operandType (result);
4554 etype = getSpec (type);
4555 /* if left is of type of pointer then it is simple */
4556 if (IS_PTR (type) && !IS_FUNC (type->next)) {
4557 p_type = DCL_TYPE (type);
4560 /* we have to go by the storage class */
4561 p_type = PTR_TYPE (SPEC_OCLS (etype));
4565 /* now that we have the pointer type we assign
4566 the pointer values */
4573 genMemPointerSet (right, result, ic, pi);
4577 genGenPointerSet (right, result, ic, pi);
4583 /*-----------------------------------------------------------------*/
4584 /* genIfx - generate code for Ifx statement */
4585 /*-----------------------------------------------------------------*/
4587 genIfx (iCode * ic, iCode * popIc)
4589 operand *cond = IC_COND (ic);
4594 aopOp (cond, ic, FALSE);
4596 /* get the value into acc */
4597 if (AOP_SIZE(cond) == 1 && AOP_ISHIGHREG(AOP(cond),0)) {
4598 cname = aopGet(AOP(cond),0);
4600 toBoolean (cond, "r24", 0);
4604 /* the result is now in the accumulator */
4605 freeAsmop (cond, NULL, ic, TRUE);
4607 /* if there was something to be popped then do it */
4610 emitcode("cpi","%s,0",cname);
4611 } else if (!tob) emitcode("cpi","%s,0",cname);
4613 lbl = newiTempLabel(NULL);
4616 emitcode ("breq","L%05d",lbl->key);
4618 emitcode ("brne","L%05d",lbl->key);
4619 emitcode ("jmp","L%05d",IC_TRUE(ic)->key);
4620 emitcode ("","L%05d:",lbl->key);
4623 emitcode ("brne","L%05d",lbl->key);
4625 emitcode ("breq","L%05d",lbl->key);
4626 emitcode ("jmp","L%05d",IC_FALSE(ic)->key);
4627 emitcode ("","L%05d:",lbl->key);
4632 /*-----------------------------------------------------------------*/
4633 /* genAddrOf - generates code for address of */
4634 /*-----------------------------------------------------------------*/
4636 genAddrOf (iCode * ic)
4638 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
4641 aopOp (IC_RESULT (ic), ic, FALSE);
4642 assert(AOP_SIZE(IC_RESULT(ic)) >= 2);
4643 /* if the operand is on the stack then we
4644 need to get the stack offset of this
4647 /* if it has an offset then we need to compute it */
4650 if (AOP_ISHIGHREG(AOP(
4651 ((char) sym->stack & 0xff));
4653 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4656 /* we can just move _bp */
4657 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
4659 /* fill the result with zero */
4660 size = AOP_SIZE (IC_RESULT (ic)) - 2;
4663 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
4669 /* object not on stack then we need the name */
4670 size = AOP_SIZE (IC_RESULT (ic));
4674 char s[SDCC_NAME_MAX];
4676 sprintf (s, "(%s >> %d)", sym->rname, offset * 8);
4678 sprintf (s, "%s", sym->rname);
4679 aopPut (AOP (IC_RESULT (ic)), s, offset++);
4683 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4687 /*-----------------------------------------------------------------*/
4688 /* genFarFarAssign - assignment when both are in far space */
4689 /*-----------------------------------------------------------------*/
4691 genFarFarAssign (operand * result, operand * right, iCode * ic)
4693 int size = AOP_SIZE (right);
4696 /* first push the right side on to the stack */
4698 l = aopGet (AOP (right), offset++);
4700 emitcode ("push", "acc");
4703 freeAsmop (right, NULL, ic, FALSE);
4704 /* now assign DPTR to result */
4705 aopOp (result, ic, FALSE);
4706 size = AOP_SIZE (result);
4708 emitcode ("pop", "acc");
4709 aopPut (AOP (result), "a", --offset);
4711 freeAsmop (result, NULL, ic, FALSE);
4715 /*-----------------------------------------------------------------*/
4716 /* genAssign - generate code for assignment */
4717 /*-----------------------------------------------------------------*/
4719 genAssign (iCode * ic)
4721 operand *result, *right;
4723 unsigned long lit = 0L;
4725 result = IC_RESULT (ic);
4726 right = IC_RIGHT (ic);
4728 /* if they are the same */
4729 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4732 aopOp (right, ic, FALSE);
4734 /* special case both in far space */
4735 if (AOP_TYPE (right) == AOP_DPTR &&
4736 IS_TRUE_SYMOP (result) && isOperandInFarSpace (result)) {
4738 genFarFarAssign (result, right, ic);
4742 aopOp (result, ic, TRUE);
4744 /* if they are the same registers */
4745 if (sameRegs (AOP (right), AOP (result)))
4748 /* if the result is a bit */
4749 if (AOP_TYPE (result) == AOP_CRY) {
4751 /* if the right size is a literal then
4752 we know what the value is */
4753 if (AOP_TYPE (right) == AOP_LIT) {
4754 if (((int) operandLitValue (right)))
4755 aopPut (AOP (result), one, 0);
4757 aopPut (AOP (result), zero, 0);
4761 /* the right is also a bit variable */
4762 if (AOP_TYPE (right) == AOP_CRY) {
4763 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4764 aopPut (AOP (result), "c", 0);
4769 toBoolean (right, "", 0);
4770 aopPut (AOP (result), "a", 0);
4774 /* bit variables done */
4776 size = AOP_SIZE (result);
4778 if (AOP_TYPE (right) == AOP_LIT)
4780 (unsigned long) floatFromVal (AOP (right)->aopu.
4782 if ((size > 1) && (AOP_TYPE (result) != AOP_REG)
4783 && (AOP_TYPE (right) == AOP_LIT)
4784 && !IS_FLOAT (operandType (right)) && (lit < 256L)) {
4785 emitcode ("clr", "a");
4787 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) ==
4788 0) aopPut (AOP (result), "a", size);
4790 aopPut (AOP (result),
4791 aopGet (AOP (right), size), size);
4796 aopPut (AOP (result),
4797 aopGet (AOP (right), offset), offset);
4803 freeAsmop (right, NULL, ic, FALSE);
4804 freeAsmop (result, NULL, ic, TRUE);
4807 /*-----------------------------------------------------------------*/
4808 /* genJumpTab - genrates code for jump table */
4809 /*-----------------------------------------------------------------*/
4811 genJumpTab (iCode * ic)
4816 aopOp (IC_JTCOND (ic), ic, FALSE);
4817 /* get the condition into accumulator */
4818 l = aopGet (AOP (IC_JTCOND (ic)), 0);
4820 /* multiply by three */
4821 emitcode ("add", "a,acc");
4822 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0));
4823 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
4825 jtab = newiTempLabel (NULL);
4826 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
4827 emitcode ("jmp", "@a+dptr");
4828 emitcode ("", "%05d$:", jtab->key + 100);
4829 /* now generate the jump labels */
4830 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
4831 jtab = setNextItem (IC_JTLABELS (ic)))
4832 emitcode ("ljmp", "%05d$", jtab->key + 100);
4836 /*-----------------------------------------------------------------*/
4837 /* genCast - gen code for casting */
4838 /*-----------------------------------------------------------------*/
4840 genCast (iCode * ic)
4842 operand *result = IC_RESULT (ic);
4843 sym_link *ctype = operandType (IC_LEFT (ic));
4844 sym_link *rtype = operandType (IC_RIGHT (ic));
4845 operand *right = IC_RIGHT (ic);
4848 /* if they are equivalent then do nothing */
4849 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4852 aopOp (right, ic, FALSE);
4853 aopOp (result, ic, FALSE);
4855 /* if the result is a bit */
4856 if (AOP_TYPE (result) == AOP_CRY) {
4857 /* if the right size is a literal then
4858 we know what the value is */
4859 if (AOP_TYPE (right) == AOP_LIT) {
4860 if (((int) operandLitValue (right)))
4861 aopPut (AOP (result), one, 0);
4863 aopPut (AOP (result), zero, 0);
4868 /* the right is also a bit variable */
4869 if (AOP_TYPE (right) == AOP_CRY) {
4870 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4871 aopPut (AOP (result), "c", 0);
4876 toBoolean (right, "", 0);
4877 aopPut (AOP (result), "a", 0);
4881 /* if they are the same size : or less */
4882 if (AOP_SIZE (result) <= AOP_SIZE (right)) {
4884 /* if they are in the same place */
4885 if (sameRegs (AOP (right), AOP (result)))
4888 /* if they in different places then copy */
4889 size = AOP_SIZE (result);
4892 aopPut (AOP (result),
4893 aopGet (AOP (right), offset), offset);
4900 /* if the result is of type pointer */
4901 if (IS_PTR (ctype)) {
4904 sym_link *type = operandType (right);
4905 sym_link *etype = getSpec (type);
4907 /* pointer to generic pointer */
4908 if (IS_GENPTR (ctype)) {
4912 p_type = DCL_TYPE (type);
4914 /* we have to go by the storage class */
4915 p_type = PTR_TYPE (SPEC_OCLS (etype));
4918 /* the first two bytes are known */
4919 size = GPTRSIZE - 1;
4922 aopPut (AOP (result),
4923 aopGet (AOP (right), offset), offset);
4926 /* the last byte depending on type */
4943 /* this should never happen */
4944 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4945 "got unknown pointer type");
4948 aopPut (AOP (result), l, GPTRSIZE - 1);
4952 /* just copy the pointers */
4953 size = AOP_SIZE (result);
4956 aopPut (AOP (result),
4957 aopGet (AOP (right), offset), offset);
4963 /* so we now know that the size of destination is greater
4964 than the size of the source */
4965 /* we move to result for the size of source */
4966 size = AOP_SIZE (right);
4969 aopPut (AOP (result), aopGet (AOP (right), offset), offset);
4973 /* now depending on the sign of the source && destination */
4974 size = AOP_SIZE (result) - AOP_SIZE (right);
4975 /* if unsigned or not an integral type */
4976 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype)) {
4978 aopPut (AOP (result), zero, offset++);
4981 /* we need to extend the sign :{ */
4982 // PENDING: Does nothing on avr
4984 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1);
4987 emitcode ("rlc", "a");
4988 emitcode ("subb", "a,acc");
4990 aopPut (AOP (result), "a", offset++);
4993 /* we are done hurray !!!! */
4996 freeAsmop (right, NULL, ic, TRUE);
4997 freeAsmop (result, NULL, ic, TRUE);
5001 /*-----------------------------------------------------------------*/
5002 /* genDjnz - generate decrement & jump if not zero instrucion */
5003 /*-----------------------------------------------------------------*/
5005 genDjnz (iCode * ic, iCode * ifx)
5011 /* if the if condition has a false label
5012 then we cannot save */
5016 /* if the minus is not of the form
5018 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
5019 !IS_OP_LITERAL (IC_RIGHT (ic)))
5022 if (operandLitValue (IC_RIGHT (ic)) != 1)
5025 /* if the size of this greater than one then no
5027 if (getSize (operandType (IC_RESULT (ic))) > 1)
5030 /* otherwise we can save BIG */
5031 lbl = newiTempLabel (NULL);
5032 lbl1 = newiTempLabel (NULL);
5034 aopOp (IC_RESULT (ic), ic, FALSE);
5036 if (IS_AOP_PREG (IC_RESULT (ic))) {
5037 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0));
5038 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0));
5039 emitcode ("jnz", "%05d$", lbl->key + 100);
5042 emitcode ("djnz", "%s,%05d$",
5043 aopGet (AOP (IC_RESULT (ic)), 0), lbl->key + 100);
5045 emitcode ("sjmp", "%05d$", lbl1->key + 100);
5046 emitcode ("", "%05d$:", lbl->key + 100);
5047 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5048 emitcode ("", "%05d$:", lbl1->key + 100);
5050 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5055 static char *recvregs[8] = {
5056 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23"
5059 static int recvCnt = 0;
5061 /*-----------------------------------------------------------------*/
5062 /* genReceive - generate code for a receive iCode */
5063 /*-----------------------------------------------------------------*/
5065 genReceive (iCode * ic)
5067 int size, offset = 0;
5068 aopOp (IC_RESULT (ic), ic, FALSE);
5069 size = AOP_SIZE (IC_RESULT (ic));
5071 aopPut (AOP (IC_RESULT (ic)), recvregs[recvCnt++], offset);
5074 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5077 /*-----------------------------------------------------------------*/
5078 /* gen51Code - generate code for 8051 based controllers */
5079 /*-----------------------------------------------------------------*/
5081 genAVRCode (iCode * lic)
5086 lineHead = lineCurr = NULL;
5088 /* print the allocation information */
5090 printAllocInfo (currFunc, codeOutFile);
5091 /* if debug information required */
5092 /* if (options.debug && currFunc) { */
5094 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
5096 /* emitcode ("", ".type %s,@function", currFunc->name); */
5099 /* stack pointer name */
5103 for (ic = lic; ic; ic = ic->next) {
5105 if (cln != ic->lineno) {
5106 if (options.debug) {
5108 emitcode ("", "C$%s$%d$%d$%d ==.",
5109 FileBaseName (ic->filename),
5110 ic->lineno, ic->level, ic->block);
5113 emitcode (";", "%s %d", ic->filename, ic->lineno);
5116 /* if the result is marked as
5117 spilt and rematerializable or code for
5118 this has already been generated then
5120 if (resultRemat (ic) || ic->generated)
5123 /* depending on the operation */
5142 /* IPOP happens only when trying to restore a
5143 spilt live range, if there is an ifx statement
5144 following this pop then the if statement might
5145 be using some of the registers being popped which
5146 would destory the contents of the register so
5147 we need to check for this condition and handle it */
5149 ic->next->op == IFX &&
5150 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
5151 genIfx (ic->next, ic);
5169 genEndFunction (ic);
5189 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
5206 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
5210 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
5214 genCmpLe (ic, ifxForOp (IC_RESULT (ic), ic));
5218 genCmpGe (ic, ifxForOp (IC_RESULT (ic), ic));
5222 genCmpNe (ic, ifxForOp (IC_RESULT (ic), ic));
5226 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
5238 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
5242 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
5246 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
5273 case GET_VALUE_AT_ADDRESS:
5274 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
5278 if (POINTER_SET (ic))
5279 genPointerSet (ic, hasInc(IC_RESULT(ic),ic));
5305 addSet (&_G.sendSet, ic);
5314 /* now we are ready to call the
5315 peep hole optimizer */
5316 if (!options.nopeep)
5317 peepHole (&lineHead);
5319 /* now do the actual printing */
5320 printLine (lineHead, codeOutFile);