1 /*-------------------------------------------------------------------------
2 avrgen.c - source file for code generation for ATMEL AVR
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (2000)
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding!
25 -------------------------------------------------------------------------*/
31 #include "SDCCglobl.h"
34 #ifdef HAVE_SYS_ISA_DEFS_H
35 #include <sys/isa_defs.h>
37 #ifdef HAVE_MACHINE_ENDIAN_H
38 #include <machine/endian.h>
43 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
44 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
45 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
52 #include "SDCCpeeph.h"
56 char *aopLiteral (value * val, int offset);
59 /* this is the down and dirty file with all kinds of
60 kludgy & hacky stuff. This is what it is all about
61 CODE GENERATION for a specific MCU . some of the
62 routines may be reusable, will have to see */
64 static char *zero = "0x00";
65 static char *one = "0x01";
68 char *fReturnAVR[] = { "r16", "r17", "r18", "r19" };
69 unsigned fAVRReturnSize = 4; /* shared with ralloc.c */
70 char **fAVRReturn = fReturnAVR;
71 static char *larray[4] = { "lo8", "hi8", "hlo8", "hhi8" };
75 static short rbank = -1;
76 static char *tscr[4] = { "r0", "r1", "r24", "r25" };
77 static unsigned char SLMask[] = { 0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
78 0xE0, 0xC0, 0x80, 0x00
80 static unsigned char SRMask[] = { 0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
81 0x07, 0x03, 0x01, 0x00
96 extern int avr_ptrRegReq;
98 extern FILE *codeOutFile;
99 #define RESULTONSTACK(x) \
100 (IC_RESULT(x) && IC_RESULT(x)->aop && \
101 IC_RESULT(x)->aop->type == AOP_STK )
103 #define MOVR0(x) if (strcmp(x,"r0")) emitcode("mov","r0,%s",x);
104 #define MOVR24(x) if (strcmp(x,"r24")) emitcode("mov","r24,%s",x);
105 #define AOP_ISHIGHREG(a,n) (a->type == AOP_REG && a->aopu.aop_reg[n] && a->aopu.aop_reg[n]->rIdx >= R16_IDX)
106 #define CLRC emitcode("clc","")
107 #define SETC emitcode("stc","")
109 #define IS_REGIDX(a,r) (a->type == AOP_REG && a->aopu.aop_reg[0]->rIdx == r)
111 static lineNode *lineHead = NULL;
112 static lineNode *lineCurr = NULL;
121 /*-----------------------------------------------------------------*/
122 /* reAdjustPreg - points a register back to where it should */
123 /*-----------------------------------------------------------------*/
125 reAdjustPreg (asmop * aop)
130 if ((size = aop->size) <= 1)
136 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name, size);
142 /*-----------------------------------------------------------------*/
143 /* outBitC - output a bit C */
144 /*-----------------------------------------------------------------*/
146 outBitC (operand * result)
148 emitcode ("clr", "r0");
149 emitcode ("rol", "r0");
153 /*-----------------------------------------------------------------*/
154 /* inExcludeList - return 1 if the string is in exclude Reg list */
155 /*-----------------------------------------------------------------*/
157 inExcludeList (char *s)
161 if (options.excludeRegs[i] &&
162 STRCASECMP (options.excludeRegs[i], "none") == 0)
165 for (i = 0; options.excludeRegs[i]; i++) {
166 if (options.excludeRegs[i] &&
167 STRCASECMP (s, options.excludeRegs[i]) == 0)
173 /*-----------------------------------------------------------------*/
174 /* findLabelBackwards: walks back through the iCode chain looking */
175 /* for the given label. Returns number of iCode instructions */
176 /* between that label and given ic. */
177 /* Returns zero if label not found. */
178 /*-----------------------------------------------------------------*/
180 findLabelBackwards (iCode * ic, int key)
188 if (ic->op == LABEL && IC_LABEL (ic)->key == key) {
189 /* printf("findLabelBackwards = %d\n", count); */
197 /*-----------------------------------------------------------------*/
198 /* addSign - complete with sign */
199 /*-----------------------------------------------------------------*/
201 addSign (operand * result, int offset, int sign)
203 int size = (getDataSize (result) - offset);
206 emitcode ("rlc", "a");
207 emitcode ("subb", "a,acc");
209 aopPut (AOP (result), "a", offset++);
213 aopPut (AOP (result), zero, offset++);
217 /*-----------------------------------------------------------------*/
218 /* isLiteralBit - test if lit == 2^n */
219 /*-----------------------------------------------------------------*/
221 isLiteralBit (unsigned long lit)
223 unsigned long pw[32] = { 1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
224 0x100L, 0x200L, 0x400L, 0x800L,
225 0x1000L, 0x2000L, 0x4000L, 0x8000L,
226 0x10000L, 0x20000L, 0x40000L, 0x80000L,
227 0x100000L, 0x200000L, 0x400000L, 0x800000L,
228 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
229 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L
233 for (idx = 0; idx < 32; idx++)
239 /*-----------------------------------------------------------------*/
240 /* outAcc - output Acc */
241 /*-----------------------------------------------------------------*/
243 outAcc (operand * result)
246 size = getDataSize (result);
248 aopPut (AOP (result), "r0", 0);
251 /* unsigned or positive */
253 aopPut (AOP (result), zero, offset++);
258 #endif // End Unused code section
260 /*-----------------------------------------------------------------*/
261 /* emitcode - writes the code into a file : for now it is simple */
262 /*-----------------------------------------------------------------*/
264 emitcode (char *inst, char *fmt, ...)
267 char lb[INITIAL_INLINEASM];
274 sprintf (lb, "%s\t", inst);
276 sprintf (lb, "%s", inst);
277 vsprintf (lb + (strlen (lb)), fmt, ap);
280 vsprintf (lb, fmt, ap);
282 while (isspace (*lbp))
286 lineCurr = (lineCurr ?
287 connectLine (lineCurr, newLineNode (lb)) :
288 (lineHead = newLineNode (lb)));
289 lineCurr->isInline = _G.inLine;
290 lineCurr->isDebug = _G.debugLine;
294 /*-----------------------------------------------------------------*/
295 /* hasInc - operand is incremented before any other use */
296 /*-----------------------------------------------------------------*/
298 hasInc (operand *op, iCode *ic)
300 sym_link *type = operandType(op);
301 sym_link *retype = getSpec (type);
302 iCode *lic = ic->next;
305 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
306 isize = getSize(type->next);
308 /* if operand of the form op = op + <sizeof *op> */
309 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
310 isOperandEqual(IC_RESULT(lic),op) &&
311 isOperandLiteral(IC_RIGHT(lic)) &&
312 operandLitValue(IC_RIGHT(lic)) == isize) {
315 /* if the operand used or deffed */
316 if (bitVectBitValue(OP_USES(op),lic->key) || ((unsigned) lic->defKey == op->key)) {
324 /*-----------------------------------------------------------------*/
325 /* getFreePtr - returns X or Z whichever is free or can be pushed */
326 /*-----------------------------------------------------------------*/
328 getFreePtr (iCode * ic, asmop ** aopp, bool result, bool zonly)
330 bool xiu = FALSE, ziu = FALSE;
331 bool xou = FALSE, zou = FALSE;
333 /* the logic: if x & z used in the instruction
334 then we are in trouble otherwise */
336 /* first check if x & z are used by this
337 instruction, in which case we are in trouble */
338 if ((xiu = bitVectBitValue (ic->rUsed, X_IDX)) &&
339 (ziu = bitVectBitValue (ic->rUsed, Z_IDX))) {
343 xou = bitVectBitValue (ic->rMask, X_IDX);
344 zou = bitVectBitValue (ic->rMask, Z_IDX);
346 /* if no usage of Z then return it */
348 ic->rUsed = bitVectSetBit (ic->rUsed, Z_IDX);
349 (*aopp)->type = AOP_Z;
351 (*aopp)->aop_ptr2 = avr_regWithIdx (R31_IDX);
352 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R30_IDX);
355 /* if no usage of X then return it */
356 if (!xiu && !xou && !zonly) {
357 ic->rUsed = bitVectSetBit (ic->rUsed, X_IDX);
358 (*aopp)->type = AOP_X;
360 (*aopp)->aop_ptr2 = avr_regWithIdx (R27_IDX);
361 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R26_IDX);
364 /* if z not used then */
367 /* push it if not already pushed */
369 emitcode ("push", "%s",
370 avr_regWithIdx (R30_IDX)->dname);
371 emitcode ("push", "%s",
372 avr_regWithIdx (R31_IDX)->dname);
376 ic->rUsed = bitVectSetBit (ic->rUsed, Z_IDX);
377 (*aopp)->type = AOP_Z;
378 (*aopp)->aop_ptr2 = avr_regWithIdx (R31_IDX);
379 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R30_IDX);
382 /* now we know they both have usage */
383 /* if x not used in this instruction */
384 if (!xiu && !zonly) {
385 /* push it if not already pushed */
387 emitcode ("push", "%s",
388 avr_regWithIdx (R26_IDX)->dname);
389 emitcode ("push", "%s",
390 avr_regWithIdx (R27_IDX)->dname);
394 ic->rUsed = bitVectSetBit (ic->rUsed, X_IDX);
395 (*aopp)->type = AOP_X;
397 (*aopp)->aop_ptr2 = avr_regWithIdx (R27_IDX);
398 return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R26_IDX);
403 /* I said end of world but not quite end of world yet */
404 /* if this is a result then we can push it on the stack */
406 (*aopp)->type = AOP_STK;
410 /* other wise this is true end of the world */
411 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
412 "getFreePtr should never reach here");
416 /*-----------------------------------------------------------------*/
417 /* newAsmop - creates a new asmOp */
418 /*-----------------------------------------------------------------*/
420 newAsmop (short type)
424 aop = Safe_calloc (1, sizeof (asmop));
429 /*-----------------------------------------------------------------*/
430 /* pointerCode - returns the code for a pointer type */
431 /*-----------------------------------------------------------------*/
433 pointerCode (sym_link * etype)
436 return PTR_TYPE (SPEC_OCLS (etype));
440 /*-----------------------------------------------------------------*/
441 /* aopForSym - for a true symbol */
442 /*-----------------------------------------------------------------*/
444 aopForSym (iCode * ic, symbol * sym, bool result)
447 memmap *space = SPEC_OCLS (sym->etype);
449 /* if already has one */
453 /* assign depending on the storage class */
454 /* if it is on the stack */
456 sym->aop = aop = newAsmop (0);
457 aop->size = getSize (sym->type);
459 /* we can use std / ldd instruction */
461 && (sym->stack + getSize (sym->type) - 1) <= 63) {
462 aop->type = AOP_STK_D;
463 aop->aopu.aop_stk = sym->stack;
467 /* otherwise get a free pointer register X/Z */
468 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result, FALSE);
470 /* now assign the address of the variable to
471 the pointer register */
472 if (aop->type != AOP_STK) {
473 emitcode ("movw", "%s,r28", aop->aopu.aop_ptr->name);
474 if (sym->stack < 0) {
475 if ((sym->stack - _G.nRegsSaved) > -63) {
476 emitcode ("sbiw", "%s,0x%02x",
477 aop->aopu.aop_ptr->name,
482 emitcode ("subi", "%s,<(%d)",
483 aop->aopu.aop_ptr->name,
484 sym->stack - _G.nRegsSaved);
485 emitcode ("sbci", "%s,>(%d)",
487 sym->stack - _G.nRegsSaved);
491 if (sym->stack <= 63) {
492 emitcode ("adiw", "%s,0x%02x",
493 aop->aopu.aop_ptr->name,
497 emitcode ("subi", "%s,<(-%d)",
498 aop->aopu.aop_ptr->name,
500 emitcode ("sbci", "%s,>(-%d)",
509 /* if in bit space */
510 if (IN_BITSPACE (space)) {
511 sym->aop = aop = newAsmop (AOP_CRY);
512 aop->aopu.aop_dir = sym->rname;
513 aop->size = getSize (sym->type);
516 /* if it is in direct space */
517 if (IN_DIRSPACE (space)) {
518 sym->aop = aop = newAsmop (AOP_DIR);
519 aop->aopu.aop_dir = sym->rname;
520 aop->size = getSize (sym->type);
524 /* special case for a function */
525 if (IS_FUNC (sym->type)) {
526 sym->aop = aop = newAsmop (AOP_IMMD);
527 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
528 strcpy (aop->aopu.aop_immd, sym->rname);
529 aop->size = FPTRSIZE;
533 /* only remaining is code / eeprom which will need pointer reg */
534 /* if it is in code space */
536 sym->aop = aop = newAsmop (0);
538 if (IN_CODESPACE (space))
541 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result, aop->code);
542 aop->size = getSize (sym->type);
543 emitcode ("ldi", "%s,<(%s)", aop->aopu.aop_ptr->name, sym->rname);
544 emitcode ("ldi", "%s,>(%s)", aop->aop_ptr2);
549 /*-----------------------------------------------------------------*/
550 /* aopForRemat - rematerialzes an object */
551 /*-----------------------------------------------------------------*/
553 aopForRemat (symbol * sym)
555 iCode *ic = sym->rematiCode;
556 asmop *aop = newAsmop (AOP_IMMD);
561 val += (int) operandLitValue (IC_RIGHT (ic));
562 else if (ic->op == '-')
563 val -= (int) operandLitValue (IC_RIGHT (ic));
567 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
571 sprintf (buffer, "(%s %c 0x%04x)",
572 OP_SYMBOL (IC_LEFT (ic))->rname,
573 val >= 0 ? '+' : '-', abs (val) & 0xffff);
575 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
577 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
578 strcpy (aop->aopu.aop_immd, buffer);
582 /*-----------------------------------------------------------------*/
583 /* regsInCommon - two operands have some registers in common */
584 /*-----------------------------------------------------------------*/
586 regsInCommon (operand * op1, operand * op2)
591 /* if they have registers in common */
592 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
595 sym1 = OP_SYMBOL (op1);
596 sym2 = OP_SYMBOL (op2);
598 if (sym1->nRegs == 0 || sym2->nRegs == 0)
601 for (i = 0; i < sym1->nRegs; i++) {
606 for (j = 0; j < sym2->nRegs; j++) {
610 if (sym2->regs[j] == sym1->regs[i])
618 /*-----------------------------------------------------------------*/
619 /* operandsEqu - equivalent */
620 /*-----------------------------------------------------------------*/
622 operandsEqu (operand * op1, operand * op2)
626 /* if they not symbols */
627 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
630 sym1 = OP_SYMBOL (op1);
631 sym2 = OP_SYMBOL (op2);
633 /* if both are itemps & one is spilt
634 and the other is not then false */
635 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
636 sym1->isspilt != sym2->isspilt) return FALSE;
638 /* if they are the same */
642 if (strcmp (sym1->rname, sym2->rname) == 0)
646 /* if left is a tmp & right is not */
647 if (IS_ITEMP (op1) &&
648 !IS_ITEMP (op2) && sym1->isspilt && (sym1->usl.spillLoc == sym2))
651 if (IS_ITEMP (op2) &&
653 sym2->isspilt && sym1->level > 0 && (sym2->usl.spillLoc == sym1))
659 /*-----------------------------------------------------------------*/
660 /* sameRegs - two asmops have the same registers */
661 /*-----------------------------------------------------------------*/
663 sameRegs (asmop * aop1, asmop * aop2)
670 if (aop1->type != AOP_REG || aop2->type != AOP_REG)
673 if (aop1->size != aop2->size)
676 for (i = 0; i < aop1->size; i++)
677 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
683 /*-----------------------------------------------------------------*/
684 /* isRegPair - for size 2 if this operand has a register pair */
685 /*-----------------------------------------------------------------*/
687 isRegPair (asmop * aop)
689 if (!aop || aop->size < 2)
691 if (aop->type == AOP_X || aop->type == AOP_Z)
693 if (aop->type != AOP_REG)
695 if ( ((aop->aopu.aop_reg[1]->rIdx - aop->aopu.aop_reg[0]->rIdx) == 1) &&
696 (aop->aopu.aop_reg[0]->rIdx & 1) == 0)
702 /*-----------------------------------------------------------------*/
703 /* aopOp - allocates an asmop for an operand : */
704 /*-----------------------------------------------------------------*/
706 aopOp (operand * op, iCode * ic, bool result)
715 /* if this a literal */
716 if (IS_OP_LITERAL (op)) {
717 op->aop = aop = newAsmop (AOP_LIT);
718 aop->aopu.aop_lit = op->operand.valOperand;
719 aop->size = getSize (operandType (op));
723 /* if already has a asmop then continue */
727 /* if the underlying symbol has a aop */
728 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop) {
729 op->aop = OP_SYMBOL (op)->aop;
733 /* if this is a true symbol */
734 if (IS_TRUE_SYMOP (op)) {
735 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
739 /* this is a temporary : this has
745 e) can be a return use only */
747 sym = OP_SYMBOL (op);
750 /* if the type is a conditional */
751 if (sym->regType & REG_CND) {
752 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
757 /* if it is spilt then two situations
759 b) has a spill location */
760 if (sym->isspilt || sym->nRegs == 0) {
762 /* rematerialize it NOW */
764 sym->aop = op->aop = aop = aopForRemat (sym);
765 aop->size = getSize (sym->type);
770 assert ("ACC_USE cannot happen in AVR\n");
775 aop = op->aop = sym->aop = newAsmop (AOP_STR);
776 aop->size = getSize (sym->type);
777 for (i = 0; i < (int) fAVRReturnSize; i++)
778 aop->aopu.aop_str[i] = fAVRReturn[i];
782 /* else spill location */
783 sym->aop = op->aop = aop =
784 aopForSym (ic, sym->usl.spillLoc, result);
785 aop->size = getSize (sym->type);
789 /* must be in a register */
790 sym->aop = op->aop = aop = newAsmop (AOP_REG);
791 aop->size = sym->nRegs;
792 for (i = 0; i < sym->nRegs; i++)
793 aop->aopu.aop_reg[i] = sym->regs[i];
796 /*-----------------------------------------------------------------*/
797 /* freeAsmop - free up the asmop given to an operand */
798 /*----------------------------------------------------------------*/
800 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
817 /* depending on the asmop type only three cases need work AOP_RO
818 , AOP_R1 && AOP_STK */
823 emitcode ("pop", "r26");
824 emitcode ("pop", "r27");
828 bitVectUnSetBit (ic->rUsed, X_IDX);
834 emitcode ("pop", "r30");
835 emitcode ("pop", "r31");
839 bitVectUnSetBit (ic->rUsed, Z_IDX);
845 int stk = aop->aopu.aop_stk + aop->size;
846 bitVectUnSetBit (ic->rUsed, X_IDX);
847 bitVectUnSetBit (ic->rUsed, Z_IDX);
849 getFreePtr (ic, &aop, FALSE, 0);
851 emitcode ("movw", "%s,r28");
853 if (stk <= 63 && stk > 0) {
854 emitcode ("adiw", "%s,0x%02x",
855 aop->aopu.aop_ptr->name,
859 emitcode ("subi", "%s,<(%d)",
860 aop->aopu.aop_ptr->name,
862 emitcode ("sbci", "%s,>(%d)",
869 emitcode ("pop", "r24");
870 emitcode ("st", "-%s,r24",
871 aop->type == AOP_X ? "X" : "Z");
876 freeAsmop (op, NULL, ic, TRUE);
878 emitcode ("pop", "r26");
879 emitcode ("pop", "r27");
884 emitcode ("pop", "r30");
885 emitcode ("pop", "r31");
892 /* all other cases just dealloc */
896 OP_SYMBOL (op)->aop = NULL;
897 /* if the symbol has a spill */
899 SPIL_LOC (op)->aop = NULL;
904 /*-----------------------------------------------------------------*/
905 /* aopGet - for fetching value of the aop */
906 /*-----------------------------------------------------------------*/
908 aopGet (asmop * aop, int offset)
913 /* offset is greater than
915 if (offset > (aop->size - 1) && aop->type != AOP_LIT)
918 /* depending on type */
922 if (offset > aop->coff) {
923 emitcode ("adiw", "%s,%d", aop->aopu.aop_ptr->name,
927 if (offset < aop->coff) {
928 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name,
933 emitcode ("ld", "%s,x",
934 (rs = ((offset & 1) ? "r25" : "r24")));
939 if (offset > aop->coff) {
940 emitcode ("adiw", "r30,%d",
944 emitcode ("sbiw", "r30,%d",
947 emitcode ("lpm", "%s,z",
948 (rs = ((offset & 1) ? "r25" : "r24")));
952 if (offset > aop->coff) {
953 emitcode ("ldd", "%s,z+%d",
955 ((offset & 1) ? "r25" : "r24")),
959 emitcode ("sbiw", "%s,%d",
960 aop->aopu.aop_ptr->name,
963 emitcode ("ld", "%s,z",
965 ((offset & 1) ? "r25" : "r24")));
972 emitcode ("lds", "%s,(%s)+%d",
973 (rs = ((offset & 1) ? "r25" : "r24")),
974 aop->aopu.aop_immd, offset);
978 emitcode ("lds", "%s,(%s)+%d",
979 (rs = ((offset & 1) ? "r25" : "r24")),
980 aop->aopu.aop_dir, offset);
984 return aop->aopu.aop_reg[offset]->name;
987 assert ("cannot be in bit space AOP_CRY\n");
991 s = aopLiteral (aop->aopu.aop_lit, offset);
992 emitcode ("ldi", "%s,<(%s)",
993 (rs = ((offset & 1) ? "r24" : "r25")), s);
998 return aop->aopu.aop_str[offset];
1001 emitcode ("ldd", "%s,Y+%d",
1002 (rs = ((offset & 1) ? "r25" : "r24")),
1003 aop->aopu.aop_stk + offset);
1007 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1008 "aopget got unsupported aop->type");
1012 /*-----------------------------------------------------------------*/
1013 /* aopPut - puts a string for a aop */
1014 /*-----------------------------------------------------------------*/
1016 aopPut (asmop * aop, char *s, int offset)
1020 if (aop->size && offset > (aop->size - 1)) {
1021 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1022 "aopPut got offset > aop->size");
1026 /* will assign value to value */
1027 /* depending on where it is ofcourse */
1028 switch (aop->type) {
1031 sprintf (d, "(%s)+%d", aop->aopu.aop_dir, offset);
1034 sprintf (d, "%s", aop->aopu.aop_dir);
1037 emitcode ("sts", "%s,%s", d, s);
1041 if (toupper (*s) != 'R') {
1043 emitcode ("clr", "%s",
1044 aop->aopu.aop_reg[offset]->name);
1047 emitcode ("ldi", "r25,%s", s);
1048 emitcode ("mov", "%s,r35",
1049 aop->aopu.aop_reg[offset]->name);
1053 if (strcmp (aop->aopu.aop_reg[offset]->name, s)) {
1054 emitcode ("mov", "%s,%s",
1055 aop->aopu.aop_reg[offset]->name, s);
1061 if (offset > aop->coff) {
1062 emitcode ("adiw", "%s,%d", aop->aopu.aop_ptr->name,
1063 offset - aop->coff);
1066 if (offset < aop->coff) {
1067 emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name,
1068 aop->coff - offset);
1072 emitcode ("st", "x,%s", s);
1077 if (offset > aop->coff) {
1078 emitcode ("adiw", "r30,%d",
1079 offset - aop->coff);
1082 emitcode ("sbiw", "r30,%d",
1083 aop->coff - offset);
1085 emitcode ("lpm", "%s,z", s);
1088 /* we can use lds */
1089 if (offset > aop->coff) {
1090 emitcode ("sdd", "z+%d,%s",
1091 offset - aop->coff, s);
1094 emitcode ("sbiw", "%s,%d",
1095 aop->aopu.aop_ptr->name,
1096 aop->coff - offset);
1098 emitcode ("ld", "%s,z", s);
1104 emitcode ("push", "%s", s);
1108 /* if used only for a condition code check */
1109 assert (toupper (*s) == 'R');
1111 emitcode ("xrl", "r0,r0");
1112 emitcode ("cpi", "%s,0", s);
1115 emitcode ("cpc", "r0,%s", s);
1121 if (strcmp (aop->aopu.aop_str[offset], s))
1122 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset],
1127 emitcode ("std", "y+%d,%s", offset, s);
1131 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1132 "aopPut got unsupported aop->type");
1138 #define AOP(op) op->aop
1139 #define AOP_TYPE(op) AOP(op)->type
1140 #define AOP_SIZE(op) AOP(op)->size
1141 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_X || \
1142 AOP_TYPE(x) == AOP_Z))
1143 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1144 ((x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R27_IDX)) || \
1145 (x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R31_IDX)) )))
1146 #define AOP_ISX(x) (x && (x->type == AOP_REG && \
1147 ((x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R27_IDX)))))
1148 #define AOP_ISZ(x) (x && (x->type == AOP_REG && \
1149 ((x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R31_IDX)))))
1151 /*-----------------------------------------------------------------*/
1152 /* genNotFloat - generates not for float operations */
1153 /*-----------------------------------------------------------------*/
1155 genNotFloat (operand * op, operand * res)
1161 /* we will put 127 in the first byte of
1163 aopPut (AOP (res), "127", 0);
1164 size = AOP_SIZE (op) - 1;
1167 l = aopGet (op->aop, offset++);
1171 emitcode ("or", "R0,%s", aopGet (op->aop, offset++));
1173 tlbl = newiTempLabel (NULL);
1175 tlbl = newiTempLabel (NULL);
1176 aopPut (res->aop, zero, 1);
1177 emitcode ("cpi", "r0,0");
1178 emitcode ("breq", "L%05d", tlbl->key);
1179 aopPut (res->aop, one, 1);
1180 emitcode ("", "L%05d:", tlbl->key);
1182 size = res->aop->size - 2;
1184 /* put zeros in the rest */
1186 aopPut (res->aop, zero, offset++);
1189 /*-----------------------------------------------------------------*/
1190 /* opIsGptr: returns non-zero if the passed operand is */
1191 /* a generic pointer type. */
1192 /*-----------------------------------------------------------------*/
1194 opIsGptr (operand * op)
1196 sym_link *type = operandType (op);
1198 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type)) {
1204 /*-----------------------------------------------------------------*/
1205 /* getDataSize - get the operand data size */
1206 /*-----------------------------------------------------------------*/
1208 getDataSize (operand * op)
1211 size = AOP_SIZE (op);
1212 if (size == GPTRSIZE) {
1213 sym_link *type = operandType (op);
1214 if (IS_GENPTR (type)) {
1215 /* generic pointer; arithmetic operations
1216 * should ignore the high byte (pointer type).
1224 /*-----------------------------------------------------------------*/
1225 /* toBoolean - emit code for orl a,operator(sizeop) */
1226 /*-----------------------------------------------------------------*/
1228 toBoolean (operand * oper, char *r, bool clr)
1230 int size = AOP_SIZE (oper);
1233 emitcode ("clr", "%s", r);
1235 emitcode ("or", "%s,%s", r, aopGet (AOP (oper), offset++));
1238 emitcode("mov","%s,%s",r,aopGet (AOP (oper), offset++));
1239 if (size) while (size--) emitcode ("or", "%s,%s", r, aopGet (AOP (oper), offset++));
1244 /*-----------------------------------------------------------------*/
1245 /* genNot - generate code for ! operation */
1246 /*-----------------------------------------------------------------*/
1251 sym_link *optype = operandType (IC_LEFT (ic));
1252 int size, offset = 1;
1254 /* assign asmOps to operand & result */
1255 aopOp (IC_LEFT (ic), ic, FALSE);
1256 aopOp (IC_RESULT (ic), ic, TRUE);
1258 /* if type float then do float */
1259 if (IS_FLOAT (optype)) {
1260 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1263 emitcode ("clr", "r24");
1264 tlbl = newiTempLabel (NULL);
1265 size = AOP_SIZE (IC_LEFT (ic));
1268 emitcode ("cpse", "%s,r24", aopGet (AOP (IC_LEFT (ic)), 0));
1273 emitcode ("cpc", "%s,r24",
1274 aopGet (AOP (IC_LEFT (ic)),
1277 emitcode ("cpi", "%s,0",
1278 aopGet (AOP (IC_LEFT (ic)),
1282 emitcode ("bne", "L%05d", tlbl->key);
1284 emitcode ("ldi", "r24,1");
1285 emitcode ("", "L%05d:", tlbl->key);
1286 aopPut (AOP (IC_RESULT (ic)), "r24", 0);
1287 size = AOP_SIZE (IC_RESULT (ic)) - 1;
1290 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
1294 /* release the aops */
1295 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1296 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1300 /*-----------------------------------------------------------------*/
1301 /* genCpl - generate code for complement */
1302 /*-----------------------------------------------------------------*/
1310 /* assign asmOps to operand & result */
1311 aopOp (IC_LEFT (ic), ic, FALSE);
1312 aopOp (IC_RESULT (ic), ic, TRUE);
1313 samer = sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)));
1314 size = AOP_SIZE (IC_RESULT (ic));
1316 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
1318 emitcode ("com", "%s", l);
1321 aopPut (AOP (IC_RESULT (ic)), l, offset);
1322 emitcode ("com", "%s",
1323 aopGet (AOP (IC_RESULT (ic)), offset));
1328 /* release the aops */
1329 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1330 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1333 /*-----------------------------------------------------------------*/
1334 /* genUminusFloat - unary minus for floating points */
1335 /*-----------------------------------------------------------------*/
1337 genUminusFloat (operand * op, operand * result)
1339 int size, offset = 0;
1341 /* for this we just need to flip the
1342 first it then copy the rest in place */
1343 size = AOP_SIZE (op) - 1;
1344 l = aopGet (AOP (op), 3);
1346 emitcode ("ldi", "r24,0x80");
1347 if (sameRegs (AOP (op), AOP (result))) {
1348 emitcode ("eor", "%s,r24", l);
1351 aopPut (AOP (result), l, 3);
1352 emitcode ("eor", "%s,r24", aopGet (AOP (result), 3));
1355 aopPut (AOP (result), aopGet (AOP (op), offset), offset);
1360 /*-----------------------------------------------------------------*/
1361 /* genUminus - unary minus code generation */
1362 /*-----------------------------------------------------------------*/
1364 genUminus (iCode * ic)
1367 sym_link *optype, *rtype;
1371 aopOp (IC_LEFT (ic), ic, FALSE);
1372 aopOp (IC_RESULT (ic), ic, TRUE);
1374 optype = operandType (IC_LEFT (ic));
1375 rtype = operandType (IC_RESULT (ic));
1377 /* if float then do float stuff */
1378 if (IS_FLOAT (optype)) {
1379 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1383 /* otherwise subtract from zero */
1384 size = AOP_SIZE (IC_LEFT (ic));
1386 samer = sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)));
1389 emitcode ("neg", "%s",
1390 aopGet (AOP (IC_LEFT (ic)), 0));
1393 aopPut (AOP (IC_RESULT (ic)),
1394 aopGet (AOP (IC_LEFT (ic)), 0), 0);
1395 emitcode ("neg", "%s",
1396 aopGet (AOP (IC_RESULT (ic)), 0));
1402 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
1404 aopPut (AOP (IC_RESULT (ic)), l, offset);
1405 l = aopGet (AOP (IC_RESULT (ic)), offset);
1408 emitcode ("com", "%s", l);
1410 emitcode ("neg", "%s", l);
1413 size = AOP_SIZE (IC_LEFT (ic)) - 1;
1416 emitcode ("sbci", "%s,0xff",
1417 aopGet (AOP (IC_RESULT (ic)), offset++));
1421 /* if any remaining bytes in the result */
1422 /* we just need to propagate the sign */
1423 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic))))) {
1424 symbol *tlbl = newiTempLabel (NULL);
1425 emitcode ("clr", "r0");
1426 emitcode ("brcc", "L%05d", tlbl->key);
1427 emitcode ("com", "r0");
1428 emitcode ("", "L%05d:", tlbl->key);
1430 aopPut (AOP (IC_RESULT (ic)), "r0", offset++);
1434 /* release the aops */
1435 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1436 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1439 /*-----------------------------------------------------------------*/
1440 /* assignResultValue - */
1441 /*-----------------------------------------------------------------*/
1443 assignResultValue (operand * oper)
1446 int size = AOP_SIZE (oper);
1448 aopPut (AOP (oper), fAVRReturn[offset], offset);
1453 /*-----------------------------------------------------------------*/
1454 /* saveZreg - if indirect call then save z-pointer register */
1455 /*-----------------------------------------------------------------*/
1457 saveZreg (iCode * ic)
1459 /* only if live accross this call */
1460 if (ic->regsSaved == 0 &&
1461 (bitVectBitValue (ic->rMask, R30_IDX) ||
1462 bitVectBitValue (ic->rMask, R31_IDX))) {
1464 emitcode ("push", "r30");
1465 emitcode ("push", "r31");
1469 /*-----------------------------------------------------------------*/
1470 /* popZreg - restore values of zreg */
1471 /*-----------------------------------------------------------------*/
1473 popZreg (iCode * ic)
1475 if (ic->regsSaved) {
1476 emitcode ("pop", "r31");
1477 emitcode ("pop", "r30");
1481 /*-----------------------------------------------------------------*/
1482 /* genIpush - genrate code for pushing this gets a little complex */
1483 /*-----------------------------------------------------------------*/
1485 genIpush (iCode * ic)
1487 int size, offset = 0;
1491 if (!ic->parmPush) {
1492 /* and the item is spilt then do nothing */
1493 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1498 for (lic = ic->next; lic; lic = lic->next)
1499 if (lic->op == PCALL)
1505 /* this is a paramter push */
1506 aopOp (IC_LEFT (ic), ic, FALSE);
1507 size = AOP_SIZE (IC_LEFT (ic));
1509 l = aopGet (AOP (IC_LEFT (ic)), offset++);
1510 emitcode ("push", "%s", l);
1513 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1516 /*-----------------------------------------------------------------*/
1517 /* genIpop - recover the registers: can happen only for spilling */
1518 /*-----------------------------------------------------------------*/
1520 genIpop (iCode * ic)
1525 /* if the temp was not pushed then */
1526 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1529 aopOp (IC_LEFT (ic), ic, FALSE);
1530 size = AOP_SIZE (IC_LEFT (ic));
1531 offset = (size - 1);
1533 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--));
1535 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1538 /*-----------------------------------------------------------------*/
1539 /* genCall - generates a call statement */
1540 /*-----------------------------------------------------------------*/
1542 genCall (iCode * ic)
1545 /* if send set is not empty the assign */
1549 for (sic = setFirstItem (_G.sendSet); sic;
1550 sic = setNextItem (_G.sendSet)) {
1551 int size, offset = 0;
1552 aopOp (IC_LEFT (sic), sic, FALSE);
1553 size = AOP_SIZE (IC_LEFT (sic));
1556 aopGet (AOP (IC_LEFT (sic)), offset);
1558 sprintf (buffer, "r%d", rnum++);
1560 emitcode ("mov", "%s,%s", b, l);
1563 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1568 emitcode ("call", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1569 OP_SYMBOL (IC_LEFT (ic))->rname :
1570 OP_SYMBOL (IC_LEFT (ic))->name));
1572 /* if we need assign a result value */
1573 if ((IS_ITEMP (IC_RESULT (ic)) &&
1574 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1575 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1576 IS_TRUE_SYMOP (IC_RESULT (ic))) {
1578 aopOp (IC_RESULT (ic), ic, FALSE);
1579 assignResultValue (IC_RESULT (ic));
1580 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1583 /* adjust the stack for parameters if required */
1584 if (ic->parmBytes) {
1585 if (ic->parmBytes > 63) {
1586 emitcode ("sbiw", "r28,%d", ic->parmBytes);
1589 emitcode ("subi", "r28,<(%d)",
1591 emitcode ("sbci", "r29,>(%d)",
1598 /*-----------------------------------------------------------------*/
1599 /* genPcall - generates a call by pointer statement */
1600 /*-----------------------------------------------------------------*/
1602 genPcall (iCode * ic)
1608 aopOp (IC_LEFT (ic), ic, FALSE);
1609 emitcode ("mov", "r30", aopGet (AOP (IC_LEFT (ic)), 0));
1610 emitcode ("mov", "r31", aopGet (AOP (IC_RIGHT (ic)), 0));
1611 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1613 /* if send set is not empty the assign */
1617 for (sic = setFirstItem (_G.sendSet); sic;
1618 sic = setNextItem (_G.sendSet)) {
1619 int size, offset = 0;
1620 aopOp (IC_LEFT (sic), sic, FALSE);
1621 size = AOP_SIZE (IC_LEFT (sic));
1624 aopGet (AOP (IC_LEFT (sic)), offset);
1626 sprintf (b, "r%d", rnum++);
1628 emitcode ("mov", "%s,%s", b, l);
1631 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1636 emitcode ("icall", "");
1638 /* if we need assign a result value */
1639 if ((IS_ITEMP (IC_RESULT (ic)) &&
1640 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1641 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1642 IS_TRUE_SYMOP (IC_RESULT (ic))) {
1644 aopOp (IC_RESULT (ic), ic, FALSE);
1646 assignResultValue (IC_RESULT (ic));
1647 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1650 /* adjust the stack for parameters if
1652 if (ic->parmBytes) {
1654 if (ic->parmBytes > 3) {
1655 emitcode ("mov", "a,%s", spname);
1656 emitcode ("add", "a,#0x%02x",
1657 (-ic->parmBytes) & 0xff);
1658 emitcode ("mov", "%s,a", spname);
1661 for (i = 0; i < ic->parmBytes; i++)
1662 emitcode ("dec", "%s", spname);
1666 /* adjust the stack for parameters if required */
1667 if (ic->parmBytes) {
1668 if (ic->parmBytes > 63) {
1669 emitcode ("sbiw", "r28,%d", ic->parmBytes);
1672 emitcode ("subi", "r28,<(%d)",
1674 emitcode ("sbci", "r29,>(%d)",
1682 /*-----------------------------------------------------------------*/
1683 /* resultRemat - result is rematerializable */
1684 /*-----------------------------------------------------------------*/
1686 resultRemat (iCode * ic)
1688 if (SKIP_IC (ic) || ic->op == IFX)
1691 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic))) {
1692 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
1693 if (sym->remat && !POINTER_SET (ic))
1700 #if defined(__BORLANDC__) || defined(_MSC_VER)
1701 #define STRCASECMP stricmp
1703 #define STRCASECMP strcasecmp
1706 /*-----------------------------------------------------------------*/
1707 /* genFunction - generated code for function entry */
1708 /*-----------------------------------------------------------------*/
1710 genFunction (iCode * ic)
1717 /* create the function header */
1718 emitcode (";", "-----------------------------------------");
1719 emitcode (";", " function %s",
1720 (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
1721 emitcode (";", "-----------------------------------------");
1723 emitcode ("", "%s:", sym->rname);
1724 fetype = getSpec (operandType (IC_LEFT (ic)));
1726 /* if critical function then turn interrupts off */
1727 if (SPEC_CRTCL (fetype))
1728 emitcode ("cli", "");
1730 if (IS_ISR (sym->etype)) {
1733 /* save the preserved registers that are used in this function */
1734 for (i = R2_IDX; i <= R15_IDX; i++) {
1735 if (bitVectBitValue (sym->regsUsed, i)) {
1737 emitcode ("push", "%s", avr_regWithIdx (i)->name);
1740 /* now for the pointer registers */
1741 if (bitVectBitValue (sym->regsUsed, R26_IDX)) {
1743 emitcode ("push", "r26");
1745 if (bitVectBitValue (sym->regsUsed, R27_IDX)) {
1747 emitcode ("push", "r27");
1749 if (bitVectBitValue (sym->regsUsed, R30_IDX)) {
1751 emitcode ("push", "r30");
1753 if (bitVectBitValue (sym->regsUsed, R31_IDX)) {
1755 emitcode ("push", "r31");
1757 /* adjust the stack for the function */
1759 emitcode ("push", "r28");
1760 emitcode ("push", "r29");
1761 emitcode ("in", "r28,__SP_L__");
1762 emitcode ("in", "r29,__SP_H__");
1763 if (sym->stack <= 63) {
1764 emitcode ("sbiw", "r28,%d", sym->stack);
1767 emitcode ("subi", "r28,<(%d)", sym->stack);
1768 emitcode ("sbci", "r29,>(%d)", sym->stack);
1770 emitcode ("out", "__SP_L__,r28");
1771 emitcode ("out", "__SP_H__,r29");
1775 /*-----------------------------------------------------------------*/
1776 /* genEndFunction - generates epilogue for functions */
1777 /*-----------------------------------------------------------------*/
1779 genEndFunction (iCode * ic)
1781 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
1784 /* restore stack pointer */
1786 if (sym->stack <= 63) {
1787 emitcode ("adiw", "r28,%d", sym->stack);
1790 emitcode ("subi", "r28,<(-%d)", sym->stack);
1791 emitcode ("sbci", "r29,>(-%d)", sym->stack);
1793 emitcode ("out", "__SP_L__,r28");
1794 emitcode ("out", "__SP_H__,r29");
1796 /* pop frame pointer */
1797 emitcode ("pop", "r29");
1798 emitcode ("pop", "r28");
1800 /* restore preserved registers */
1801 if (bitVectBitValue (sym->regsUsed, R31_IDX)) {
1803 emitcode ("pop", "r31");
1805 if (bitVectBitValue (sym->regsUsed, R30_IDX)) {
1807 emitcode ("pop", "r30");
1809 if (bitVectBitValue (sym->regsUsed, R27_IDX)) {
1811 emitcode ("pop", "r27");
1813 if (bitVectBitValue (sym->regsUsed, R26_IDX)) {
1815 emitcode ("pop", "r26");
1817 for (i = R15_IDX; i >= R2_IDX; i--) {
1818 if (bitVectBitValue (sym->regsUsed, i)) {
1820 emitcode ("pop", "%s", avr_regWithIdx (i)->name);
1824 if (SPEC_CRTCL (sym->etype))
1825 emitcode ("sti", "");
1827 if (IS_ISR (sym->etype)) {
1828 emitcode ("rti", "");
1831 emitcode ("ret", "");
1836 /*-----------------------------------------------------------------*/
1837 /* genRet - generate code for return statement */
1838 /*-----------------------------------------------------------------*/
1842 int size, offset = 0;
1844 /* if we have no return value then
1845 just generate the "ret" */
1849 /* we have something to return then
1850 move the return value into place */
1851 aopOp (IC_LEFT (ic), ic, FALSE);
1852 size = AOP_SIZE (IC_LEFT (ic));
1855 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) {
1856 emitcode ("ldi", "%s,%s(%d)", fAVRReturn[offset],
1858 (int) floatFromVal (AOP (IC_LEFT (ic))->
1859 aopu.aop_lit), offset);
1863 l = aopGet (AOP (IC_LEFT (ic)), offset);
1864 if (strcmp (fAVRReturn[offset], l))
1865 emitcode ("mov", "%s,%s", fAVRReturn[offset],
1871 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1874 /* generate a jump to the return label
1875 if the next is not the return statement */
1876 if (!(ic->next && ic->next->op == LABEL &&
1877 IC_LABEL (ic->next) == returnLabel))
1879 emitcode ("rjmp", "L%05d", returnLabel->key);
1883 /*-----------------------------------------------------------------*/
1884 /* genLabel - generates a label */
1885 /*-----------------------------------------------------------------*/
1887 genLabel (iCode * ic)
1889 /* special case never generate */
1890 if (IC_LABEL (ic) == entryLabel)
1893 emitcode ("", "L%05d:", IC_LABEL (ic)->key);
1896 /*-----------------------------------------------------------------*/
1897 /* genGoto - generates a ljmp */
1898 /*-----------------------------------------------------------------*/
1900 genGoto (iCode * ic)
1902 emitcode ("rjmp", "L%05d", (IC_LABEL (ic)->key));
1905 /*-----------------------------------------------------------------*/
1906 /* genPlusIncr :- does addition with increment if possible */
1907 /*-----------------------------------------------------------------*/
1909 genPlusIncr (iCode * ic)
1911 unsigned int icount;
1914 /* will try to generate an increment */
1915 /* if the right side is not a literal
1917 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
1920 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.
1923 /* if the sizes are greater than 2 or they are not the same regs
1925 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1928 /* so we know LEFT & RESULT in the same registers and add
1930 /* for short & char types */
1931 if (AOP_SIZE (IC_RESULT (ic)) < 2) {
1933 emitcode ("inc", "%s",
1934 aopGet (AOP (IC_LEFT (ic)), 0));
1937 if (AOP_ISHIGHREG( AOP (IC_LEFT (ic)),0)) {
1938 emitcode ("subi", "%s,<(%d)",
1939 aopGet (AOP (IC_LEFT (ic)), 0), 0-icount);
1944 for (offset = 0 ; offset < AOP_SIZE(IC_RESULT(ic)) ; offset++) {
1945 if (!(AOP_ISHIGHREG(AOP(IC_RESULT(ic)),offset))) return FALSE;
1948 if (AOP_SIZE (IC_RESULT (ic)) <= 3) {
1949 /* if register pair and starts with 26/30 then adiw */
1950 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0
1952 && (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX) ||
1953 IS_REGIDX (AOP (IC_RESULT (ic)), R24_IDX) ||
1954 IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX))) {
1955 emitcode ("adiw", "%s,%d",
1956 aopGet (AOP (IC_RESULT (ic)), 0), icount);
1961 emitcode ("subi", "%s,<(%d)",
1962 aopGet (AOP (IC_RESULT (ic)), 0), 0-icount);
1963 emitcode ("sbci", "%s,>(%d)",
1964 aopGet (AOP (IC_RESULT (ic)), 1), 0-icount);
1968 /* for 32 bit longs */
1969 emitcode ("subi", "%s,<(%d)", aopGet (AOP (IC_RESULT (ic)), 0),
1971 emitcode ("sbci", "%s,>(%d)", aopGet (AOP (IC_RESULT (ic)), 1),
1973 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2),
1975 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3),
1981 /* This is the pure and virtuous version of this code.
1982 * I'm pretty certain it's right, but not enough to toss the old
1986 adjustArithmeticResult (iCode * ic)
1988 if (opIsGptr (IC_RESULT (ic)) &&
1989 opIsGptr (IC_LEFT (ic)) &&
1990 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)))) {
1991 aopPut (AOP (IC_RESULT (ic)),
1992 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1),
1996 if (opIsGptr (IC_RESULT (ic)) &&
1997 opIsGptr (IC_RIGHT (ic)) &&
1998 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)))) {
1999 aopPut (AOP (IC_RESULT (ic)),
2000 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1),
2004 if (opIsGptr (IC_RESULT (ic)) &&
2005 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2006 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2007 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2008 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)))) {
2010 sprintf (buffer, "%d",
2011 pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2012 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2016 /*-----------------------------------------------------------------*/
2017 /* genPlus - generates code for addition */
2018 /*-----------------------------------------------------------------*/
2020 genPlus (iCode * ic)
2022 int size, offset = 0;
2026 /* special cases :- */
2028 aopOp (IC_LEFT (ic), ic, FALSE);
2029 aopOp (IC_RIGHT (ic), ic, FALSE);
2030 aopOp (IC_RESULT (ic), ic, TRUE);
2032 /* if I can do an increment instead
2033 of add then GOOD for ME */
2034 if (genPlusIncr (ic) == TRUE)
2037 size = getDataSize (IC_RESULT (ic));
2038 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2042 aopPut (AOP (IC_RESULT (ic)),
2043 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2045 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
2052 emitcode (l, "%s,%s",
2053 aopGet (AOP (IC_RESULT (ic)), offset),
2054 aopGet (AOP (IC_RIGHT (ic)), offset));
2057 if (AOP_ISHIGHREG( AOP( IC_RESULT(ic)),offset)) {
2063 emitcode (l, "%s,%s(-%d)",
2064 aopGet (AOP (IC_RESULT (ic)), offset),
2066 (int) floatFromVal (AOP (IC_RIGHT (ic))->
2074 emitcode (l, "%s,%s",
2075 aopGet (AOP (IC_RESULT (ic)), offset),
2076 aopGet (AOP (IC_RIGHT (ic)), offset));
2082 adjustArithmeticResult (ic);
2085 freeAsmop (IC_LEFT (ic), NULL, ic,
2086 (RESULTONSTACK (ic) ? FALSE : TRUE));
2087 freeAsmop (IC_RIGHT (ic), NULL, ic,
2088 (RESULTONSTACK (ic) ? FALSE : TRUE));
2089 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2092 /*-----------------------------------------------------------------*/
2093 /* genMinusDec :- does subtraction with deccrement if possible */
2094 /*-----------------------------------------------------------------*/
2096 genMinusDec (iCode * ic)
2098 unsigned int icount;
2101 /* will try to generate an increment */
2102 /* if the right side is not a literal
2104 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2108 (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.
2111 /* if the sizes are greater than 2 or they are not the same regs
2113 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic))))
2116 /* so we know LEFT & RESULT in the same registers and add
2118 /* for short & char types */
2119 if (AOP_SIZE (IC_RESULT (ic)) < 2) {
2121 emitcode ("dec", "%s",
2122 aopGet (AOP (IC_LEFT (ic)), 0));
2125 if (AOP_ISHIGHREG( AOP ( IC_LEFT(ic)),0)) {
2126 emitcode ("subi", "%s,<(%d)",
2127 aopGet (AOP (IC_LEFT (ic)), 0), icount);
2132 for (offset = 0 ; offset < AOP_SIZE(IC_RESULT(ic)) ; offset++) {
2133 if (!(AOP_ISHIGHREG(AOP(IC_RESULT(ic)),offset))) return FALSE;
2136 if (AOP_SIZE (IC_RESULT (ic)) <= 3) {
2137 /* if register pair and starts with 26/30 then adiw */
2138 if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0
2140 && (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX) ||
2141 IS_REGIDX (AOP (IC_RESULT (ic)), R24_IDX) ||
2142 IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX))) {
2143 emitcode ("sbiw", "%s,%d",
2144 aopGet (AOP (IC_RESULT (ic)), 0), icount);
2149 emitcode ("subi", "%s,<(%d)",
2150 aopGet (AOP (IC_RESULT (ic)), 0), icount);
2151 emitcode ("sbci", "%s,>(%d)",
2152 aopGet (AOP (IC_RESULT (ic)), 1), icount);
2155 /* for 32 bit longs */
2156 emitcode ("subi", "%s,<(%d)", aopGet (AOP (IC_RESULT (ic)), 0),
2158 emitcode ("sbci", "%s,>(%d)", aopGet (AOP (IC_RESULT (ic)), 1),
2160 emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2),
2162 emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3),
2168 /*-----------------------------------------------------------------*/
2169 /* genMinus - generates code for subtraction */
2170 /*-----------------------------------------------------------------*/
2172 genMinus (iCode * ic)
2174 int size, offset = 0, samer;
2177 aopOp (IC_LEFT (ic), ic, FALSE);
2178 aopOp (IC_RIGHT (ic), ic, FALSE);
2179 aopOp (IC_RESULT (ic), ic, TRUE);
2181 /* if I can do an decrement instead
2182 of subtract then GOOD for ME */
2183 if (genMinusDec (ic) == TRUE)
2186 size = getDataSize (IC_RESULT (ic));
2187 samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2190 aopPut (AOP (IC_RESULT (ic)),
2191 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2193 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
2200 emitcode (l, "%s,%s",
2201 aopGet (AOP (IC_RESULT (ic)), offset),
2202 aopGet (AOP (IC_RIGHT (ic)), offset));
2205 if (AOP_ISHIGHREG(AOP (IC_RESULT (ic)),offset)) {
2211 emitcode (l, "%s,%s(%d)",
2212 aopGet (AOP (IC_RESULT (ic)), offset),
2214 (int) floatFromVal (AOP (IC_RIGHT (ic))->
2222 emitcode (l, "%s,%s",
2223 aopGet (AOP (IC_RESULT (ic)), offset),
2224 aopGet (AOP (IC_RIGHT (ic)), offset));
2230 adjustArithmeticResult (ic);
2233 freeAsmop (IC_LEFT (ic), NULL, ic,
2234 (RESULTONSTACK (ic) ? FALSE : TRUE));
2235 freeAsmop (IC_RIGHT (ic), NULL, ic,
2236 (RESULTONSTACK (ic) ? FALSE : TRUE));
2237 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2240 /*-----------------------------------------------------------------*/
2241 /* genMultOneByte : 8 bit multiplication & division */
2242 /*-----------------------------------------------------------------*/
2244 genMultOneByte (operand * left, operand * right, operand * result)
2246 sym_link *opetype = operandType (result);
2250 /* (if two literals, the value is computed before) */
2251 /* if one literal, literal on the right */
2252 if (AOP_TYPE (left) == AOP_LIT) {
2258 size = AOP_SIZE (result);
2260 if (SPEC_USIGN (opetype)) {
2261 emitcode ("mul", "%s,%s", aopGet (AOP (left), 0),
2262 aopGet (AOP (right), 0));
2265 emitcode ("muls", "%s,%s", aopGet (AOP (left), 0),
2266 aopGet (AOP (right), 0));
2268 aopPut (AOP (result), "r0", 0);
2270 aopPut (AOP (result), "r1", 1);
2273 if (SPEC_USIGN (opetype)) {
2275 aopPut (AOP (result), zero, offset++);
2280 lbl = newiTempLabel (NULL);
2281 emitcode ("ldi", "r24,0");
2282 emitcode ("brcc", "L%05d", lbl->key);
2283 emitcode ("ldi", "r24,0xff)");
2284 emitcode ("", "L%05d:", lbl->key);
2286 aopPut (AOP (result), "r24",
2294 /*-----------------------------------------------------------------*/
2295 /* genMult - generates code for multiplication */
2296 /*-----------------------------------------------------------------*/
2298 genMult (iCode * ic)
2300 operand *left = IC_LEFT (ic);
2301 operand *right = IC_RIGHT (ic);
2302 operand *result = IC_RESULT (ic);
2304 /* assign the amsops */
2305 aopOp (left, ic, FALSE);
2306 aopOp (right, ic, FALSE);
2307 aopOp (result, ic, TRUE);
2309 /* if both are of size == 1 */
2310 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1) {
2311 genMultOneByte (left, right, result);
2315 /* should have been converted to function call */
2319 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2320 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2321 freeAsmop (result, NULL, ic, TRUE);
2324 /*-----------------------------------------------------------------*/
2325 /* genDiv - generates code for division */
2326 /*-----------------------------------------------------------------*/
2330 /* should have been converted to function call */
2334 /*-----------------------------------------------------------------*/
2335 /* genMod - generates code for division */
2336 /*-----------------------------------------------------------------*/
2340 /* should have been converted to function call */
2352 /*-----------------------------------------------------------------*/
2353 /* revavrcnd - reverse a conditional for avr */
2354 /*-----------------------------------------------------------------*/
2356 revavrcnd (int type)
2368 for (i = 0; i < (sizeof (rar) / sizeof (rar[0])); i++) {
2369 if (rar[i].type == type)
2370 return rar[i].rtype;
2371 if (rar[i].rtype == type)
2374 assert (1); /* cannot happen */
2375 return 0; /* makes the compiler happy */
2378 static char *br_name[4] = { "breq", "brne", "brlt", "brge" };
2379 static char *br_uname[4] = { "breq", "brne", "brlo", "brcc" };
2381 /*-----------------------------------------------------------------*/
2382 /* genBranch - generate the branch instruction */
2383 /*-----------------------------------------------------------------*/
2385 genBranch (iCode * ifx, int br_type, int sign)
2387 int tj = (IC_TRUE (ifx) ? 1 : 0);
2389 if (tj) { /* if true jump */
2390 char *nm = (sign ? br_name[br_type] : br_uname[br_type]);
2391 emitcode (nm, "L%05d", IC_TRUE (ifx)->key);
2393 else { /* if false jump */
2394 int rtype = revavrcnd (br_type);
2395 char *nm = (sign ? br_name[rtype] : br_uname[rtype]);
2396 emitcode (nm, "L%05d", IC_FALSE (ifx)->key);
2401 /*-----------------------------------------------------------------*/
2402 /* genCmp - compare & jump */
2403 /*-----------------------------------------------------------------*/
2405 genCmp (iCode * ic, iCode * ifx, int br_type)
2407 operand *left, *right, *result;
2408 sym_link *letype, *retype;
2410 int sign, size, offset = 0;
2412 left = IC_LEFT (ic);
2413 right = IC_RIGHT (ic);
2414 result = IC_RESULT (ic);
2416 letype = getSpec (operandType (left));
2417 retype = getSpec (operandType (right));
2418 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
2420 /* assign the amsops */
2421 aopOp (left, ic, FALSE);
2422 aopOp (right, ic, FALSE);
2423 aopOp (result, ic, TRUE);
2424 size = AOP_SIZE (left);
2428 if (AOP_TYPE (right) == AOP_LIT) {
2429 emitcode ("cpi", "%s,<(%d)",
2430 aopGet (AOP (left), 0),
2432 floatFromVal (AOP (IC_RIGHT (ic))->
2434 genBranch (ifx, br_type, sign);
2436 else { /* right != literal */
2437 emitcode ("cp", "%s,%s",
2438 aopGet (AOP (left), 0),
2439 aopGet (AOP (right), 0));
2440 genBranch (ifx, br_type, sign);
2443 else { /* size != 1 */
2446 emitcode ("cp", "%s,%s",
2447 aopGet (AOP (left), 0),
2448 aopGet (AOP (right), 0));
2450 emitcode ("cpc", "%s,%s",
2451 aopGet (AOP (left), offset),
2452 aopGet (AOP (right),
2456 genBranch (ifx, br_type, sign);
2460 emitcode ("clr", "r0");
2463 emitcode ("cp", "%s,%s",
2464 aopGet (AOP (left), 0),
2465 aopGet (AOP (right), 0));
2467 emitcode ("cpc", "%s,%s",
2468 aopGet (AOP (left), offset),
2469 aopGet (AOP (right), offset));
2472 lbl = newiTempLabel (NULL);
2473 br_type = revavrcnd (br_type);
2475 emitcode (br_uname[br_type], "L%05d", lbl->key);
2477 emitcode (br_name[br_type], "L%05d", lbl->key);
2478 emitcode ("inc", "r0");
2479 emitcode ("", "L%05d:", lbl->key);
2480 aopPut (AOP (result), "r0", 0);
2481 size = AOP_SIZE (result) - 1;
2484 aopPut (AOP (result), zero, offset++);
2487 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2488 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2489 freeAsmop (result, NULL, ic, TRUE);
2492 /*-----------------------------------------------------------------*/
2493 /* genCmpGt :- greater than comparison */
2494 /*-----------------------------------------------------------------*/
2496 genCmpGt (iCode * ic, iCode * ifx)
2498 /* should have transformed by the parser */
2502 /*-----------------------------------------------------------------*/
2503 /* genCmpLt - less than comparisons */
2504 /*-----------------------------------------------------------------*/
2506 genCmpLt (iCode * ic, iCode * ifx)
2508 genCmp (ic, ifx, AVR_LT);
2511 /*-----------------------------------------------------------------*/
2512 /* genCmpEq - generates code for equal to */
2513 /*-----------------------------------------------------------------*/
2515 genCmpEq (iCode * ic, iCode * ifx)
2517 genCmp (ic, ifx, AVR_EQ);
2520 /*-----------------------------------------------------------------*/
2521 /* genCmpNe - generates code for not equal to */
2522 /*-----------------------------------------------------------------*/
2524 genCmpNe (iCode * ic, iCode * ifx)
2526 genCmp (ic, ifx, AVR_NE);
2529 /*-----------------------------------------------------------------*/
2530 /* genCmpGe - generates code for greater than equal to */
2531 /*-----------------------------------------------------------------*/
2533 genCmpGe (iCode * ic, iCode * ifx)
2535 genCmp (ic, ifx, AVR_GE);
2538 /*-----------------------------------------------------------------*/
2539 /* genCmpLe - generates code for less than equal to */
2540 /*-----------------------------------------------------------------*/
2542 genCmpLe (iCode * ic, iCode * ifx)
2544 operand *left = IC_LEFT (ic);
2545 operand *right = IC_RIGHT (ic);
2547 IC_RIGHT (ic) = left;
2548 IC_LEFT (ic) = right;
2549 genCmp (ic, ifx, AVR_GE);
2552 /*-----------------------------------------------------------------*/
2553 /* ifxForOp - returns the icode containing the ifx for operand */
2554 /*-----------------------------------------------------------------*/
2556 ifxForOp (operand * op, iCode * ic)
2558 /* if true symbol then needs to be assigned */
2559 if (IS_TRUE_SYMOP (op))
2562 /* if this has register type condition and
2563 the next instruction is ifx with the same operand
2564 and live to of the operand is upto the ifx only then */
2566 ic->next->op == IFX &&
2567 IC_COND (ic->next)->key == op->key &&
2568 OP_SYMBOL (op)->liveTo <= ic->next->seq) return ic->next;
2573 /*-----------------------------------------------------------------*/
2574 /* genAndOp - for && operation */
2575 /*-----------------------------------------------------------------*/
2577 genAndOp (iCode * ic)
2579 operand *left, *right, *result;
2583 /* note here that && operations that are in an
2584 if statement are taken away by backPatchLabels
2585 only those used in arthmetic operations remain */
2586 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2587 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2588 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
2590 tlbl = newiTempLabel (NULL);
2591 toBoolean (left, "r0", TRUE);
2592 toBoolean (right, "r1", TRUE);
2593 emitcode ("and", "r0,r1");
2594 emitcode ("ldi", "r24,1");
2595 emitcode ("breq", "L%05d", tlbl->key);
2596 emitcode ("dec", "r24");
2597 emitcode ("", "L%05d:", tlbl->key);
2598 aopPut (AOP (result), "r24", 0);
2599 size = AOP_SIZE (result) - 1;
2602 aopPut (AOP (result), zero, offset++);
2604 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2605 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2606 freeAsmop (result, NULL, ic, TRUE);
2610 /*-----------------------------------------------------------------*/
2611 /* genOrOp - for || operation */
2612 /*-----------------------------------------------------------------*/
2614 genOrOp (iCode * ic)
2616 operand *left, *right, *result;
2620 /* note here that || operations that are in an
2621 if statement are taken away by backPatchLabels
2622 only those used in arthmetic operations remain */
2623 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2624 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2625 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
2627 tlbl = newiTempLabel (NULL);
2628 toBoolean (left, "r0", TRUE);
2629 toBoolean (right, "r0", FALSE);
2630 emitcode ("ldi", "r24,1");
2631 emitcode ("breq", "L%05d", tlbl->key);
2632 emitcode ("dec", "r24");
2633 emitcode ("", "L%05d:", tlbl->key);
2634 aopPut (AOP (result), "r24", 0);
2635 size = AOP_SIZE (result) - 1;
2638 aopPut (AOP (result), zero, offset++);
2640 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2641 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2642 freeAsmop (result, NULL, ic, TRUE);
2646 AVR_AND = 0, AVR_OR, AVR_XOR
2648 static char *bopnames_lit[] = { "andi", "ori" };
2649 static char *bopnames[] = { "and", "or", "eor" };
2650 /*-----------------------------------------------------------------*/
2651 /* genBitWise - generate bitwise operations */
2652 /*-----------------------------------------------------------------*/
2654 genBitWise (iCode * ic, iCode * ifx, int bitop)
2656 operand *left, *right, *result;
2657 int size, offset = 0;
2662 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
2663 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
2664 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
2666 size = AOP_SIZE (left);
2668 if (ifx) { /* used only for jumps */
2669 if (AOP_TYPE (right) == AOP_LIT &&
2670 (bitop == AVR_AND || bitop == AVR_OR)) {
2672 (int) floatFromVal (AOP (right)->aopu.
2674 int p2 = powof2 (lit);
2675 if (bitop == AVR_AND && p2) { /* right side is a power of 2 */
2676 l = aopGet (AOP (left), p2 / 8);
2677 if (IC_TRUE (ifx)) {
2678 emitcode ("sbrc", "%s,%d", l,
2680 emitcode ("rjmp", "L%05d",
2681 IC_TRUE (ifx)->key);
2684 emitcode ("sbrs", "%s,%d", l,
2686 emitcode ("rjmp", "L%05d",
2687 IC_FALSE (ifx)->key);
2690 else { /* right not power of two */
2691 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2693 if (eh && AOP_ISHIGHREG(AOP(IC_LEFT(ic)),0)) {
2694 emitcode (bopnames_lit[bitop],
2696 aopGet (AOP (IC_LEFT (ic)), 0), lit);
2699 MOVR24 (aopGet (AOP (IC_LEFT (ic)), 0));
2700 emitcode (bopnames_lit[bitop], "r24,<(%d)", lit);
2702 lbl = newiTempLabel (NULL);
2703 if (IC_TRUE (ifx)) {
2704 emitcode ("breq", "L%05d", lbl->key);
2705 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2708 emitcode ("brne", "L%05d", lbl->key);
2709 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)-> key);
2711 emitcode ("", "L%05d:", lbl->key);
2713 else if (size == 2) {
2714 emitcode ("mov", "r24,%s", aopGet (AOP (IC_LEFT (ic)), 0));
2715 emitcode ("mov", "r25,%s", aopGet (AOP (IC_LEFT (ic)), 1));
2716 emitcode (bopnames_lit[bitop], "r24,<(%d)", lit);
2717 emitcode (bopnames_lit[bitop], "r25,>(%d)", lit);
2718 emitcode ("sbiw", "r24,0");
2719 lbl = newiTempLabel (NULL);
2720 if (IC_TRUE (ifx)) {
2721 emitcode ("breq", "L%05d", lbl->key);
2722 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2725 emitcode ("brne", "L%05d", lbl->key);
2726 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2728 emitcode ("", "L%05d:", lbl->key);
2731 lbl = newiTempLabel (NULL);
2732 lbl1 = newiTempLabel (NULL);
2734 if (eh && AOP_ISHIGHREG(AOP(IC_LEFT(ic)),offset)) {
2735 emitcode (bopnames_lit [bitop], "%s,<(%d)",
2736 aopGet (AOP (IC_LEFT (ic)), offset),
2740 char *l = aopGet (AOP (IC_LEFT (ic)), offset);
2742 emitcode ("andi", "r24,<(%d)", lit);
2744 emitcode ("brne", "L%05d", lbl->key);
2749 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)-> key);
2751 emitcode ("rjmp", "L%05d", lbl1->key);
2752 emitcode ("", "L%05d:", lbl->key);
2755 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2756 emitcode ("", "L%05d:", lbl1->key);
2761 else { /* right is not a literal */
2762 int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
2763 int reh = OP_SYMBOL (right)->liveTo <= ic->seq;
2766 emitcode (bopnames[bitop], "%s,%s", aopGet (AOP (IC_LEFT (ic)), 0),
2767 aopGet (AOP (IC_RIGHT (ic)), 0));
2770 emitcode (bopnames[bitop], "%s,%s",
2771 aopGet (AOP (IC_RIGHT (ic)), 0),
2772 aopGet (AOP (IC_LEFT (ic)), 0));
2775 MOVR0 (aopGet (AOP (IC_LEFT (ic)), 0));
2776 emitcode (bopnames[bitop], "r0,%s",
2777 aopGet (AOP (IC_RIGHT (ic)), 0));
2779 lbl = newiTempLabel (NULL);
2780 if (IC_TRUE (ifx)) {
2781 emitcode ("breq", "L%05d", lbl->key);
2782 emitcode ("rjmp", "L%05d",
2783 IC_TRUE (ifx)->key);
2786 emitcode ("brne", "L%05d", lbl->key);
2787 emitcode ("rjmp", "L%05d",
2788 IC_FALSE (ifx)->key);
2790 emitcode ("", "L%05d:", lbl->key);
2792 else if (size == 2) {
2793 emitcode ("mov", "r24,%s",
2794 aopGet (AOP (IC_LEFT (ic)), 0));
2795 emitcode ("mov", "r25,%s",
2796 aopGet (AOP (IC_LEFT (ic)), 1));
2797 emitcode (bopnames[bitop], "r24,%s",
2798 aopGet (AOP (IC_RIGHT (ic)), 0));
2799 emitcode (bopnames[bitop], "r25,%s",
2800 aopGet (AOP (IC_RIGHT (ic)), 1));
2801 emitcode ("sbiw", "r24,0");
2802 lbl = newiTempLabel (NULL);
2803 if (IC_TRUE (ifx)) {
2804 emitcode ("breq", "L%05d", lbl->key);
2805 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2808 emitcode ("brne", "L%05d", lbl->key);
2809 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2811 emitcode ("", "L%05d:", lbl->key);
2814 lbl = newiTempLabel (NULL);
2815 lbl1 = newiTempLabel (NULL);
2818 emitcode (bopnames[bitop], "%s,%s",
2819 aopGet (AOP (IC_LEFT (ic)), offset),
2820 aopGet (AOP (IC_RIGHT (ic)), offset));
2823 emitcode (bopnames[bitop], "%s,%s",
2824 aopGet (AOP (IC_RIGHT (ic)), offset),
2825 aopGet (AOP (IC_LEFT (ic)), offset));
2828 MOVR0 (aopGet (AOP (IC_LEFT (ic)), offset));
2829 emitcode (bopnames[bitop], "r0,%s",
2830 aopGet (AOP (IC_RIGHT (ic)), offset));
2832 emitcode ("brne", "L%05d", lbl->key);
2837 emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
2839 emitcode ("rjmp", "L%05d", lbl1->key);
2840 emitcode ("", "L%05d:", lbl->key);
2843 emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
2844 emitcode ("", "L%05d:", lbl1->key);
2851 /* result needs to go a register */
2852 samerl = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
2853 samerr = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)));
2855 if (AOP_TYPE (right) == AOP_LIT) {
2857 (int) floatFromVal (AOP (right)->aopu.
2859 if (((lit >> (8 * offset)) & 0xff) == 0) {
2860 if (bitop == AVR_AND) {
2861 aopPut (AOP (result), zero, offset++);
2864 else if (bitop == AVR_OR) {
2866 aopPut (AOP (result),
2876 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT &&
2877 AOP_ISHIGHREG(AOP(IC_LEFT(ic)),offset) &&
2878 (bitop == AVR_AND || bitop == AVR_OR)) {
2879 emitcode (bopnames_lit[bitop], "%s,%s(%d)",
2880 aopGet (AOP (IC_LEFT (ic)), offset),
2882 (int) floatFromVal (AOP (right)-> aopu.aop_lit));
2885 emitcode (bopnames[bitop], "%s,%s",
2886 aopGet (AOP (IC_LEFT (ic)), offset),
2887 aopGet (AOP (IC_RIGHT (ic)), offset));
2891 emitcode (bopnames[bitop], "%s,%s",
2892 aopGet (AOP (IC_RIGHT (ic)), offset),
2893 aopGet (AOP (IC_LEFT (ic)), offset));
2896 aopPut (AOP (IC_RESULT (ic)),
2897 aopGet (AOP (IC_LEFT (ic)), offset), offset);
2898 emitcode (bopnames[bitop],
2899 aopGet (AOP (IC_RESULT (ic)), offset),
2900 aopGet (AOP (IC_RIGHT (ic)), offset));
2905 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2906 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2907 freeAsmop (result, NULL, ic, TRUE);
2910 /*-----------------------------------------------------------------*/
2911 /* genAnd - code for and */
2912 /*-----------------------------------------------------------------*/
2914 genAnd (iCode * ic, iCode * ifx)
2916 genBitWise (ic, ifx, AVR_AND);
2919 /*-----------------------------------------------------------------*/
2920 /* genOr - code for or */
2921 /*-----------------------------------------------------------------*/
2923 genOr (iCode * ic, iCode * ifx)
2925 genBitWise (ic, ifx, AVR_OR);
2928 /*-----------------------------------------------------------------*/
2929 /* genXor - code for xclusive or */
2930 /*-----------------------------------------------------------------*/
2932 genXor (iCode * ic, iCode * ifx)
2934 genBitWise (ic, ifx, AVR_XOR);
2937 /*-----------------------------------------------------------------*/
2938 /* genInline - write the inline code out */
2939 /*-----------------------------------------------------------------*/
2941 genInline (iCode * ic)
2943 char *buffer, *bp, *bp1;
2945 _G.inLine += (!options.asmpeep);
2947 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
2948 strcpy (buffer, IC_INLINE (ic));
2950 /* emit each line as a code */
2971 /* emitcode("",buffer); */
2972 _G.inLine -= (!options.asmpeep);
2975 /*-----------------------------------------------------------------*/
2976 /* genRotC - rotate right/left with carry , lr = 1 rotate right */
2977 /*-----------------------------------------------------------------*/
2979 genRotC (iCode * ic, int lr)
2981 operand *left, *result;
2982 int size, offset = 0;
2984 /* rotate right with carry */
2985 left = IC_LEFT (ic);
2986 result = IC_RESULT (ic);
2987 aopOp (left, ic, FALSE);
2988 aopOp (result, ic, FALSE);
2990 /* move it to the result */
2991 size = AOP_SIZE (result);
2992 if (!sameRegs (AOP (left), AOP (result))) {
2995 aopPut (AOP (result),
2996 aopGet (AOP (left), offset), offset);
2999 size = AOP_SIZE (result);
3007 emitcode ("sbrc", "%s,%d", aopGet (AOP (result), offset),
3009 emitcode ("sec", "");
3012 emitcode ((lr ? "ror" : "rol"), "%s",
3013 aopGet (AOP (result), offset));
3019 freeAsmop (left, NULL, ic, TRUE);
3020 freeAsmop (result, NULL, ic, TRUE);
3023 /*-----------------------------------------------------------------*/
3024 /* genRRC - rotate right with carry */
3025 /*-----------------------------------------------------------------*/
3032 /*-----------------------------------------------------------------*/
3033 /* genRLC - generate code for rotate left with carry */
3034 /*-----------------------------------------------------------------*/
3041 /*-----------------------------------------------------------------*/
3042 /* genGetHbit - generates code get highest order bit */
3043 /*-----------------------------------------------------------------*/
3045 genGetHbit (iCode * ic)
3047 operand *left, *result;
3050 left = IC_LEFT (ic);
3051 result = IC_RESULT (ic);
3052 aopOp (left, ic, FALSE);
3053 aopOp (result, ic, FALSE);
3055 size = AOP_SIZE (result);
3056 if (!sameRegs (AOP (left), AOP (result))) {
3057 emitcode ("clr", "%s", aopGet (AOP (result), size - 1));
3058 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3059 emitcode ("subi", "%s,<(-1)",
3060 aopGet (AOP (result), size - 1));
3063 emitcode ("clr", "r0");
3064 emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
3065 emitcode ("subi", "r0,<(-1)");
3066 aopPut (AOP (result), "r0", 0);
3071 emitcode ("clr", aopGet (AOP (result), offset++));
3073 freeAsmop (left, NULL, ic, TRUE);
3074 freeAsmop (result, NULL, ic, TRUE);
3077 /*-----------------------------------------------------------------*/
3078 /* genShiftLeftLit - shift left by a known amount */
3079 /*-----------------------------------------------------------------*/
3081 genShiftLeftLit (iCode * ic)
3083 operand *left, *right, *result;
3084 int size, shCount, offset = 0;
3087 right = IC_RIGHT (ic);
3088 left = IC_LEFT (ic);
3089 result = IC_RESULT (ic);
3091 aopOp (left, ic, FALSE);
3092 aopOp (result, ic, FALSE);
3093 size = AOP_SIZE (result);
3094 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3096 if (shCount > (size * 8 - 1)) {
3098 aopPut (AOP (result), zero, offset++);
3103 if (!sameRegs (AOP (left), AOP (result)))
3104 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3106 if (AOP_ISHIGHREG(AOP(result),0)) {
3107 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3108 emitcode ("andi", "%s,0xf0");
3110 emitcode ("ldi","r24,0xf0");
3111 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3112 emitcode ("and", "%s,r24");
3117 emitcode ("add", "%s,%s", aopGet (AOP (result), 0),
3118 aopGet (AOP (result), 0));
3122 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3125 if (shCount >= 12) {
3126 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3127 aopPut (AOP (result), zero, 0);
3128 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3129 if (AOP_ISHIGHREG(AOP(result),1)) {
3130 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3132 emitcode ("ldi","r24,0xf0");
3133 emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
3139 aopPut (AOP (result), aopGet (AOP (left), 0), 1);
3140 aopPut (AOP (result), zero, 0);
3146 if (!sameRegs (AOP (left), AOP (result))) {
3147 aopPut (AOP (result), aopGet (AOP (left), 0),
3149 aopPut (AOP (result), aopGet (AOP (left), 1),
3152 emitcode ("mov", "r24,%s", aopGet (AOP (result), 0));
3153 emitcode ("andi", "r24,0x0f");
3154 if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
3155 emitcode("ldi","r25,0xf0");
3157 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3158 if (AOP_ISHIGHREG(AOP(result),0)) {
3159 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 0));
3161 emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
3163 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3164 if (AOP_ISHIGHREG(AOP(result),1)) {
3165 emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
3167 emitcode ("and", "%s,r25", aopGet (AOP (result), 1));
3169 emitcode ("or", "%s,r24", aopGet (AOP (result), 1));
3171 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3172 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3175 if (!lByteZ && !sameRegs (AOP (result), AOP (left))
3179 aopPut (AOP (result),
3180 aopGet (AOP (left), offset), offset);
3186 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3189 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3190 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3195 assert ("shifting generic pointer ?\n");
3198 /* 32 bits we do only byte boundaries */
3199 if (shCount >= 24) {
3200 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3201 aopPut (AOP (result), zero, 2);
3202 aopPut (AOP (result), zero, 1);
3203 aopPut (AOP (result), zero, 0);
3207 if (shCount >= 16) {
3208 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3209 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3210 aopPut (AOP (result), zero, 1);
3211 aopPut (AOP (result), zero, 0);
3216 aopPut (AOP (result), aopGet (AOP (left), 0), 3);
3217 aopPut (AOP (result), aopGet (AOP (left), 1), 2);
3218 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3219 aopPut (AOP (result), zero, 0);
3223 if (!lByteZ && !sameRegs (AOP (left), AOP (right))) {
3226 aopPut (AOP (result),
3227 aopGet (AOP (left), offset), offset);
3231 size = AOP_SIZE (result);
3237 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3238 emitcode ("rol", "%s", aopGet (AOP (result), 1));
3239 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3240 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3245 emitcode ("lsl", "%s", aopGet (AOP (result), 1));
3246 emitcode ("rol", "%s", aopGet (AOP (result), 2));
3247 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3252 emitcode ("lsl", "%s", aopGet (AOP (result), 2));
3253 emitcode ("rol", "%s", aopGet (AOP (result), 3));
3258 emitcode ("lsl", "%s", aopGet (AOP (result), 3));
3266 freeAsmop (left, NULL, ic, TRUE);
3267 freeAsmop (right, NULL, ic, TRUE);
3268 freeAsmop (result, NULL, ic, TRUE);
3271 /*-----------------------------------------------------------------*/
3272 /* genLeftShift - generates code for left shifting */
3273 /*-----------------------------------------------------------------*/
3275 genLeftShift (iCode * ic)
3277 operand *left, *right, *result;
3281 right = IC_RIGHT (ic);
3282 left = IC_LEFT (ic);
3283 result = IC_RESULT (ic);
3285 aopOp (right, ic, FALSE);
3287 if (AOP_TYPE (right) == AOP_LIT) {
3288 genShiftLeftLit (ic);
3293 aopOp (left, ic, FALSE);
3294 aopOp (result, ic, FALSE);
3295 size = AOP_SIZE (result);
3297 if (AOP_SIZE (right) > 1) {
3298 if (isRegPair (AOP (right))) {
3299 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3302 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3303 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3307 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3309 if (!sameRegs (AOP (left), AOP (result))) {
3311 aopPut (AOP (result), aopGet (AOP (left), offset),
3315 size = AOP_SIZE (result);
3317 tlbl = newiTempLabel (NULL);
3318 emitcode ("", "L%05d:", tlbl->key);
3322 emitcode ("rol", "%s", aopGet (AOP (result), offset));
3324 emitcode ("lsl", "%s", aopGet (AOP (result), 0));
3327 if (AOP_SIZE (right) > 1)
3328 emitcode ("sbiw", "r24,1");
3330 emitcode ("dec", "r24");
3331 emitcode ("brne", "L%05d", tlbl->key);
3333 freeAsmop (left, NULL, ic, TRUE);
3334 freeAsmop (right, NULL, ic, TRUE);
3335 freeAsmop (result, NULL, ic, TRUE);
3338 /*-----------------------------------------------------------------*/
3339 /* genShiftRightLit - generate for right shift with known count */
3340 /*-----------------------------------------------------------------*/
3342 genShiftRightLit (iCode * ic)
3344 operand *left = IC_LEFT (ic)
3345 , *right = IC_RIGHT (ic)
3346 , *result = IC_RESULT (ic);
3347 int size, shCount, offset = 0;
3349 sym_link *letype = getSpec (operandType (left));
3350 int sign = !SPEC_USIGN (letype);
3352 right = IC_RIGHT (ic);
3353 left = IC_LEFT (ic);
3354 result = IC_RESULT (ic);
3356 aopOp (left, ic, FALSE);
3357 aopOp (result, ic, FALSE);
3358 size = AOP_SIZE (result);
3359 shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
3361 /* if signed then give up and use a loop to shift */
3364 if (!sameRegs (AOP (left), AOP (result))) {
3366 aopPut (AOP (result),
3367 aopGet (AOP (left), offset), offset);
3370 size = AOP_SIZE (result);
3373 /* be as economical as possible */
3376 size = AOP_SIZE (result);
3379 /* highest order byte */
3380 if (offset == (AOP_SIZE(result)-1))
3381 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3383 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3389 emitcode ("ldi", "r24,<(%d)", shCount);
3390 tlbl = newiTempLabel (NULL);
3391 emitcode ("", "L%05d:", tlbl->key);
3394 if (offset == (AOP_SIZE(result) - 1))
3395 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3397 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3400 emitcode ("dec", "r24");
3401 emitcode ("brne", "L%05d", tlbl->key);
3405 if (shCount > (size * 8 - 1)) {
3407 aopPut (AOP (result), zero, offset++);
3410 /* for unsigned we can much more efficient */
3413 if (!sameRegs (AOP (left), AOP (result)))
3414 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3416 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3417 if (AOP_ISHIGHREG(AOP(result),0)) {
3418 emitcode ("andi", "%s,0x0f",aopGet(AOP(result),0));
3420 emitcode ("ldi","r24,0x0f");
3421 emitcode ("and", "%s,r24",aopGet(AOP(result),0));
3426 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3429 if (shCount >= 12) {
3430 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3431 aopPut (AOP (result), zero, 1);
3432 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3433 if (AOP_ISHIGHREG(AOP(result),0)) {
3434 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3436 emitcode ("ldi","r24,0x0f");
3437 emitcode ("and", "%s,r24",aopGet(AOP(result),0));
3443 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3444 aopPut (AOP (result), zero, 1);
3450 if (!sameRegs (AOP (left), AOP (result))) {
3451 aopPut (AOP (result), aopGet (AOP (left), 0), 0);
3452 aopPut (AOP (result), aopGet (AOP (left), 1), 1);
3454 if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
3455 emitcode("ldi","r25,0x0f");
3457 emitcode ("mov", "r24,%s", aopGet (AOP (result), 1));
3458 emitcode ("andi", "r24,0xf0");
3459 emitcode ("swap", "%s", aopGet (AOP (result), 0));
3460 if (AOP_ISHIGHREG(AOP(result),0)) {
3461 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
3463 emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
3465 emitcode ("or", "%s,r24", aopGet (AOP (result), 0));
3466 emitcode ("swap", "%s", aopGet (AOP (result), 1));
3467 if (AOP_ISHIGHREG(AOP(result),1)) {
3468 emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 1));
3470 emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
3473 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3474 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3478 if (!hByteZ && !sameRegs (AOP (result), AOP (left))
3482 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3488 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3491 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3492 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3498 assert ("shifting generic pointer ?\n");
3501 /* 32 bits we do only byte boundaries */
3502 if (shCount >= 24) {
3503 aopPut (AOP (result), aopGet (AOP (left), 3), 0);
3504 aopPut (AOP (result), zero, 1);
3505 aopPut (AOP (result), zero, 2);
3506 aopPut (AOP (result), zero, 3);
3510 if (shCount >= 16) {
3511 aopPut (AOP (result), aopGet (AOP (left), 3), 1);
3512 aopPut (AOP (result), aopGet (AOP (left), 2), 0);
3513 aopPut (AOP (result), zero, 2);
3514 aopPut (AOP (result), zero, 3);
3519 aopPut (AOP (result), aopGet (AOP (left), 1), 0);
3520 aopPut (AOP (result), aopGet (AOP (left), 2), 1);
3521 aopPut (AOP (result), aopGet (AOP (left), 3), 2);
3522 aopPut (AOP (result), zero, 3);
3526 if (!hByteZ && !sameRegs (AOP (left), AOP (right))) {
3529 aopPut (AOP (result),
3530 aopGet (AOP (left), offset), offset);
3534 size = AOP_SIZE (result);
3540 emitcode ("lsr", "%s", aopGet (AOP (result), 3));
3541 emitcode ("ror", "%s", aopGet (AOP (result), 2));
3542 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3543 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3548 emitcode ("lsr", "%s", aopGet (AOP (result), 2));
3549 emitcode ("ror", "%s", aopGet (AOP (result), 1));
3550 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3555 emitcode ("lsr", "%s", aopGet (AOP (result), 1));
3556 emitcode ("ror", "%s", aopGet (AOP (result), 0));
3561 emitcode ("lsr", "%s", aopGet (AOP (result), 0));
3568 freeAsmop (left, NULL, ic, TRUE);
3569 freeAsmop (right, NULL, ic, TRUE);
3570 freeAsmop (result, NULL, ic, TRUE);
3573 /*-----------------------------------------------------------------*/
3574 /* genRightShift - generate code for right shifting */
3575 /*-----------------------------------------------------------------*/
3577 genRightShift (iCode * ic)
3579 operand *right, *left, *result;
3582 int sign = 0, first = 1;
3585 aopOp (right = IC_RIGHT (ic), ic, FALSE);
3587 if (AOP_TYPE (right) == AOP_LIT) {
3588 genShiftRightLit (ic);
3592 if (AOP_SIZE (right) > 1) {
3593 if (isRegPair (AOP (right))) {
3594 emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
3597 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3598 emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
3602 emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
3604 aopOp (left = IC_LEFT (ic), ic, FALSE);
3605 aopOp (result = IC_RESULT (ic), ic, FALSE);
3606 size = AOP_SIZE (result);
3607 tlbl = newiTempLabel (NULL);
3608 emitcode ("", "L%05d:", tlbl->key);
3610 letype = getSpec (operandType (left));
3611 sign = !SPEC_USIGN (letype);
3612 if (!sameRegs (AOP (left), AOP (result))) {
3614 aopPut (AOP (result), aopGet (AOP (left), offset), offset);
3617 size = AOP_SIZE (result);
3619 size = AOP_SIZE (result);
3623 emitcode ("asr", "%s", aopGet (AOP (result), offset));
3625 emitcode ("lsr", "%s", aopGet (AOP (result), offset));
3629 emitcode ("ror", "%s", aopGet (AOP (result), offset));
3632 if (AOP_SIZE (right) > 1)
3633 emitcode ("sbiw", "r24,1");
3635 emitcode ("dec", "r24");
3636 emitcode ("brne", "L%05d", tlbl->key);
3638 freeAsmop (left, NULL, ic, TRUE);
3639 freeAsmop (result, NULL, ic, TRUE);
3642 /*-----------------------------------------------------------------*/
3643 /* RRsh - shift right rn by known count */
3644 /*-----------------------------------------------------------------*/
3646 RRsh (int shCount,int reg)
3648 shCount &= 0x0007; // shCount : 0..7
3654 emitcode ("lsr", "r%d",reg);
3657 emitcode ("lsr", "r%d",reg);
3658 emitcode ("lsr", "r%d",reg);
3661 emitcode ("swap", "r%d",reg);
3662 emitcode ("lsl", "r%d",reg);
3665 emitcode ("swap", "r%d",reg);
3668 emitcode ("swap", "r%d",reg);
3669 emitcode ("lsr", "r%d",reg);
3672 emitcode ("swap","r%d",reg);
3673 emitcode ("lsr", "r%d",reg);
3674 emitcode ("lsr", "r%d",reg);
3677 emitcode ("swap","r%d",reg);
3678 emitcode ("lsr", "r%d",reg);
3679 emitcode ("lsr", "r%d",reg);
3680 emitcode ("lsr", "r%d",reg);
3685 /*-----------------------------------------------------------------*/
3686 /* RLsh - shift left rn by known count */
3687 /*-----------------------------------------------------------------*/
3689 RLsh (int shCount, int reg)
3691 shCount &= 0x0007; // shCount : 0..7
3697 emitcode ("lsl", "r%d",reg);
3700 emitcode ("lsl", "r%d",reg);
3701 emitcode ("lsl", "r%d",reg);
3704 emitcode ("swap","r%d",reg);
3705 emitcode ("lsr", "r%d",reg);
3708 emitcode ("swap", "r%d",reg);
3711 emitcode ("swap","r%d",reg);
3712 emitcode ("lsl", "r%d",reg);
3715 emitcode ("swap","r%d",reg);
3716 emitcode ("lsl", "r%d",reg);
3717 emitcode ("lsl", "r%d",reg);
3720 emitcode ("swap","r%d",reg);
3721 emitcode ("lsl", "r%d",reg);
3722 emitcode ("lsl", "r%d",reg);
3723 emitcode ("lsl", "r%d",reg);
3728 /*-----------------------------------------------------------------*/
3729 /* genUnpackBits - generates code for unpacking bits */
3730 /*-----------------------------------------------------------------*/
3732 genUnpackBits (operand * result, char *rname, int ptype)
3740 etype = getSpec (operandType (result));
3741 rsize = getSize (operandType (result));
3742 /* read the first byte */
3749 emitcode ("ld", "r24,%s+", rname);
3753 emitcode ("lpm", "r24,%s+", rname);
3757 emitcode ("call","__gptrget_pi");
3758 emitcode ("mov","r24,r0");
3762 rlen = SPEC_BLEN (etype);
3764 /* if we have bitdisplacement then it fits */
3765 /* into this byte completely or if length is */
3766 /* less than a byte */
3767 if ((shCnt = SPEC_BSTR (etype)) || (SPEC_BLEN (etype) <= 8)) {
3769 /* shift right acc */
3772 emitcode ("andi", "r24,lo(0x%x)",
3773 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
3774 aopPut (AOP (result), "r24", offset++);
3778 /* bit field did not fit in a byte */
3779 aopPut (AOP (result), "r24", offset++);
3789 emitcode ("ld", "r24,%s+");
3793 emitcode ("lpm", "r24,%s+");
3797 emitcode ("call", "__gptrget_pi");
3802 /* if we are done */
3806 aopPut (AOP (result), "r24", offset++);
3811 aopPut (AOP (result), "r24", offset++);
3815 if (offset < rsize) {
3818 aopPut (AOP (result), zero, offset++);
3823 /*-----------------------------------------------------------------*/
3824 /* genDataPointerGet - generates code when ptr offset is known */
3825 /*-----------------------------------------------------------------*/
3827 genDataPointerGet (operand * left, operand * result, iCode * ic)
3831 int size, offset = 0;
3832 aopOp (result, ic, TRUE);
3834 /* get the string representation of the name */
3835 l = aopGet (AOP (left), 0);
3836 size = AOP_SIZE (result);
3839 sprintf (buffer, "(%s + %d)", l, offset);
3841 sprintf (buffer, "%s", l);
3842 emitcode ("lds", "%s,%s", aopGet (AOP (result), offset++),
3846 freeAsmop (left, NULL, ic, TRUE);
3847 freeAsmop (result, NULL, ic, TRUE);
3850 /*-----------------------------------------------------------------*/
3851 /* genNearPointerGet - emitcode for near pointer fetch */
3852 /*-----------------------------------------------------------------*/
3854 genMemPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
3859 char *rname, *frname = NULL;
3860 sym_link *rtype, *retype;
3861 sym_link *ltype = operandType (left);
3863 rtype = operandType (result);
3864 retype = getSpec (rtype);
3866 aopOp (left, ic, FALSE);
3868 /* if left is rematerialisable and
3869 result is not bit variable type and
3870 the left is pointer to data space i.e
3871 lower 128 bytes of space */
3872 if (AOP_TYPE (left) == AOP_IMMD &&
3873 !IS_BITVAR (retype) && DCL_TYPE (ltype) == POINTER) {
3874 genDataPointerGet (left, result, ic);
3878 /* if the value is already in a pointer register
3879 then don't need anything more */
3880 if (!AOP_INPREG (AOP (left))) {
3881 /* otherwise get a free pointer register */
3883 preg = getFreePtr (ic, &aop, FALSE, 0);
3884 if (isRegPair (AOP (left) )) {
3885 emitcode ("movw", "%s,%s",
3886 aop->aopu.aop_ptr->name,
3887 aopGet(AOP(left),0));
3889 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
3890 aopGet (AOP (left), 0));
3891 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
3892 aopGet (AOP (left), 1));
3898 frname = aopGet(aop,0);
3902 } else if (AOP_ISZ(aop)) {
3905 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
3906 "pointer not in correct register");
3910 aopOp (result, ic, FALSE);
3912 /* if bitfield then unpack the bits */
3913 if (IS_BITVAR (retype))
3914 genUnpackBits (result, rname, POINTER);
3916 /* we have can just get the values */
3917 int size = AOP_SIZE (result);
3922 emitcode ("ld","%s,%s+",aopGet(AOP(result),offset), rname);
3924 emitcode ("ld","%s,%s",aopGet(AOP(result),offset), rname);
3929 /* now some housekeeping stuff */
3931 /* we had to allocate for this iCode */
3933 if (isRegPair (AOP (left) )) {
3934 emitcode ("movw", "%s,%s",
3935 aopGet (AOP(left),0),
3936 aop->aopu.aop_ptr->name);
3938 emitcode ("mov", "%s,%s",
3939 aopGet (AOP (left), 0),
3940 aop->aopu.aop_ptr->name);
3941 emitcode ("mov", "%s,%s",
3942 aopGet (AOP (left), 1),
3943 aop->aop_ptr2->name);
3946 freeAsmop (NULL, aop, ic, TRUE);
3949 /* we did not allocate which means left
3950 already in a pointer register, then
3951 if size > 0 && this could be used again
3952 we have to point it back to where it
3954 if ((AOP_SIZE (result) > 1 &&
3955 !OP_SYMBOL (left)->remat &&
3956 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) && !pi) {
3957 int size = AOP_SIZE (result) - 1;
3958 emitcode ("sbiw", "%s,%d",frname,size);
3963 if (pi) pi->generated = 1;
3964 freeAsmop (left, NULL, ic, TRUE);
3965 freeAsmop (result, NULL, ic, TRUE);
3969 /*-----------------------------------------------------------------*/
3970 /* genCodePointerGet - gget value from code space */
3971 /*-----------------------------------------------------------------*/
3973 genCodePointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
3976 sym_link *retype = getSpec (operandType (result));
3980 aopOp (left, ic, FALSE);
3982 /* if the operand is already in Z register
3983 then we do nothing else we move the value to Z register */
3984 if (AOP_ISZ(AOP(left))) {
3988 getFreePtr(ic,&aop,FALSE,TRUE);
3989 if (isRegPair(AOP (left))) {
3990 emitcode ("movw","r30,%s",aopGet (AOP (left), 0));
3992 emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
3993 emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
3998 aopOp (result, ic, FALSE);
4000 /* if bit then unpack */
4001 if (IS_BITVAR (retype))
4002 genUnpackBits (result, "Z", CPOINTER);
4004 size = AOP_SIZE (result);
4009 emitcode ("lpm","%s,Z+",aopGet(AOP(result),offset++));
4011 emitcode ("lpm","%s,Z",aopGet(AOP(result),offset++));
4016 /* now some housekeeping stuff */
4018 /* we had to allocate for this iCode */
4020 if (isRegPair(AOP (left))) {
4021 emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
4023 emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
4024 emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
4027 freeAsmop (NULL, aop, ic, TRUE);
4030 /* we did not allocate which means left
4031 already in a pointer register, then
4032 if size > 0 && this could be used again
4033 we have to point it back to where it
4035 if ((AOP_SIZE (result) > 1 &&
4036 !OP_SYMBOL (left)->remat &&
4037 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) &&
4039 int size = AOP_SIZE (result) - 1;
4040 emitcode ("sbiw", "r30,%d",size);
4045 if (pi) pi->generated=1;
4046 freeAsmop (left, NULL, ic, TRUE);
4047 freeAsmop (result, NULL, ic, TRUE);
4051 /*-----------------------------------------------------------------*/
4052 /* genGenPointerGet - gget value from generic pointer space */
4053 /*-----------------------------------------------------------------*/
4055 genGenPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
4059 sym_link *retype = getSpec (operandType (result));
4062 aopOp (left, ic, FALSE);
4064 /* if the operand is already in dptr
4065 then we do nothing else we move the value to dptr */
4066 if (AOP_ISZ(AOP(left))) {
4070 getFreePtr(ic,&aop,FALSE,TRUE);
4071 if (isRegPair(AOP(left))) {
4072 emitcode ("movw", "r30,%s", aopGet (AOP (left), 0));
4074 emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
4075 emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
4077 emitcode ("mov", "r24,%s", aopGet (AOP (left), 2));
4081 /* so Z register now contains the address */
4083 aopOp (result, ic, FALSE);
4085 /* if bit then unpack */
4086 if (IS_BITVAR (retype))
4087 genUnpackBits (result, "Z", GPOINTER);
4089 size = AOP_SIZE (result);
4094 emitcode ("call", "__gptrget_pi");
4096 emitcode ("call", "__gptrget");
4097 aopPut (AOP (result), "r0", offset++);
4102 /* now some housekeeping stuff */
4104 /* we had to allocate for this iCode */
4106 if (isRegPair(AOP (left))) {
4107 emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
4109 emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
4110 emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
4113 freeAsmop (NULL, aop, ic, TRUE);
4116 /* we did not allocate which means left
4117 already in a pointer register, then
4118 if size > 0 && this could be used again
4119 we have to point it back to where it
4121 if ((AOP_SIZE (result) > 1 &&
4122 !OP_SYMBOL (left)->remat &&
4123 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) &&
4125 int size = AOP_SIZE (result) - 1;
4126 emitcode ("sbiw", "r30,%d",size);
4129 if (pi) pi->generated=1;
4130 freeAsmop (left, NULL, ic, TRUE);
4131 freeAsmop (result, NULL, ic, TRUE);
4134 /*-----------------------------------------------------------------*/
4135 /* genPointerGet - generate code for pointer get */
4136 /*-----------------------------------------------------------------*/
4138 genPointerGet (iCode * ic, iCode *pi)
4140 operand *left, *result;
4141 sym_link *type, *etype;
4144 left = IC_LEFT (ic);
4145 result = IC_RESULT (ic);
4147 /* depending on the type of pointer we need to
4148 move it to the correct pointer register */
4149 type = operandType (left);
4150 etype = getSpec (type);
4151 /* if left is of type of pointer then it is simple */
4152 if (IS_PTR (type) && !IS_FUNC (type->next))
4153 p_type = DCL_TYPE (type);
4155 /* we have to go by the storage class */
4156 p_type = PTR_TYPE (SPEC_OCLS (etype));
4161 /* now that we have the pointer type we assign
4162 the pointer values */
4169 genMemPointerGet (left, result, ic, pi);
4173 genCodePointerGet (left, result, ic, pi);
4177 genGenPointerGet (left, result, ic, pi);
4183 /*-----------------------------------------------------------------*/
4184 /* genPackBits - generates code for packed bit storage */
4185 /*-----------------------------------------------------------------*/
4187 genPackBits (sym_link * etype,
4189 char *rname, int p_type)
4197 blen = SPEC_BLEN (etype);
4198 bstr = SPEC_BSTR (etype);
4200 l = aopGet (AOP (right), offset++);
4203 /* if the bit lenth is less than or */
4204 /* it exactly fits a byte then */
4205 if (SPEC_BLEN (etype) <= 8) {
4206 shCount = SPEC_BSTR (etype);
4208 /* shift left acc */
4211 if (SPEC_BLEN (etype) < 8) { /* if smaller than a byte */
4218 emitcode ("ld", "r1,%s",rname);
4222 emitcode ("push", "r1");
4223 emitcode ("push", "r24");
4224 emitcode ("call", "__gptrget");
4225 emitcode ("pop", "r1");
4226 emitcode ("mov","r24,r0");
4230 emitcode ("andi", "r24,#0x%02x", (unsigned char)
4231 ((unsigned char) (0xFF << (blen + bstr)) |
4232 (unsigned char) (0xFF >> (8 - bstr))));
4233 emitcode ("or", "r24,r1");
4234 if (p_type == GPOINTER)
4235 emitcode ("pop", "r1");
4244 emitcode("st","%s+,r24");
4248 emitcode("mov","r0,r24");
4249 emitcode ("call", "__gptrput_pi");
4254 if (SPEC_BLEN (etype) <= 8)
4257 rLen = SPEC_BLEN (etype);
4259 /* now generate for lengths greater than one byte */
4262 l = aopGet (AOP (right), offset++);
4273 emitcode ("st", "%s+,%s",rname,l);
4278 emitcode ("lcall", "__gptrput_pi");
4285 /* last last was not complete */
4287 /* save the byte & read byte */
4293 emitcode ("st","%s+,r24",rname);
4296 emitcode ("push", "r1");
4297 emitcode ("push", "r24");
4298 emitcode ("lcall", "__gptrget");
4299 emitcode ("mov","r24,r0");
4300 emitcode ("pop", "r1");
4304 emitcode ("andi", "r24,0x%02x", (((unsigned char) -1 << rLen) & 0xff));
4305 emitcode ("or", "r24,r1");
4308 if (p_type == GPOINTER)
4309 emitcode ("pop", "r1");
4317 emitcode ("st", "%s,r24", rname);
4321 emitcode ("mov","r0,r24");
4322 emitcode ("call", "__gptrput");
4327 /*-----------------------------------------------------------------*/
4328 /* genDataPointerSet - remat pointer to data space */
4329 /*-----------------------------------------------------------------*/
4331 genDataPointerSet (operand * right, operand * result, iCode * ic)
4333 int size, offset = 0;
4334 char *l, buffer[256];
4336 aopOp (right, ic, FALSE);
4338 l = aopGet (AOP (result), 0);
4339 size = AOP_SIZE (right);
4342 sprintf (buffer, "(%s + %d)", l, offset);
4344 sprintf (buffer, "%s", l);
4345 emitcode ("sts", "%s,%s", buffer,
4346 aopGet (AOP (right), offset++));
4349 freeAsmop (right, NULL, ic, TRUE);
4350 freeAsmop (result, NULL, ic, TRUE);
4353 /*-----------------------------------------------------------------*/
4354 /* genNearPointerSet - emitcode for near pointer put */
4355 /*-----------------------------------------------------------------*/
4357 genMemPointerSet (operand * right, operand * result, iCode * ic, iCode *pi)
4360 char *frname = NULL, *rname, *l;
4363 sym_link *ptype = operandType (result);
4365 retype = getSpec (operandType (right));
4367 aopOp (result, ic, FALSE);
4369 /* if the result is rematerializable &
4370 in data space & not a bit variable */
4371 if (AOP_TYPE (result) == AOP_IMMD &&
4372 DCL_TYPE (ptype) == POINTER && !IS_BITVAR (retype)) {
4373 genDataPointerSet (right, result, ic);
4376 if (!AOP_INPREG(AOP(result))) {
4377 /* otherwise get a free pointer register */
4379 getFreePtr (ic, &aop, FALSE, 0);
4380 if (isRegPair (AOP (result) )) {
4381 emitcode ("movw", "%s,%s",aop->aopu.aop_ptr->name,
4382 aopGet(AOP (result), 0));
4384 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
4385 aopGet (AOP (result), 0));
4386 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
4387 aopGet (AOP (result), 1));
4392 frname = aopGet(aop,0);
4395 aopOp (right, ic, FALSE);
4398 } else if (AOP_ISZ(aop)) {
4401 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4402 "pointer not in correct register");
4405 /* if bitfield then unpack the bits */
4406 if (IS_BITVAR (retype))
4407 genPackBits (retype, right, rname, POINTER);
4409 /* we have can just get the values */
4410 int size = AOP_SIZE (right);
4414 l = aopGet (AOP (right), offset);
4416 emitcode ("st", "%s+,%s", rname,l);
4418 emitcode ("st", "%s,%s", rname,l);
4423 /* now some housekeeping stuff */
4425 /* we had to allocate for this iCode */
4427 if (isRegPair (AOP (result) )) {
4428 emitcode ("movw", "%s,%s",
4429 aopGet(AOP(result),0),
4430 aop->aopu.aop_ptr->name);
4432 emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
4433 aopGet (AOP (result), 0));
4434 emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
4435 aopGet (AOP (result), 1));
4438 freeAsmop (NULL, aop, ic, TRUE);
4441 /* we did not allocate which means left
4442 already in a pointer register, then
4443 if size > 0 && this could be used again
4444 we have to point it back to where it
4446 if ((AOP_SIZE (right) > 1 &&
4447 !OP_SYMBOL (result)->remat &&
4448 (OP_SYMBOL (right)->liveTo > ic->seq || ic->depth)) && !pi) {
4449 int size = AOP_SIZE (right) - 1;
4450 emitcode ("sbiw", "%s,%d",frname,size);
4455 if (pi) pi->generated = 1;
4456 freeAsmop (result, NULL, ic, TRUE);
4457 freeAsmop (right, NULL, ic, TRUE);
4460 /*-----------------------------------------------------------------*/
4461 /* genGenPointerSet - set value from generic pointer space */
4462 /*-----------------------------------------------------------------*/
4464 genGenPointerSet (operand * right, operand * result, iCode * ic, iCode *pi)
4468 sym_link *retype = getSpec (operandType (right));
4471 aopOp (result, ic, FALSE);
4473 /* if the operand is already in dptr
4474 then we do nothing else we move the value to dptr */
4475 if (AOP_ISZ(AOP(result))) {
4479 getFreePtr(ic,&aop,FALSE,TRUE);
4480 if (isRegPair(AOP(result))) {
4481 emitcode ("movw", "r30,%s", aopGet (AOP (result), 0));
4483 emitcode ("mov", "r30,%s", aopGet (AOP (result), 0));
4484 emitcode ("mov", "r31,%s", aopGet (AOP (result), 1));
4486 emitcode ("mov", "r24,%s", aopGet (AOP (result), 2));
4490 /* so Z register now contains the address */
4491 aopOp (right, ic, FALSE);
4493 /* if bit then unpack */
4494 if (IS_BITVAR (retype))
4495 genUnpackBits (result, "Z", GPOINTER);
4497 size = AOP_SIZE (right);
4501 char *l = aopGet(AOP (right), offset++);
4505 emitcode ("call", "__gptrput_pi");
4507 emitcode ("call", "__gptrput");
4511 /* now some housekeeping stuff */
4513 /* we had to allocate for this iCode */
4515 if (isRegPair(AOP(result))) {
4516 emitcode ("movw", "%s,r30", aopGet (AOP (result), 0));
4518 emitcode ("mov", "%s,r30", aopGet (AOP (result), 0));
4519 emitcode ("mov", "%s,r31", aopGet (AOP (result), 1));
4522 freeAsmop (NULL, aop, ic, TRUE);
4525 /* we did not allocate which means left
4526 already in a pointer register, then
4527 if size > 0 && this could be used again
4528 we have to point it back to where it
4530 if ((AOP_SIZE (right) > 1 &&
4531 !OP_SYMBOL (result)->remat &&
4532 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) && !pi) {
4533 int size = AOP_SIZE (right) - 1;
4534 emitcode ("sbiw", "r30,%d",size);
4537 if (pi) pi->generated = 1;
4538 freeAsmop (right, NULL, ic, TRUE);
4539 freeAsmop (result, NULL, ic, TRUE);
4542 /*-----------------------------------------------------------------*/
4543 /* genPointerSet - stores the value into a pointer location */
4544 /*-----------------------------------------------------------------*/
4546 genPointerSet (iCode * ic, iCode *pi)
4548 operand *right, *result;
4549 sym_link *type, *etype;
4552 right = IC_RIGHT (ic);
4553 result = IC_RESULT (ic);
4555 /* depending on the type of pointer we need to
4556 move it to the correct pointer register */
4557 type = operandType (result);
4558 etype = getSpec (type);
4559 /* if left is of type of pointer then it is simple */
4560 if (IS_PTR (type) && !IS_FUNC (type->next)) {
4561 p_type = DCL_TYPE (type);
4564 /* we have to go by the storage class */
4565 p_type = PTR_TYPE (SPEC_OCLS (etype));
4569 /* now that we have the pointer type we assign
4570 the pointer values */
4577 genMemPointerSet (right, result, ic, pi);
4581 genGenPointerSet (right, result, ic, pi);
4587 /*-----------------------------------------------------------------*/
4588 /* genIfx - generate code for Ifx statement */
4589 /*-----------------------------------------------------------------*/
4591 genIfx (iCode * ic, iCode * popIc)
4593 operand *cond = IC_COND (ic);
4598 aopOp (cond, ic, FALSE);
4600 /* get the value into acc */
4601 if (AOP_SIZE(cond) == 1 && AOP_ISHIGHREG(AOP(cond),0)) {
4602 cname = aopGet(AOP(cond),0);
4604 toBoolean (cond, "r24", 0);
4608 /* the result is now in the accumulator */
4609 freeAsmop (cond, NULL, ic, TRUE);
4611 /* if there was something to be popped then do it */
4614 emitcode("cpi","%s,0",cname);
4615 } else if (!tob) emitcode("cpi","%s,0",cname);
4617 lbl = newiTempLabel(NULL);
4620 emitcode ("breq","L%05d",lbl->key);
4622 emitcode ("brne","L%05d",lbl->key);
4623 emitcode ("jmp","L%05d",IC_TRUE(ic)->key);
4624 emitcode ("","L%05d:",lbl->key);
4627 emitcode ("brne","L%05d",lbl->key);
4629 emitcode ("breq","L%05d",lbl->key);
4630 emitcode ("jmp","L%05d",IC_FALSE(ic)->key);
4631 emitcode ("","L%05d:",lbl->key);
4636 /*-----------------------------------------------------------------*/
4637 /* genAddrOf - generates code for address of */
4638 /*-----------------------------------------------------------------*/
4640 genAddrOf (iCode * ic)
4642 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
4645 aopOp (IC_RESULT (ic), ic, FALSE);
4646 assert(AOP_SIZE(IC_RESULT(ic)) >= 2);
4647 /* if the operand is on the stack then we
4648 need to get the stack offset of this
4651 /* if it has an offset then we need to compute it */
4654 if (AOP_ISHIGHREG(AOP(
4655 ((char) sym->stack & 0xff));
4657 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4660 /* we can just move _bp */
4661 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
4663 /* fill the result with zero */
4664 size = AOP_SIZE (IC_RESULT (ic)) - 2;
4667 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
4673 /* object not on stack then we need the name */
4674 size = AOP_SIZE (IC_RESULT (ic));
4678 char s[SDCC_NAME_MAX];
4680 sprintf (s, "(%s >> %d)", sym->rname, offset * 8);
4682 sprintf (s, "%s", sym->rname);
4683 aopPut (AOP (IC_RESULT (ic)), s, offset++);
4687 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4691 /*-----------------------------------------------------------------*/
4692 /* genFarFarAssign - assignment when both are in far space */
4693 /*-----------------------------------------------------------------*/
4695 genFarFarAssign (operand * result, operand * right, iCode * ic)
4697 int size = AOP_SIZE (right);
4700 /* first push the right side on to the stack */
4702 l = aopGet (AOP (right), offset++);
4704 emitcode ("push", "acc");
4707 freeAsmop (right, NULL, ic, FALSE);
4708 /* now assign DPTR to result */
4709 aopOp (result, ic, FALSE);
4710 size = AOP_SIZE (result);
4712 emitcode ("pop", "acc");
4713 aopPut (AOP (result), "a", --offset);
4715 freeAsmop (result, NULL, ic, FALSE);
4719 /*-----------------------------------------------------------------*/
4720 /* genAssign - generate code for assignment */
4721 /*-----------------------------------------------------------------*/
4723 genAssign (iCode * ic)
4725 operand *result, *right;
4727 unsigned long lit = 0L;
4729 result = IC_RESULT (ic);
4730 right = IC_RIGHT (ic);
4732 /* if they are the same */
4733 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4736 aopOp (right, ic, FALSE);
4738 /* special case both in far space */
4739 if (AOP_TYPE (right) == AOP_DPTR &&
4740 IS_TRUE_SYMOP (result) && isOperandInFarSpace (result)) {
4742 genFarFarAssign (result, right, ic);
4746 aopOp (result, ic, TRUE);
4748 /* if they are the same registers */
4749 if (sameRegs (AOP (right), AOP (result)))
4752 /* if the result is a bit */
4753 if (AOP_TYPE (result) == AOP_CRY) {
4755 /* if the right size is a literal then
4756 we know what the value is */
4757 if (AOP_TYPE (right) == AOP_LIT) {
4758 if (((int) operandLitValue (right)))
4759 aopPut (AOP (result), one, 0);
4761 aopPut (AOP (result), zero, 0);
4765 /* the right is also a bit variable */
4766 if (AOP_TYPE (right) == AOP_CRY) {
4767 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4768 aopPut (AOP (result), "c", 0);
4773 toBoolean (right, "", 0);
4774 aopPut (AOP (result), "a", 0);
4778 /* bit variables done */
4780 size = AOP_SIZE (result);
4782 if (AOP_TYPE (right) == AOP_LIT)
4784 (unsigned long) floatFromVal (AOP (right)->aopu.
4786 if ((size > 1) && (AOP_TYPE (result) != AOP_REG)
4787 && (AOP_TYPE (right) == AOP_LIT)
4788 && !IS_FLOAT (operandType (right)) && (lit < 256L)) {
4789 emitcode ("clr", "a");
4791 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) ==
4792 0) aopPut (AOP (result), "a", size);
4794 aopPut (AOP (result),
4795 aopGet (AOP (right), size), size);
4800 aopPut (AOP (result),
4801 aopGet (AOP (right), offset), offset);
4807 freeAsmop (right, NULL, ic, FALSE);
4808 freeAsmop (result, NULL, ic, TRUE);
4811 /*-----------------------------------------------------------------*/
4812 /* genJumpTab - genrates code for jump table */
4813 /*-----------------------------------------------------------------*/
4815 genJumpTab (iCode * ic)
4820 aopOp (IC_JTCOND (ic), ic, FALSE);
4821 /* get the condition into accumulator */
4822 l = aopGet (AOP (IC_JTCOND (ic)), 0);
4824 /* multiply by three */
4825 emitcode ("add", "a,acc");
4826 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0));
4827 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
4829 jtab = newiTempLabel (NULL);
4830 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
4831 emitcode ("jmp", "@a+dptr");
4832 emitcode ("", "%05d$:", jtab->key + 100);
4833 /* now generate the jump labels */
4834 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
4835 jtab = setNextItem (IC_JTLABELS (ic)))
4836 emitcode ("ljmp", "%05d$", jtab->key + 100);
4840 /*-----------------------------------------------------------------*/
4841 /* genCast - gen code for casting */
4842 /*-----------------------------------------------------------------*/
4844 genCast (iCode * ic)
4846 operand *result = IC_RESULT (ic);
4847 sym_link *ctype = operandType (IC_LEFT (ic));
4848 sym_link *rtype = operandType (IC_RIGHT (ic));
4849 operand *right = IC_RIGHT (ic);
4852 /* if they are equivalent then do nothing */
4853 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
4856 aopOp (right, ic, FALSE);
4857 aopOp (result, ic, FALSE);
4859 /* if the result is a bit */
4860 if (AOP_TYPE (result) == AOP_CRY) {
4861 /* if the right size is a literal then
4862 we know what the value is */
4863 if (AOP_TYPE (right) == AOP_LIT) {
4864 if (((int) operandLitValue (right)))
4865 aopPut (AOP (result), one, 0);
4867 aopPut (AOP (result), zero, 0);
4872 /* the right is also a bit variable */
4873 if (AOP_TYPE (right) == AOP_CRY) {
4874 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4875 aopPut (AOP (result), "c", 0);
4880 toBoolean (right, "", 0);
4881 aopPut (AOP (result), "a", 0);
4885 /* if they are the same size : or less */
4886 if (AOP_SIZE (result) <= AOP_SIZE (right)) {
4888 /* if they are in the same place */
4889 if (sameRegs (AOP (right), AOP (result)))
4892 /* if they in different places then copy */
4893 size = AOP_SIZE (result);
4896 aopPut (AOP (result),
4897 aopGet (AOP (right), offset), offset);
4904 /* if the result is of type pointer */
4905 if (IS_PTR (ctype)) {
4908 sym_link *type = operandType (right);
4909 sym_link *etype = getSpec (type);
4911 /* pointer to generic pointer */
4912 if (IS_GENPTR (ctype)) {
4916 p_type = DCL_TYPE (type);
4918 /* we have to go by the storage class */
4919 p_type = PTR_TYPE (SPEC_OCLS (etype));
4922 /* the first two bytes are known */
4923 size = GPTRSIZE - 1;
4926 aopPut (AOP (result),
4927 aopGet (AOP (right), offset), offset);
4930 /* the last byte depending on type */
4947 /* this should never happen */
4948 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4949 "got unknown pointer type");
4952 aopPut (AOP (result), l, GPTRSIZE - 1);
4956 /* just copy the pointers */
4957 size = AOP_SIZE (result);
4960 aopPut (AOP (result),
4961 aopGet (AOP (right), offset), offset);
4967 /* so we now know that the size of destination is greater
4968 than the size of the source */
4969 /* we move to result for the size of source */
4970 size = AOP_SIZE (right);
4973 aopPut (AOP (result), aopGet (AOP (right), offset), offset);
4977 /* now depending on the sign of the source && destination */
4978 size = AOP_SIZE (result) - AOP_SIZE (right);
4979 /* if unsigned or not an integral type */
4980 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype)) {
4982 aopPut (AOP (result), zero, offset++);
4985 /* we need to extend the sign :{ */
4986 // PENDING: Does nothing on avr
4988 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1);
4991 emitcode ("rlc", "a");
4992 emitcode ("subb", "a,acc");
4994 aopPut (AOP (result), "a", offset++);
4997 /* we are done hurray !!!! */
5000 freeAsmop (right, NULL, ic, TRUE);
5001 freeAsmop (result, NULL, ic, TRUE);
5005 /*-----------------------------------------------------------------*/
5006 /* genDjnz - generate decrement & jump if not zero instrucion */
5007 /*-----------------------------------------------------------------*/
5009 genDjnz (iCode * ic, iCode * ifx)
5015 /* if the if condition has a false label
5016 then we cannot save */
5020 /* if the minus is not of the form
5022 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
5023 !IS_OP_LITERAL (IC_RIGHT (ic)))
5026 if (operandLitValue (IC_RIGHT (ic)) != 1)
5029 /* if the size of this greater than one then no
5031 if (getSize (operandType (IC_RESULT (ic))) > 1)
5034 /* otherwise we can save BIG */
5035 lbl = newiTempLabel (NULL);
5036 lbl1 = newiTempLabel (NULL);
5038 aopOp (IC_RESULT (ic), ic, FALSE);
5040 if (IS_AOP_PREG (IC_RESULT (ic))) {
5041 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0));
5042 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0));
5043 emitcode ("jnz", "%05d$", lbl->key + 100);
5046 emitcode ("djnz", "%s,%05d$",
5047 aopGet (AOP (IC_RESULT (ic)), 0), lbl->key + 100);
5049 emitcode ("sjmp", "%05d$", lbl1->key + 100);
5050 emitcode ("", "%05d$:", lbl->key + 100);
5051 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5052 emitcode ("", "%05d$:", lbl1->key + 100);
5054 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5059 static char *recvregs[8] = {
5060 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23"
5063 static int recvCnt = 0;
5065 /*-----------------------------------------------------------------*/
5066 /* genReceive - generate code for a receive iCode */
5067 /*-----------------------------------------------------------------*/
5069 genReceive (iCode * ic)
5071 int size, offset = 0;
5072 aopOp (IC_RESULT (ic), ic, FALSE);
5073 size = AOP_SIZE (IC_RESULT (ic));
5075 aopPut (AOP (IC_RESULT (ic)), recvregs[recvCnt++], offset);
5078 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5081 /*-----------------------------------------------------------------*/
5082 /* gen51Code - generate code for 8051 based controllers */
5083 /*-----------------------------------------------------------------*/
5085 genAVRCode (iCode * lic)
5090 lineHead = lineCurr = NULL;
5092 /* print the allocation information */
5094 printAllocInfo (currFunc, codeOutFile);
5095 /* if debug information required */
5096 /* if (options.debug && currFunc) { */
5098 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
5100 /* emitcode ("", ".type %s,@function", currFunc->name); */
5103 /* stack pointer name */
5107 for (ic = lic; ic; ic = ic->next) {
5109 if (cln != ic->lineno) {
5110 if (options.debug) {
5112 emitcode ("", "C$%s$%d$%d$%d ==.",
5113 FileBaseName (ic->filename),
5114 ic->lineno, ic->level, ic->block);
5117 emitcode (";", "%s %d", ic->filename, ic->lineno);
5120 /* if the result is marked as
5121 spilt and rematerializable or code for
5122 this has already been generated then
5124 if (resultRemat (ic) || ic->generated)
5127 /* depending on the operation */
5146 /* IPOP happens only when trying to restore a
5147 spilt live range, if there is an ifx statement
5148 following this pop then the if statement might
5149 be using some of the registers being popped which
5150 would destory the contents of the register so
5151 we need to check for this condition and handle it */
5153 ic->next->op == IFX &&
5154 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
5155 genIfx (ic->next, ic);
5173 genEndFunction (ic);
5193 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
5210 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
5214 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
5218 genCmpLe (ic, ifxForOp (IC_RESULT (ic), ic));
5222 genCmpGe (ic, ifxForOp (IC_RESULT (ic), ic));
5226 genCmpNe (ic, ifxForOp (IC_RESULT (ic), ic));
5230 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
5242 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
5246 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
5250 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
5277 case GET_VALUE_AT_ADDRESS:
5278 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
5282 if (POINTER_SET (ic))
5283 genPointerSet (ic, hasInc(IC_RESULT(ic),ic));
5309 addSet (&_G.sendSet, ic);
5318 /* now we are ready to call the
5319 peep hole optimizer */
5320 if (!options.nopeep)
5321 peepHole (&lineHead);
5323 /* now do the actual printing */
5324 printLine (lineHead, codeOutFile);