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__)
41 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
42 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
48 #include "SDCCpeeph.h"
52 char *aopLiteral (value * val, int offset);
55 /* this is the down and dirty file with all kinds of
56 kludgy & hacky stuff. This is what it is all about
57 CODE GENERATION for a specific MCU . some of the
58 routines may be reusable, will have to see */
60 static char *zero = "0x00";
61 static char *one = "0x01";
64 char *fReturnAVR[] = { "r16", "r17", "r18", "r19" };
65 unsigned fAVRReturnSize = 4; /* shared with ralloc.c */
66 char **fAVRReturn = fReturnAVR;
67 static char *larray[4] = { "lo8", "hi8", "hlo8", "hhi8" };
71 static short rbank = -1;
72 static char *tscr[4] = { "r0", "r1", "r24", "r25" };
73 static unsigned char SLMask[] = { 0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
74 0xE0, 0xC0, 0x80, 0x00
76 static unsigned char SRMask[] = { 0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
77 0x07, 0x03, 0x01, 0x00
92 extern int avr_ptrRegReq;
94 extern FILE *codeOutFile;
95 #define RESULTONSTACK(x) \
96 (IC_RESULT(x) && IC_RESULT(x)->aop && \
97 IC_RESULT(x)->aop->type == AOP_STK )
99 #define MOVR0(x) if (strcmp(x,"r0")) emitcode("mov","r0,%s",x);
100 #define MOVR24(x) if (strcmp(x,"r24")) emitcode("mov","r24,%s",x);
101 #define AOP_ISHIGHREG(a,n) (a->type == AOP_REG && a->aopu.aop_reg[n] && a->aopu.aop_reg[n]->rIdx >= R16_IDX)
102 #define CLRC emitcode("clc","")
103 #define SETC emitcode("stc","")
105 #define IS_REGIDX(a,r) (a->type == AOP_REG && a->aopu.aop_reg[0]->rIdx == r)
107 static lineNode *lineHead = NULL;
108 static lineNode *lineCurr = NULL;
117 /*-----------------------------------------------------------------*/
118 /* reAdjustPreg - points a register back to where it should */
119 /*-----------------------------------------------------------------*/
121 reAdjustPreg (asmop * aop)
126 if ((size = aop->size) <= 1)
132 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name, size);
138 /*-----------------------------------------------------------------*/
139 /* outBitC - output a bit C */
140 /*-----------------------------------------------------------------*/
142 outBitC (operand * result)
144 emitcode ("clr", "r0");
145 emitcode ("rol", "r0");
149 /*-----------------------------------------------------------------*/
150 /* inExcludeList - return 1 if the string is in exclude Reg list */
151 /*-----------------------------------------------------------------*/
153 inExcludeList (char *s)
157 if (options.excludeRegs[i] &&
158 STRCASECMP (options.excludeRegs[i], "none") == 0)
161 for (i = 0; options.excludeRegs[i]; i++) {
162 if (options.excludeRegs[i] &&
163 STRCASECMP (s, options.excludeRegs[i]) == 0)
169 /*-----------------------------------------------------------------*/
170 /* findLabelBackwards: walks back through the iCode chain looking */
171 /* for the given label. Returns number of iCode instructions */
172 /* between that label and given ic. */
173 /* Returns zero if label not found. */
174 /*-----------------------------------------------------------------*/
176 findLabelBackwards (iCode * ic, int key)
184 if (ic->op == LABEL && IC_LABEL (ic)->key == key) {
185 /* printf("findLabelBackwards = %d\n", count); */
193 /*-----------------------------------------------------------------*/
194 /* addSign - complete with sign */
195 /*-----------------------------------------------------------------*/
197 addSign (operand * result, int offset, int sign)
199 int size = (getDataSize (result) - offset);
202 emitcode ("rlc", "a");
203 emitcode ("subb", "a,acc");
205 aopPut (AOP (result), "a", offset++);
209 aopPut (AOP (result), zero, offset++);
213 /*-----------------------------------------------------------------*/
214 /* isLiteralBit - test if lit == 2^n */
215 /*-----------------------------------------------------------------*/
217 isLiteralBit (unsigned long lit)
219 unsigned long pw[32] = { 1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
220 0x100L, 0x200L, 0x400L, 0x800L,
221 0x1000L, 0x2000L, 0x4000L, 0x8000L,
222 0x10000L, 0x20000L, 0x40000L, 0x80000L,
223 0x100000L, 0x200000L, 0x400000L, 0x800000L,
224 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
225 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L
229 for (idx = 0; idx < 32; idx++)
235 /*-----------------------------------------------------------------*/
236 /* outAcc - output Acc */
237 /*-----------------------------------------------------------------*/
239 outAcc (operand * result)
242 size = getDataSize (result);
244 aopPut (AOP (result), "r0", 0);
247 /* unsigned or positive */
249 aopPut (AOP (result), zero, offset++);
254 #endif // End Unused code section
256 /*-----------------------------------------------------------------*/
257 /* emitcode - writes the code into a file : for now it is simple */
258 /*-----------------------------------------------------------------*/
260 emitcode (char *inst, char *fmt, ...)
263 char lb[INITIAL_INLINEASM];
270 sprintf (lb, "%s\t", inst);
272 sprintf (lb, "%s", inst);
273 vsprintf (lb + (strlen (lb)), fmt, ap);
276 vsprintf (lb, fmt, ap);
278 while (isspace (*lbp))
282 lineCurr = (lineCurr ?
283 connectLine (lineCurr, newLineNode (lb)) :
284 (lineHead = newLineNode (lb)));
285 lineCurr->isInline = _G.inLine;
286 lineCurr->isDebug = _G.debugLine;
290 /*-----------------------------------------------------------------*/
291 /* hasInc - operand is incremented before any other use */
292 /*-----------------------------------------------------------------*/
294 hasInc (operand *op, iCode *ic)
296 sym_link *type = operandType(op);
297 sym_link *retype = getSpec (type);
298 iCode *lic = ic->next;
301 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
302 isize = getSize(type->next);
304 /* if operand of the form op = op + <sizeof *op> */
305 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
306 isOperandEqual(IC_RESULT(lic),op) &&
307 isOperandLiteral(IC_RIGHT(lic)) &&
308 operandLitValue(IC_RIGHT(lic)) == isize) {
311 /* if the operand used or deffed */
312 if (bitVectBitValue(ic->uses,op->key) || ((unsigned) ic->defKey == op->key)) {
320 /*-----------------------------------------------------------------*/
321 /* getFreePtr - returns X or Z whichever is free or can be pushed */
322 /*-----------------------------------------------------------------*/
324 getFreePtr (iCode * ic, asmop ** aopp, bool result, bool zonly)
326 bool xiu = FALSE, ziu = FALSE;
327 bool xou = FALSE, zou = FALSE;
329 /* the logic: if x & z used in the instruction
330 then we are in trouble otherwise */
332 /* first check if x & z are used by this
333 instruction, in which case we are in trouble */
334 if ((xiu = bitVectBitValue (ic->rUsed, X_IDX)) &&
335 (ziu = bitVectBitValue (ic->rUsed, Z_IDX))) {
339 xou = bitVectBitValue (ic->rMask, X_IDX);
340 zou = bitVectBitValue (ic->rMask, Z_IDX);
342 /* if no usage of Z then return it */
344 ic->rUsed = bitVectSetBit (ic->rUsed, Z_IDX);
345 (*aopp)->type = AOP_Z;
347 (*aopp)->aop_ptr2 = avr_regWithIdx (R31_IDX);
348 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R30_IDX);
351 /* if no usage of X then return it */
352 if (!xiu && !xou && !zonly) {
353 ic->rUsed = bitVectSetBit (ic->rUsed, X_IDX);
354 (*aopp)->type = AOP_X;
356 (*aopp)->aop_ptr2 = avr_regWithIdx (R27_IDX);
357 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R26_IDX);
360 /* if z not used then */
363 /* push it if not already pushed */
365 emitcode ("push", "%s",
366 avr_regWithIdx (R30_IDX)->dname);
367 emitcode ("push", "%s",
368 avr_regWithIdx (R31_IDX)->dname);
372 ic->rUsed = bitVectSetBit (ic->rUsed, Z_IDX);
373 (*aopp)->type = AOP_Z;
374 (*aopp)->aop_ptr2 = avr_regWithIdx (R31_IDX);
375 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R30_IDX);
378 /* now we know they both have usage */
379 /* if x not used in this instruction */
380 if (!xiu && !zonly) {
381 /* push it if not already pushed */
383 emitcode ("push", "%s",
384 avr_regWithIdx (R26_IDX)->dname);
385 emitcode ("push", "%s",
386 avr_regWithIdx (R27_IDX)->dname);
390 ic->rUsed = bitVectSetBit (ic->rUsed, X_IDX);
391 (*aopp)->type = AOP_X;
393 (*aopp)->aop_ptr2 = avr_regWithIdx (R27_IDX);
394 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R26_IDX);
399 /* I said end of world but not quite end of world yet */
400 /* if this is a result then we can push it on the stack */
402 (*aopp)->type = AOP_STK;
406 /* other wise this is true end of the world */
407 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
408 "getFreePtr should never reach here");
412 /*-----------------------------------------------------------------*/
413 /* newAsmop - creates a new asmOp */
414 /*-----------------------------------------------------------------*/
416 newAsmop (short type)
420 aop = Safe_calloc (1, sizeof (asmop));
425 /*-----------------------------------------------------------------*/
426 /* pointerCode - returns the code for a pointer type */
427 /*-----------------------------------------------------------------*/
429 pointerCode (sym_link * etype)
432 return PTR_TYPE (SPEC_OCLS (etype));
436 /*-----------------------------------------------------------------*/
437 /* aopForSym - for a true symbol */
438 /*-----------------------------------------------------------------*/
440 aopForSym (iCode * ic, symbol * sym, bool result)
443 memmap *space = SPEC_OCLS (sym->etype);
445 /* if already has one */
449 /* assign depending on the storage class */
450 /* if it is on the stack */
452 sym->aop = aop = newAsmop (0);
453 aop->size = getSize (sym->type);
455 /* we can use std / ldd instruction */
457 && (sym->stack + getSize (sym->type) - 1) <= 63) {
458 aop->type = AOP_STK_D;
459 aop->aopu.aop_stk = sym->stack;
463 /* otherwise get a free pointer register X/Z */
464 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result, FALSE);
466 /* now assign the address of the variable to
467 the pointer register */
468 if (aop->type != AOP_STK) {
469 emitcode ("movw", "%s,r28", aop->aopu.aop_ptr->name);
470 if (sym->stack < 0) {
471 if ((sym->stack - _G.nRegsSaved) > -63) {
472 emitcode ("sbiw", "%s,0x%02x",
473 aop->aopu.aop_ptr->name,
478 emitcode ("subi", "%s,lo8(%d)",
479 aop->aopu.aop_ptr->name,
480 sym->stack - _G.nRegsSaved);
481 emitcode ("sbci", "%s,hi8(%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,lo8(-%d)",
494 aop->aopu.aop_ptr->name,
496 emitcode ("sbci", "%s,hi8(-%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,lo8(%s)", aop->aopu.aop_ptr->name, sym->rname);
540 emitcode ("ldi", "%s,hi8(%s)", aop->aop_ptr2);
545 /*-----------------------------------------------------------------*/
546 /* aopForRemat - rematerialzes an object */
547 /*-----------------------------------------------------------------*/
549 aopForRemat (symbol * sym)
551 iCode *ic = sym->rematiCode;
552 asmop *aop = newAsmop (AOP_IMMD);
557 val += (int) operandLitValue (IC_RIGHT (ic));
558 else if (ic->op == '-')
559 val -= (int) operandLitValue (IC_RIGHT (ic));
563 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
567 sprintf (buffer, "(%s %c 0x%04x)",
568 OP_SYMBOL (IC_LEFT (ic))->rname,
569 val >= 0 ? '+' : '-', abs (val) & 0xffff);
571 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
573 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
574 strcpy (aop->aopu.aop_immd, buffer);
578 /*-----------------------------------------------------------------*/
579 /* regsInCommon - two operands have some registers in common */
580 /*-----------------------------------------------------------------*/
582 regsInCommon (operand * op1, operand * op2)
587 /* if they have registers in common */
588 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
591 sym1 = OP_SYMBOL (op1);
592 sym2 = OP_SYMBOL (op2);
594 if (sym1->nRegs == 0 || sym2->nRegs == 0)
597 for (i = 0; i < sym1->nRegs; i++) {
602 for (j = 0; j < sym2->nRegs; j++) {
606 if (sym2->regs[j] == sym1->regs[i])
614 /*-----------------------------------------------------------------*/
615 /* operandsEqu - equivalent */
616 /*-----------------------------------------------------------------*/
618 operandsEqu (operand * op1, operand * op2)
622 /* if they not symbols */
623 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
626 sym1 = OP_SYMBOL (op1);
627 sym2 = OP_SYMBOL (op2);
629 /* if both are itemps & one is spilt
630 and the other is not then false */
631 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
632 sym1->isspilt != sym2->isspilt) return FALSE;
634 /* if they are the same */
638 if (strcmp (sym1->rname, sym2->rname) == 0)
642 /* if left is a tmp & right is not */
643 if (IS_ITEMP (op1) &&
644 !IS_ITEMP (op2) && sym1->isspilt && (sym1->usl.spillLoc == sym2))
647 if (IS_ITEMP (op2) &&
649 sym2->isspilt && sym1->level > 0 && (sym2->usl.spillLoc == sym1))
655 /*-----------------------------------------------------------------*/
656 /* sameRegs - two asmops have the same registers */
657 /*-----------------------------------------------------------------*/
659 sameRegs (asmop * aop1, asmop * aop2)
666 if (aop1->type != AOP_REG || aop2->type != AOP_REG)
669 if (aop1->size != aop2->size)
672 for (i = 0; i < aop1->size; i++)
673 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
679 /*-----------------------------------------------------------------*/
680 /* isRegPair - for size 2 if this operand has a register pair */
681 /*-----------------------------------------------------------------*/
683 isRegPair (asmop * aop)
685 if (!aop || aop->size < 2)
687 if (aop->type == AOP_X || aop->type == AOP_Z)
689 if (aop->type != AOP_REG)
691 if ( ((aop->aopu.aop_reg[1]->rIdx - aop->aopu.aop_reg[0]->rIdx) == 1) &&
692 (aop->aopu.aop_reg[0]->rIdx & 1) == 0)
698 /*-----------------------------------------------------------------*/
699 /* aopOp - allocates an asmop for an operand : */
700 /*-----------------------------------------------------------------*/
702 aopOp (operand * op, iCode * ic, bool result)
711 /* if this a literal */
712 if (IS_OP_LITERAL (op)) {
713 op->aop = aop = newAsmop (AOP_LIT);
714 aop->aopu.aop_lit = op->operand.valOperand;
715 aop->size = getSize (operandType (op));
719 /* if already has a asmop then continue */
723 /* if the underlying symbol has a aop */
724 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop) {
725 op->aop = OP_SYMBOL (op)->aop;
729 /* if this is a true symbol */
730 if (IS_TRUE_SYMOP (op)) {
731 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
735 /* this is a temporary : this has
741 e) can be a return use only */
743 sym = OP_SYMBOL (op);
746 /* if the type is a conditional */
747 if (sym->regType & REG_CND) {
748 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
753 /* if it is spilt then two situations
755 b) has a spill location */
756 if (sym->isspilt || sym->nRegs == 0) {
758 /* rematerialize it NOW */
760 sym->aop = op->aop = aop = aopForRemat (sym);
761 aop->size = getSize (sym->type);
766 assert ("ACC_USE cannot happen in AVR\n");
771 aop = op->aop = sym->aop = newAsmop (AOP_STR);
772 aop->size = getSize (sym->type);
773 for (i = 0; i < (int) fAVRReturnSize; i++)
774 aop->aopu.aop_str[i] = fAVRReturn[i];
778 /* else spill location */
779 sym->aop = op->aop = aop =
780 aopForSym (ic, sym->usl.spillLoc, result);
781 aop->size = getSize (sym->type);
785 /* must be in a register */
786 sym->aop = op->aop = aop = newAsmop (AOP_REG);
787 aop->size = sym->nRegs;
788 for (i = 0; i < sym->nRegs; i++)
789 aop->aopu.aop_reg[i] = sym->regs[i];
792 /*-----------------------------------------------------------------*/
793 /* freeAsmop - free up the asmop given to an operand */
794 /*----------------------------------------------------------------*/
796 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
813 /* depending on the asmop type only three cases need work AOP_RO
814 , AOP_R1 && AOP_STK */
819 emitcode ("pop", "r26");
820 emitcode ("pop", "r27");
824 bitVectUnSetBit (ic->rUsed, X_IDX);
830 emitcode ("pop", "r30");
831 emitcode ("pop", "r31");
835 bitVectUnSetBit (ic->rUsed, Z_IDX);
841 int stk = aop->aopu.aop_stk + aop->size;
842 bitVectUnSetBit (ic->rUsed, X_IDX);
843 bitVectUnSetBit (ic->rUsed, Z_IDX);
845 getFreePtr (ic, &aop, FALSE, 0);
847 emitcode ("movw", "%s,r28");
849 if (stk <= 63 && stk > 0) {
850 emitcode ("adiw", "%s,0x%02x",
851 aop->aopu.aop_ptr->name,
855 emitcode ("subi", "%s,lo8(%d)",
856 aop->aopu.aop_ptr->name,
858 emitcode ("sbci", "%s,hi8(%d)",
865 emitcode ("pop", "r24");
866 emitcode ("st", "-%s,r24",
867 aop->type == AOP_X ? "X" : "Z");
872 freeAsmop (op, NULL, ic, TRUE);
874 emitcode ("pop", "r26");
875 emitcode ("pop", "r27");
880 emitcode ("pop", "r30");
881 emitcode ("pop", "r31");
888 /* all other cases just dealloc */
892 OP_SYMBOL (op)->aop = NULL;
893 /* if the symbol has a spill */
895 SPIL_LOC (op)->aop = NULL;
900 /*-----------------------------------------------------------------*/
901 /* aopGet - for fetching value of the aop */
902 /*-----------------------------------------------------------------*/
904 aopGet (asmop * aop, int offset)
909 /* offset is greater than
911 if (offset > (aop->size - 1) && aop->type != AOP_LIT)
914 /* depending on type */
918 if (offset > aop->coff) {
919 emitcode ("adiw", "%s,%d", aop->aopu.aop_ptr->name,
923 if (offset < aop->coff) {
924 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name,
929 emitcode ("ld", "%s,x",
930 (rs = ((offset & 1) ? "r25" : "r24")));
935 if (offset > aop->coff) {
936 emitcode ("adiw", "r30,%d",
940 emitcode ("sbiw", "r30,%d",
943 emitcode ("lpm", "%s,z",
944 (rs = ((offset & 1) ? "r25" : "r24")));
948 if (offset > aop->coff) {
949 emitcode ("ldd", "%s,z+%d",
951 ((offset & 1) ? "r25" : "r24")),
955 emitcode ("sbiw", "%s,%d",
956 aop->aopu.aop_ptr->name,
959 emitcode ("ld", "%s,z",
961 ((offset & 1) ? "r25" : "r24")));
968 emitcode ("lds", "%s,(%s)+%d",
969 (rs = ((offset & 1) ? "r25" : "r24")),
970 aop->aopu.aop_immd, offset);
974 emitcode ("lds", "%s,(%s)+%d",
975 (rs = ((offset & 1) ? "r25" : "r24")),
976 aop->aopu.aop_dir, offset);
980 return aop->aopu.aop_reg[offset]->name;
983 assert ("cannot be in bit space AOP_CRY\n");
987 s = aopLiteral (aop->aopu.aop_lit, offset);
988 emitcode ("ldi", "%s,lo8(%s)",
989 (rs = ((offset & 1) ? "r24" : "r25")), s);
994 return aop->aopu.aop_str[offset];
997 emitcode ("ldd", "%s,Y+%d",
998 (rs = ((offset & 1) ? "r25" : "r24")),
999 aop->aopu.aop_stk + offset);
1003 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1004 "aopget got unsupported aop->type");
1008 /*-----------------------------------------------------------------*/
1009 /* aopPut - puts a string for a aop */
1010 /*-----------------------------------------------------------------*/
1012 aopPut (asmop * aop, char *s, int offset)
1016 if (aop->size && offset > (aop->size - 1)) {
1017 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1018 "aopPut got offset > aop->size");
1022 /* will assign value to value */
1023 /* depending on where it is ofcourse */
1024 switch (aop->type) {
1027 sprintf (d, "(%s)+%d", aop->aopu.aop_dir, offset);
1030 sprintf (d, "%s", aop->aopu.aop_dir);
1033 emitcode ("sts", "%s,%s", d, s);
1037 if (toupper (*s) != 'R') {
1039 emitcode ("clr", "%s",
1040 aop->aopu.aop_reg[offset]->name);
1043 emitcode ("ldi", "r25,%s", s);
1044 emitcode ("mov", "%s,r35",
1045 aop->aopu.aop_reg[offset]->name);
1049 if (strcmp (aop->aopu.aop_reg[offset]->name, s)) {
1050 emitcode ("mov", "%s,%s",
1051 aop->aopu.aop_reg[offset]->name, s);
1057 if (offset > aop->coff) {
1058 emitcode ("adiw", "%s,%d", aop->aopu.aop_ptr->name,
1059 offset - aop->coff);
1062 if (offset < aop->coff) {
1063 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name,
1064 aop->coff - offset);
1068 emitcode ("st", "x,%s", s);
1073 if (offset > aop->coff) {
1074 emitcode ("adiw", "r30,%d",
1075 offset - aop->coff);
1078 emitcode ("sbiw", "r30,%d",
1079 aop->coff - offset);
1081 emitcode ("lpm", "%s,z", s);
1084 /* we can use lds */
1085 if (offset > aop->coff) {
1086 emitcode ("sdd", "z+%d,%s",
1087 offset - aop->coff, s);
1090 emitcode ("sbiw", "%s,%d",
1091 aop->aopu.aop_ptr->name,
1092 aop->coff - offset);
1094 emitcode ("ld", "%s,z", s);
1100 emitcode ("push", "%s", s);
1104 /* if used only for a condition code check */
1105 assert (toupper (*s) == 'R');
1107 emitcode ("xrl", "r0,r0");
1108 emitcode ("cpi", "%s,0", s);
1111 emitcode ("cpc", "r0,%s", s);
1117 if (strcmp (aop->aopu.aop_str[offset], s))
1118 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset],
1123 emitcode ("std", "y+%d,%s", offset, s);
1127 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1128 "aopPut got unsupported aop->type");
1134 #define AOP(op) op->aop
1135 #define AOP_TYPE(op) AOP(op)->type
1136 #define AOP_SIZE(op) AOP(op)->size
1137 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_X || \
1138 AOP_TYPE(x) == AOP_Z))
1139 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1140 ((x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R27_IDX)) || \
1141 (x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R31_IDX)) )))
1142 #define AOP_ISX(x) (x && (x->type == AOP_REG && \
1143 ((x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R27_IDX)))))
1144 #define AOP_ISZ(x) (x && (x->type == AOP_REG && \
1145 ((x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R31_IDX)))))
1147 /*-----------------------------------------------------------------*/
1148 /* genNotFloat - generates not for float operations */
1149 /*-----------------------------------------------------------------*/
1151 genNotFloat (operand * op, operand * res)
1157 /* we will put 127 in the first byte of
1159 aopPut (AOP (res), "127", 0);
1160 size = AOP_SIZE (op) - 1;
1163 l = aopGet (op->aop, offset++);
1167 emitcode ("or", "R0,%s", aopGet (op->aop, offset++));
1169 tlbl = newiTempLabel (NULL);
1171 tlbl = newiTempLabel (NULL);
1172 aopPut (res->aop, zero, 1);
1173 emitcode ("cpi", "r0,0");
1174 emitcode ("breq", "L%05d", tlbl->key);
1175 aopPut (res->aop, one, 1);
1176 emitcode ("", "L%05d:", tlbl->key);
1178 size = res->aop->size - 2;
1180 /* put zeros in the rest */
1182 aopPut (res->aop, zero, offset++);
1185 /*-----------------------------------------------------------------*/
1186 /* opIsGptr: returns non-zero if the passed operand is */
1187 /* a generic pointer type. */
1188 /*-----------------------------------------------------------------*/
1190 opIsGptr (operand * op)
1192 sym_link *type = operandType (op);
1194 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type)) {
1200 /*-----------------------------------------------------------------*/
1201 /* getDataSize - get the operand data size */
1202 /*-----------------------------------------------------------------*/
1204 getDataSize (operand * op)
1207 size = AOP_SIZE (op);
1208 if (size == GPTRSIZE) {
1209 sym_link *type = operandType (op);
1210 if (IS_GENPTR (type)) {
1211 /* generic pointer; arithmetic operations
1212 * should ignore the high byte (pointer type).
1220 /*-----------------------------------------------------------------*/
1221 /* toBoolean - emit code for orl a,operator(sizeop) */
1222 /*-----------------------------------------------------------------*/
1224 toBoolean (operand * oper, char *r, bool clr)
1226 int size = AOP_SIZE (oper);
1229 emitcode ("clr", "%s", r);
1231 emitcode ("or", "%s,%s", r, aopGet (AOP (oper), offset++));
1235 /*-----------------------------------------------------------------*/
1236 /* genNot - generate code for ! operation */
1237 /*-----------------------------------------------------------------*/
1242 sym_link *optype = operandType (IC_LEFT (ic));
1243 int size, offset = 1;
1245 /* assign asmOps to operand & result */
1246 aopOp (IC_LEFT (ic), ic, FALSE);
1247 aopOp (IC_RESULT (ic), ic, TRUE);
1249 /* if type float then do float */
1250 if (IS_FLOAT (optype)) {
1251 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1254 emitcode ("clr", "r24");
1255 tlbl = newiTempLabel (NULL);
1256 size = AOP_SIZE (IC_LEFT (ic));
1259 emitcode ("cpse", "%s,r24", aopGet (AOP (IC_LEFT (ic)), 0));
1264 emitcode ("cpc", "%s,r24",
1265 aopGet (AOP (IC_LEFT (ic)),
1268 emitcode ("cpi", "%s,0",
1269 aopGet (AOP (IC_LEFT (ic)),
1273 emitcode ("bne", "L%05d", tlbl->key);
1275 emitcode ("ldi", "r24,1");
1276 emitcode ("", "L%05d:", tlbl->key);
1277 aopPut (AOP (IC_RESULT (ic)), "r24", 0);
1278 size = AOP_SIZE (IC_RESULT (ic)) - 1;
1281 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
1285 /* release the aops */
1286 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1287 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1291 /*-----------------------------------------------------------------*/
1292 /* genCpl - generate code for complement */
1293 /*-----------------------------------------------------------------*/
1301 /* assign asmOps to operand & result */
1302 aopOp (IC_LEFT (ic), ic, FALSE);
1303 aopOp (IC_RESULT (ic), ic, TRUE);
1304 samer = sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)));
1305 size = AOP_SIZE (IC_RESULT (ic));
1307 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
1309 emitcode ("com", "%s", l);
1312 aopPut (AOP (IC_RESULT (ic)), l, offset);
1313 emitcode ("com", "%s",
1314 aopGet (AOP (IC_RESULT (ic)), offset));
1319 /* release the aops */
1320 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1321 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1324 /*-----------------------------------------------------------------*/
1325 /* genUminusFloat - unary minus for floating points */
1326 /*-----------------------------------------------------------------*/
1328 genUminusFloat (operand * op, operand * result)
1330 int size, offset = 0;
1332 /* for this we just need to flip the
1333 first it then copy the rest in place */
1334 size = AOP_SIZE (op) - 1;
1335 l = aopGet (AOP (op), 3);
1337 emitcode ("ldi", "r24,0x80");
1338 if (sameRegs (AOP (op), AOP (result))) {
1339 emitcode ("eor", "%s,r24", l);
1342 aopPut (AOP (result), l, 3);
1343 emitcode ("eor", "%s,r24", aopGet (AOP (result), 3));
1346 aopPut (AOP (result), aopGet (AOP (op), offset), offset);
1351 /*-----------------------------------------------------------------*/
1352 /* genUminus - unary minus code generation */
1353 /*-----------------------------------------------------------------*/
1355 genUminus (iCode * ic)
1358 sym_link *optype, *rtype;
1362 aopOp (IC_LEFT (ic), ic, FALSE);
1363 aopOp (IC_RESULT (ic), ic, TRUE);
1365 optype = operandType (IC_LEFT (ic));
1366 rtype = operandType (IC_RESULT (ic));
1368 /* if float then do float stuff */
1369 if (IS_FLOAT (optype)) {
1370 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1374 /* otherwise subtract from zero */
1375 size = AOP_SIZE (IC_LEFT (ic));
1377 samer = sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)));
1380 emitcode ("neg", "%s",
1381 aopGet (AOP (IC_LEFT (ic)), 0));
1384 aopPut (AOP (IC_RESULT (ic)),
1385 aopGet (AOP (IC_LEFT (ic)), 0), 0);
1386 emitcode ("neg", "%s",
1387 aopGet (AOP (IC_RESULT (ic)), 0));
1393 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
1395 aopPut (AOP (IC_RESULT (ic)), l, offset);
1396 l = aopGet (AOP (IC_RESULT (ic)), offset);
1399 emitcode ("com", "%s", l);
1401 emitcode ("neg", "%s", l);
1404 size = AOP_SIZE (IC_LEFT (ic)) - 1;
1407 emitcode ("sbci", "%s,lo8(-1)",
1408 aopGet (AOP (IC_RESULT (ic)), offset++));
1412 /* if any remaining bytes in the result */
1413 /* we just need to propagate the sign */
1414 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic))))) {
1415 symbol *tlbl = newiTempLabel (NULL);
1416 emitcode ("clr", "r0");
1417 emitcode ("brcc", "L%05d", tlbl->key);
1418 emitcode ("com", "r0");
1419 emitcode ("", "L%05d:", tlbl->key);
1421 aopPut (AOP (IC_RESULT (ic)), "r0", offset++);
1425 /* release the aops */
1426 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1427 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1430 /*-----------------------------------------------------------------*/
1431 /* assignResultValue - */
1432 /*-----------------------------------------------------------------*/
1434 assignResultValue (operand * oper)
1437 int size = AOP_SIZE (oper);
1439 aopPut (AOP (oper), fAVRReturn[offset], offset);
1444 /*-----------------------------------------------------------------*/
1445 /* saveZreg - if indirect call then save z-pointer register */
1446 /*-----------------------------------------------------------------*/
1448 saveZreg (iCode * ic)
1450 /* only if live accross this call */
1451 if (ic->regsSaved == 0 &&
1452 (bitVectBitValue (ic->rMask, R30_IDX) ||
1453 bitVectBitValue (ic->rMask, R31_IDX))) {
1455 emitcode ("push", "r30");
1456 emitcode ("push", "r31");
1460 /*-----------------------------------------------------------------*/
1461 /* popZreg - restore values of zreg */
1462 /*-----------------------------------------------------------------*/
1464 popZreg (iCode * ic)
1466 if (ic->regsSaved) {
1467 emitcode ("pop", "r31");
1468 emitcode ("pop", "r30");
1472 /*-----------------------------------------------------------------*/
1473 /* genIpush - genrate code for pushing this gets a little complex */
1474 /*-----------------------------------------------------------------*/
1476 genIpush (iCode * ic)
1478 int size, offset = 0;
1482 if (!ic->parmPush) {
1483 /* and the item is spilt then do nothing */
1484 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1489 for (lic = ic->next; lic; lic = lic->next)
1490 if (lic->op == PCALL)
1496 /* this is a paramter push */
1497 aopOp (IC_LEFT (ic), ic, FALSE);
1498 size = AOP_SIZE (IC_LEFT (ic));
1500 l = aopGet (AOP (IC_LEFT (ic)), offset++);
1501 emitcode ("push", "%s", l);
1504 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1507 /*-----------------------------------------------------------------*/
1508 /* genIpop - recover the registers: can happen only for spilling */
1509 /*-----------------------------------------------------------------*/
1511 genIpop (iCode * ic)
1516 /* if the temp was not pushed then */
1517 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1520 aopOp (IC_LEFT (ic), ic, FALSE);
1521 size = AOP_SIZE (IC_LEFT (ic));
1522 offset = (size - 1);
1524 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--));
1526 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1529 /*-----------------------------------------------------------------*/
1530 /* genCall - generates a call statement */
1531 /*-----------------------------------------------------------------*/
1533 genCall (iCode * ic)
1536 /* if send set is not empty the assign */
1540 for (sic = setFirstItem (_G.sendSet); sic;
1541 sic = setNextItem (_G.sendSet)) {
1542 int size, offset = 0;
1543 aopOp (IC_LEFT (sic), sic, FALSE);
1544 size = AOP_SIZE (IC_LEFT (sic));
1547 aopGet (AOP (IC_LEFT (sic)), offset);
1549 sprintf (buffer, "r%d", rnum++);
1551 emitcode ("mov", "%s,%s", b, l);
1554 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1559 emitcode ("call", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1560 OP_SYMBOL (IC_LEFT (ic))->rname :
1561 OP_SYMBOL (IC_LEFT (ic))->name));
1563 /* if we need assign a result value */
1564 if ((IS_ITEMP (IC_RESULT (ic)) &&
1565 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1566 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1567 IS_TRUE_SYMOP (IC_RESULT (ic))) {
1569 aopOp (IC_RESULT (ic), ic, FALSE);
1570 assignResultValue (IC_RESULT (ic));
1571 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1574 /* adjust the stack for parameters if required */
1575 if (ic->parmBytes) {
1576 if (ic->parmBytes > 63) {
1577 emitcode ("sbiw", "r28,%d", ic->parmBytes);
1580 emitcode ("subi", "r28,lo8(%d)",
1582 emitcode ("sbci", "r29,hi8(%d)",
1589 /*-----------------------------------------------------------------*/
1590 /* genPcall - generates a call by pointer statement */
1591 /*-----------------------------------------------------------------*/
1593 genPcall (iCode * ic)
1599 aopOp (IC_LEFT (ic), ic, FALSE);
1600 emitcode ("mov", "r30", aopGet (AOP (IC_LEFT (ic)), 0));
1601 emitcode ("mov", "r31", aopGet (AOP (IC_RIGHT (ic)), 0));
1602 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1604 /* if send set is not empty the assign */
1608 for (sic = setFirstItem (_G.sendSet); sic;
1609 sic = setNextItem (_G.sendSet)) {
1610 int size, offset = 0;
1611 aopOp (IC_LEFT (sic), sic, FALSE);
1612 size = AOP_SIZE (IC_LEFT (sic));
1615 aopGet (AOP (IC_LEFT (sic)), offset);
1617 sprintf (b, "r%d", rnum++);
1619 emitcode ("mov", "%s,%s", b, l);
1622 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1627 emitcode ("icall", "");
1629 /* if we need assign a result value */
1630 if ((IS_ITEMP (IC_RESULT (ic)) &&
1631 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1632 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1633 IS_TRUE_SYMOP (IC_RESULT (ic))) {
1635 aopOp (IC_RESULT (ic), ic, FALSE);
1637 assignResultValue (IC_RESULT (ic));
1638 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1641 /* adjust the stack for parameters if
1643 if (ic->parmBytes) {
1645 if (ic->parmBytes > 3) {
1646 emitcode ("mov", "a,%s", spname);
1647 emitcode ("add", "a,#0x%02x",
1648 (-ic->parmBytes) & 0xff);
1649 emitcode ("mov", "%s,a", spname);
1652 for (i = 0; i < ic->parmBytes; i++)
1653 emitcode ("dec", "%s", spname);
1657 /* adjust the stack for parameters if required */
1658 if (ic->parmBytes) {
1659 if (ic->parmBytes > 63) {
1660 emitcode ("sbiw", "r28,%d", ic->parmBytes);
1663 emitcode ("subi", "r28,lo8(%d)",
1665 emitcode ("sbci", "r29,hi8(%d)",
1673 /*-----------------------------------------------------------------*/
1674 /* resultRemat - result is rematerializable */
1675 /*-----------------------------------------------------------------*/
1677 resultRemat (iCode * ic)
1679 if (SKIP_IC (ic) || ic->op == IFX)
1682 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic))) {
1683 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
1684 if (sym->remat && !POINTER_SET (ic))
1691 #if defined(__BORLANDC__) || defined(_MSC_VER)
1692 #define STRCASECMP stricmp
1694 #define STRCASECMP strcasecmp
1697 /*-----------------------------------------------------------------*/
1698 /* genFunction - generated code for function entry */
1699 /*-----------------------------------------------------------------*/
1701 genFunction (iCode * ic)
1708 /* create the function header */
1709 emitcode (";", "-----------------------------------------");
1710 emitcode (";", " function %s",
1711 (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
1712 emitcode (";", "-----------------------------------------");
1714 emitcode ("", "%s:", sym->rname);
1715 fetype = getSpec (operandType (IC_LEFT (ic)));
1717 /* if critical function then turn interrupts off */
1718 if (SPEC_CRTCL (fetype))
1719 emitcode ("cli", "");
1721 if (IS_ISR (sym->etype)) {
1724 /* save the preserved registers that are used in this function */
1725 for (i = R2_IDX; i <= R15_IDX; i++) {
1726 if (bitVectBitValue (sym->regsUsed, i)) {
1728 emitcode ("push", "%s", avr_regWithIdx (i)->name);
1731 /* now for the pointer registers */
1732 if (bitVectBitValue (sym->regsUsed, R26_IDX)) {
1734 emitcode ("push", "r26");
1736 if (bitVectBitValue (sym->regsUsed, R27_IDX)) {
1738 emitcode ("push", "r27");
1740 if (bitVectBitValue (sym->regsUsed, R30_IDX)) {
1742 emitcode ("push", "r30");
1744 if (bitVectBitValue (sym->regsUsed, R31_IDX)) {
1746 emitcode ("push", "r31");
1748 /* adjust the stack for the function */
1750 emitcode ("push", "r28");
1751 emitcode ("push", "r29");
1752 emitcode ("in", "r28,__SP_L__");
1753 emitcode ("in", "r29,__SP_H__");
1754 if (sym->stack <= 63) {
1755 emitcode ("sbiw", "r28,%d", sym->stack);
1758 emitcode ("subi", "r28,lo8(%d)", sym->stack);
1759 emitcode ("sbci", "r29,hi8(%d)", sym->stack);
1761 emitcode ("out", "__SP_L__,r28");
1762 emitcode ("out", "__SP_H__,r29");
1766 /*-----------------------------------------------------------------*/
1767 /* genEndFunction - generates epilogue for functions */
1768 /*-----------------------------------------------------------------*/
1770 genEndFunction (iCode * ic)
1772 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
1775 /* restore stack pointer */
1777 if (sym->stack <= 63) {
1778 emitcode ("adiw", "r28,%d", sym->stack);
1781 emitcode ("subi", "r28,lo8(-%d)", sym->stack);
1782 emitcode ("sbci", "r29,hi8(-%d)", sym->stack);
1784 emitcode ("out", "__SP_L__,r28");
1785 emitcode ("out", "__SP_H__,r29");
1787 /* pop frame pointer */
1788 emitcode ("pop", "r29");
1789 emitcode ("pop", "r28");
1791 /* restore preserved registers */
1792 if (bitVectBitValue (sym->regsUsed, R31_IDX)) {
1794 emitcode ("pop", "r31");
1796 if (bitVectBitValue (sym->regsUsed, R30_IDX)) {
1798 emitcode ("pop", "r30");
1800 if (bitVectBitValue (sym->regsUsed, R27_IDX)) {
1802 emitcode ("pop", "r27");
1804 if (bitVectBitValue (sym->regsUsed, R26_IDX)) {
1806 emitcode ("pop", "r26");
1808 for (i = R15_IDX; i >= R2_IDX; i--) {
1809 if (bitVectBitValue (sym->regsUsed, i)) {
1811 emitcode ("pop", "%s", avr_regWithIdx (i)->name);
1815 if (SPEC_CRTCL (sym->etype))
1816 emitcode ("sti", "");
1818 if (IS_ISR (sym->etype)) {
1819 emitcode ("rti", "");
1822 emitcode ("ret", "");
1827 /*-----------------------------------------------------------------*/
1828 /* genRet - generate code for return statement */
1829 /*-----------------------------------------------------------------*/
1833 int size, offset = 0;
1835 /* if we have no return value then
1836 just generate the "ret" */
1840 /* we have something to return then
1841 move the return value into place */
1842 aopOp (IC_LEFT (ic), ic, FALSE);
1843 size = AOP_SIZE (IC_LEFT (ic));
1846 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) {
1847 emitcode ("ldi", "%s,%s(%d)", fAVRReturn[offset],
1849 (int) floatFromVal (AOP (IC_LEFT (ic))->
1850 aopu.aop_lit), offset);
1854 l = aopGet (AOP (IC_LEFT (ic)), offset);
1855 if (strcmp (fAVRReturn[offset], l))
1856 emitcode ("mov", "%s,%s", fAVRReturn[offset],
1862 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1865 /* generate a jump to the return label
1866 if the next is not the return statement */
1867 if (!(ic->next && ic->next->op == LABEL &&
1868 IC_LABEL (ic->next) == returnLabel))
1870 emitcode ("rjmp", "L%05d", returnLabel->key);
1874 /*-----------------------------------------------------------------*/
1875 /* genLabel - generates a label */
1876 /*-----------------------------------------------------------------*/
1878 genLabel (iCode * ic)
1880 /* special case never generate */
1881 if (IC_LABEL (ic) == entryLabel)
1884 emitcode ("", "L%05d:", IC_LABEL (ic)->key);
1887 /*-----------------------------------------------------------------*/
1888 /* genGoto - generates a ljmp */
1889 /*-----------------------------------------------------------------*/
1891 genGoto (iCode * ic)
1893 emitcode ("rjmp", "L%05d", (IC_LABEL (ic)->key + 100));
1896 /*-----------------------------------------------------------------*/
1897 /* genPlusIncr :- does addition with increment if possible */
1898 /*-----------------------------------------------------------------*/
1900 genPlusIncr (iCode * ic)
1902 unsigned int icount;
1904 /* will try to generate an increment */
1905 /* if the right side is not a literal
1907 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
1911 (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.
1914 /* if the sizes are greater than 2 or they are not the same regs
1916 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1919 /* so we know LEFT & RESULT in the same registers and add
1921 /* for short & char types */
1922 if (AOP_SIZE (IC_RESULT (ic)) < 2) {
1924 emitcode ("inc", "%s",
1925 aopGet (AOP (IC_LEFT (ic)), 0));
1928 emitcode ("subi", "%s,lo8(%d)",
1929 aopGet (AOP (IC_LEFT (ic)), 0), 0-icount);
1933 if (AOP_SIZE (IC_RESULT (ic)) <= 3) {
1934 /* if register pair and starts with 26/30 then adiw */
1935 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0
1937 && (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX)
1938 || IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX))) {
1939 emitcode ("adiw", "%s,%d",
1940 aopGet (AOP (IC_RESULT (ic)), 0), icount);
1945 emitcode ("subi", "%s,lo8(%d)",
1946 aopGet (AOP (IC_RESULT (ic)), 0), 0-icount);
1947 emitcode ("sbci", "%s,hi8(%d)",
1948 aopGet (AOP (IC_RESULT (ic)), 1), 0-icount);
1952 /* for 32 bit longs */
1953 emitcode ("subi", "%s,lo8(%d)", aopGet (AOP (IC_RESULT (ic)), 0),
1955 emitcode ("sbci", "%s,hi8(%d)", aopGet (AOP (IC_RESULT (ic)), 1),
1957 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2),
1959 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3),
1965 /* This is the pure and virtuous version of this code.
1966 * I'm pretty certain it's right, but not enough to toss the old
1970 adjustArithmeticResult (iCode * ic)
1972 if (opIsGptr (IC_RESULT (ic)) &&
1973 opIsGptr (IC_LEFT (ic)) &&
1974 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)))) {
1975 aopPut (AOP (IC_RESULT (ic)),
1976 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1),
1980 if (opIsGptr (IC_RESULT (ic)) &&
1981 opIsGptr (IC_RIGHT (ic)) &&
1982 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)))) {
1983 aopPut (AOP (IC_RESULT (ic)),
1984 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1),
1988 if (opIsGptr (IC_RESULT (ic)) &&
1989 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
1990 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
1991 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
1992 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)))) {
1994 sprintf (buffer, "%d",
1995 pointerCode (getSpec (operandType (IC_LEFT (ic)))));
1996 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2000 /*-----------------------------------------------------------------*/
2001 /* genPlus - generates code for addition */
2002 /*-----------------------------------------------------------------*/
2004 genPlus (iCode * ic)
2006 int size, offset = 0;
2010 /* special cases :- */
2012 aopOp (IC_LEFT (ic), ic, FALSE);
2013 aopOp (IC_RIGHT (ic), ic, FALSE);
2014 aopOp (IC_RESULT (ic), ic, TRUE);
2016 /* if I can do an increment instead
2017 of add then GOOD for ME */
2018 if (genPlusIncr (ic) == TRUE)
2021 size = getDataSize (IC_RESULT (ic));
2022 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2026 aopPut (AOP (IC_RESULT (ic)),
2027 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2029 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
2036 emitcode (l, "%s,%s",
2037 aopGet (AOP (IC_RESULT (ic)), offset),
2038 aopGet (AOP (IC_RIGHT (ic)), offset));
2046 emitcode (l, "%s,%s(-%d)",
2047 aopGet (AOP (IC_RESULT (ic)), offset),
2049 (int) floatFromVal (AOP (IC_RIGHT (ic))->
2055 adjustArithmeticResult (ic);
2058 freeAsmop (IC_LEFT (ic), NULL, ic,
2059 (RESULTONSTACK (ic) ? FALSE : TRUE));
2060 freeAsmop (IC_RIGHT (ic), NULL, ic,
2061 (RESULTONSTACK (ic) ? FALSE : TRUE));
2062 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2065 /*-----------------------------------------------------------------*/
2066 /* genMinusDec :- does subtraction with deccrement if possible */
2067 /*-----------------------------------------------------------------*/
2069 genMinusDec (iCode * ic)
2071 unsigned int icount;
2073 /* will try to generate an increment */
2074 /* if the right side is not a literal
2076 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2080 (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.
2083 /* if the sizes are greater than 2 or they are not the same regs
2085 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic))))
2088 /* so we know LEFT & RESULT in the same registers and add
2090 /* for short & char types */
2091 if (AOP_SIZE (IC_RESULT (ic)) < 2) {
2093 emitcode ("dec", "%s",
2094 aopGet (AOP (IC_LEFT (ic)), 0));
2097 emitcode ("subi", "%s,lo8(%d)",
2098 aopGet (AOP (IC_LEFT (ic)), 0), icount);
2102 if (AOP_SIZE (IC_RESULT (ic)) <= 3) {
2103 /* if register pair and starts with 26/30 then adiw */
2104 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0
2106 && (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX)
2107 || IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX))) {
2108 emitcode ("sbiw", "%s,%d",
2109 aopGet (AOP (IC_RESULT (ic)), 0), icount);
2114 emitcode ("subi", "%s,lo8(%d)",
2115 aopGet (AOP (IC_RESULT (ic)), 0), icount);
2116 emitcode ("sbci", "%s,hi8(%d)",
2117 aopGet (AOP (IC_RESULT (ic)), 1), icount);
2120 /* for 32 bit longs */
2121 emitcode ("subi", "%s,lo8(%d)", aopGet (AOP (IC_RESULT (ic)), 0),
2123 emitcode ("sbci", "%s,hi8(%d)", aopGet (AOP (IC_RESULT (ic)), 1),
2125 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2),
2127 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3),
2133 /*-----------------------------------------------------------------*/
2134 /* genMinus - generates code for subtraction */
2135 /*-----------------------------------------------------------------*/
2137 genMinus (iCode * ic)
2139 int size, offset = 0, samer;
2142 aopOp (IC_LEFT (ic), ic, FALSE);
2143 aopOp (IC_RIGHT (ic), ic, FALSE);
2144 aopOp (IC_RESULT (ic), ic, TRUE);
2146 /* if I can do an decrement instead
2147 of subtract then GOOD for ME */
2148 if (genMinusDec (ic) == TRUE)
2151 size = getDataSize (IC_RESULT (ic));
2152 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2155 aopPut (AOP (IC_RESULT (ic)),
2156 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2158 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
2165 emitcode (l, "%s,%s",
2166 aopGet (AOP (IC_RESULT (ic)), offset),
2167 aopGet (AOP (IC_RIGHT (ic)), offset));
2175 emitcode (l, "%s,%s(%d)",
2176 aopGet (AOP (IC_RESULT (ic)), offset),
2178 (int) floatFromVal (AOP (IC_RIGHT (ic))->
2184 adjustArithmeticResult (ic);
2187 freeAsmop (IC_LEFT (ic), NULL, ic,
2188 (RESULTONSTACK (ic) ? FALSE : TRUE));
2189 freeAsmop (IC_RIGHT (ic), NULL, ic,
2190 (RESULTONSTACK (ic) ? FALSE : TRUE));
2191 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2194 /*-----------------------------------------------------------------*/
2195 /* genMultOneByte : 8 bit multiplication & division */
2196 /*-----------------------------------------------------------------*/
2198 genMultOneByte (operand * left, operand * right, operand * result)
2200 sym_link *opetype = operandType (result);
2204 /* (if two literals, the value is computed before) */
2205 /* if one literal, literal on the right */
2206 if (AOP_TYPE (left) == AOP_LIT) {
2212 size = AOP_SIZE (result);
2214 if (SPEC_USIGN (opetype)) {
2215 emitcode ("mul", "%s,%s", aopGet (AOP (left), 0),
2216 aopGet (AOP (right), 0));
2219 emitcode ("muls", "%s,%s", aopGet (AOP (left), 0),
2220 aopGet (AOP (right), 0));
2222 aopPut (AOP (result), "r0", 0);
2224 aopPut (AOP (result), "r1", 1);
2227 if (SPEC_USIGN (opetype)) {
2229 aopPut (AOP (result), zero, offset++);
2234 lbl = newiTempLabel (NULL);
2235 emitcode ("ldi", "r24,0");
2236 emitcode ("brcc", "L%05d", lbl->key);
2237 emitcode ("ldi", "r24,lo8(-1)");
2238 emitcode ("", "L%05d:", lbl->key);
2240 aopPut (AOP (result), "r24",
2248 /*-----------------------------------------------------------------*/
2249 /* genMult - generates code for multiplication */
2250 /*-----------------------------------------------------------------*/
2252 genMult (iCode * ic)
2254 operand *left = IC_LEFT (ic);
2255 operand *right = IC_RIGHT (ic);
2256 operand *result = IC_RESULT (ic);
2258 /* assign the amsops */
2259 aopOp (left, ic, FALSE);
2260 aopOp (right, ic, FALSE);
2261 aopOp (result, ic, TRUE);
2263 /* if both are of size == 1 */
2264 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1) {
2265 genMultOneByte (left, right, result);
2269 /* should have been converted to function call */
2273 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2274 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2275 freeAsmop (result, NULL, ic, TRUE);
2278 /*-----------------------------------------------------------------*/
2279 /* genDiv - generates code for division */
2280 /*-----------------------------------------------------------------*/
2284 /* should have been converted to function call */
2288 /*-----------------------------------------------------------------*/
2289 /* genMod - generates code for division */
2290 /*-----------------------------------------------------------------*/
2294 /* should have been converted to function call */
2306 /*-----------------------------------------------------------------*/
2307 /* revavrcnd - reverse a conditional for avr */
2308 /*-----------------------------------------------------------------*/
2310 revavrcnd (int type)
2322 for (i = 0; i < (sizeof (rar) / sizeof (rar[0])); i++) {
2323 if (rar[i].type == type)
2324 return rar[i].rtype;
2325 if (rar[i].rtype == type)
2328 assert (1); /* cannot happen */
2329 return 0; /* makes the compiler happy */
2332 static char *br_name[4] = { "breq", "brne", "brlt", "brge" };
2333 static char *br_uname[4] = { "breq", "brne", "brlo", "brcc" };
2335 /*-----------------------------------------------------------------*/
2336 /* genBranch - generate the branch instruction */
2337 /*-----------------------------------------------------------------*/
2339 genBranch (iCode * ifx, int br_type, int sign)
2341 int tj = (IC_TRUE (ifx) ? 1 : 0);
2343 if (tj) { /* if true jump */
2344 char *nm = (sign ? br_name[br_type] : br_uname[br_type]);
2345 emitcode (nm, "L%05d", IC_TRUE (ifx)->key);
2347 else { /* if false jump */
2348 int rtype = revavrcnd (br_type);
2349 char *nm = (sign ? br_name[rtype] : br_uname[rtype]);
2350 emitcode (nm, "L%05d", IC_FALSE (ifx)->key);
2355 /*-----------------------------------------------------------------*/
2356 /* genCmp - compare & jump */
2357 /*-----------------------------------------------------------------*/
2359 genCmp (iCode * ic, iCode * ifx, int br_type)
2361 operand *left, *right, *result;
2362 sym_link *letype, *retype;
2364 int sign, size, offset = 0;
2366 left = IC_LEFT (ic);
2367 right = IC_RIGHT (ic);
2368 result = IC_RESULT (ic);
2370 letype = getSpec (operandType (left));
2371 retype = getSpec (operandType (right));
2372 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
2374 /* assign the amsops */
2375 aopOp (left, ic, FALSE);
2376 aopOp (right, ic, FALSE);
2377 aopOp (result, ic, TRUE);
2378 size = AOP_SIZE (left);
2382 if (AOP_TYPE (right) == AOP_LIT) {
2383 emitcode ("cpi", "%s,lo8(%d)",
2384 aopGet (AOP (left), 0),
2386 floatFromVal (AOP (IC_RIGHT (ic))->
2388 genBranch (ifx, br_type, sign);
2390 else { /* right != literal */
2391 emitcode ("cp", "%s,%s",
2392 aopGet (AOP (left), 0),
2393 aopGet (AOP (right), 0));
2394 genBranch (ifx, br_type, sign);
2397 else { /* size != 1 */
2400 emitcode ("cp", "%s,%s",
2401 aopGet (AOP (left), 0),
2402 aopGet (AOP (right), 0));
2404 emitcode ("cpc", "%s,%s",
2405 aopGet (AOP (left), offset),
2406 aopGet (AOP (right),
2410 genBranch (ifx, br_type, sign);
2414 emitcode ("clr", "r0");
2417 emitcode ("cp", "%s,%s",
2418 aopGet (AOP (left), 0),
2419 aopGet (AOP (right), 0));
2421 emitcode ("cpc", "%s,%s",
2422 aopGet (AOP (left), offset),
2423 aopGet (AOP (right), offset));
2426 lbl = newiTempLabel (NULL);
2427 br_type = revavrcnd (br_type);
2429 emitcode (br_uname[br_type], "L%05d", lbl->key);
2431 emitcode (br_name[br_type], "L%05d", lbl->key);
2432 emitcode ("inc", "r0");
2433 emitcode ("", "L%05d:", lbl->key);
2434 aopPut (AOP (result), "r0", 0);
2435 size = AOP_SIZE (result) - 1;
2438 aopPut (AOP (result), zero, offset++);
2441 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2442 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2443 freeAsmop (result, NULL, ic, TRUE);
2446 /*-----------------------------------------------------------------*/
2447 /* genCmpGt :- greater than comparison */
2448 /*-----------------------------------------------------------------*/
2450 genCmpGt (iCode * ic, iCode * ifx)
2452 /* should have transformed by the parser */
2456 /*-----------------------------------------------------------------*/
2457 /* genCmpLt - less than comparisons */
2458 /*-----------------------------------------------------------------*/
2460 genCmpLt (iCode * ic, iCode * ifx)
2462 genCmp (ic, ifx, AVR_LT);
2465 /*-----------------------------------------------------------------*/
2466 /* genCmpEq - generates code for equal to */
2467 /*-----------------------------------------------------------------*/
2469 genCmpEq (iCode * ic, iCode * ifx)
2471 genCmp (ic, ifx, AVR_EQ);
2474 /*-----------------------------------------------------------------*/
2475 /* genCmpNe - generates code for not equal to */
2476 /*-----------------------------------------------------------------*/
2478 genCmpNe (iCode * ic, iCode * ifx)
2480 genCmp (ic, ifx, AVR_NE);
2483 /*-----------------------------------------------------------------*/
2484 /* genCmpGe - generates code for greater than equal to */
2485 /*-----------------------------------------------------------------*/
2487 genCmpGe (iCode * ic, iCode * ifx)
2489 genCmp (ic, ifx, AVR_GE);
2492 /*-----------------------------------------------------------------*/
2493 /* genCmpLe - generates code for less than equal to */
2494 /*-----------------------------------------------------------------*/
2496 genCmpLe (iCode * ic, iCode * ifx)
2498 operand *left = IC_LEFT (ic);
2499 operand *right = IC_RIGHT (ic);
2501 IC_RIGHT (ic) = left;
2502 IC_LEFT (ic) = right;
2503 genCmp (ic, ifx, AVR_GE);
2506 /*-----------------------------------------------------------------*/
2507 /* ifxForOp - returns the icode containing the ifx for operand */
2508 /*-----------------------------------------------------------------*/
2510 ifxForOp (operand * op, iCode * ic)
2512 /* if true symbol then needs to be assigned */
2513 if (IS_TRUE_SYMOP (op))
2516 /* if this has register type condition and
2517 the next instruction is ifx with the same operand
2518 and live to of the operand is upto the ifx only then */
2520 ic->next->op == IFX &&
2521 IC_COND (ic->next)->key == op->key &&
2522 OP_SYMBOL (op)->liveTo <= ic->next->seq) return ic->next;
2527 /*-----------------------------------------------------------------*/
2528 /* genAndOp - for && operation */
2529 /*-----------------------------------------------------------------*/
2531 genAndOp (iCode * ic)
2533 operand *left, *right, *result;
2537 /* note here that && operations that are in an
2538 if statement are taken away by backPatchLabels
2539 only those used in arthmetic operations remain */
2540 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2541 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2542 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
2544 tlbl = newiTempLabel (NULL);
2545 toBoolean (left, "r0", TRUE);
2546 toBoolean (right, "r1", TRUE);
2547 emitcode ("and", "r0,r1");
2548 emitcode ("ldi", "r24,1");
2549 emitcode ("breq", "L%05d", tlbl->key);
2550 emitcode ("dec", "r24");
2551 emitcode ("", "L%05d:", tlbl->key);
2552 aopPut (AOP (result), "r24", 0);
2553 size = AOP_SIZE (result) - 1;
2556 aopPut (AOP (result), zero, offset++);
2558 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2559 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2560 freeAsmop (result, NULL, ic, TRUE);
2564 /*-----------------------------------------------------------------*/
2565 /* genOrOp - for || operation */
2566 /*-----------------------------------------------------------------*/
2568 genOrOp (iCode * ic)
2570 operand *left, *right, *result;
2574 /* note here that || operations that are in an
2575 if statement are taken away by backPatchLabels
2576 only those used in arthmetic operations remain */
2577 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2578 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2579 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
2581 tlbl = newiTempLabel (NULL);
2582 toBoolean (left, "r0", TRUE);
2583 toBoolean (right, "r0", FALSE);
2584 emitcode ("ldi", "r24,1");
2585 emitcode ("breq", "L%05d", tlbl->key);
2586 emitcode ("dec", "r24");
2587 emitcode ("", "L%05d:", tlbl->key);
2588 aopPut (AOP (result), "r24", 0);
2589 size = AOP_SIZE (result) - 1;
2592 aopPut (AOP (result), zero, offset++);
2594 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2595 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2596 freeAsmop (result, NULL, ic, TRUE);
2600 AVR_AND = 0, AVR_OR, AVR_XOR
2602 static char *bopnames_lit[] = { "andi", "ori" };
2603 static char *bopnames[] = { "and", "or", "eor" };
2604 /*-----------------------------------------------------------------*/
2605 /* genBitWise - generate bitwise operations */
2606 /*-----------------------------------------------------------------*/
2608 genBitWise (iCode * ic, iCode * ifx, int bitop)
2610 operand *left, *right, *result;
2611 int size, offset = 0;
2616 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2617 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2618 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
2620 size = AOP_SIZE (left);
2622 if (ifx) { /* used only for jumps */
2623 if (AOP_TYPE (right) == AOP_LIT &&
2624 (bitop == AVR_AND || bitop == AVR_OR)) {
2626 (int) floatFromVal (AOP (right)->aopu.
2628 int p2 = powof2 (lit);
2629 if (bitop == AVR_AND && p2) { /* right side is a power of 2 */
2630 l = aopGet (AOP (left), p2 / 8);
2631 if (IC_TRUE (ifx)) {
2632 emitcode ("sbrc", "%s,%d", l,
2634 emitcode ("rjmp", "L%05d",
2635 IC_TRUE (ifx)->key);
2638 emitcode ("sbrs", "%s,%d", l,
2640 emitcode ("rjmp", "L%05d",
2641 IC_FALSE (ifx)->key);
2644 else { /* right not power of two */
2645 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2647 if (eh && AOP_ISHIGHREG(AOP(IC_LEFT(ic)),0)) {
2648 emitcode (bopnames_lit[bitop],
2650 aopGet (AOP (IC_LEFT (ic)), 0), lit);
2653 MOVR24 (aopGet (AOP (IC_LEFT (ic)), 0));
2654 emitcode (bopnames_lit[bitop], "r24,lo8(%d)", lit);
2656 lbl = newiTempLabel (NULL);
2657 if (IC_TRUE (ifx)) {
2658 emitcode ("breq", "L%05d", lbl->key);
2659 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2662 emitcode ("brne", "L%05d", lbl->key);
2663 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)-> key);
2665 emitcode ("", "L%05d:", lbl->key);
2667 else if (size == 2) {
2668 emitcode ("mov", "r24,%s", aopGet (AOP (IC_LEFT (ic)), 0));
2669 emitcode ("mov", "r25,%s", aopGet (AOP (IC_LEFT (ic)), 1));
2670 emitcode (bopnames_lit[bitop], "r24,lo8(%d)", lit);
2671 emitcode (bopnames_lit[bitop], "r25,hi8(%d)", lit);
2672 emitcode ("sbiw", "r24,0");
2673 lbl = newiTempLabel (NULL);
2674 if (IC_TRUE (ifx)) {
2675 emitcode ("breq", "L%05d", lbl->key);
2676 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2679 emitcode ("brne", "L%05d", lbl->key);
2680 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2682 emitcode ("", "L%05d:", lbl->key);
2685 lbl = newiTempLabel (NULL);
2686 lbl1 = newiTempLabel (NULL);
2688 if (eh && AOP_ISHIGHREG(AOP(IC_LEFT(ic)),offset)) {
2689 emitcode (bopnames_lit [bitop], "%s,lo8(%d)",
2690 aopGet (AOP (IC_LEFT (ic)), offset),
2694 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
2696 emitcode ("andi", "r24,lo8(%d)", lit);
2698 emitcode ("brne", "L%05d", lbl->key);
2703 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)-> key);
2705 emitcode ("rjmp", "L%05d", lbl1->key);
2706 emitcode ("", "L%05d:", lbl->key);
2709 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2710 emitcode ("", "L%05d:", lbl1->key);
2715 else { /* right is not a literal */
2716 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2717 int reh = OP_SYMBOL (right)->liveTo <= ic->seq;
2720 emitcode (bopnames[bitop], "%s,%s", aopGet (AOP (IC_LEFT (ic)), 0),
2721 aopGet (AOP (IC_RIGHT (ic)), 0));
2724 emitcode (bopnames[bitop], "%s,%s",
2725 aopGet (AOP (IC_RIGHT (ic)), 0),
2726 aopGet (AOP (IC_LEFT (ic)), 0));
2729 MOVR0 (aopGet (AOP (IC_LEFT (ic)), 0));
2730 emitcode (bopnames[bitop], "r0,%s",
2731 aopGet (AOP (IC_RIGHT (ic)), 0));
2733 lbl = newiTempLabel (NULL);
2734 if (IC_TRUE (ifx)) {
2735 emitcode ("breq", "L%05d", lbl->key);
2736 emitcode ("rjmp", "L%05d",
2737 IC_TRUE (ifx)->key);
2740 emitcode ("brne", "L%05d", lbl->key);
2741 emitcode ("rjmp", "L%05d",
2742 IC_FALSE (ifx)->key);
2744 emitcode ("", "L%05d:", lbl->key);
2746 else if (size == 2) {
2747 emitcode ("mov", "r24,%s",
2748 aopGet (AOP (IC_LEFT (ic)), 0));
2749 emitcode ("mov", "r25,%s",
2750 aopGet (AOP (IC_LEFT (ic)), 1));
2751 emitcode (bopnames[bitop], "r24,%s",
2752 aopGet (AOP (IC_RIGHT (ic)), 0));
2753 emitcode (bopnames[bitop], "r25,%s",
2754 aopGet (AOP (IC_RIGHT (ic)), 1));
2755 emitcode ("sbiw", "r24,0");
2756 lbl = newiTempLabel (NULL);
2757 if (IC_TRUE (ifx)) {
2758 emitcode ("breq", "L%05d", lbl->key);
2759 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2762 emitcode ("brne", "L%05d", lbl->key);
2763 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2765 emitcode ("", "L%05d:", lbl->key);
2768 lbl = newiTempLabel (NULL);
2769 lbl1 = newiTempLabel (NULL);
2772 emitcode (bopnames[bitop], "%s,%s",
2773 aopGet (AOP (IC_LEFT (ic)), offset),
2774 aopGet (AOP (IC_RIGHT (ic)), offset));
2777 emitcode (bopnames[bitop], "%s,%s",
2778 aopGet (AOP (IC_RIGHT (ic)), offset),
2779 aopGet (AOP (IC_LEFT (ic)), offset));
2782 MOVR0 (aopGet (AOP (IC_LEFT (ic)), offset));
2783 emitcode (bopnames[bitop], "r0,%s",
2784 aopGet (AOP (IC_RIGHT (ic)), offset));
2786 emitcode ("brne", "L%05d", lbl->key);
2791 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2793 emitcode ("rjmp", "L%05d", lbl1->key);
2794 emitcode ("", "L%05d:", lbl->key);
2797 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2798 emitcode ("", "L%05d:", lbl1->key);
2805 /* result needs to go a register */
2806 samerl = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2807 samerr = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)));
2809 if (AOP_TYPE (right) == AOP_LIT) {
2811 (int) floatFromVal (AOP (right)->aopu.
2813 if (((lit >> (8 * offset)) & 0xff) == 0) {
2814 if (bitop == AVR_AND) {
2815 aopPut (AOP (result), zero, offset++);
2818 else if (bitop == AVR_OR) {
2820 aopPut (AOP (result),
2830 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT &&
2831 AOP_ISHIGHREG(AOP(IC_LEFT(ic)),offset) &&
2832 (bitop == AVR_AND || bitop == AVR_OR)) {
2833 emitcode (bopnames_lit[bitop], "%s,%s(%d)",
2834 aopGet (AOP (IC_LEFT (ic)), offset),
2836 (int) floatFromVal (AOP (right)-> aopu.aop_lit));
2839 emitcode (bopnames[bitop], "%s,%s",
2840 aopGet (AOP (IC_LEFT (ic)), offset),
2841 aopGet (AOP (IC_RIGHT (ic)), offset));
2845 emitcode (bopnames[bitop], "%s,%s",
2846 aopGet (AOP (IC_RIGHT (ic)), offset),
2847 aopGet (AOP (IC_LEFT (ic)), offset));
2850 aopPut (AOP (IC_RESULT (ic)),
2851 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2852 emitcode (bopnames[bitop],
2853 aopGet (AOP (IC_RESULT (ic)), offset),
2854 aopGet (AOP (IC_RIGHT (ic)), offset));
2859 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2860 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2861 freeAsmop (result, NULL, ic, TRUE);
2864 /*-----------------------------------------------------------------*/
2865 /* genAnd - code for and */
2866 /*-----------------------------------------------------------------*/
2868 genAnd (iCode * ic, iCode * ifx)
2870 genBitWise (ic, ifx, AVR_AND);
2873 /*-----------------------------------------------------------------*/
2874 /* genOr - code for or */
2875 /*-----------------------------------------------------------------*/
2877 genOr (iCode * ic, iCode * ifx)
2879 genBitWise (ic, ifx, AVR_OR);
2882 /*-----------------------------------------------------------------*/
2883 /* genXor - code for xclusive or */
2884 /*-----------------------------------------------------------------*/
2886 genXor (iCode * ic, iCode * ifx)
2888 genBitWise (ic, ifx, AVR_XOR);
2891 /*-----------------------------------------------------------------*/
2892 /* genInline - write the inline code out */
2893 /*-----------------------------------------------------------------*/
2895 genInline (iCode * ic)
2897 char *buffer, *bp, *bp1;
2899 _G.inLine += (!options.asmpeep);
2901 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
2902 strcpy (buffer, IC_INLINE (ic));
2904 /* emit each line as a code */
2925 /* emitcode("",buffer); */
2926 _G.inLine -= (!options.asmpeep);
2929 /*-----------------------------------------------------------------*/
2930 /* genRotC - rotate right/left with carry , lr = 1 rotate right */
2931 /*-----------------------------------------------------------------*/
2933 genRotC (iCode * ic, int lr)
2935 operand *left, *result;
2936 int size, offset = 0;
2938 /* rotate right with carry */
2939 left = IC_LEFT (ic);
2940 result = IC_RESULT (ic);
2941 aopOp (left, ic, FALSE);
2942 aopOp (result, ic, FALSE);
2944 /* move it to the result */
2945 size = AOP_SIZE (result);
2946 if (!sameRegs (AOP (left), AOP (result))) {
2949 aopPut (AOP (result),
2950 aopGet (AOP (left), offset), offset);
2953 size = AOP_SIZE (result);
2961 emitcode ("sbrc", "%s,%d", aopGet (AOP (result), offset),
2963 emitcode ("sec", "");
2966 emitcode ((lr ? "ror" : "rol"), "%s",
2967 aopGet (AOP (result), offset));
2973 freeAsmop (left, NULL, ic, TRUE);
2974 freeAsmop (result, NULL, ic, TRUE);
2977 /*-----------------------------------------------------------------*/
2978 /* genRRC - rotate right with carry */
2979 /*-----------------------------------------------------------------*/
2986 /*-----------------------------------------------------------------*/
2987 /* genRLC - generate code for rotate left with carry */
2988 /*-----------------------------------------------------------------*/
2995 /*-----------------------------------------------------------------*/
2996 /* genGetHbit - generates code get highest order bit */
2997 /*-----------------------------------------------------------------*/
2999 genGetHbit (iCode * ic)
3001 operand *left, *result;
3004 left = IC_LEFT (ic);
3005 result = IC_RESULT (ic);
3006 aopOp (left, ic, FALSE);
3007 aopOp (result, ic, FALSE);
3009 size = AOP_SIZE (result);
3010 if (!sameRegs (AOP (left), AOP (result))) {
3011 emitcode ("clr", "%s", aopGet (AOP (result), size - 1));
3012 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3013 emitcode ("subi", "%s,lo8(-1)",
3014 aopGet (AOP (result), size - 1));
3017 emitcode ("clr", "r0");
3018 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3019 emitcode ("subi", "r0,lo8(-1)");
3020 aopPut (AOP (result), "r0", 0);
3025 emitcode ("clr", aopGet (AOP (result), offset++));
3027 freeAsmop (left, NULL, ic, TRUE);
3028 freeAsmop (result, NULL, ic, TRUE);
3031 /*-----------------------------------------------------------------*/
3032 /* genShiftLeftLit - shift left by a known amount */
3033 /*-----------------------------------------------------------------*/
3035 genShiftLeftLit (iCode * ic)
3037 operand *left, *right, *result;
3038 int size, shCount, offset = 0;
3041 right = IC_RIGHT (ic);
3042 left = IC_LEFT (ic);
3043 result = IC_RESULT (ic);
3045 aopOp (left, ic, FALSE);
3046 aopOp (result, ic, FALSE);
3047 size = AOP_SIZE (result);
3048 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3050 if (shCount > (size * 8 - 1)) {
3052 aopPut (AOP (result), zero, offset++);
3057 if (!sameRegs (AOP (left), AOP (result)))
3058 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3060 if (AOP_ISHIGHREG(AOP(result),0)) {
3061 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3062 emitcode ("andi", "%s,0xf0");
3064 emitcode ("ldi","r24,0xf0");
3065 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3066 emitcode ("and", "%s,r24");
3071 emitcode ("add", "%s,%s", aopGet (AOP (result), 0),
3072 aopGet (AOP (result), 0));
3076 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3079 if (shCount >= 12) {
3080 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3081 aopPut (AOP (result), zero, 0);
3082 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3083 if (AOP_ISHIGHREG(AOP(result),1)) {
3084 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3086 emitcode ("ldi","r24,0xf0");
3087 emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
3093 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3094 aopPut (AOP (result), zero, 0);
3100 if (!sameRegs (AOP (left), AOP (result))) {
3101 aopPut (AOP (result), aopGet (AOP (left), 0),
3103 aopPut (AOP (result), aopGet (AOP (left), 1),
3106 emitcode ("mov", "r24,%s", aopGet (AOP (result), 0));
3107 emitcode ("andi", "r24,0x0f");
3108 if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
3109 emitcode("ldi","r25,0xf0");
3111 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3112 if (AOP_ISHIGHREG(AOP(result),0)) {
3113 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 0));
3115 emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
3117 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3118 if (AOP_ISHIGHREG(AOP(result),1)) {
3119 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3121 emitcode ("and", "%s,r25", aopGet (AOP (result), 1));
3123 emitcode ("or", "%s,r24", aopGet (AOP (result), 1));
3125 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3126 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3129 if (!lByteZ && !sameRegs (AOP (result), AOP (left))
3133 aopPut (AOP (result),
3134 aopGet (AOP (left), offset), offset);
3140 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3143 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3144 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3149 assert ("shifting generic pointer ?\n");
3152 /* 32 bits we do only byte boundaries */
3153 if (shCount >= 24) {
3154 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3155 aopPut (AOP (result), zero, 2);
3156 aopPut (AOP (result), zero, 1);
3157 aopPut (AOP (result), zero, 0);
3161 if (shCount >= 16) {
3162 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3163 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3164 aopPut (AOP (result), zero, 1);
3165 aopPut (AOP (result), zero, 0);
3170 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3171 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3172 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3173 aopPut (AOP (result), zero, 0);
3177 if (!lByteZ && !sameRegs (AOP (left), AOP (right))) {
3180 aopPut (AOP (result),
3181 aopGet (AOP (left), offset), offset);
3185 size = AOP_SIZE (result);
3191 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3192 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3193 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3194 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3199 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3200 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3201 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3206 emitcode ("lsl", "%s", aopGet (AOP (result), 2));
3207 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3212 emitcode ("lsl", "%s", aopGet (AOP (result), 3));
3220 freeAsmop (left, NULL, ic, TRUE);
3221 freeAsmop (right, NULL, ic, TRUE);
3222 freeAsmop (result, NULL, ic, TRUE);
3225 /*-----------------------------------------------------------------*/
3226 /* genLeftShift - generates code for left shifting */
3227 /*-----------------------------------------------------------------*/
3229 genLeftShift (iCode * ic)
3231 operand *left, *right, *result;
3235 right = IC_RIGHT (ic);
3236 left = IC_LEFT (ic);
3237 result = IC_RESULT (ic);
3239 aopOp (right, ic, FALSE);
3241 if (AOP_TYPE (right) == AOP_LIT) {
3242 genShiftLeftLit (ic);
3247 aopOp (left, ic, FALSE);
3248 aopOp (result, ic, FALSE);
3249 size = AOP_SIZE (result);
3251 if (AOP_SIZE (right) > 1) {
3252 if (isRegPair (AOP (right))) {
3253 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3256 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3257 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3261 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3263 if (!sameRegs (AOP (left), AOP (result))) {
3265 aopPut (AOP (result), aopGet (AOP (left), offset),
3269 size = AOP_SIZE (result);
3271 tlbl = newiTempLabel (NULL);
3272 emitcode ("", "L%05d:", tlbl->key);
3276 emitcode ("rol", "%s", aopGet (AOP (result), offset));
3278 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3281 if (AOP_SIZE (right) > 1)
3282 emitcode ("sbiw", "r24,1");
3284 emitcode ("dec", "r24");
3285 emitcode ("brne", "L%05d", tlbl->key);
3287 freeAsmop (left, NULL, ic, TRUE);
3288 freeAsmop (right, NULL, ic, TRUE);
3289 freeAsmop (result, NULL, ic, TRUE);
3292 /*-----------------------------------------------------------------*/
3293 /* genShiftRightLit - generate for right shift with known count */
3294 /*-----------------------------------------------------------------*/
3296 genShiftRightLit (iCode * ic)
3298 operand *left = IC_LEFT (ic)
3299 , *right = IC_RIGHT (ic)
3300 , *result = IC_RESULT (ic);
3301 int size, shCount, offset = 0;
3303 sym_link *letype = getSpec (operandType (left));
3304 int sign = !SPEC_USIGN (letype);
3306 right = IC_RIGHT (ic);
3307 left = IC_LEFT (ic);
3308 result = IC_RESULT (ic);
3310 aopOp (left, ic, FALSE);
3311 aopOp (result, ic, FALSE);
3312 size = AOP_SIZE (result);
3313 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3315 /* if signed then give up and use a loop to shift */
3318 if (!sameRegs (AOP (left), AOP (result))) {
3320 aopPut (AOP (result),
3321 aopGet (AOP (left), offset), offset);
3324 size = size = AOP_SIZE (result);
3327 /* be as economical as possible */
3332 size = AOP_SIZE (result);
3334 if (offset == (size - 1))
3335 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3337 emitcode ("lsr", "%s", aopGet (AOP (result), offset));
3343 emitcode ("ldi", "r24,lo8(%d)", shCount);
3344 tlbl = newiTempLabel (NULL);
3345 emitcode ("", "L%05d:", tlbl->key);
3348 if (offset == (size - 1))
3349 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3351 emitcode ("lsr", "%s", aopGet (AOP (result), offset));
3354 emitcode ("dec", "r24");
3355 emitcode ("brne", "L%05d", tlbl->key);
3359 if (shCount > (size * 8 - 1)) {
3361 aopPut (AOP (result), zero, offset++);
3364 /* for unsigned we can much more efficient */
3367 if (!sameRegs (AOP (left), AOP (result)))
3368 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3370 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3371 if (AOP_ISHIGHREG(AOP(result),0)) {
3372 emitcode ("andi", "%s,0x0f",aopGet(AOP(result),0));
3374 emitcode ("ldi","r24,0x0f");
3375 emitcode ("and", "%s,r24",aopGet(AOP(result),0));
3380 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3383 if (shCount >= 12) {
3384 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3385 aopPut (AOP (result), zero, 1);
3386 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3387 if (AOP_ISHIGHREG(AOP(result),0)) {
3388 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3390 emitcode ("ldi","r24,0x0f");
3391 emitcode ("and", "%s,r24",aopGet(AOP(result),0));
3397 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3398 aopPut (AOP (result), zero, 1);
3404 if (!sameRegs (AOP (left), AOP (result))) {
3405 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3406 aopPut (AOP (result), aopGet (AOP (left), 1), 1);
3408 if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
3409 emitcode("ldi","r25,0x0f");
3411 emitcode ("mov", "r24,%s", aopGet (AOP (result), 1));
3412 emitcode ("andi", "r24,0xf0");
3413 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3414 if (AOP_ISHIGHREG(AOP(result),0)) {
3415 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3417 emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
3419 emitcode ("or", "%s,r24", aopGet (AOP (result), 0));
3420 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3421 if (AOP_ISHIGHREG(AOP(result),1)) {
3422 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 1));
3424 emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
3427 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3428 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3432 if (!hByteZ && !sameRegs (AOP (result), AOP (left))
3436 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3442 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3445 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3446 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3452 assert ("shifting generic pointer ?\n");
3455 /* 32 bits we do only byte boundaries */
3456 if (shCount >= 24) {
3457 aopPut (AOP (result), aopGet (AOP (left), 3), 0);
3458 aopPut (AOP (result), zero, 1);
3459 aopPut (AOP (result), zero, 2);
3460 aopPut (AOP (result), zero, 3);
3464 if (shCount >= 16) {
3465 aopPut (AOP (result), aopGet (AOP (left), 3), 1);
3466 aopPut (AOP (result), aopGet (AOP (left), 2), 0);
3467 aopPut (AOP (result), zero, 2);
3468 aopPut (AOP (result), zero, 3);
3473 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3474 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3475 aopPut (AOP (result), aopGet (AOP (left), 3), 2);
3476 aopPut (AOP (result), zero, 3);
3480 if (!hByteZ && !sameRegs (AOP (left), AOP (right))) {
3483 aopPut (AOP (result),
3484 aopGet (AOP (left), offset), offset);
3488 size = AOP_SIZE (result);
3494 emitcode ("lsr", "%s", aopGet (AOP (result), 3));
3495 emitcode ("ror", "%s", aopGet (AOP (result), 2));
3496 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3497 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3502 emitcode ("lsr", "%s", aopGet (AOP (result), 2));
3503 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3504 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3509 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3510 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3515 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3522 freeAsmop (left, NULL, ic, TRUE);
3523 freeAsmop (right, NULL, ic, TRUE);
3524 freeAsmop (result, NULL, ic, TRUE);
3527 /*-----------------------------------------------------------------*/
3528 /* genRightShift - generate code for right shifting */
3529 /*-----------------------------------------------------------------*/
3531 genRightShift (iCode * ic)
3533 operand *right, *left, *result;
3536 int sign = 0, first = 1;
3539 aopOp (right = IC_RIGHT (ic), ic, FALSE);
3541 if (AOP_TYPE (right) == AOP_LIT) {
3542 genShiftRightLit (ic);
3546 if (AOP_SIZE (right) > 1) {
3547 if (isRegPair (AOP (right))) {
3548 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3551 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3552 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3556 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3558 aopOp (left = IC_LEFT (ic), ic, FALSE);
3559 aopOp (result = IC_RESULT (ic), ic, FALSE);
3560 size = AOP_SIZE (result);
3561 tlbl = newiTempLabel (NULL);
3562 emitcode ("", "L%05d:", tlbl->key);
3564 letype = getSpec (operandType (left));
3565 sign = !SPEC_USIGN (letype);
3566 if (!sameRegs (AOP (left), AOP (result))) {
3568 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3571 size = AOP_SIZE (result);
3573 size = AOP_SIZE (result);
3577 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3579 emitcode ("lsr", "%s", aopGet (AOP (result), offset));
3583 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3586 if (AOP_SIZE (right) > 1)
3587 emitcode ("sbiw", "r24,1");
3589 emitcode ("dec", "r24");
3590 emitcode ("brne", "L%05d", tlbl->key);
3592 freeAsmop (left, NULL, ic, TRUE);
3593 freeAsmop (result, NULL, ic, TRUE);
3596 /*-----------------------------------------------------------------*/
3597 /* RRsh - shift right rn by known count */
3598 /*-----------------------------------------------------------------*/
3600 RRsh (int shCount,int reg)
3602 shCount &= 0x0007; // shCount : 0..7
3608 emitcode ("lsr", "r%d",reg);
3611 emitcode ("lsr", "r%d",reg);
3612 emitcode ("lsr", "r%d",reg);
3615 emitcode ("swap", "r%d",reg);
3616 emitcode ("lsl", "r%d",reg);
3619 emitcode ("swap", "r%d",reg);
3622 emitcode ("swap", "r%d",reg);
3623 emitcode ("lsr", "r%d",reg);
3626 emitcode ("swap","r%d",reg);
3627 emitcode ("lsr", "r%d",reg);
3628 emitcode ("lsr", "r%d",reg);
3631 emitcode ("swap","r%d",reg);
3632 emitcode ("lsr", "r%d",reg);
3633 emitcode ("lsr", "r%d",reg);
3634 emitcode ("lsr", "r%d",reg);
3639 /*-----------------------------------------------------------------*/
3640 /* RLsh - shift left rn by known count */
3641 /*-----------------------------------------------------------------*/
3643 RLsh (int shCount, int reg)
3645 shCount &= 0x0007; // shCount : 0..7
3651 emitcode ("lsl", "r%d",reg);
3654 emitcode ("lsl", "r%d",reg);
3655 emitcode ("lsl", "r%d",reg);
3658 emitcode ("swap","r%d",reg);
3659 emitcode ("lsr", "r%d",reg);
3662 emitcode ("swap", "r%d",reg);
3665 emitcode ("swap","r%d",reg);
3666 emitcode ("lsl", "r%d",reg);
3669 emitcode ("swap","r%d",reg);
3670 emitcode ("lsl", "r%d",reg);
3671 emitcode ("lsl", "r%d",reg);
3674 emitcode ("swap","r%d",reg);
3675 emitcode ("lsl", "r%d",reg);
3676 emitcode ("lsl", "r%d",reg);
3677 emitcode ("lsl", "r%d",reg);
3682 /*-----------------------------------------------------------------*/
3683 /* genUnpackBits - generates code for unpacking bits */
3684 /*-----------------------------------------------------------------*/
3686 genUnpackBits (operand * result, char *rname, int ptype)
3694 etype = getSpec (operandType (result));
3695 rsize = getSize (operandType (result));
3696 /* read the first byte */
3703 emitcode ("ld", "r24,%s+", rname);
3707 emitcode ("lpm", "r24,%s+", rname);
3711 emitcode ("call","__gptrget_pi");
3712 emitcode ("mov","r24,r0");
3716 rlen = SPEC_BLEN (etype);
3718 /* if we have bitdisplacement then it fits */
3719 /* into this byte completely or if length is */
3720 /* less than a byte */
3721 if ((shCnt = SPEC_BSTR (etype)) || (SPEC_BLEN (etype) <= 8)) {
3723 /* shift right acc */
3726 emitcode ("andi", "r24,lo(0x%x)",
3727 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
3728 aopPut (AOP (result), "r24", offset++);
3732 /* bit field did not fit in a byte */
3733 aopPut (AOP (result), "r24", offset++);
3743 emitcode ("ld", "r24,%s+");
3747 emitcode ("lpm", "r24,%s+");
3751 emitcode ("call", "__gptrget_pi");
3756 /* if we are done */
3760 aopPut (AOP (result), "r24", offset++);
3765 aopPut (AOP (result), "r24", offset++);
3769 if (offset < rsize) {
3772 aopPut (AOP (result), zero, offset++);
3777 /*-----------------------------------------------------------------*/
3778 /* genDataPointerGet - generates code when ptr offset is known */
3779 /*-----------------------------------------------------------------*/
3781 genDataPointerGet (operand * left, operand * result, iCode * ic)
3785 int size, offset = 0;
3786 aopOp (result, ic, TRUE);
3788 /* get the string representation of the name */
3789 l = aopGet (AOP (left), 0);
3790 size = AOP_SIZE (result);
3793 sprintf (buffer, "(%s + %d)", l, offset);
3795 sprintf (buffer, "%s", l);
3796 emitcode ("lds", "%s,%s", aopGet (AOP (result), offset++),
3800 freeAsmop (left, NULL, ic, TRUE);
3801 freeAsmop (result, NULL, ic, TRUE);
3804 /*-----------------------------------------------------------------*/
3805 /* genNearPointerGet - emitcode for near pointer fetch */
3806 /*-----------------------------------------------------------------*/
3808 genMemPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
3813 char *rname, *frname = NULL;
3814 sym_link *rtype, *retype;
3815 sym_link *ltype = operandType (left);
3817 rtype = operandType (result);
3818 retype = getSpec (rtype);
3820 aopOp (left, ic, FALSE);
3822 /* if left is rematerialisable and
3823 result is not bit variable type and
3824 the left is pointer to data space i.e
3825 lower 128 bytes of space */
3826 if (AOP_TYPE (left) == AOP_IMMD &&
3827 !IS_BITVAR (retype) && DCL_TYPE (ltype) == POINTER) {
3828 genDataPointerGet (left, result, ic);
3832 /* if the value is already in a pointer register
3833 then don't need anything more */
3834 if (!AOP_INPREG (AOP (left))) {
3835 /* otherwise get a free pointer register */
3837 preg = getFreePtr (ic, &aop, FALSE, 0);
3838 if (isRegPair (AOP (left) )) {
3839 emitcode ("movw", "%s,%s",
3840 aop->aopu.aop_ptr->name,
3841 aopGet(AOP(left),0));
3843 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
3844 aopGet (AOP (left), 0));
3845 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
3846 aopGet (AOP (left), 1));
3852 frname = aopGet(aop,0);
3856 } else if (AOP_ISZ(aop)) {
3859 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
3860 "pointer not in correct register");
3864 aopOp (result, ic, FALSE);
3866 /* if bitfield then unpack the bits */
3867 if (IS_BITVAR (retype))
3868 genUnpackBits (result, rname, POINTER);
3870 /* we have can just get the values */
3871 int size = AOP_SIZE (result);
3876 emitcode ("ld","%s,%s+",aopGet(AOP(result),offset), rname);
3878 emitcode ("ld","%s,%s",aopGet(AOP(result),offset), rname);
3883 /* now some housekeeping stuff */
3885 /* we had to allocate for this iCode */
3887 if (isRegPair (AOP (left) )) {
3888 emitcode ("movw", "%s,%s",
3889 aopGet (AOP(left),0),
3890 aop->aopu.aop_ptr->name);
3892 emitcode ("mov", "%s,%s",
3893 aopGet (AOP (left), 0),
3894 aop->aopu.aop_ptr->name);
3895 emitcode ("mov", "%s,%s",
3896 aopGet (AOP (left), 1),
3897 aop->aop_ptr2->name);
3900 freeAsmop (NULL, aop, ic, TRUE);
3903 /* we did not allocate which means left
3904 already in a pointer register, then
3905 if size > 0 && this could be used again
3906 we have to point it back to where it
3908 if ((AOP_SIZE (result) > 1 &&
3909 !OP_SYMBOL (left)->remat &&
3910 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) && !pi) {
3911 int size = AOP_SIZE (result) - 1;
3912 emitcode ("sbiw", "%s,%d",frname,size);
3917 if (pi) pi->generated = 1;
3918 freeAsmop (left, NULL, ic, TRUE);
3919 freeAsmop (result, NULL, ic, TRUE);
3923 /*-----------------------------------------------------------------*/
3924 /* genCodePointerGet - gget value from code space */
3925 /*-----------------------------------------------------------------*/
3927 genCodePointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
3930 sym_link *retype = getSpec (operandType (result));
3934 aopOp (left, ic, FALSE);
3936 /* if the operand is already in Z register
3937 then we do nothing else we move the value to Z register */
3938 if (AOP_ISZ(AOP(left))) {
3942 getFreePtr(ic,&aop,FALSE,TRUE);
3943 if (isRegPair(AOP (left))) {
3944 emitcode ("movw","r30,%s",aopGet (AOP (left), 0));
3946 emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
3947 emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
3952 aopOp (result, ic, FALSE);
3954 /* if bit then unpack */
3955 if (IS_BITVAR (retype))
3956 genUnpackBits (result, "Z", CPOINTER);
3958 size = AOP_SIZE (result);
3963 emitcode ("lpm","%s,Z+",aopGet(AOP(result),offset++));
3965 emitcode ("lpm","%s,Z",aopGet(AOP(result),offset++));
3970 /* now some housekeeping stuff */
3972 /* we had to allocate for this iCode */
3974 if (isRegPair(AOP (left))) {
3975 emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
3977 emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
3978 emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
3981 freeAsmop (NULL, aop, ic, TRUE);
3984 /* we did not allocate which means left
3985 already in a pointer register, then
3986 if size > 0 && this could be used again
3987 we have to point it back to where it
3989 if ((AOP_SIZE (result) > 1 &&
3990 !OP_SYMBOL (left)->remat &&
3991 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) &&
3993 int size = AOP_SIZE (result) - 1;
3994 emitcode ("sbiw", "r30,%d",size);
3999 if (pi) pi->generated=1;
4000 freeAsmop (left, NULL, ic, TRUE);
4001 freeAsmop (result, NULL, ic, TRUE);
4005 /*-----------------------------------------------------------------*/
4006 /* genGenPointerGet - gget value from generic pointer space */
4007 /*-----------------------------------------------------------------*/
4009 genGenPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
4013 sym_link *retype = getSpec (operandType (result));
4016 aopOp (left, ic, FALSE);
4018 /* if the operand is already in dptr
4019 then we do nothing else we move the value to dptr */
4020 if (AOP_ISZ(AOP(left))) {
4024 getFreePtr(ic,&aop,FALSE,TRUE);
4025 if (isRegPair(AOP(left))) {
4026 emitcode ("movw", "r30,%s", aopGet (AOP (left), 0));
4028 emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
4029 emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
4031 emitcode ("mov", "r24,%s", aopGet (AOP (left), 2));
4035 /* so Z register now contains the address */
4037 aopOp (result, ic, FALSE);
4039 /* if bit then unpack */
4040 if (IS_BITVAR (retype))
4041 genUnpackBits (result, "Z", GPOINTER);
4043 size = AOP_SIZE (result);
4048 emitcode ("call", "__gptrget_pi");
4050 emitcode ("call", "__gptrget");
4051 aopPut (AOP (result), "r0", offset++);
4056 /* now some housekeeping stuff */
4058 /* we had to allocate for this iCode */
4060 if (isRegPair(AOP (left))) {
4061 emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
4063 emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
4064 emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
4067 freeAsmop (NULL, aop, ic, TRUE);
4070 /* we did not allocate which means left
4071 already in a pointer register, then
4072 if size > 0 && this could be used again
4073 we have to point it back to where it
4075 if ((AOP_SIZE (result) > 1 &&
4076 !OP_SYMBOL (left)->remat &&
4077 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) &&
4079 int size = AOP_SIZE (result) - 1;
4080 emitcode ("sbiw", "r30,%d",size);
4083 if (pi) pi->generated=1;
4084 freeAsmop (left, NULL, ic, TRUE);
4085 freeAsmop (result, NULL, ic, TRUE);
4088 /*-----------------------------------------------------------------*/
4089 /* genPointerGet - generate code for pointer get */
4090 /*-----------------------------------------------------------------*/
4092 genPointerGet (iCode * ic, iCode *pi)
4094 operand *left, *result;
4095 sym_link *type, *etype;
4098 left = IC_LEFT (ic);
4099 result = IC_RESULT (ic);
4101 /* depending on the type of pointer we need to
4102 move it to the correct pointer register */
4103 type = operandType (left);
4104 etype = getSpec (type);
4105 /* if left is of type of pointer then it is simple */
4106 if (IS_PTR (type) && !IS_FUNC (type->next))
4107 p_type = DCL_TYPE (type);
4109 /* we have to go by the storage class */
4110 p_type = PTR_TYPE (SPEC_OCLS (etype));
4115 /* now that we have the pointer type we assign
4116 the pointer values */
4123 genMemPointerGet (left, result, ic, pi);
4127 genCodePointerGet (left, result, ic, pi);
4131 genGenPointerGet (left, result, ic, pi);
4137 /*-----------------------------------------------------------------*/
4138 /* genPackBits - generates code for packed bit storage */
4139 /*-----------------------------------------------------------------*/
4141 genPackBits (sym_link * etype,
4143 char *rname, int p_type)
4151 blen = SPEC_BLEN (etype);
4152 bstr = SPEC_BSTR (etype);
4154 l = aopGet (AOP (right), offset++);
4157 /* if the bit lenth is less than or */
4158 /* it exactly fits a byte then */
4159 if (SPEC_BLEN (etype) <= 8) {
4160 shCount = SPEC_BSTR (etype);
4162 /* shift left acc */
4165 if (SPEC_BLEN (etype) < 8) { /* if smaller than a byte */
4172 emitcode ("ld", "r1,%s",rname);
4176 emitcode ("push", "r1");
4177 emitcode ("push", "r24");
4178 emitcode ("call", "__gptrget");
4179 emitcode ("pop", "r1");
4180 emitcode ("mov","r24,r0");
4184 emitcode ("andi", "r24,#0x%02x", (unsigned char)
4185 ((unsigned char) (0xFF << (blen + bstr)) |
4186 (unsigned char) (0xFF >> (8 - bstr))));
4187 emitcode ("or", "r24,r1");
4188 if (p_type == GPOINTER)
4189 emitcode ("pop", "r1");
4198 emitcode("st","%s+,r24");
4202 emitcode("mov","r0,r24");
4203 emitcode ("call", "__gptrput_pi");
4208 if (SPEC_BLEN (etype) <= 8)
4211 rLen = SPEC_BLEN (etype);
4213 /* now generate for lengths greater than one byte */
4216 l = aopGet (AOP (right), offset++);
4227 emitcode ("st", "%s+,%s",rname,l);
4232 emitcode ("lcall", "__gptrput_pi");
4239 /* last last was not complete */
4241 /* save the byte & read byte */
4247 emitcode ("st","%s+,r24",rname);
4250 emitcode ("push", "r1");
4251 emitcode ("push", "r24");
4252 emitcode ("lcall", "__gptrget");
4253 emitcode ("mov","r24,r0");
4254 emitcode ("pop", "r1");
4258 emitcode ("andi", "r24,0x%02x", (((unsigned char) -1 << rLen) & 0xff));
4259 emitcode ("or", "r24,r1");
4262 if (p_type == GPOINTER)
4263 emitcode ("pop", "r1");
4271 emitcode ("st", "%s,r24", rname);
4275 emitcode ("mov","r0,r24");
4276 emitcode ("call", "__gptrput");
4281 /*-----------------------------------------------------------------*/
4282 /* genDataPointerSet - remat pointer to data space */
4283 /*-----------------------------------------------------------------*/
4285 genDataPointerSet (operand * right, operand * result, iCode * ic)
4287 int size, offset = 0;
4288 char *l, buffer[256];
4290 aopOp (right, ic, FALSE);
4292 l = aopGet (AOP (result), 0);
4293 size = AOP_SIZE (right);
4296 sprintf (buffer, "(%s + %d)", l, offset);
4298 sprintf (buffer, "%s", l);
4299 emitcode ("sts", "%s,%s", buffer,
4300 aopGet (AOP (right), offset++));
4303 freeAsmop (right, NULL, ic, TRUE);
4304 freeAsmop (result, NULL, ic, TRUE);
4307 /*-----------------------------------------------------------------*/
4308 /* genNearPointerSet - emitcode for near pointer put */
4309 /*-----------------------------------------------------------------*/
4311 genMemPointerSet (operand * right, operand * result, iCode * ic, iCode *pi)
4314 char *frname = NULL, *rname, *l;
4317 sym_link *ptype = operandType (result);
4319 retype = getSpec (operandType (right));
4321 aopOp (result, ic, FALSE);
4323 /* if the result is rematerializable &
4324 in data space & not a bit variable */
4325 if (AOP_TYPE (result) == AOP_IMMD &&
4326 DCL_TYPE (ptype) == POINTER && !IS_BITVAR (retype)) {
4327 genDataPointerSet (right, result, ic);
4330 if (!AOP_INPREG(AOP(result))) {
4331 /* otherwise get a free pointer register */
4333 getFreePtr (ic, &aop, FALSE, 0);
4334 if (isRegPair (AOP (result) )) {
4335 emitcode ("movw", "%s,%s",aop->aopu.aop_ptr->name,
4336 aopGet(AOP (result), 0));
4338 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
4339 aopGet (AOP (result), 0));
4340 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
4341 aopGet (AOP (result), 1));
4346 frname = aopGet(aop,0);
4349 aopOp (right, ic, FALSE);
4352 } else if (AOP_ISZ(aop)) {
4355 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4356 "pointer not in correct register");
4359 /* if bitfield then unpack the bits */
4360 if (IS_BITVAR (retype))
4361 genPackBits (retype, right, rname, POINTER);
4363 /* we have can just get the values */
4364 int size = AOP_SIZE (right);
4368 l = aopGet (AOP (right), offset);
4370 emitcode ("st", "%s+,%s", rname,l);
4372 emitcode ("st", "%s,%s", rname,l);
4377 /* now some housekeeping stuff */
4379 /* we had to allocate for this iCode */
4381 if (isRegPair (AOP (result) )) {
4382 emitcode ("movw", "%s,%s",
4383 aopGet(AOP(result),0),
4384 aop->aopu.aop_ptr->name);
4386 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
4387 aopGet (AOP (result), 0));
4388 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
4389 aopGet (AOP (result), 1));
4392 freeAsmop (NULL, aop, ic, TRUE);
4395 /* we did not allocate which means left
4396 already in a pointer register, then
4397 if size > 0 && this could be used again
4398 we have to point it back to where it
4400 if ((AOP_SIZE (right) > 1 &&
4401 !OP_SYMBOL (result)->remat &&
4402 (OP_SYMBOL (right)->liveTo > ic->seq || ic->depth)) && !pi) {
4403 int size = AOP_SIZE (right) - 1;
4404 emitcode ("sbiw", "%s,%d",frname,size);
4409 if (pi) pi->generated = 1;
4410 freeAsmop (result, NULL, ic, TRUE);
4411 freeAsmop (right, NULL, ic, TRUE);
4414 /*-----------------------------------------------------------------*/
4415 /* genGenPointerSet - set value from generic pointer space */
4416 /*-----------------------------------------------------------------*/
4418 genGenPointerSet (operand * right, operand * result, iCode * ic, iCode *pi)
4422 sym_link *retype = getSpec (operandType (right));
4425 aopOp (result, ic, FALSE);
4427 /* if the operand is already in dptr
4428 then we do nothing else we move the value to dptr */
4429 if (AOP_ISZ(AOP(result))) {
4433 getFreePtr(ic,&aop,FALSE,TRUE);
4434 if (isRegPair(AOP(result))) {
4435 emitcode ("movw", "r30,%s", aopGet (AOP (result), 0));
4437 emitcode ("mov", "r30,%s", aopGet (AOP (result), 0));
4438 emitcode ("mov", "r31,%s", aopGet (AOP (result), 1));
4440 emitcode ("mov", "r24,%s", aopGet (AOP (result), 2));
4444 /* so Z register now contains the address */
4445 aopOp (right, ic, FALSE);
4447 /* if bit then unpack */
4448 if (IS_BITVAR (retype))
4449 genUnpackBits (result, "Z", GPOINTER);
4451 size = AOP_SIZE (right);
4455 char *l = aopGet(AOP (right), offset++);
4459 emitcode ("call", "__gptrput_pi");
4461 emitcode ("call", "__gptrput");
4465 /* now some housekeeping stuff */
4467 /* we had to allocate for this iCode */
4469 if (isRegPair(AOP(result))) {
4470 emitcode ("movw", "%s,r30", aopGet (AOP (result), 0));
4472 emitcode ("mov", "%s,r30", aopGet (AOP (result), 0));
4473 emitcode ("mov", "%s,r31", aopGet (AOP (result), 1));
4476 freeAsmop (NULL, aop, ic, TRUE);
4479 /* we did not allocate which means left
4480 already in a pointer register, then
4481 if size > 0 && this could be used again
4482 we have to point it back to where it
4484 if ((AOP_SIZE (right) > 1 &&
4485 !OP_SYMBOL (result)->remat &&
4486 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) && !pi) {
4487 int size = AOP_SIZE (right) - 1;
4488 emitcode ("sbiw", "r30,%d",size);
4491 if (pi) pi->generated = 1;
4492 freeAsmop (right, NULL, ic, TRUE);
4493 freeAsmop (result, NULL, ic, TRUE);
4496 /*-----------------------------------------------------------------*/
4497 /* genPointerSet - stores the value into a pointer location */
4498 /*-----------------------------------------------------------------*/
4500 genPointerSet (iCode * ic, iCode *pi)
4502 operand *right, *result;
4503 sym_link *type, *etype;
4506 right = IC_RIGHT (ic);
4507 result = IC_RESULT (ic);
4509 /* depending on the type of pointer we need to
4510 move it to the correct pointer register */
4511 type = operandType (result);
4512 etype = getSpec (type);
4513 /* if left is of type of pointer then it is simple */
4514 if (IS_PTR (type) && !IS_FUNC (type->next)) {
4515 p_type = DCL_TYPE (type);
4518 /* we have to go by the storage class */
4519 p_type = PTR_TYPE (SPEC_OCLS (etype));
4523 /* now that we have the pointer type we assign
4524 the pointer values */
4531 genMemPointerSet (right, result, ic, pi);
4535 genGenPointerSet (right, result, ic, pi);
4541 /*-----------------------------------------------------------------*/
4542 /* genIfx - generate code for Ifx statement */
4543 /*-----------------------------------------------------------------*/
4545 genIfx (iCode * ic, iCode * popIc)
4547 operand *cond = IC_COND (ic);
4551 aopOp (cond, ic, FALSE);
4553 /* get the value into acc */
4554 if (AOP_SIZE(cond) == 1 && AOP_ISHIGHREG(AOP(cond),0)) {
4555 cname = aopGet(AOP(cond),0);
4557 toBoolean (cond, "r24", 1);
4560 /* the result is now in the accumulator */
4561 freeAsmop (cond, NULL, ic, TRUE);
4563 /* if there was something to be popped then do it */
4567 emitcode("cpi","%s,0",cname);
4568 lbl = newiTempLabel(NULL);
4570 emitcode ("brne","L%05d",lbl->key);
4571 emitcode ("jmp","L%05d",IC_TRUE(ic)->key);
4572 emitcode ("","L%05d:",lbl->key);
4574 emitcode ("breq","L%05d",lbl->key);
4575 emitcode ("jmp","L%05d",IC_FALSE(ic)->key);
4576 emitcode ("","L%05d:",lbl->key);
4581 /*-----------------------------------------------------------------*/
4582 /* genAddrOf - generates code for address of */
4583 /*-----------------------------------------------------------------*/
4585 genAddrOf (iCode * ic)
4587 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
4590 aopOp (IC_RESULT (ic), ic, FALSE);
4592 /* if the operand is on the stack then we
4593 need to get the stack offset of this
4596 /* if it has an offset then we need to compute it */
4598 emitcode ("mov", "a,_bp");
4599 emitcode ("add", "a,#0x%02x",
4600 ((char) sym->stack & 0xff));
4601 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4604 /* we can just move _bp */
4605 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
4607 /* fill the result with zero */
4608 size = AOP_SIZE (IC_RESULT (ic)) - 2;
4611 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
4617 /* object not on stack then we need the name */
4618 size = AOP_SIZE (IC_RESULT (ic));
4622 char s[SDCC_NAME_MAX];
4624 sprintf (s, "(%s >> %d)", sym->rname, offset * 8);
4626 sprintf (s, "%s", sym->rname);
4627 aopPut (AOP (IC_RESULT (ic)), s, offset++);
4631 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4635 /*-----------------------------------------------------------------*/
4636 /* genFarFarAssign - assignment when both are in far space */
4637 /*-----------------------------------------------------------------*/
4639 genFarFarAssign (operand * result, operand * right, iCode * ic)
4641 int size = AOP_SIZE (right);
4644 /* first push the right side on to the stack */
4646 l = aopGet (AOP (right), offset++);
4648 emitcode ("push", "acc");
4651 freeAsmop (right, NULL, ic, FALSE);
4652 /* now assign DPTR to result */
4653 aopOp (result, ic, FALSE);
4654 size = AOP_SIZE (result);
4656 emitcode ("pop", "acc");
4657 aopPut (AOP (result), "a", --offset);
4659 freeAsmop (result, NULL, ic, FALSE);
4663 /*-----------------------------------------------------------------*/
4664 /* genAssign - generate code for assignment */
4665 /*-----------------------------------------------------------------*/
4667 genAssign (iCode * ic)
4669 operand *result, *right;
4671 unsigned long lit = 0L;
4673 result = IC_RESULT (ic);
4674 right = IC_RIGHT (ic);
4676 /* if they are the same */
4677 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4680 aopOp (right, ic, FALSE);
4682 /* special case both in far space */
4683 if (AOP_TYPE (right) == AOP_DPTR &&
4684 IS_TRUE_SYMOP (result) && isOperandInFarSpace (result)) {
4686 genFarFarAssign (result, right, ic);
4690 aopOp (result, ic, TRUE);
4692 /* if they are the same registers */
4693 if (sameRegs (AOP (right), AOP (result)))
4696 /* if the result is a bit */
4697 if (AOP_TYPE (result) == AOP_CRY) {
4699 /* if the right size is a literal then
4700 we know what the value is */
4701 if (AOP_TYPE (right) == AOP_LIT) {
4702 if (((int) operandLitValue (right)))
4703 aopPut (AOP (result), one, 0);
4705 aopPut (AOP (result), zero, 0);
4709 /* the right is also a bit variable */
4710 if (AOP_TYPE (right) == AOP_CRY) {
4711 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4712 aopPut (AOP (result), "c", 0);
4717 toBoolean (right, "", 0);
4718 aopPut (AOP (result), "a", 0);
4722 /* bit variables done */
4724 size = AOP_SIZE (result);
4726 if (AOP_TYPE (right) == AOP_LIT)
4728 (unsigned long) floatFromVal (AOP (right)->aopu.
4730 if ((size > 1) && (AOP_TYPE (result) != AOP_REG)
4731 && (AOP_TYPE (right) == AOP_LIT)
4732 && !IS_FLOAT (operandType (right)) && (lit < 256L)) {
4733 emitcode ("clr", "a");
4735 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) ==
4736 0) aopPut (AOP (result), "a", size);
4738 aopPut (AOP (result),
4739 aopGet (AOP (right), size), size);
4744 aopPut (AOP (result),
4745 aopGet (AOP (right), offset), offset);
4751 freeAsmop (right, NULL, ic, FALSE);
4752 freeAsmop (result, NULL, ic, TRUE);
4755 /*-----------------------------------------------------------------*/
4756 /* genJumpTab - genrates code for jump table */
4757 /*-----------------------------------------------------------------*/
4759 genJumpTab (iCode * ic)
4764 aopOp (IC_JTCOND (ic), ic, FALSE);
4765 /* get the condition into accumulator */
4766 l = aopGet (AOP (IC_JTCOND (ic)), 0);
4768 /* multiply by three */
4769 emitcode ("add", "a,acc");
4770 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0));
4771 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
4773 jtab = newiTempLabel (NULL);
4774 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
4775 emitcode ("jmp", "@a+dptr");
4776 emitcode ("", "%05d$:", jtab->key + 100);
4777 /* now generate the jump labels */
4778 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
4779 jtab = setNextItem (IC_JTLABELS (ic)))
4780 emitcode ("ljmp", "%05d$", jtab->key + 100);
4784 /*-----------------------------------------------------------------*/
4785 /* genCast - gen code for casting */
4786 /*-----------------------------------------------------------------*/
4788 genCast (iCode * ic)
4790 operand *result = IC_RESULT (ic);
4791 sym_link *ctype = operandType (IC_LEFT (ic));
4792 sym_link *rtype = operandType (IC_RIGHT (ic));
4793 operand *right = IC_RIGHT (ic);
4796 /* if they are equivalent then do nothing */
4797 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4800 aopOp (right, ic, FALSE);
4801 aopOp (result, ic, FALSE);
4803 /* if the result is a bit */
4804 if (AOP_TYPE (result) == AOP_CRY) {
4805 /* if the right size is a literal then
4806 we know what the value is */
4807 if (AOP_TYPE (right) == AOP_LIT) {
4808 if (((int) operandLitValue (right)))
4809 aopPut (AOP (result), one, 0);
4811 aopPut (AOP (result), zero, 0);
4816 /* the right is also a bit variable */
4817 if (AOP_TYPE (right) == AOP_CRY) {
4818 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4819 aopPut (AOP (result), "c", 0);
4824 toBoolean (right, "", 0);
4825 aopPut (AOP (result), "a", 0);
4829 /* if they are the same size : or less */
4830 if (AOP_SIZE (result) <= AOP_SIZE (right)) {
4832 /* if they are in the same place */
4833 if (sameRegs (AOP (right), AOP (result)))
4836 /* if they in different places then copy */
4837 size = AOP_SIZE (result);
4840 aopPut (AOP (result),
4841 aopGet (AOP (right), offset), offset);
4848 /* if the result is of type pointer */
4849 if (IS_PTR (ctype)) {
4852 sym_link *type = operandType (right);
4853 sym_link *etype = getSpec (type);
4855 /* pointer to generic pointer */
4856 if (IS_GENPTR (ctype)) {
4860 p_type = DCL_TYPE (type);
4862 /* we have to go by the storage class */
4863 p_type = PTR_TYPE (SPEC_OCLS (etype));
4866 /* the first two bytes are known */
4867 size = GPTRSIZE - 1;
4870 aopPut (AOP (result),
4871 aopGet (AOP (right), offset), offset);
4874 /* the last byte depending on type */
4891 /* this should never happen */
4892 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4893 "got unknown pointer type");
4896 aopPut (AOP (result), l, GPTRSIZE - 1);
4900 /* just copy the pointers */
4901 size = AOP_SIZE (result);
4904 aopPut (AOP (result),
4905 aopGet (AOP (right), offset), offset);
4911 /* so we now know that the size of destination is greater
4912 than the size of the source */
4913 /* we move to result for the size of source */
4914 size = AOP_SIZE (right);
4917 aopPut (AOP (result), aopGet (AOP (right), offset), offset);
4921 /* now depending on the sign of the source && destination */
4922 size = AOP_SIZE (result) - AOP_SIZE (right);
4923 /* if unsigned or not an integral type */
4924 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype)) {
4926 aopPut (AOP (result), zero, offset++);
4929 /* we need to extend the sign :{ */
4930 // PENDING: Does nothing on avr
4932 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1);
4935 emitcode ("rlc", "a");
4936 emitcode ("subb", "a,acc");
4938 aopPut (AOP (result), "a", offset++);
4941 /* we are done hurray !!!! */
4944 freeAsmop (right, NULL, ic, TRUE);
4945 freeAsmop (result, NULL, ic, TRUE);
4949 /*-----------------------------------------------------------------*/
4950 /* genDjnz - generate decrement & jump if not zero instrucion */
4951 /*-----------------------------------------------------------------*/
4953 genDjnz (iCode * ic, iCode * ifx)
4959 /* if the if condition has a false label
4960 then we cannot save */
4964 /* if the minus is not of the form
4966 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
4967 !IS_OP_LITERAL (IC_RIGHT (ic)))
4970 if (operandLitValue (IC_RIGHT (ic)) != 1)
4973 /* if the size of this greater than one then no
4975 if (getSize (operandType (IC_RESULT (ic))) > 1)
4978 /* otherwise we can save BIG */
4979 lbl = newiTempLabel (NULL);
4980 lbl1 = newiTempLabel (NULL);
4982 aopOp (IC_RESULT (ic), ic, FALSE);
4984 if (IS_AOP_PREG (IC_RESULT (ic))) {
4985 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0));
4986 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0));
4987 emitcode ("jnz", "%05d$", lbl->key + 100);
4990 emitcode ("djnz", "%s,%05d$",
4991 aopGet (AOP (IC_RESULT (ic)), 0), lbl->key + 100);
4993 emitcode ("sjmp", "%05d$", lbl1->key + 100);
4994 emitcode ("", "%05d$:", lbl->key + 100);
4995 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4996 emitcode ("", "%05d$:", lbl1->key + 100);
4998 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5003 static char *recvregs[8] = {
5004 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23"
5007 static int recvCnt = 0;
5009 /*-----------------------------------------------------------------*/
5010 /* genReceive - generate code for a receive iCode */
5011 /*-----------------------------------------------------------------*/
5013 genReceive (iCode * ic)
5015 int size, offset = 0;
5016 aopOp (IC_RESULT (ic), ic, FALSE);
5017 size = AOP_SIZE (IC_RESULT (ic));
5019 aopPut (AOP (IC_RESULT (ic)), recvregs[recvCnt++], offset);
5022 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5025 /*-----------------------------------------------------------------*/
5026 /* gen51Code - generate code for 8051 based controllers */
5027 /*-----------------------------------------------------------------*/
5029 genAVRCode (iCode * lic)
5034 lineHead = lineCurr = NULL;
5036 /* print the allocation information */
5038 printAllocInfo (currFunc, codeOutFile);
5039 /* if debug information required */
5040 /* if (options.debug && currFunc) { */
5042 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
5044 emitcode ("", ".type %s,@function", currFunc->name);
5047 /* stack pointer name */
5051 for (ic = lic; ic; ic = ic->next) {
5053 if (cln != ic->lineno) {
5054 if (options.debug) {
5056 emitcode ("", "C$%s$%d$%d$%d ==.",
5057 FileBaseName (ic->filename),
5058 ic->lineno, ic->level, ic->block);
5061 emitcode (";", "%s %d", ic->filename, ic->lineno);
5064 /* if the result is marked as
5065 spilt and rematerializable or code for
5066 this has already been generated then
5068 if (resultRemat (ic) || ic->generated)
5071 /* depending on the operation */
5090 /* IPOP happens only when trying to restore a
5091 spilt live range, if there is an ifx statement
5092 following this pop then the if statement might
5093 be using some of the registers being popped which
5094 would destory the contents of the register so
5095 we need to check for this condition and handle it */
5097 ic->next->op == IFX &&
5098 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
5099 genIfx (ic->next, ic);
5117 genEndFunction (ic);
5137 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
5154 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
5158 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
5162 genCmpLe (ic, ifxForOp (IC_RESULT (ic), ic));
5166 genCmpGe (ic, ifxForOp (IC_RESULT (ic), ic));
5170 genCmpNe (ic, ifxForOp (IC_RESULT (ic), ic));
5174 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
5186 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
5190 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
5194 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
5221 case GET_VALUE_AT_ADDRESS:
5222 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
5226 if (POINTER_SET (ic))
5227 genPointerSet (ic, hasInc(IC_RESULT(ic),ic));
5253 addSet (&_G.sendSet, ic);
5262 /* now we are ready to call the
5263 peep hole optimizer */
5264 if (!options.nopeep)
5265 peepHole (&lineHead);
5267 /* now do the actual printing */
5268 printLine (lineHead, codeOutFile);