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"
33 #ifdef HAVE_SYS_ISA_DEFS_H
34 #include <sys/isa_defs.h>
40 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
41 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
47 #include "SDCCpeeph.h"
51 char *aopLiteral (value *val, int offset);
54 /* this is the down and dirty file with all kinds of
55 kludgy & hacky stuff. This is what it is all about
56 CODE GENERATION for a specific MCU . some of the
57 routines may be reusable, will have to see */
59 static char *zero = "0x00";
60 static char *one = "0x01";
63 char *fReturnAVR[] = {"r16","r17","r18","r19" };
64 unsigned fAVRReturnSize = 4; /* shared with ralloc.c */
65 char **fAVRReturn = fReturnAVR;
66 static short rbank = -1;
67 static char *larray[4] = {"lo8","hi8","hlo8","hhi8"};
68 static char *tscr[4] = {"r0","r1","r24","r25"};
79 extern int avr_ptrRegReq ;
81 extern FILE *codeOutFile;
82 static void saverbank (int, iCode *,bool);
83 #define RESULTONSTACK(x) \
84 (IC_RESULT(x) && IC_RESULT(x)->aop && \
85 IC_RESULT(x)->aop->type == AOP_STK )
87 #define MOVR0(x) if (strcmp(x,"r0")) emitcode("mov","r0,%s",x);
88 #define CLRC emitcode("clc","")
89 #define SETC emitcode("stc","")
91 #define IS_REGIDX(a,r) (a->type == AOP_REG && a->aopu.aop_reg[0]->rIdx == r)
93 static lineNode *lineHead = NULL;
94 static lineNode *lineCurr = NULL;
96 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
97 0xE0, 0xC0, 0x80, 0x00};
98 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
99 0x07, 0x03, 0x01, 0x00};
106 /*-----------------------------------------------------------------*/
107 /* emitcode - writes the code into a file : for now it is simple */
108 /*-----------------------------------------------------------------*/
109 static void emitcode (char *inst,char *fmt, ...)
112 char lb[MAX_INLINEASM];
119 sprintf(lb,"%s\t",inst);
121 sprintf(lb,"%s",inst);
122 vsprintf(lb+(strlen(lb)),fmt,ap);
126 while (isspace(*lbp)) lbp++;
129 lineCurr = (lineCurr ?
130 connectLine(lineCurr,newLineNode(lb)) :
131 (lineHead = newLineNode(lb)));
132 lineCurr->isInline = _G.inLine;
133 lineCurr->isDebug = _G.debugLine;
137 /*-----------------------------------------------------------------*/
138 /* getFreePtr - returns X or Z whichever is free or can be pushed */
139 /*-----------------------------------------------------------------*/
140 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result, bool zonly)
142 bool xiu = FALSE , ziu = FALSE;
143 bool xou = FALSE , zou = FALSE;
145 /* the logic: if x & z used in the instruction
146 then we are in trouble otherwise */
148 /* first check if x & z are used by this
149 instruction, in which case we are in trouble */
150 if ((xiu = bitVectBitValue(ic->rUsed,X_IDX)) &&
151 (ziu = bitVectBitValue(ic->rUsed,Z_IDX)))
156 xou = bitVectBitValue(ic->rMask,X_IDX);
157 zou = bitVectBitValue(ic->rMask,Z_IDX);
159 /* if no usage of Z then return it */
161 ic->rUsed = bitVectSetBit(ic->rUsed,Z_IDX);
162 (*aopp)->type = AOP_Z;
164 (*aopp)->aop_ptr2 = avr_regWithIdx(R31_IDX);
165 return (*aopp)->aopu.aop_ptr = avr_regWithIdx(R30_IDX);
168 /* if no usage of X then return it */
169 if (!xiu && !xou && !zonly) {
170 ic->rUsed = bitVectSetBit(ic->rUsed,X_IDX);
171 (*aopp)->type = AOP_X;
173 (*aopp)->aop_ptr2 = avr_regWithIdx(R27_IDX);
174 return (*aopp)->aopu.aop_ptr = avr_regWithIdx(R26_IDX);
177 /* if z not used then */
180 /* push it if not already pushed */
182 emitcode ("push","%s",
183 avr_regWithIdx(R30_IDX)->dname);
184 emitcode ("push","%s",
185 avr_regWithIdx(R31_IDX)->dname);
189 ic->rUsed = bitVectSetBit(ic->rUsed,Z_IDX);
190 (*aopp)->type = AOP_Z;
191 (*aopp)->aop_ptr2 = avr_regWithIdx(R31_IDX);
192 return (*aopp)->aopu.aop_ptr = avr_regWithIdx(R30_IDX);
195 /* now we know they both have usage */
196 /* if x not used in this instruction */
197 if (!xiu && !zonly) {
198 /* push it if not already pushed */
200 emitcode ("push","%s",
201 avr_regWithIdx(R26_IDX)->dname);
202 emitcode ("push","%s",
203 avr_regWithIdx(R27_IDX)->dname);
207 ic->rUsed = bitVectSetBit(ic->rUsed,X_IDX);
208 (*aopp)->type = AOP_X;
210 (*aopp)->aop_ptr2 = avr_regWithIdx(R27_IDX);
211 return (*aopp)->aopu.aop_ptr = avr_regWithIdx(R26_IDX);
216 /* I said end of world but not quite end of world yet */
217 /* if this is a result then we can push it on the stack*/
219 (*aopp)->type = AOP_STK;
224 /* other wise this is true end of the world */
225 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
226 "getFreePtr should never reach here");
230 /*-----------------------------------------------------------------*/
231 /* newAsmop - creates a new asmOp */
232 /*-----------------------------------------------------------------*/
233 static asmop *newAsmop (short type)
237 ALLOC(aop,sizeof(asmop));
242 /*-----------------------------------------------------------------*/
243 /* pointerCode - returns the code for a pointer type */
244 /*-----------------------------------------------------------------*/
245 static int pointerCode (link *etype)
248 return PTR_TYPE(SPEC_OCLS(etype));
252 /*-----------------------------------------------------------------*/
253 /* aopForSym - for a true symbol */
254 /*-----------------------------------------------------------------*/
255 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
258 memmap *space= SPEC_OCLS(sym->etype);
260 /* if already has one */
264 /* assign depending on the storage class */
265 /* if it is on the stack */
267 sym->aop = aop = newAsmop(0);
268 aop->size = getSize(sym->type);
270 /* we can use std / ldd instruction */
271 if (sym->stack > 0 && (sym->stack + getSize(sym->type) - 1) <= 63) {
272 aop->type = AOP_STK_D;
273 aop->aopu.aop_stk = sym->stack;
277 /* otherwise get a free pointer register X/Z */
278 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result,FALSE);
280 /* now assign the address of the variable to
281 the pointer register */
282 if (aop->type != AOP_STK) {
283 emitcode("movw","%s,r28",aop->aopu.aop_ptr->name);
284 if (sym->stack < 0) {
285 if ((sym->stack - _G.nRegsSaved) > -63) {
286 emitcode("sbiw","%s,0x%02x",
287 aop->aopu.aop_ptr->name,
288 (sym->stack - _G.nRegsSaved));
290 emitcode("subi","%s,lo8(%d)", aop->aopu.aop_ptr->name,
291 sym->stack - _G.nRegsSaved);
292 emitcode("sbci","%s,hi8(%d)",aop->aop_ptr2->name,
293 sym->stack - _G.nRegsSaved);
296 if (sym->stack <= 63) {
297 emitcode("adiw","%s,0x%02x",aop->aopu.aop_ptr->name,sym->stack);
299 emitcode("subi","%s,lo8(-%d)",aop->aopu.aop_ptr->name,sym->stack);
300 emitcode("sbci","%s,hi8(-%d)",aop->aop_ptr2->name,sym->stack);
307 /* if in bit space */
308 if (IN_BITSPACE(space)) {
309 sym->aop = aop = newAsmop (AOP_CRY);
310 aop->aopu.aop_dir = sym->rname ;
311 aop->size = getSize(sym->type);
314 /* if it is in direct space */
315 if (IN_DIRSPACE(space)) {
316 sym->aop = aop = newAsmop (AOP_DIR);
317 aop->aopu.aop_dir = sym->rname ;
318 aop->size = getSize(sym->type);
322 /* special case for a function */
323 if (IS_FUNC(sym->type)) {
324 sym->aop = aop = newAsmop(AOP_IMMD);
325 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
326 strcpy(aop->aopu.aop_immd,sym->rname);
327 aop->size = FPTRSIZE;
331 /* only remaining is code / eeprom which will need pointer reg */
332 /* if it is in code space */
333 if (IN_CODESPACE(space))
336 sym->aop = aop = newAsmop(0);
337 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result,aop->code);
338 aop->size = getSize(sym->type);
339 emitcode ("ldi","%s,lo8(%s)",aop->aopu.aop_ptr->name,sym->rname);
340 emitcode ("ldi","%s,hi8(%s)",aop->aop_ptr2);
345 /*-----------------------------------------------------------------*/
346 /* aopForRemat - rematerialzes an object */
347 /*-----------------------------------------------------------------*/
348 static asmop *aopForRemat (symbol *sym)
350 iCode *ic = sym->rematiCode;
351 asmop *aop = newAsmop(AOP_IMMD);
356 val += operandLitValue(IC_RIGHT(ic));
357 else if (ic->op == '-')
358 val -= operandLitValue(IC_RIGHT(ic));
362 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
366 sprintf(buffer,"(%s %c 0x%04x)",
367 OP_SYMBOL(IC_LEFT(ic))->rname,
368 val >= 0 ? '+' : '-',
371 strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
373 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
374 strcpy(aop->aopu.aop_immd,buffer);
378 /*-----------------------------------------------------------------*/
379 /* regsInCommon - two operands have some registers in common */
380 /*-----------------------------------------------------------------*/
381 static bool regsInCommon (operand *op1, operand *op2)
386 /* if they have registers in common */
387 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
390 sym1 = OP_SYMBOL(op1);
391 sym2 = OP_SYMBOL(op2);
393 if (sym1->nRegs == 0 || sym2->nRegs == 0)
396 for (i = 0 ; i < sym1->nRegs ; i++) {
401 for (j = 0 ; j < sym2->nRegs ;j++ ) {
405 if (sym2->regs[j] == sym1->regs[i])
413 /*-----------------------------------------------------------------*/
414 /* operandsEqu - equivalent */
415 /*-----------------------------------------------------------------*/
416 static bool operandsEqu ( operand *op1, operand *op2)
420 /* if they not symbols */
421 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
424 sym1 = OP_SYMBOL(op1);
425 sym2 = OP_SYMBOL(op2);
427 /* if both are itemps & one is spilt
428 and the other is not then false */
429 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
430 sym1->isspilt != sym2->isspilt )
433 /* if they are the same */
437 if (strcmp(sym1->rname,sym2->rname) == 0)
441 /* if left is a tmp & right is not */
445 (sym1->usl.spillLoc == sym2))
452 (sym2->usl.spillLoc == sym1))
458 /*-----------------------------------------------------------------*/
459 /* sameRegs - two asmops have the same registers */
460 /*-----------------------------------------------------------------*/
461 static bool sameRegs (asmop *aop1, asmop *aop2 )
468 if (aop1->type != AOP_REG ||
469 aop2->type != AOP_REG )
472 if (aop1->size != aop2->size )
475 for (i = 0 ; i < aop1->size ; i++ )
476 if (aop1->aopu.aop_reg[i] !=
477 aop2->aopu.aop_reg[i] )
483 /*-----------------------------------------------------------------*/
484 /* isRegPair - for size 2 if this operand has a register pair */
485 /*-----------------------------------------------------------------*/
486 static int isRegPair (asmop *aop)
488 if (!aop || aop->size != 2) return 0;
489 if (aop->type == AOP_X || aop->type == AOP_Z) return 1;
490 if (aop->type != AOP_REG) return 0;
491 if ((aop->aopu.aop_reg[1]->rIdx -
492 aop->aopu.aop_reg[0]->rIdx) == 1) return 1;
496 /*-----------------------------------------------------------------*/
497 /* aopOp - allocates an asmop for an operand : */
498 /*-----------------------------------------------------------------*/
499 static void aopOp (operand *op, iCode *ic, bool result)
508 /* if this a literal */
509 if (IS_OP_LITERAL(op)) {
510 op->aop = aop = newAsmop(AOP_LIT);
511 aop->aopu.aop_lit = op->operand.valOperand;
512 aop->size = getSize(operandType(op));
516 /* if already has a asmop then continue */
520 /* if the underlying symbol has a aop */
521 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
522 op->aop = OP_SYMBOL(op)->aop;
526 /* if this is a true symbol */
527 if (IS_TRUE_SYMOP(op)) {
528 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
532 /* this is a temporary : this has
538 e) can be a return use only */
543 /* if the type is a conditional */
544 if (sym->regType == REG_CND) {
545 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
550 /* if it is spilt then two situations
552 b) has a spill location */
553 if (sym->isspilt || sym->nRegs == 0) {
555 /* rematerialize it NOW */
557 sym->aop = op->aop = aop =
559 aop->size = getSize(sym->type);
564 assert("ACC_USE cannot happen in AVR\n");
569 aop = op->aop = sym->aop = newAsmop(AOP_STR);
570 aop->size = getSize(sym->type);
571 for ( i = 0 ; i < fAVRReturnSize ; i++ )
572 aop->aopu.aop_str[i] = fAVRReturn[i];
576 /* else spill location */
577 sym->aop = op->aop = aop =
578 aopForSym(ic,sym->usl.spillLoc,result);
579 aop->size = getSize(sym->type);
583 /* must be in a register */
584 sym->aop = op->aop = aop = newAsmop(AOP_REG);
585 aop->size = sym->nRegs;
586 for ( i = 0 ; i < sym->nRegs ;i++)
587 aop->aopu.aop_reg[i] = sym->regs[i];
590 /*-----------------------------------------------------------------*/
591 /* freeAsmop - free up the asmop given to an operand */
592 /*----------------------------------------------------------------*/
593 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
610 /* depending on the asmop type only three cases need work AOP_RO
611 , AOP_R1 && AOP_STK */
616 emitcode ("pop","r26");
617 emitcode ("pop","r27");
621 bitVectUnSetBit(ic->rUsed,X_IDX);
627 emitcode ("pop","r30");
628 emitcode ("pop","r31");
632 bitVectUnSetBit(ic->rUsed,Z_IDX);
638 int stk = aop->aopu.aop_stk + aop->size;
639 bitVectUnSetBit(ic->rUsed,X_IDX);
640 bitVectUnSetBit(ic->rUsed,Z_IDX);
642 getFreePtr(ic,&aop,FALSE,0);
644 emitcode ("movw","%s,r28");
646 if (stk <= 63 && stk > 0) {
647 emitcode ("adiw","%s,0x%02x",aop->aopu.aop_ptr->name,stk+1);
649 emitcode ("subi","%s,lo8(%d)",aop->aopu.aop_ptr->name,-(stk+1));
650 emitcode ("sbci","%s,hi8(%d)",aop->aop_ptr2->name,-(stk+1));
655 emitcode("pop","r24");
656 emitcode("st","-%s,r24",aop->type == AOP_X ? "X" : "Z");
660 freeAsmop(op,NULL,ic,TRUE);
662 emitcode("pop","r26");
663 emitcode("pop","r27");
668 emitcode("pop","r30");
669 emitcode("pop","r31");
676 /* all other cases just dealloc */
680 OP_SYMBOL(op)->aop = NULL;
681 /* if the symbol has a spill */
683 SPIL_LOC(op)->aop = NULL;
688 /*-----------------------------------------------------------------*/
689 /* aopGet - for fetching value of the aop */
690 /*-----------------------------------------------------------------*/
691 static char *aopGet (asmop *aop, int offset)
696 /* offset is greater than
698 if (offset > (aop->size - 1) &&
699 aop->type != AOP_LIT)
702 /* depending on type */
706 if (offset > aop->coff) {
707 emitcode ("adiw","%s,%d",aop->aopu.aop_ptr->name,offset - aop->coff);
710 if (offset < aop->coff) {
711 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,aop->coff - offset);
715 emitcode("ld","%s,x",
716 (rs = ((offset & 1) ? "r25" : "r24")));
721 if (offset > aop->coff) {
722 emitcode("adiw","r30,%d",offset - aop->coff);
724 emitcode("sbiw","r30,%d",aop->coff - offset);
726 emitcode("lpm","%s,z",(rs = ((offset & 1) ? "r25" : "r24")));
729 if (offset > aop->coff) {
730 emitcode ("ldd","%s,z+%d",(rs = ((offset & 1) ? "r25" : "r24")),
733 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,aop->coff - offset);
735 emitcode ("ld","%s,z",(rs = ((offset & 1) ? "r25" : "r24")));
742 emitcode ("lds","%s,(%s)+%d",
743 (rs = ((offset & 1) ? "r25" : "r24")),
744 aop->aopu.aop_immd, offset);
748 emitcode ("lds","%s,(%s)+%d",
749 (rs = ((offset & 1) ? "r25" : "r24")),
750 aop->aopu.aop_dir, offset);
754 return aop->aopu.aop_reg[offset]->name;
757 assert("cannot be in bit space AOP_CRY\n");
761 s = aopLiteral(aop->aopu.aop_lit,offset);
762 emitcode("ldi","%s,lo8(%s)",(rs = ((offset & 1)?"r24" : "r25")),s);
767 return aop->aopu.aop_str[offset];
770 emitcode ("ldd","%s,Y+%d",
771 (rs = ((offset & 1) ? "r25" : "r24")),
772 aop->aopu.aop_stk+offset);
776 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
777 "aopget got unsupported aop->type");
780 /*-----------------------------------------------------------------*/
781 /* aopPut - puts a string for a aop */
782 /*-----------------------------------------------------------------*/
783 static void aopPut (asmop *aop, char *s, int offset)
787 if (aop->size && offset > ( aop->size - 1)) {
788 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
789 "aopPut got offset > aop->size");
793 /* will assign value to value */
794 /* depending on where it is ofcourse */
798 sprintf(d,"(%s)+%d", aop->aopu.aop_dir,offset);
801 sprintf(d,"%s",aop->aopu.aop_dir);
804 emitcode("sts","%s,%s",d,s);
808 if (toupper(*s) != 'R') {
810 emitcode("clr","%s",aop->aopu.aop_reg[offset]->name);
812 emitcode("ldi","r25,%s",s);
813 emitcode("mov","%s,r35",aop->aopu.aop_reg[offset]->name);
816 if (strcmp( aop->aopu.aop_reg[offset]->name,s)) {
817 emitcode("mov","%s,%s", aop->aopu.aop_reg[offset]->name,s);
823 if (offset > aop->coff) {
824 emitcode ("adiw","%s,%d",aop->aopu.aop_ptr->name,offset - aop->coff);
827 if (offset < aop->coff) {
828 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,aop->coff - offset);
832 emitcode("st","x,%s", s);
837 if (offset > aop->coff) {
838 emitcode("adiw","r30,%d",offset - aop->coff);
840 emitcode("sbiw","r30,%d",aop->coff - offset);
842 emitcode("lpm","%s,z",s);
845 if (offset > aop->coff) {
846 emitcode ("sdd","z+%d,%s",offset - aop->coff,s);
848 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,aop->coff - offset);
850 emitcode ("ld","%s,z",s);
856 emitcode("push","%s",s);
860 /* if used only for a condition code check */
861 assert(toupper(*s) == 'R');
863 emitcode("xrl","r0,r0");
864 emitcode("cpi","%s,0",s);
867 emitcode("cpc","r0,%s",s);
873 if (strcmp(aop->aopu.aop_str[offset],s))
874 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
878 emitcode ("std","y+%d,%s",offset,s);
882 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
883 "aopPut got unsupported aop->type");
889 /*-----------------------------------------------------------------*/
890 /* reAdjustPreg - points a register back to where it should */
891 /*-----------------------------------------------------------------*/
892 static void reAdjustPreg (asmop *aop)
897 if ((size = aop->size) <= 1)
903 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,size);
909 #define AOP(op) op->aop
910 #define AOP_TYPE(op) AOP(op)->type
911 #define AOP_SIZE(op) AOP(op)->size
912 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_X || \
913 AOP_TYPE(x) == AOP_Z))
914 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
915 (x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) || \
916 x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) )))
918 /*-----------------------------------------------------------------*/
919 /* genNotFloat - generates not for float operations */
920 /*-----------------------------------------------------------------*/
921 static void genNotFloat (operand *op, operand *res)
927 /* we will put 127 in the first byte of
929 aopPut(AOP(res),"127",0);
930 size = AOP_SIZE(op) - 1;
933 l = aopGet(op->aop,offset++);
937 emitcode("or","R0,%s", aopGet(op->aop, offset++));
939 tlbl = newiTempLabel(NULL);
941 tlbl = newiTempLabel(NULL);
942 aopPut(res->aop,zero,1);
943 emitcode("cpi","r0,0");
944 emitcode("breq","L%05d",tlbl->key);
945 aopPut(res->aop,one,1);
946 emitcode("","L%05d:",tlbl->key);
948 size = res->aop->size - 2;
950 /* put zeros in the rest */
952 aopPut(res->aop,zero,offset++);
955 /*-----------------------------------------------------------------*/
956 /* opIsGptr: returns non-zero if the passed operand is */
957 /* a generic pointer type. */
958 /*-----------------------------------------------------------------*/
959 static int opIsGptr(operand *op)
961 link *type = operandType(op);
963 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
970 /*-----------------------------------------------------------------*/
971 /* getDataSize - get the operand data size */
972 /*-----------------------------------------------------------------*/
973 static int getDataSize(operand *op)
977 if (size == GPTRSIZE)
979 link *type = operandType(op);
982 /* generic pointer; arithmetic operations
983 * should ignore the high byte (pointer type).
991 /*-----------------------------------------------------------------*/
992 /* outAcc - output Acc */
993 /*-----------------------------------------------------------------*/
994 static void outAcc(operand *result)
997 size = getDataSize(result);
999 aopPut(AOP(result),"r0",0);
1002 /* unsigned or positive */
1004 aopPut(AOP(result),zero,offset++);
1009 /*-----------------------------------------------------------------*/
1010 /* outBitC - output a bit C */
1011 /*-----------------------------------------------------------------*/
1012 static void outBitC(operand *result)
1014 emitcode("clr","r0");
1015 emitcode("rol","r0");
1019 /*-----------------------------------------------------------------*/
1020 /* toBoolean - emit code for orl a,operator(sizeop) */
1021 /*-----------------------------------------------------------------*/
1022 static void toBoolean(operand *oper, char *r, bool clr)
1024 int size = AOP_SIZE(oper) ;
1026 if (clr) emitcode ("clr","%s",r);
1028 emitcode("or","%s,%s",r,aopGet(AOP(oper),offset++));
1032 /*-----------------------------------------------------------------*/
1033 /* genNot - generate code for ! operation */
1034 /*-----------------------------------------------------------------*/
1035 static void genNot (iCode *ic)
1038 link *optype = operandType(IC_LEFT(ic));
1039 int size, offset = 1;
1041 /* assign asmOps to operand & result */
1042 aopOp (IC_LEFT(ic),ic,FALSE);
1043 aopOp (IC_RESULT(ic),ic,TRUE);
1045 /* if type float then do float */
1046 if (IS_FLOAT(optype)) {
1047 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1050 emitcode("clr","r0");
1051 tlbl = newiTempLabel(NULL);
1052 size = AOP_SIZE(IC_LEFT(ic));
1055 emitcode("cpse","%s,r0",aopGet(AOP(IC_LEFT(ic)),0));
1059 if (offset) emitcode("cpc","%s,r0",aopGet(AOP(IC_LEFT(ic)),offset));
1060 else emitcode("cpi","%s,0",aopGet(AOP(IC_LEFT(ic)),offset));
1063 emitcode("bne","L%05d",tlbl->key);
1065 emitcode("ldi","r0,1");
1066 emitcode("","L%05d:",tlbl->key);
1067 aopPut(AOP(IC_RESULT(ic)),"r0",0);
1068 size = AOP_SIZE(IC_RESULT(ic)) -1;
1070 while (size--) aopPut(AOP(IC_RESULT(ic)),zero,offset++);
1074 /* release the aops */
1075 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1076 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1080 /*-----------------------------------------------------------------*/
1081 /* genCpl - generate code for complement */
1082 /*-----------------------------------------------------------------*/
1083 static void genCpl (iCode *ic)
1089 /* assign asmOps to operand & result */
1090 aopOp (IC_LEFT(ic),ic,FALSE);
1091 aopOp (IC_RESULT(ic),ic,TRUE);
1092 samer = sameRegs(AOP(IC_LEFT(ic)),AOP(IC_RESULT(ic)));
1093 size = AOP_SIZE(IC_RESULT(ic));
1095 char *l = aopGet(AOP(IC_LEFT(ic)),offset);
1097 emitcode ("com","%s",l);
1099 aopPut(AOP(IC_RESULT(ic)),l,offset);
1100 emitcode ("com","%s",aopGet(AOP(IC_RESULT(ic)),offset));
1105 /* release the aops */
1106 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1107 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1110 /*-----------------------------------------------------------------*/
1111 /* genUminusFloat - unary minus for floating points */
1112 /*-----------------------------------------------------------------*/
1113 static void genUminusFloat(operand *op,operand *result)
1115 int size ,offset =0 ;
1117 /* for this we just need to flip the
1118 first it then copy the rest in place */
1119 size = AOP_SIZE(op) - 1;
1120 l = aopGet(AOP(op),3);
1122 emitcode("ldi","r24,0x80");
1123 if (sameRegs(AOP(op),AOP(result))) {
1124 emitcode("eor","%s,r24",l);
1126 aopPut(AOP(result),l,3);
1127 emitcode("eor","%s,r24",aopGet(AOP(result),3));
1130 aopPut(AOP(result), aopGet(AOP(op),offset), offset);
1135 /*-----------------------------------------------------------------*/
1136 /* genUminus - unary minus code generation */
1137 /*-----------------------------------------------------------------*/
1138 static void genUminus (iCode *ic)
1141 link *optype, *rtype;
1145 aopOp(IC_LEFT(ic),ic,FALSE);
1146 aopOp(IC_RESULT(ic),ic,TRUE);
1148 optype = operandType(IC_LEFT(ic));
1149 rtype = operandType(IC_RESULT(ic));
1151 /* if float then do float stuff */
1152 if (IS_FLOAT(optype)) {
1153 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1157 /* otherwise subtract from zero */
1158 size = AOP_SIZE(IC_LEFT(ic));
1160 samer = sameRegs(AOP(IC_LEFT(ic)),AOP(IC_RESULT(ic)));
1163 emitcode("neg","%s",aopGet(AOP(IC_LEFT(ic)),0));
1165 aopPut(AOP(IC_RESULT(ic)),aopGet(AOP(IC_LEFT(ic)),0),0);
1166 emitcode("neg","%s",aopGet(AOP(IC_RESULT(ic)),0));
1171 char *l = aopGet(AOP(IC_LEFT(ic)),offset);
1173 aopPut(AOP(IC_RESULT(ic)),l,offset);
1174 l = aopGet(AOP(IC_RESULT(ic)),offset);
1176 if (offset) emitcode("com","%s",l);
1177 else emitcode("neg","%s",l);
1180 size = AOP_SIZE(IC_LEFT(ic)) -1;
1183 emitcode("sbci","%s,lo8(-1)",aopGet(AOP(IC_RESULT(ic)),offset++));
1187 /* if any remaining bytes in the result */
1188 /* we just need to propagate the sign */
1189 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1190 symbol *tlbl = newiTempLabel(NULL);
1191 emitcode("clr","r0");
1192 emitcode("brcc","L%05d",tlbl->key);
1193 emitcode("com","r0");
1194 emitcode("","L%05d:",tlbl->key);
1196 aopPut(AOP(IC_RESULT(ic)),"r0",offset++);
1200 /* release the aops */
1201 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1202 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1205 /*-----------------------------------------------------------------*/
1206 /* assignResultValue - */
1207 /*-----------------------------------------------------------------*/
1208 static void assignResultValue(operand * oper)
1211 int size = AOP_SIZE(oper);
1213 aopPut(AOP(oper),fAVRReturn[offset],offset);
1218 /*-----------------------------------------------------------------*/
1219 /* saveZreg - if indirect call then save z-pointer register */
1220 /*-----------------------------------------------------------------*/
1221 static void saveZreg (iCode *ic)
1223 /* only if live accross this call */
1224 if (ic->regsSaved == 0 &&
1225 (bitVectBitValue(ic->rMask,R30_IDX) ||
1226 bitVectBitValue(ic->rMask,R31_IDX))) {
1228 emitcode("push","r30");
1229 emitcode("push","r31");
1233 /*-----------------------------------------------------------------*/
1234 /* popZreg - restore values of zreg */
1235 /*-----------------------------------------------------------------*/
1236 static void popZreg (iCode *ic)
1238 if (ic->regsSaved) {
1239 emitcode ("pop","r31");
1240 emitcode ("pop","r30");
1244 /*-----------------------------------------------------------------*/
1245 /* genIpush - genrate code for pushing this gets a little complex */
1246 /*-----------------------------------------------------------------*/
1247 static void genIpush (iCode *ic)
1249 int size, offset = 0 ;
1253 if (!ic->parmPush) {
1254 /* and the item is spilt then do nothing */
1255 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1259 for (lic = ic->next ; lic ; lic = lic->next)
1260 if (lic->op == PCALL) break;
1261 if (lic) saveZreg(lic);
1264 /* this is a paramter push */
1265 aopOp(IC_LEFT(ic),ic,FALSE);
1266 size = AOP_SIZE(IC_LEFT(ic));
1268 l = aopGet(AOP(IC_LEFT(ic)),offset++);
1269 emitcode("push","%s",l);
1272 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1275 /*-----------------------------------------------------------------*/
1276 /* genIpop - recover the registers: can happen only for spilling */
1277 /*-----------------------------------------------------------------*/
1278 static void genIpop (iCode *ic)
1283 /* if the temp was not pushed then */
1284 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1287 aopOp(IC_LEFT(ic),ic,FALSE);
1288 size = AOP_SIZE(IC_LEFT(ic));
1291 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--));
1293 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1296 /*-----------------------------------------------------------------*/
1297 /* genCall - generates a call statement */
1298 /*-----------------------------------------------------------------*/
1299 static void genCall (iCode *ic)
1302 /* if send set is not empty the assign */
1306 for (sic = setFirstItem(_G.sendSet) ; sic ;
1307 sic = setNextItem(_G.sendSet)) {
1308 int size, offset = 0;
1309 aopOp(IC_LEFT(sic),sic,FALSE);
1310 size = AOP_SIZE(IC_LEFT(sic));
1312 char *l = aopGet(AOP(IC_LEFT(sic)),offset);
1314 sprintf(buffer,"r%d",rnum++);
1316 emitcode("mov","%s,%s",b,l);
1319 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1324 emitcode("call","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1325 OP_SYMBOL(IC_LEFT(ic))->rname :
1326 OP_SYMBOL(IC_LEFT(ic))->name));
1328 /* if we need assign a result value */
1329 if ((IS_ITEMP(IC_RESULT(ic)) &&
1330 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1331 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1332 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1334 aopOp(IC_RESULT(ic),ic,FALSE);
1335 assignResultValue(IC_RESULT(ic));
1336 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1339 /* adjust the stack for parameters if required */
1340 if (IC_LEFT(ic)->parmBytes) {
1341 if (IC_LEFT(ic)->parmBytes > 63) {
1342 emitcode("sbiw","r28,%d",IC_LEFT(ic)->parmBytes);
1344 emitcode("subi","r28,lo8(%d)",IC_LEFT(ic)->parmBytes);
1345 emitcode("sbci","r29,hi8(%d)",IC_LEFT(ic)->parmBytes);
1351 /*-----------------------------------------------------------------*/
1352 /* genPcall - generates a call by pointer statement */
1353 /*-----------------------------------------------------------------*/
1354 static void genPcall (iCode *ic)
1357 if (!ic->regsSaved) saveZreg(ic);
1359 aopOp(IC_LEFT(ic),ic,FALSE);
1360 emitcode("mov","r30",aopGet(AOP(IC_LEFT(ic)),0));
1361 emitcode("mov","r31",aopGet(AOP(IC_RIGHT(ic)),0));
1362 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1364 /* if send set is not empty the assign */
1368 for (sic = setFirstItem(_G.sendSet) ; sic ;
1369 sic = setNextItem(_G.sendSet)) {
1370 int size, offset = 0;
1371 aopOp(IC_LEFT(sic),sic,FALSE);
1372 size = AOP_SIZE(IC_LEFT(sic));
1374 char *l = aopGet(AOP(IC_LEFT(sic)),offset);
1376 sprintf(b,"r%d",rnum++);
1378 emitcode("mov","%s,%s",b,l);
1381 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1386 emitcode("icall","");
1388 /* if we need assign a result value */
1389 if ((IS_ITEMP(IC_RESULT(ic)) &&
1390 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1391 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
1392 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1394 aopOp(IC_RESULT(ic),ic,FALSE);
1396 assignResultValue(IC_RESULT(ic));
1397 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1400 /* adjust the stack for parameters if
1402 if (IC_LEFT(ic)->parmBytes) {
1404 if (IC_LEFT(ic)->parmBytes > 3) {
1405 emitcode("mov","a,%s",spname);
1406 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1407 emitcode("mov","%s,a",spname);
1409 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1410 emitcode("dec","%s",spname);
1414 /* adjust the stack for parameters if required */
1415 if (IC_LEFT(ic)->parmBytes) {
1416 if (IC_LEFT(ic)->parmBytes > 63) {
1417 emitcode("sbiw","r28,%d",IC_LEFT(ic)->parmBytes);
1419 emitcode("subi","r28,lo8(%d)",IC_LEFT(ic)->parmBytes);
1420 emitcode("sbci","r29,hi8(%d)",IC_LEFT(ic)->parmBytes);
1423 if (ic->regsSaved) popZreg(ic);
1426 /*-----------------------------------------------------------------*/
1427 /* resultRemat - result is rematerializable */
1428 /*-----------------------------------------------------------------*/
1429 static int resultRemat (iCode *ic)
1431 if (SKIP_IC(ic) || ic->op == IFX)
1434 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1435 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1436 if (sym->remat && !POINTER_SET(ic))
1444 #define STRCASECMP stricmp
1446 #define STRCASECMP strcasecmp
1449 /*-----------------------------------------------------------------*/
1450 /* inExcludeList - return 1 if the string is in exclude Reg list */
1451 /*-----------------------------------------------------------------*/
1452 static bool inExcludeList(char *s)
1456 if (options.excludeRegs[i] &&
1457 STRCASECMP(options.excludeRegs[i],"none") == 0)
1460 for ( i = 0 ; options.excludeRegs[i]; i++) {
1461 if (options.excludeRegs[i] &&
1462 STRCASECMP(s,options.excludeRegs[i]) == 0)
1468 /*-----------------------------------------------------------------*/
1469 /* genFunction - generated code for function entry */
1470 /*-----------------------------------------------------------------*/
1471 static void genFunction (iCode *ic)
1478 /* create the function header */
1479 emitcode(";","-----------------------------------------");
1480 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1481 emitcode(";","-----------------------------------------");
1483 emitcode("","%s:",sym->rname);
1484 fetype = getSpec(operandType(IC_LEFT(ic)));
1486 /* if critical function then turn interrupts off */
1487 if (SPEC_CRTCL(fetype))
1490 if (IS_ISR(sym->etype)) {
1493 /* save the preserved registers that are used in this function */
1494 for (i = R2_IDX ; i <= R15_IDX ; i++ ) {
1495 if (bitVectBitValue(sym->regsUsed,i)) {
1497 emitcode("push","%s",avr_regWithIdx(i)->name);
1500 /* now for the pointer registers */
1501 if (bitVectBitValue(sym->regsUsed,R26_IDX)) {
1503 emitcode("push","r26");
1505 if (bitVectBitValue(sym->regsUsed,R27_IDX)) {
1507 emitcode("push","r27");
1509 if (bitVectBitValue(sym->regsUsed,R30_IDX)) {
1511 emitcode("push","r30");
1513 if (bitVectBitValue(sym->regsUsed,R31_IDX)) {
1515 emitcode("push","r31");
1517 /* adjust the stack for the function */
1519 emitcode ("push","r28");
1520 emitcode ("push","r29");
1521 emitcode ("in","r28,__SP_L__");
1522 emitcode ("in","r29,__SP_H__");
1523 if (sym->stack <= 63) {
1524 emitcode("sbiw","r28,%d",sym->stack);
1526 emitcode ("subi","r28,lo8(%d)",sym->stack);
1527 emitcode ("sbci","r29,hi8(%d)",sym->stack);
1529 emitcode("out","__SP_L__,r28");
1530 emitcode("out","__SP_H__,r29");
1534 /*-----------------------------------------------------------------*/
1535 /* genEndFunction - generates epilogue for functions */
1536 /*-----------------------------------------------------------------*/
1537 static void genEndFunction (iCode *ic)
1539 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1542 /* restore stack pointer */
1544 if (sym->stack <= 63) {
1545 emitcode("adiw","r28,%d",sym->stack);
1547 emitcode ("subi","r28,lo8(-%d)",sym->stack);
1548 emitcode ("sbci","r29,hi8(-%d)",sym->stack);
1550 emitcode("out","__SP_L__,r28");
1551 emitcode("out","__SP_H__,r29");
1553 /* pop frame pointer */
1554 emitcode ("pop","r29");
1555 emitcode ("pop","r28");
1557 /* restore preserved registers */
1558 if (bitVectBitValue(sym->regsUsed,R31_IDX)) {
1560 emitcode("pop","r31");
1562 if (bitVectBitValue(sym->regsUsed,R30_IDX)) {
1564 emitcode("pop","r30");
1566 if (bitVectBitValue(sym->regsUsed,R27_IDX)) {
1568 emitcode("push","r27");
1570 if (bitVectBitValue(sym->regsUsed,R26_IDX)) {
1572 emitcode("push","r26");
1574 for (i = R15_IDX ; i >= R2_IDX ; i-- ) {
1575 if (bitVectBitValue(sym->regsUsed,i)) {
1577 emitcode("pop","%s",avr_regWithIdx(i)->name);
1581 if (SPEC_CRTCL(sym->etype))
1584 if (IS_ISR(sym->etype)) {
1592 /*-----------------------------------------------------------------*/
1593 /* genRet - generate code for return statement */
1594 /*-----------------------------------------------------------------*/
1595 static void genRet (iCode *ic)
1597 int size,offset = 0 ;
1599 /* if we have no return value then
1600 just generate the "ret" */
1604 /* we have something to return then
1605 move the return value into place */
1606 aopOp(IC_LEFT(ic),ic,FALSE);
1607 size = AOP_SIZE(IC_LEFT(ic));
1610 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
1611 emitcode("ldi","%s,%s(%d)",fAVRReturn[offset],larray[offset],
1612 (int)floatFromVal (AOP(IC_LEFT(ic))->aopu.aop_lit),offset);
1615 l = aopGet(AOP(IC_LEFT(ic)),offset);
1616 if (strcmp(fAVRReturn[offset],l))
1617 emitcode("mov","%s,%s",fAVRReturn[offset],l);
1622 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
1625 /* generate a jump to the return label
1626 if the next is not the return statement */
1627 if (!(ic->next && ic->next->op == LABEL &&
1628 IC_LABEL(ic->next) == returnLabel))
1630 emitcode("rjmp","L%05d",returnLabel->key);
1634 /*-----------------------------------------------------------------*/
1635 /* genLabel - generates a label */
1636 /*-----------------------------------------------------------------*/
1637 static void genLabel (iCode *ic)
1639 /* special case never generate */
1640 if (IC_LABEL(ic) == entryLabel)
1643 emitcode("","L%05d:",IC_LABEL(ic)->key);
1646 /*-----------------------------------------------------------------*/
1647 /* genGoto - generates a ljmp */
1648 /*-----------------------------------------------------------------*/
1649 static void genGoto (iCode *ic)
1651 emitcode ("rjmp","L%05d:",(IC_LABEL(ic)->key+100));
1654 /*-----------------------------------------------------------------*/
1655 /* findLabelBackwards: walks back through the iCode chain looking */
1656 /* for the given label. Returns number of iCode instructions */
1657 /* between that label and given ic. */
1658 /* Returns zero if label not found. */
1659 /*-----------------------------------------------------------------*/
1660 static int findLabelBackwards(iCode *ic, int key)
1669 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
1671 /* printf("findLabelBackwards = %d\n", count); */
1679 /*-----------------------------------------------------------------*/
1680 /* genPlusIncr :- does addition with increment if possible */
1681 /*-----------------------------------------------------------------*/
1682 static bool genPlusIncr (iCode *ic)
1684 unsigned int icount ;
1686 /* will try to generate an increment */
1687 /* if the right side is not a literal
1689 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1692 icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
1694 /* if the sizes are greater than 2 or they are not the same regs
1696 if (!sameRegs(AOP(IC_LEFT(ic)),AOP(IC_RESULT(ic))))
1699 /* so we know LEFT & RESULT in the same registers and add
1701 /* for short & char types */
1702 if (AOP_SIZE(IC_RESULT(ic)) < 2) {
1704 emitcode("inc","%s",aopGet(AOP(IC_LEFT(ic)),0));
1707 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_LEFT(ic)),0),-icount);
1711 if (AOP_SIZE(IC_RESULT(ic)) <= 3) {
1712 /* if register pair and starts with 26/30 then adiw */
1713 if (isRegPair(AOP(IC_RESULT(ic))) && icount > 0 && icount < 64 &&
1714 ( IS_REGIDX(AOP(IC_RESULT(ic)),R26_IDX) ||
1715 IS_REGIDX(AOP(IC_RESULT(ic)),R30_IDX) )) {
1716 emitcode("adiw","%s,%d",aopGet(AOP(IC_RESULT(ic)),0),icount);
1721 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_RESULT(ic)),0),-icount);
1722 emitcode("sbci","%s,hi8(%d)",aopGet(AOP(IC_RESULT(ic)),1),-icount);
1726 /* for 32 bit longs */
1727 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_RESULT(ic)),0),-icount);
1728 emitcode("sbci","%s,hi8(%d)",aopGet(AOP(IC_RESULT(ic)),1),-icount);
1729 emitcode("sbci","%s,hlo8(%d)",aopGet(AOP(IC_RESULT(ic)),2),-icount);
1730 emitcode("sbci","%s,hhi8(%d)",aopGet(AOP(IC_RESULT(ic)),3),-icount);
1735 /* This is the pure and virtuous version of this code.
1736 * I'm pretty certain it's right, but not enough to toss the old
1739 static void adjustArithmeticResult (iCode *ic)
1741 if (opIsGptr(IC_RESULT(ic)) &&
1742 opIsGptr(IC_LEFT(ic)) &&
1743 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1745 aopPut(AOP(IC_RESULT(ic)),
1746 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1),
1750 if (opIsGptr(IC_RESULT(ic)) &&
1751 opIsGptr(IC_RIGHT(ic)) &&
1752 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
1754 aopPut(AOP(IC_RESULT(ic)),
1755 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1),
1759 if (opIsGptr(IC_RESULT(ic)) &&
1760 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
1761 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
1762 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
1763 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
1765 sprintf(buffer,"%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
1766 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
1770 /*-----------------------------------------------------------------*/
1771 /* genPlus - generates code for addition */
1772 /*-----------------------------------------------------------------*/
1773 static void genPlus (iCode *ic)
1775 int size, offset = 0;
1779 /* special cases :- */
1781 aopOp (IC_LEFT(ic),ic,FALSE);
1782 aopOp (IC_RIGHT(ic),ic,FALSE);
1783 aopOp (IC_RESULT(ic),ic,TRUE);
1785 /* if I can do an increment instead
1786 of add then GOOD for ME */
1787 if (genPlusIncr (ic) == TRUE)
1790 size = getDataSize(IC_RESULT(ic));
1791 samer = sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic)));
1795 aopPut(AOP(IC_RESULT(ic)),aopGet(AOP(IC_LEFT(ic)),offset),offset);
1797 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
1799 if(offset == 0) l = "add";
1802 emitcode(l,"%s,%s",aopGet(AOP(IC_RESULT(ic)),offset),
1803 aopGet(AOP(IC_RIGHT(ic)),offset));
1805 if (offset == 0) l = "subi";
1808 emitcode(l,"%s,%s(-%d)",aopGet(AOP(IC_RESULT(ic)),offset),
1810 (int)floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
1815 adjustArithmeticResult(ic);
1818 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1819 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1820 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1823 /*-----------------------------------------------------------------*/
1824 /* genMinusDec :- does subtraction with deccrement if possible */
1825 /*-----------------------------------------------------------------*/
1826 static bool genMinusDec (iCode *ic)
1828 unsigned int icount ;
1830 /* will try to generate an increment */
1831 /* if the right side is not a literal
1833 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1836 icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
1838 /* if the sizes are greater than 2 or they are not the same regs
1840 if (!sameRegs(AOP(IC_LEFT(ic)),AOP(IC_RIGHT(ic))))
1843 /* so we know LEFT & RESULT in the same registers and add
1845 /* for short & char types */
1846 if (AOP_SIZE(IC_RESULT(ic)) < 2) {
1848 emitcode("dec","%s",aopGet(AOP(IC_LEFT(ic)),0));
1851 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_LEFT(ic)),0),icount);
1855 if (AOP_SIZE(IC_RESULT(ic)) <= 3) {
1856 /* if register pair and starts with 26/30 then adiw */
1857 if (isRegPair(AOP(IC_RESULT(ic))) && icount > 0 && icount < 64 &&
1858 ( IS_REGIDX(AOP(IC_RESULT(ic)),R26_IDX) ||
1859 IS_REGIDX(AOP(IC_RESULT(ic)),R30_IDX) )) {
1860 emitcode("sbiw","%s,%d",aopGet(AOP(IC_RESULT(ic)),0),icount);
1865 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_RESULT(ic)),0),icount);
1866 emitcode("sbci","%s,hi8(%d)",aopGet(AOP(IC_RESULT(ic)),1),icount);
1869 /* for 32 bit longs */
1870 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_RESULT(ic)),0),icount);
1871 emitcode("sbci","%s,hi8(%d)",aopGet(AOP(IC_RESULT(ic)),1),icount);
1872 emitcode("sbci","%s,hlo8(%d)",aopGet(AOP(IC_RESULT(ic)),2),icount);
1873 emitcode("sbci","%s,hhi8(%d)",aopGet(AOP(IC_RESULT(ic)),3),icount);
1878 /*-----------------------------------------------------------------*/
1879 /* addSign - complete with sign */
1880 /*-----------------------------------------------------------------*/
1881 static void addSign(operand *result, int offset, int sign)
1883 int size = (getDataSize(result) - offset);
1886 emitcode("rlc","a");
1887 emitcode("subb","a,acc");
1889 aopPut(AOP(result),"a",offset++);
1892 aopPut(AOP(result),zero,offset++);
1896 /*-----------------------------------------------------------------*/
1897 /* genMinus - generates code for subtraction */
1898 /*-----------------------------------------------------------------*/
1899 static void genMinus (iCode *ic)
1901 int size, offset = 0, samer;
1904 aopOp (IC_LEFT(ic),ic,FALSE);
1905 aopOp (IC_RIGHT(ic),ic,FALSE);
1906 aopOp (IC_RESULT(ic),ic,TRUE);
1908 /* if I can do an decrement instead
1909 of subtract then GOOD for ME */
1910 if (genMinusDec (ic) == TRUE)
1913 size = getDataSize(IC_RESULT(ic));
1914 samer = sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic)));
1917 aopPut(AOP(IC_RESULT(ic)),aopGet(AOP(IC_LEFT(ic)),offset),offset);
1919 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
1921 if(offset == 0) l = "sub";
1924 emitcode(l,"%s,%s",aopGet(AOP(IC_RESULT(ic)),offset),
1925 aopGet(AOP(IC_RIGHT(ic)),offset));
1927 if (offset == 0) l = "subi";
1930 emitcode(l,"%s,%s(%d)",aopGet(AOP(IC_RESULT(ic)),offset),
1932 (int)floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
1937 adjustArithmeticResult(ic);
1940 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1941 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1942 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1945 /*-----------------------------------------------------------------*/
1946 /* genMultOneByte : 8 bit multiplication & division */
1947 /*-----------------------------------------------------------------*/
1948 static void genMultOneByte (operand *left,
1952 link *opetype = operandType(result);
1956 /* (if two literals, the value is computed before) */
1957 /* if one literal, literal on the right */
1958 if (AOP_TYPE(left) == AOP_LIT){
1964 size = AOP_SIZE(result);
1966 if (SPEC_USIGN(opetype)) {
1967 emitcode("mul","%s,%s", aopGet(AOP(left),0),aopGet(AOP(right),0));
1969 emitcode("muls","%s,%s", aopGet(AOP(left),0),
1970 aopGet(AOP(right),0));
1972 aopPut(AOP(result),"r0",0);
1974 aopPut(AOP(result),"r1",1);
1977 if (SPEC_USIGN(opetype)) {
1979 aopPut(AOP(result),zero,offset++);
1983 lbl = newiTempLabel(NULL);
1984 emitcode("ldi","r24,0");
1985 emitcode("brcc","L%05d",lbl->key);
1986 emitcode("ldi","r24,lo8(-1)");
1987 emitcode("","L%05d:",lbl->key);
1988 while (size--) aopPut(AOP(result),"r24",offset++);
1995 /*-----------------------------------------------------------------*/
1996 /* genMult - generates code for multiplication */
1997 /*-----------------------------------------------------------------*/
1998 static void genMult (iCode *ic)
2000 operand *left = IC_LEFT(ic);
2001 operand *right = IC_RIGHT(ic);
2002 operand *result= IC_RESULT(ic);
2004 /* assign the amsops */
2005 aopOp (left,ic,FALSE);
2006 aopOp (right,ic,FALSE);
2007 aopOp (result,ic,TRUE);
2009 /* if both are of size == 1 */
2010 if (AOP_SIZE(left) == 1 &&
2011 AOP_SIZE(right) == 1 ) {
2012 genMultOneByte(left,right,result);
2016 /* should have been converted to function call */
2020 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2021 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2022 freeAsmop(result,NULL,ic,TRUE);
2025 /*-----------------------------------------------------------------*/
2026 /* genDiv - generates code for division */
2027 /*-----------------------------------------------------------------*/
2028 static void genDiv (iCode *ic)
2030 /* should have been converted to function call */
2034 /*-----------------------------------------------------------------*/
2035 /* genMod - generates code for division */
2036 /*-----------------------------------------------------------------*/
2037 static void genMod (iCode *ic)
2039 /* should have been converted to function call */
2051 /*-----------------------------------------------------------------*/
2052 /* revavrcnd - reverse a conditional for avr */
2053 /*-----------------------------------------------------------------*/
2054 static int revavrcnd(int type)
2058 } rar[] = { { AVR_EQ, AVR_NE}, {AVR_LT, AVR_GE}};
2061 for (i = 0 ; i < (sizeof(rar)/sizeof(rar[0]));i++) {
2062 if (rar[i].type == type) return rar[i].rtype;
2063 if (rar[i].rtype== type) return rar[i].type;
2065 assert(1); /* cannot happen */
2066 return 0; /* makes the compiler happy */
2069 static char *br_name[4] = {"breq","brne","brlt","brge"};
2070 static char *br_uname[4]= {"breq","brne","brlo","brcc"};
2072 /*-----------------------------------------------------------------*/
2073 /* genBranch - generate the branch instruction */
2074 /*-----------------------------------------------------------------*/
2075 static void genBranch (iCode *ifx, int br_type, int sign)
2077 int tj = (IC_TRUE(ifx) ? 1 : 0) ;
2079 if (tj) { /* if true jump */
2080 char *nm = (sign ? br_name[br_type] : br_uname[br_type]);
2081 emitcode(nm,"L%05d",IC_TRUE(ifx)->key);
2082 } else { /* if false jump */
2083 int rtype = revavrcnd(br_type);
2084 char *nm = (sign ? br_name[rtype] : br_uname[rtype]);
2085 emitcode(nm,"L%05d",IC_FALSE(ifx)->key);
2090 /*-----------------------------------------------------------------*/
2091 /* genCmp - compare & jump */
2092 /*-----------------------------------------------------------------*/
2093 static void genCmp (iCode *ic, iCode *ifx, int br_type)
2095 operand *left, *right, *result;
2096 link *letype , *retype;
2098 int sign, size, offset =0;
2101 right= IC_RIGHT(ic);
2102 result = IC_RESULT(ic);
2104 letype = getSpec(operandType(left));
2105 retype =getSpec(operandType(right));
2106 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2108 /* assign the amsops */
2109 aopOp (left,ic,FALSE);
2110 aopOp (right,ic,FALSE);
2111 aopOp (result,ic,TRUE);
2112 size = AOP_SIZE(left);
2116 if (AOP_TYPE(right) == AOP_LIT) {
2117 emitcode("cpi","%s,lo8(%d)",aopGet(AOP(left),0),
2118 (int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
2119 genBranch(ifx,br_type,sign);
2120 } else { /* right != literal */
2121 emitcode("cp","%s,%s",aopGet(AOP(left),0),aopGet(AOP(right),0));
2122 genBranch(ifx,br_type,sign);
2124 } else { /* size != 1 */
2127 emitcode("cp","%s,%s",aopGet(AOP(left),0),aopGet(AOP(right),0));
2129 emitcode("cpc","%s,%s",aopGet(AOP(left),offset),aopGet(AOP(right),offset));
2132 genBranch(ifx,br_type,sign);
2134 } else { /* no ifx */
2135 emitcode("clr","r0");
2138 emitcode("cp","%s,%s",aopGet(AOP(left),0),aopGet(AOP(right),0));
2140 emitcode("cpc","%s,%s",aopGet(AOP(left),offset),aopGet(AOP(right),offset));
2143 lbl = newiTempLabel(NULL);
2144 br_type = revavrcnd(br_type);
2145 if (sign) emitcode(br_uname[br_type],"L%05d",lbl->key);
2146 else emitcode(br_name[br_type],"L%05d",lbl->key);
2147 emitcode("inc","r0");
2148 emitcode("","L%05d:",lbl->key);
2149 aopPut(AOP(result),"r0",0);
2150 size = AOP_SIZE(result) - 1;
2152 while (size--) aopPut(AOP(result),zero,offset++);
2155 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2156 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2157 freeAsmop(result,NULL,ic,TRUE);
2160 /*-----------------------------------------------------------------*/
2161 /* genCmpGt :- greater than comparison */
2162 /*-----------------------------------------------------------------*/
2163 static void genCmpGt (iCode *ic, iCode *ifx)
2165 /* should have transformed by the parser */
2169 /*-----------------------------------------------------------------*/
2170 /* genCmpLt - less than comparisons */
2171 /*-----------------------------------------------------------------*/
2172 static void genCmpLt (iCode *ic, iCode *ifx)
2174 genCmp(ic,ifx,AVR_LT);
2177 /*-----------------------------------------------------------------*/
2178 /* genCmpEq - generates code for equal to */
2179 /*-----------------------------------------------------------------*/
2180 static void genCmpEq (iCode *ic, iCode *ifx)
2182 genCmp(ic,ifx,AVR_EQ);
2185 /*-----------------------------------------------------------------*/
2186 /* genCmpNe - generates code for not equal to */
2187 /*-----------------------------------------------------------------*/
2188 static void genCmpNe (iCode *ic, iCode *ifx)
2190 genCmp(ic,ifx,AVR_NE);
2193 /*-----------------------------------------------------------------*/
2194 /* genCmpGe - generates code for greater than equal to */
2195 /*-----------------------------------------------------------------*/
2196 static void genCmpGe (iCode *ic, iCode *ifx)
2198 genCmp(ic,ifx,AVR_GE);
2201 /*-----------------------------------------------------------------*/
2202 /* genCmpLe - generates code for less than equal to */
2203 /*-----------------------------------------------------------------*/
2204 static void genCmpLe (iCode *ic, iCode *ifx)
2206 operand *left = IC_LEFT(ic);
2207 operand *right= IC_RIGHT(ic);
2209 IC_RIGHT(ic) = left;
2210 IC_LEFT(ic) = right;
2211 genCmp(ic,ifx,AVR_GE);
2214 /*-----------------------------------------------------------------*/
2215 /* ifxForOp - returns the icode containing the ifx for operand */
2216 /*-----------------------------------------------------------------*/
2217 static iCode *ifxForOp ( operand *op, iCode *ic )
2219 /* if true symbol then needs to be assigned */
2220 if (IS_TRUE_SYMOP(op))
2223 /* if this has register type condition and
2224 the next instruction is ifx with the same operand
2225 and live to of the operand is upto the ifx only then */
2227 ic->next->op == IFX &&
2228 IC_COND(ic->next)->key == op->key &&
2229 OP_SYMBOL(op)->liveTo <= ic->next->seq )
2234 /*-----------------------------------------------------------------*/
2235 /* genAndOp - for && operation */
2236 /*-----------------------------------------------------------------*/
2237 static void genAndOp (iCode *ic)
2239 operand *left,*right, *result;
2243 /* note here that && operations that are in an
2244 if statement are taken away by backPatchLabels
2245 only those used in arthmetic operations remain */
2246 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2247 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2248 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2250 tlbl = newiTempLabel(NULL);
2251 toBoolean(left,"r0",TRUE);
2252 toBoolean(right,"r1",TRUE);
2253 emitcode("and","r0,r1");
2254 emitcode("ldi","r24,1");
2255 emitcode("breq","L%05d",tlbl->key);
2256 emitcode("dec","r24");
2257 emitcode("","L%05d:",tlbl->key);
2258 aopPut(AOP(result),"r24",0);
2259 size = AOP_SIZE(result) -1;
2261 while (size--) aopPut(AOP(result),zero,offset++);
2263 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2264 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2265 freeAsmop(result,NULL,ic,TRUE);
2269 /*-----------------------------------------------------------------*/
2270 /* genOrOp - for || operation */
2271 /*-----------------------------------------------------------------*/
2272 static void genOrOp (iCode *ic)
2274 operand *left,*right, *result;
2278 /* note here that || operations that are in an
2279 if statement are taken away by backPatchLabels
2280 only those used in arthmetic operations remain */
2281 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2282 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2283 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2285 tlbl = newiTempLabel(NULL);
2286 toBoolean(left,"r0",TRUE);
2287 toBoolean(right,"r0",FALSE);
2288 emitcode("ldi","r24,1");
2289 emitcode("breq","L%05d",tlbl->key);
2290 emitcode("dec","r24");
2291 emitcode("","L%05d:",tlbl->key);
2292 aopPut(AOP(result),"r24",0);
2293 size = AOP_SIZE(result) -1;
2295 while (size--) aopPut(AOP(result),zero,offset++);
2297 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2298 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2299 freeAsmop(result,NULL,ic,TRUE);
2302 /*-----------------------------------------------------------------*/
2303 /* isLiteralBit - test if lit == 2^n */
2304 /*-----------------------------------------------------------------*/
2305 static int isLiteralBit(unsigned long lit)
2307 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
2308 0x100L,0x200L,0x400L,0x800L,
2309 0x1000L,0x2000L,0x4000L,0x8000L,
2310 0x10000L,0x20000L,0x40000L,0x80000L,
2311 0x100000L,0x200000L,0x400000L,0x800000L,
2312 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
2313 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
2316 for(idx = 0; idx < 32; idx++)
2322 enum { AVR_AND = 0, AVR_OR, AVR_XOR };
2323 static char *bopnames_lit[] = {"andi","ori"};
2324 static char *bopnames[] = {"and","or","eor"};
2325 /*-----------------------------------------------------------------*/
2326 /* genBitWise - generate bitwise operations */
2327 /*-----------------------------------------------------------------*/
2328 static void genBitWise(iCode *ic, iCode *ifx, int bitop)
2330 operand *left, *right, *result;
2334 int samerl, samerr ;
2336 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2337 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2338 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2340 size = AOP_SIZE(left);
2342 if (ifx) { /* used only for jumps */
2343 if (AOP_TYPE(right) == AOP_LIT &&
2344 (bitop == AVR_AND || bitop == AVR_OR)) {
2345 int lit = (int) floatFromVal (AOP(right)->aopu.aop_lit);
2346 int p2 = powof2(lit);
2347 if (bitop == AVR_AND && p2) { /* right side is a power of 2 */
2348 l = aopGet(AOP(left),p2 / 8);
2350 emitcode("sbrc","%s,%d",l,(p2 % 8));
2351 emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2353 emitcode("sbrs","%s,%d",l,(p2 % 8));
2354 emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2356 } else { /* right not power of two */
2357 int eh = OP_SYMBOL(left)->liveTo <= ic->seq;
2360 emitcode(bopnames_lit[bitop],"%s,lo8(%d)",
2361 aopGet(AOP(IC_LEFT(ic)),0), lit);
2363 MOVR0(aopGet(AOP(IC_LEFT(ic)),0));
2364 emitcode(bopnames_lit[bitop],"r0,lo8(%d)",lit);
2366 lbl = newiTempLabel(NULL);
2368 emitcode("breq","L%05d",lbl->key);
2369 emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2371 emitcode("brne","L%05d",lbl->key);
2372 emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2374 emitcode("","L%05d:",lbl->key);
2375 } else if (size == 2) {
2376 emitcode("mov","r24,%s",aopGet(AOP(IC_LEFT(ic)),0));
2377 emitcode("mov","r25,%s",aopGet(AOP(IC_LEFT(ic)),1));
2378 emitcode(bopnames_lit[bitop],"r24,lo8(%d)",lit);
2379 emitcode(bopnames_lit[bitop],"r25,hi8(%d)",lit);
2380 emitcode("sbiw","r24,0");
2381 lbl = newiTempLabel(NULL);
2383 emitcode("breq","L%05d",lbl->key);
2384 emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2386 emitcode("brne","L%05d",lbl->key);
2387 emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2389 emitcode("","L%05d:",lbl->key);
2391 lbl = newiTempLabel(NULL);
2392 lbl1 = newiTempLabel(NULL);
2395 emitcode(bopnames_lit[bitop],"%s,lo8(%d)",
2396 aopGet(AOP(IC_LEFT(ic)),offset), lit);
2398 MOVR0(aopGet(AOP(IC_LEFT(ic)),offset));
2399 emitcode("andi","r0,lo8(%d)",lit);
2401 emitcode("brne","L%05d",lbl->key);
2405 if (IC_FALSE(ifx)) emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2406 else emitcode("rjmp","L%05d",lbl1->key);
2407 emitcode("","L%05d:",lbl->key);
2409 if (IC_TRUE(ifx)) emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2410 emitcode("","L%05d:",lbl1->key);
2414 } else { /* right is not a literal */
2415 int eh = OP_SYMBOL(left)->liveTo <= ic->seq;
2416 int reh = OP_SYMBOL(right)->liveTo <= ic->seq;
2419 emitcode(bopnames[bitop],"%s,%s",
2420 aopGet(AOP(IC_LEFT(ic)),0),
2421 aopGet(AOP(IC_RIGHT(ic)),0));
2423 emitcode(bopnames[bitop],"%s,%s",
2424 aopGet(AOP(IC_RIGHT(ic)),0),
2425 aopGet(AOP(IC_LEFT(ic)),0));
2427 MOVR0(aopGet(AOP(IC_LEFT(ic)),0));
2428 emitcode(bopnames[bitop],"r0,%s",aopGet(AOP(IC_RIGHT(ic)),0));
2430 lbl = newiTempLabel(NULL);
2432 emitcode("breq","L%05d",lbl->key);
2433 emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2435 emitcode("brne","L%05d",lbl->key);
2436 emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2438 emitcode("","L%05d:",lbl->key);
2439 } else if (size == 2) {
2440 emitcode("mov","r24,%s",aopGet(AOP(IC_LEFT(ic)),0));
2441 emitcode("mov","r25,%s",aopGet(AOP(IC_LEFT(ic)),1));
2442 emitcode(bopnames[bitop],"r24,%s",aopGet(AOP(IC_RIGHT(ic)),0));
2443 emitcode(bopnames[bitop],"r25,%s",aopGet(AOP(IC_RIGHT(ic)),1));
2444 emitcode("sbiw","r24,0");
2445 lbl = newiTempLabel(NULL);
2447 emitcode("breq","L%05d",lbl->key);
2448 emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2450 emitcode("brne","L%05d",lbl->key);
2451 emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2453 emitcode("","L%05d:",lbl->key);
2455 lbl = newiTempLabel(NULL);
2456 lbl1 = newiTempLabel(NULL);
2459 emitcode(bopnames[bitop],"%s,%s",
2460 aopGet(AOP(IC_LEFT(ic)),offset),
2461 aopGet(AOP(IC_RIGHT(ic)),offset));
2463 emitcode(bopnames[bitop],"%s,%s",
2464 aopGet(AOP(IC_RIGHT(ic)),offset),
2465 aopGet(AOP(IC_LEFT(ic)),offset));
2467 MOVR0(aopGet(AOP(IC_LEFT(ic)),offset));
2468 emitcode(bopnames[bitop],"r0,%s",aopGet(AOP(IC_RIGHT(ic)),offset));
2470 emitcode("brne","L%05d",lbl->key);
2474 if (IC_FALSE(ifx)) emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2475 else emitcode("rjmp","L%05d",lbl1->key);
2476 emitcode("","L%05d:",lbl->key);
2478 if (IC_TRUE(ifx)) emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2479 emitcode("","L%05d:",lbl1->key);
2486 /* result needs to go a register */
2487 samerl = sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic)));
2488 samerr = sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)));
2490 if (AOP_TYPE(right) == AOP_LIT) {
2491 unsigned int lit = (int) floatFromVal (AOP(right)->aopu.aop_lit);
2492 if (((lit >> (8*offset)) & 0xff) == 0) {
2493 if (bitop == AVR_AND) {
2494 aopPut(AOP(result),zero,offset++);
2496 } else if (bitop == AVR_OR) {
2498 aopPut(AOP(result),aopGet(AOP(left),offset),offset);
2505 if (AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT && (bitop == AVR_AND || bitop == AVR_OR)) {
2506 emitcode(bopnames_lit[bitop],"%s,%s(%d)",aopGet(AOP(IC_LEFT(ic)),offset),
2507 larray[offset],(int) floatFromVal (AOP(right)->aopu.aop_lit));
2509 emitcode(bopnames[bitop],"%s,%s",aopGet(AOP(IC_LEFT(ic)),offset),
2510 aopGet(AOP(IC_RIGHT(ic)),offset));
2512 } else if (samerr) {
2513 emitcode(bopnames[bitop],"%s,%s",aopGet(AOP(IC_RIGHT(ic)),offset),
2514 aopGet(AOP(IC_LEFT(ic)),offset));
2516 aopPut(AOP(IC_RESULT(ic)),aopGet(AOP(IC_LEFT(ic)),offset),offset);
2517 emitcode(bopnames[bitop],aopGet(AOP(IC_RESULT(ic)),offset),
2518 aopGet(AOP(IC_RIGHT(ic)),offset));
2523 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2524 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2525 freeAsmop(result,NULL,ic,TRUE);
2528 /*-----------------------------------------------------------------*/
2529 /* genAnd - code for and */
2530 /*-----------------------------------------------------------------*/
2531 static void genAnd (iCode *ic, iCode *ifx)
2533 genBitWise(ic,ifx,AVR_AND);
2536 /*-----------------------------------------------------------------*/
2537 /* genOr - code for or */
2538 /*-----------------------------------------------------------------*/
2539 static void genOr (iCode *ic, iCode *ifx)
2541 genBitWise(ic,ifx,AVR_OR);
2544 /*-----------------------------------------------------------------*/
2545 /* genXor - code for xclusive or */
2546 /*-----------------------------------------------------------------*/
2547 static void genXor (iCode *ic, iCode *ifx)
2549 genBitWise(ic,ifx,AVR_XOR);
2552 /*-----------------------------------------------------------------*/
2553 /* genInline - write the inline code out */
2554 /*-----------------------------------------------------------------*/
2555 static void genInline (iCode *ic)
2557 char buffer[MAX_INLINEASM];
2561 _G.inLine += (!options.asmpeep);
2562 strcpy(buffer,IC_INLINE(ic));
2564 /* emit each line as a code */
2583 /* emitcode("",buffer); */
2584 _G.inLine -= (!options.asmpeep);
2587 /*-----------------------------------------------------------------*/
2588 /* genRotC - rotate right/left with carry , lr = 1 rotate right */
2589 /*-----------------------------------------------------------------*/
2590 static void genRotC (iCode *ic, int lr)
2592 operand *left , *result ;
2593 int size, offset = 0;
2595 /* rotate right with carry */
2597 result=IC_RESULT(ic);
2598 aopOp (left,ic,FALSE);
2599 aopOp (result,ic,FALSE);
2601 /* move it to the result */
2602 size = AOP_SIZE(result);
2603 if (!sameRegs(AOP(left),AOP(result))) {
2607 aopGet(AOP(left),offset),
2611 size = AOP_SIZE(result);
2613 if (lr) offset = size - 1;
2617 emitcode ("sbrc","%s,%d",aopGet(AOP(result),offset),
2622 emitcode((lr ? "ror" : "rol"),"%s",aopGet(AOP(result),offset));
2626 freeAsmop(left,NULL,ic,TRUE);
2627 freeAsmop(result,NULL,ic,TRUE);
2630 /*-----------------------------------------------------------------*/
2631 /* genRRC - rotate right with carry */
2632 /*-----------------------------------------------------------------*/
2633 static void genRRC (iCode *ic)
2638 /*-----------------------------------------------------------------*/
2639 /* genRLC - generate code for rotate left with carry */
2640 /*-----------------------------------------------------------------*/
2641 static void genRLC (iCode *ic)
2646 /*-----------------------------------------------------------------*/
2647 /* genGetHbit - generates code get highest order bit */
2648 /*-----------------------------------------------------------------*/
2649 static void genGetHbit (iCode *ic)
2651 operand *left, *result;
2655 result=IC_RESULT(ic);
2656 aopOp (left,ic,FALSE);
2657 aopOp (result,ic,FALSE);
2659 size = AOP_SIZE(result);
2660 if (!sameRegs(AOP(left),AOP(result))) {
2661 emitcode("clr","%s",aopGet(AOP(result),size -1));
2662 emitcode("sbrc","%s,7",aopGet(AOP(left),size -1));
2663 emitcode("subi","%s,lo8(-1)",aopGet(AOP(result),size-1));
2665 emitcode("clr","r0");
2666 emitcode("sbrc","%s,7",aopGet(AOP(left),size-1));
2667 emitcode("subi","r0,lo8(-1)");
2668 aopPut(AOP(result),"r0",0);
2673 emitcode("clr",aopGet(AOP(result),offset++));
2675 freeAsmop(left,NULL,ic,TRUE);
2676 freeAsmop(result,NULL,ic,TRUE);
2679 /*-----------------------------------------------------------------*/
2680 /* genShiftLeftLit - shift left by a known amount */
2681 /*-----------------------------------------------------------------*/
2682 static void genShiftLeftLit (iCode *ic)
2684 operand *left,*right, *result;
2685 int size , shCount, offset =0;
2688 right = IC_RIGHT(ic);
2690 result = IC_RESULT(ic);
2692 aopOp(left,ic,FALSE);
2693 aopOp(result,ic,FALSE);
2694 size = AOP_SIZE(result);
2695 shCount = (int)floatFromVal (AOP(right)->aopu.aop_lit);
2697 if (shCount > (size*8 -1)) {
2698 while (size--) aopPut(AOP(result),zero,offset++);
2703 if (!sameRegs(AOP(left),AOP(result)))
2704 aopPut(AOP(result),aopGet(AOP(left),0),0);
2706 emitcode("swap","%s",aopGet(AOP(result),0));
2707 emitcode("andi","%s,0xf0");
2711 emitcode("add","%s,%s",aopGet(AOP(result),0),aopGet(AOP(result),0));
2715 emitcode("lsl","%s",aopGet(AOP(result),0));
2718 if (shCount >= 12) {
2719 aopPut(AOP(result),aopGet(AOP(left),0),1);
2720 aopPut(AOP(result),zero,0);
2721 emitcode("swap","%s",aopGet(AOP(result),1));
2722 emitcode("andi","%s,0xf0",aopGet(AOP(result),1));
2727 aopPut(AOP(result),aopGet(AOP(left),0),1);
2728 aopPut(AOP(result),zero,0);
2734 if (!sameRegs(AOP(left),AOP(result))) {
2735 aopPut(AOP(result),aopGet(AOP(left),0),0);
2736 aopPut(AOP(result),aopGet(AOP(left),1),1);
2738 emitcode("mov","r1,%s",aopGet(AOP(result),0));
2739 emitcode("swap","%s",aopGet(AOP(result),0));
2740 emitcode("andi","%s,0xf0",aopGet(AOP(result),0));
2741 emitcode("andi","r1,0x0f");
2742 emitcode("swap","%s",aopGet(AOP(result),1));
2743 emitcode("andi","%s,0xf0",aopGet(AOP(result),1));
2744 emitcode("or","%s,r1",aopGet(AOP(result),1));
2746 emitcode("lsl","%s",aopGet(AOP(result),0));
2747 emitcode("rol","%s",aopGet(AOP(result),1));
2750 if (!lByteZ && !sameRegs(AOP(result),AOP(left)) && shCount) {
2753 aopPut(AOP(result),aopGet(AOP(left),offset),offset);
2759 emitcode("lsl","%s",aopGet(AOP(result),1));
2761 emitcode("lsl","%s",aopGet(AOP(result),0));
2762 emitcode("rol","%s",aopGet(AOP(result),1));
2767 assert("shifting generic pointer ?\n");
2770 /* 32 bits we do only byte boundaries */
2771 if (shCount >= 24) {
2772 aopPut(AOP(result),aopGet(AOP(left),0),3);
2773 aopPut(AOP(result),zero,2);
2774 aopPut(AOP(result),zero,1);
2775 aopPut(AOP(result),zero,0);
2779 if (shCount >= 16) {
2780 aopPut(AOP(result),aopGet(AOP(left),0),3);
2781 aopPut(AOP(result),aopGet(AOP(left),1),2);
2782 aopPut(AOP(result),zero,1);
2783 aopPut(AOP(result),zero,0);
2788 aopPut(AOP(result),aopGet(AOP(left),0),3);
2789 aopPut(AOP(result),aopGet(AOP(left),1),2);
2790 aopPut(AOP(result),aopGet(AOP(left),2),1);
2791 aopPut(AOP(result),zero,0);
2795 if (!lByteZ && !sameRegs(AOP(left),AOP(right))) {
2798 aopPut(AOP(result),aopGet(AOP(left),offset),offset);
2802 size = AOP_SIZE(result);
2808 emitcode("lsl","%s",aopGet(AOP(result),0));
2809 emitcode("rol","%s",aopGet(AOP(result),1));
2810 emitcode("rol","%s",aopGet(AOP(result),2));
2811 emitcode("rol","%s",aopGet(AOP(result),3));
2816 emitcode("lsl","%s",aopGet(AOP(result),1));
2817 emitcode("rol","%s",aopGet(AOP(result),2));
2818 emitcode("rol","%s",aopGet(AOP(result),3));
2823 emitcode("lsl","%s",aopGet(AOP(result),2));
2824 emitcode("rol","%s",aopGet(AOP(result),3));
2829 emitcode("lsl","%s",aopGet(AOP(result),3));
2837 freeAsmop(left,NULL,ic,TRUE);
2838 freeAsmop(right,NULL,ic,TRUE);
2839 freeAsmop(result,NULL,ic,TRUE);
2842 /*-----------------------------------------------------------------*/
2843 /* genLeftShift - generates code for left shifting */
2844 /*-----------------------------------------------------------------*/
2845 static void genLeftShift (iCode *ic)
2847 operand *left,*right, *result;
2851 right = IC_RIGHT(ic);
2853 result = IC_RESULT(ic);
2855 aopOp(right,ic,FALSE);
2857 if (AOP_TYPE(right) == AOP_LIT) {
2858 genShiftLeftLit(ic);
2863 aopOp(left,ic,FALSE);
2864 aopOp(result,ic,FALSE);
2865 size = AOP_SIZE(result);
2867 if (AOP_SIZE(right) > 1) {
2868 if (isRegPair(AOP(right))) {
2869 emitcode("movw","r24,%s",aopGet(AOP(right),0));
2871 emitcode("mov","r24,%s",aopGet(AOP(right),0));
2872 emitcode("mov","r25,%s",aopGet(AOP(right),1));
2875 emitcode("mov","r24,%s",aopGet(AOP(right),0));
2877 if (!sameRegs(AOP(left),AOP(result))) {
2879 aopPut(AOP(result),aopGet(AOP(left),offset),offset);
2882 size = AOP_SIZE(result);
2884 tlbl = newiTempLabel(NULL);
2885 emitcode("","L%05d:",tlbl->key);
2888 if (offset) emitcode("rol","%s",aopGet(AOP(result),offset));
2889 else emitcode("lsl","%s",aopGet(AOP(result),0));
2892 if (AOP_SIZE(right) > 1) emitcode("sbiw","r24,1");
2893 else emitcode("dec","r24");
2894 emitcode("brne","L%05d",tlbl->key);
2896 freeAsmop(left,NULL,ic,TRUE);
2897 freeAsmop(right,NULL,ic,TRUE);
2898 freeAsmop(result,NULL,ic,TRUE);
2901 /*-----------------------------------------------------------------*/
2902 /* genShiftRightLit - generate for right shift with known count */
2903 /*-----------------------------------------------------------------*/
2904 static void genShiftRightLit (iCode *ic)
2906 operand *left = IC_LEFT(ic)
2907 ,*right= IC_RIGHT(ic)
2908 ,*result=IC_RESULT(ic);
2909 int size , shCount, offset =0;
2911 link *letype = getSpec(operandType(left));
2912 int sign = !SPEC_USIGN(letype);
2914 right = IC_RIGHT(ic);
2916 result = IC_RESULT(ic);
2918 aopOp(left,ic,FALSE);
2919 aopOp(result,ic,FALSE);
2920 size = AOP_SIZE(result);
2921 shCount = (int)floatFromVal (AOP(right)->aopu.aop_lit);
2923 /* if signed then give up and use a loop to shift */
2926 if (!sameRegs(AOP(left),AOP(result))) {
2928 aopPut(AOP(result),aopGet(AOP(left),offset),offset);
2931 size = size = AOP_SIZE(result);
2934 /* be as economical as possible */
2939 size = AOP_SIZE(result);
2941 if (offset == (size-1))
2942 emitcode("asr","%s",aopGet(AOP(result),offset));
2944 emitcode("lsr","%s",aopGet(AOP(result),offset));
2949 emitcode("ldi","r24,lo8(%d)",shCount);
2950 tlbl = newiTempLabel(NULL);
2951 emitcode("","L%05d:",tlbl->key);
2954 if (offset == (size-1)) emitcode("asr","%s",aopGet(AOP(result),offset));
2955 else emitcode("lsr","%s",aopGet(AOP(result),offset));
2958 emitcode("dec","r24");
2959 emitcode("brne","L%05d",tlbl->key);
2963 if (shCount > (size*8 -1)) {
2964 while (size--) aopPut(AOP(result),zero,offset++);
2967 /* for unsigned we can much more efficient */
2970 if (!sameRegs(AOP(left),AOP(result)))
2971 aopPut(AOP(result),aopGet(AOP(left),0),0);
2973 emitcode("swap","%s",aopGet(AOP(result),0));
2974 emitcode("andi","%s,0x0f");
2978 emitcode("lsr","%s",aopGet(AOP(result),0));
2981 if (shCount >= 12) {
2982 aopPut(AOP(result),aopGet(AOP(left),1),0);
2983 aopPut(AOP(result),zero,1);
2984 emitcode("swap","%s",aopGet(AOP(result),0));
2985 emitcode("andi","%s,0x0f",aopGet(AOP(result),0));
2990 aopPut(AOP(result),aopGet(AOP(left),1),0);
2991 aopPut(AOP(result),zero,1);
2997 if (!sameRegs(AOP(left),AOP(result))) {
2998 aopPut(AOP(result),aopGet(AOP(left),0),0);
2999 aopPut(AOP(result),aopGet(AOP(left),1),1);
3001 emitcode("mov","r1,%s",aopGet(AOP(result),1));
3002 emitcode("swap","%s",aopGet(AOP(result),0));
3003 emitcode("andi","%s,0x0f",aopGet(AOP(result),0));
3004 emitcode("andi","r1,0xf0");
3005 emitcode("or","%s,r1",aopGet(AOP(result),0));
3006 emitcode("swap","%s",aopGet(AOP(result),1));
3007 emitcode("andi","%s,0x0f",aopGet(AOP(result),1));
3009 emitcode("lsr","%s",aopGet(AOP(result),1));
3010 emitcode("ror","%s",aopGet(AOP(result),0));
3014 if (!hByteZ && !sameRegs(AOP(result),AOP(left)) && shCount) {
3017 aopPut(AOP(result),aopGet(AOP(left),offset),offset);
3023 emitcode("lsr","%s",aopGet(AOP(result),0));
3025 emitcode("lsr","%s",aopGet(AOP(result),1));
3026 emitcode("ror","%s",aopGet(AOP(result),0));
3032 assert("shifting generic pointer ?\n");
3035 /* 32 bits we do only byte boundaries */
3036 if (shCount >= 24) {
3037 aopPut(AOP(result),aopGet(AOP(left),3),0);
3038 aopPut(AOP(result),zero,1);
3039 aopPut(AOP(result),zero,2);
3040 aopPut(AOP(result),zero,3);
3044 if (shCount >= 16) {
3045 aopPut(AOP(result),aopGet(AOP(left),3),1);
3046 aopPut(AOP(result),aopGet(AOP(left),2),0);
3047 aopPut(AOP(result),zero,2);
3048 aopPut(AOP(result),zero,3);
3053 aopPut(AOP(result),aopGet(AOP(left),1),0);
3054 aopPut(AOP(result),aopGet(AOP(left),2),1);
3055 aopPut(AOP(result),aopGet(AOP(left),3),2);
3056 aopPut(AOP(result),zero,3);
3060 if (!hByteZ && !sameRegs(AOP(left),AOP(right))) {
3063 aopPut(AOP(result),aopGet(AOP(left),offset),offset);
3067 size = AOP_SIZE(result);
3073 emitcode("lsr","%s",aopGet(AOP(result),3));
3074 emitcode("ror","%s",aopGet(AOP(result),2));
3075 emitcode("ror","%s",aopGet(AOP(result),1));
3076 emitcode("ror","%s",aopGet(AOP(result),0));
3081 emitcode("lsr","%s",aopGet(AOP(result),2));
3082 emitcode("ror","%s",aopGet(AOP(result),1));
3083 emitcode("ror","%s",aopGet(AOP(result),0));
3088 emitcode("lsr","%s",aopGet(AOP(result),1));
3089 emitcode("ror","%s",aopGet(AOP(result),0));
3094 emitcode("lsr","%s",aopGet(AOP(result),0));
3101 freeAsmop(left,NULL,ic,TRUE);
3102 freeAsmop(right,NULL,ic,TRUE);
3103 freeAsmop(result,NULL,ic,TRUE);
3106 /*-----------------------------------------------------------------*/
3107 /* genRightShift - generate code for right shifting */
3108 /*-----------------------------------------------------------------*/
3109 static void genRightShift (iCode *ic)
3111 operand *right, *left, *result;
3114 int sign = 0, first =1;
3117 aopOp(right=IC_RIGHT(ic),ic,FALSE);
3118 if (AOP_TYPE(right) == AOP_LIT) {
3119 genShiftRightLit(ic);
3123 if (AOP_SIZE(right) > 1) {
3124 if (isRegPair(AOP(right))) {
3125 emitcode("movw","r24,%s",aopGet(AOP(right),0));
3127 emitcode("mov","r24,%s",aopGet(AOP(right),0));
3128 emitcode("mov","r25,%s",aopGet(AOP(right),1));
3131 emitcode("mov","r24,%s",aopGet(AOP(right),0));
3133 aopOp(left=IC_LEFT(ic),ic,FALSE);
3134 aopOp(result=IC_RESULT(ic),ic,FALSE);
3135 size = AOP_SIZE(result);
3136 tlbl = newiTempLabel(NULL);
3137 emitcode("","L%05d:",tlbl->key);
3139 letype = getSpec(operandType(left));
3140 sign = !SPEC_USIGN(letype);
3141 if (!sameRegs(AOP(left),AOP(result))) {
3143 aopPut(AOP(result),aopGet(AOP(left),offset),offset);
3146 size = AOP_SIZE(result);
3148 size = AOP_SIZE(result);
3151 if (sign) emitcode("asr","%s",aopGet(AOP(result),offset));
3152 else emitcode("lsr","%s",aopGet(AOP(result),offset));
3155 else emitcode("ror","%s",aopGet(AOP(result),offset));
3158 if (AOP_SIZE(right) > 1) emitcode("sbiw","r24,1");
3159 else emitcode("dec","r24");
3160 emitcode("brne","L%05d",tlbl->key);
3162 freeAsmop(left,NULL,ic,TRUE);
3163 freeAsmop(result,NULL,ic,TRUE);
3166 /*-----------------------------------------------------------------*/
3167 /* R0Rsh - shift right r0 by known count */
3168 /*-----------------------------------------------------------------*/
3169 static void R0Rsh (int shCount)
3171 shCount &= 0x0007; // shCount : 0..7
3176 emitcode("lsr","r0");
3179 emitcode("lsr","r0");
3180 emitcode("lsr","r0");
3183 emitcode("swap","r0");
3184 emitcode("lsl","r0");
3187 emitcode("swap","r0");
3190 emitcode("swap","r0");
3191 emitcode("lsr","r0");
3194 emitcode("swap","r0");
3195 emitcode("lsr","r0");
3196 emitcode("lsr","r0");
3199 emitcode("swap","r0");
3200 emitcode("lsr","r0");
3201 emitcode("lsr","r0");
3202 emitcode("lsr","r0");
3207 /*-----------------------------------------------------------------*/
3208 /* genUnpackBits - generates code for unpacking bits */
3209 /*-----------------------------------------------------------------*/
3210 static void genUnpackBits (operand *result, char *rname, int ptype)
3217 etype = getSpec(operandType(result));
3219 /* read the first byte */
3226 emitcode("ld","r0,%s+",rname);
3230 emitcode("ldm","r0,%s+",rname);
3234 emitcode("call","__gptrget_pi");
3238 /* if we have bitdisplacement then it fits */
3239 /* into this byte completely or if length is */
3240 /* less than a byte */
3241 if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8)) {
3243 /* shift right r0 */
3245 emitcode("andi","r0,0x%02x",
3246 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
3248 aopPut(AOP(result),"r0",offset);
3252 /* bit field did not fit in a byte */
3253 rlen = SPEC_BLEN(etype) - 8;
3254 aopPut(AOP(result),"a",offset++);
3263 emitcode("ld","r0,%s+",rname);
3267 emitcode("ldm","r0,%s+",rname);
3271 emitcode("lcall","__gptrget_pi");
3276 /* if we are done */
3280 aopPut(AOP(result),"r0",offset++);
3285 emitcode("andi","r0,#0x%02x",((unsigned char)-1)>>(-rlen));
3286 aopPut(AOP(result),"r0",offset);
3293 /*-----------------------------------------------------------------*/
3294 /* genDataPointerGet - generates code when ptr offset is known */
3295 /*-----------------------------------------------------------------*/
3296 static void genDataPointerGet (operand *left,
3302 int size , offset = 0;
3303 aopOp(result,ic,TRUE);
3305 /* get the string representation of the name */
3306 l = aopGet(AOP(left),0);
3307 size = AOP_SIZE(result);
3310 sprintf(buffer,"(%s + %d)",l+1,offset);
3312 sprintf(buffer,"%s",l+1);
3313 emitcode("lds","%s,%s",aopGet(AOP(result),offset++),buffer);
3316 freeAsmop(left,NULL,ic,TRUE);
3317 freeAsmop(result,NULL,ic,TRUE);
3320 /*-----------------------------------------------------------------*/
3321 /* genNearPointerGet - emitcode for near pointer fetch */
3322 /*-----------------------------------------------------------------*/
3323 static void genNearPointerGet (operand *left,
3330 link *rtype, *retype;
3331 link *ltype = operandType(left);
3334 rtype = operandType(result);
3335 retype= getSpec(rtype);
3337 aopOp(left,ic,FALSE);
3339 /* if left is rematerialisable and
3340 result is not bit variable type and
3341 the left is pointer to data space i.e
3342 lower 128 bytes of space */
3343 if (AOP_TYPE(left) == AOP_IMMD &&
3344 !IS_BITVAR(retype) &&
3345 DCL_TYPE(ltype) == POINTER) {
3346 genDataPointerGet (left,result,ic);
3350 /* if the value is already in a pointer register
3351 then don't need anything more */
3352 if (!AOP_INPREG(AOP(left))) {
3353 /* otherwise get a free pointer register */
3355 preg = getFreePtr(ic,&aop,FALSE,0);
3356 emitcode("mov","%s,%s",
3358 aopGet(AOP(left),0));
3359 rname = preg->name ;
3361 rname = aopGet(AOP(left),0);
3363 freeAsmop(left,NULL,ic,TRUE);
3364 aopOp (result,ic,FALSE);
3366 /* if bitfield then unpack the bits */
3367 if (IS_BITVAR(retype))
3368 genUnpackBits (result,rname,POINTER);
3370 /* we have can just get the values */
3371 int size = AOP_SIZE(result);
3375 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
3377 emitcode("mov","a,@%s",rname);
3378 aopPut(AOP(result),"a",offset);
3380 sprintf(buffer,"@%s",rname);
3381 aopPut(AOP(result),buffer,offset);
3385 emitcode("inc","%s",rname);
3389 /* now some housekeeping stuff */
3391 /* we had to allocate for this iCode */
3392 freeAsmop(NULL,aop,ic,TRUE);
3394 /* we did not allocate which means left
3395 already in a pointer register, then
3396 if size > 0 && this could be used again
3397 we have to point it back to where it
3399 if (AOP_SIZE(result) > 1 &&
3400 !OP_SYMBOL(left)->remat &&
3401 ( OP_SYMBOL(left)->liveTo > ic->seq ||
3403 int size = AOP_SIZE(result) - 1;
3405 emitcode("dec","%s",rname);
3410 freeAsmop(result,NULL,ic,TRUE);
3414 /*-----------------------------------------------------------------*/
3415 /* genPagedPointerGet - emitcode for paged pointer fetch */
3416 /*-----------------------------------------------------------------*/
3417 static void genPagedPointerGet (operand *left,
3424 link *rtype, *retype;
3426 rtype = operandType(result);
3427 retype= getSpec(rtype);
3429 aopOp(left,ic,FALSE);
3431 /* if the value is already in a pointer register
3432 then don't need anything more */
3433 if (!AOP_INPREG(AOP(left))) {
3434 /* otherwise get a free pointer register */
3436 preg = getFreePtr(ic,&aop,FALSE,0);
3437 emitcode("mov","%s,%s",
3439 aopGet(AOP(left),0));
3440 rname = preg->name ;
3442 rname = aopGet(AOP(left),0);
3444 freeAsmop(left,NULL,ic,TRUE);
3445 aopOp (result,ic,FALSE);
3447 /* if bitfield then unpack the bits */
3448 if (IS_BITVAR(retype))
3449 genUnpackBits (result,rname,PPOINTER);
3451 /* we have can just get the values */
3452 int size = AOP_SIZE(result);
3457 emitcode("movx","a,@%s",rname);
3458 aopPut(AOP(result),"a",offset);
3463 emitcode("inc","%s",rname);
3467 /* now some housekeeping stuff */
3469 /* we had to allocate for this iCode */
3470 freeAsmop(NULL,aop,ic,TRUE);
3472 /* we did not allocate which means left
3473 already in a pointer register, then
3474 if size > 0 && this could be used again
3475 we have to point it back to where it
3477 if (AOP_SIZE(result) > 1 &&
3478 !OP_SYMBOL(left)->remat &&
3479 ( OP_SYMBOL(left)->liveTo > ic->seq ||
3481 int size = AOP_SIZE(result) - 1;
3483 emitcode("dec","%s",rname);
3488 freeAsmop(result,NULL,ic,TRUE);
3493 /*-----------------------------------------------------------------*/
3494 /* genFarPointerGet - gget value from far space */
3495 /*-----------------------------------------------------------------*/
3496 static void genFarPointerGet (operand *left,
3497 operand *result, iCode *ic)
3500 link *retype = getSpec(operandType(result));
3502 aopOp(left,ic,FALSE);
3504 /* if the operand is already in dptr
3505 then we do nothing else we move the value to dptr */
3506 if (AOP_TYPE(left) != AOP_STR) {
3507 /* if this is remateriazable */
3508 if (AOP_TYPE(left) == AOP_IMMD)
3509 emitcode("mov","dptr,%s",aopGet(AOP(left),0));
3510 else { /* we need to get it byte by byte */
3511 emitcode("mov","dpl,%s",aopGet(AOP(left),0));
3512 emitcode("mov","dph,%s",aopGet(AOP(left),1));
3513 if (options.model == MODEL_FLAT24)
3515 emitcode("mov", "dpx,%s",aopGet(AOP(left),2));
3519 /* so dptr know contains the address */
3520 freeAsmop(left,NULL,ic,TRUE);
3521 aopOp(result,ic,FALSE);
3523 /* if bit then unpack */
3524 if (IS_BITVAR(retype))
3525 genUnpackBits(result,"dptr",FPOINTER);
3527 size = AOP_SIZE(result);
3531 emitcode("movx","a,@dptr");
3532 aopPut(AOP(result),"a",offset++);
3534 emitcode("inc","dptr");
3538 freeAsmop(result,NULL,ic,TRUE);
3541 /*-----------------------------------------------------------------*/
3542 /* emitcodePointerGet - gget value from code space */
3543 /*-----------------------------------------------------------------*/
3544 static void emitcodePointerGet (operand *left,
3545 operand *result, iCode *ic)
3548 link *retype = getSpec(operandType(result));
3550 aopOp(left,ic,FALSE);
3552 /* if the operand is already in dptr
3553 then we do nothing else we move the value to dptr */
3554 if (AOP_TYPE(left) != AOP_STR) {
3555 /* if this is remateriazable */
3556 if (AOP_TYPE(left) == AOP_IMMD)
3557 emitcode("mov","dptr,%s",aopGet(AOP(left),0));
3558 else { /* we need to get it byte by byte */
3559 emitcode("mov","dpl,%s",aopGet(AOP(left),0));
3560 emitcode("mov","dph,%s",aopGet(AOP(left),1));
3561 if (options.model == MODEL_FLAT24)
3563 emitcode("mov", "dpx,%s",aopGet(AOP(left),2));
3567 /* so dptr know contains the address */
3568 freeAsmop(left,NULL,ic,TRUE);
3569 aopOp(result,ic,FALSE);
3571 /* if bit then unpack */
3572 if (IS_BITVAR(retype))
3573 genUnpackBits(result,"dptr",CPOINTER);
3575 size = AOP_SIZE(result);
3579 emitcode("clr","a");
3580 emitcode("movc","a,@a+dptr");
3581 aopPut(AOP(result),"a",offset++);
3583 emitcode("inc","dptr");
3587 freeAsmop(result,NULL,ic,TRUE);
3590 /*-----------------------------------------------------------------*/
3591 /* genGenPointerGet - gget value from generic pointer space */
3592 /*-----------------------------------------------------------------*/
3593 static void genGenPointerGet (operand *left,
3594 operand *result, iCode *ic)
3597 link *retype = getSpec(operandType(result));
3599 aopOp(left,ic,FALSE);
3601 /* if the operand is already in dptr
3602 then we do nothing else we move the value to dptr */
3603 if (AOP_TYPE(left) != AOP_STR) {
3604 /* if this is remateriazable */
3605 if (AOP_TYPE(left) == AOP_IMMD) {
3606 emitcode("mov","dptr,%s",aopGet(AOP(left),0));
3607 emitcode("mov","b,#%d",pointerCode(retype));
3609 else { /* we need to get it byte by byte */
3610 emitcode("mov","dpl,%s",aopGet(AOP(left),0));
3611 emitcode("mov","dph,%s",aopGet(AOP(left),1));
3612 if (options.model == MODEL_FLAT24)
3614 emitcode("mov", "dpx,%s",aopGet(AOP(left),2));
3615 emitcode("mov","b,%s",aopGet(AOP(left),3));
3619 emitcode("mov","b,%s",aopGet(AOP(left),2));
3623 /* so dptr know contains the address */
3624 freeAsmop(left,NULL,ic,TRUE);
3625 aopOp(result,ic,FALSE);
3627 /* if bit then unpack */
3628 if (IS_BITVAR(retype))
3629 genUnpackBits(result,"dptr",GPOINTER);
3631 size = AOP_SIZE(result);
3635 emitcode("lcall","__gptrget");
3636 aopPut(AOP(result),"a",offset++);
3638 emitcode("inc","dptr");
3642 freeAsmop(result,NULL,ic,TRUE);
3645 /*-----------------------------------------------------------------*/
3646 /* genPointerGet - generate code for pointer get */
3647 /*-----------------------------------------------------------------*/
3648 static void genPointerGet (iCode *ic)
3650 operand *left, *result ;
3655 result = IC_RESULT(ic) ;
3657 /* depending on the type of pointer we need to
3658 move it to the correct pointer register */
3659 type = operandType(left);
3660 etype = getSpec(type);
3661 /* if left is of type of pointer then it is simple */
3662 if (IS_PTR(type) && !IS_FUNC(type->next))
3663 p_type = DCL_TYPE(type);
3665 /* we have to go by the storage class */
3666 p_type = PTR_TYPE(SPEC_OCLS(etype));
3668 /* if (SPEC_OCLS(etype)->codesp ) { */
3669 /* p_type = CPOINTER ; */
3672 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
3673 /* p_type = FPOINTER ; */
3675 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
3676 /* p_type = PPOINTER; */
3678 /* if (SPEC_OCLS(etype) == idata ) */
3679 /* p_type = IPOINTER; */
3681 /* p_type = POINTER ; */
3684 /* now that we have the pointer type we assign
3685 the pointer values */
3690 genNearPointerGet (left,result,ic);
3694 genPagedPointerGet(left,result,ic);
3698 genFarPointerGet (left,result,ic);
3702 emitcodePointerGet (left,result,ic);
3706 genGenPointerGet (left,result,ic);
3712 /*-----------------------------------------------------------------*/
3713 /* genPackBits - generates code for packed bit storage */
3714 /*-----------------------------------------------------------------*/
3715 static void genPackBits (link *etype ,
3717 char *rname, int p_type)
3725 blen = SPEC_BLEN(etype);
3726 bstr = SPEC_BSTR(etype);
3728 l = aopGet(AOP(right),offset++);
3731 /* if the bit lenth is less than or */
3732 /* it exactly fits a byte then */
3733 if (SPEC_BLEN(etype) <= 8 ) {
3734 shCount = SPEC_BSTR(etype) ;
3736 /* shift left acc */
3739 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
3744 emitcode ("mov","b,a");
3745 emitcode("mov","a,@%s",rname);
3749 emitcode ("mov","b,a");
3750 emitcode("movx","a,@dptr");
3754 emitcode ("push","b");
3755 emitcode ("push","acc");
3756 emitcode ("lcall","__gptrget");
3757 emitcode ("pop","b");
3761 emitcode ("anl","a,#0x%02x",(unsigned char)
3762 ((unsigned char)(0xFF << (blen+bstr)) |
3763 (unsigned char)(0xFF >> (8-bstr)) ) );
3764 emitcode ("orl","a,b");
3765 if (p_type == GPOINTER)
3766 emitcode("pop","b");
3772 emitcode("mov","@%s,a",rname);
3776 emitcode("movx","@dptr,a");
3780 emitcode("lcall","__gptrput");
3785 if ( SPEC_BLEN(etype) <= 8 )
3788 emitcode("inc","%s",rname);
3789 rLen = SPEC_BLEN(etype) ;
3791 /* now generate for lengths greater than one byte */
3794 l = aopGet(AOP(right),offset++);
3804 emitcode("mov","@%s,a",rname);
3806 emitcode("mov","@%s,%s",rname,l);
3811 emitcode("movx","@dptr,a");
3816 emitcode("lcall","__gptrput");
3819 emitcode ("inc","%s",rname);
3824 /* last last was not complete */
3826 /* save the byte & read byte */
3829 emitcode ("mov","b,a");
3830 emitcode("mov","a,@%s",rname);
3834 emitcode ("mov","b,a");
3835 emitcode("movx","a,@dptr");
3839 emitcode ("push","b");
3840 emitcode ("push","acc");
3841 emitcode ("lcall","__gptrget");
3842 emitcode ("pop","b");
3846 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
3847 emitcode ("orl","a,b");
3850 if (p_type == GPOINTER)
3851 emitcode("pop","b");
3856 emitcode("mov","@%s,a",rname);
3860 emitcode("movx","@dptr,a");
3864 emitcode("lcall","__gptrput");
3868 /*-----------------------------------------------------------------*/
3869 /* genDataPointerSet - remat pointer to data space */
3870 /*-----------------------------------------------------------------*/
3871 static void genDataPointerSet(operand *right,
3875 int size, offset = 0 ;
3876 char *l, buffer[256];
3878 aopOp(right,ic,FALSE);
3880 l = aopGet(AOP(result),0);
3881 size = AOP_SIZE(right);
3884 sprintf(buffer,"(%s + %d)",l+1,offset);
3886 sprintf(buffer,"%s",l+1);
3887 emitcode("mov","%s,%s",buffer,
3888 aopGet(AOP(right),offset++));
3891 freeAsmop(right,NULL,ic,TRUE);
3892 freeAsmop(result,NULL,ic,TRUE);
3895 /*-----------------------------------------------------------------*/
3896 /* genNearPointerSet - emitcode for near pointer put */
3897 /*-----------------------------------------------------------------*/
3898 static void genNearPointerSet (operand *right,
3906 link *ptype = operandType(result);
3908 retype= getSpec(operandType(right));
3910 aopOp(result,ic,FALSE);
3912 /* if the result is rematerializable &
3913 in data space & not a bit variable */
3914 if (AOP_TYPE(result) == AOP_IMMD &&
3915 DCL_TYPE(ptype) == POINTER &&
3916 !IS_BITVAR(retype)) {
3917 genDataPointerSet (right,result,ic);
3921 /* if the value is already in a pointer register
3922 then don't need anything more */
3923 if (!AOP_INPREG(AOP(result))) {
3924 /* otherwise get a free pointer register */
3926 preg = getFreePtr(ic,&aop,FALSE,0);
3927 emitcode("mov","%s,%s",
3929 aopGet(AOP(result),0));
3930 rname = preg->name ;
3932 rname = aopGet(AOP(result),0);
3934 freeAsmop(result,NULL,ic,TRUE);
3935 aopOp (right,ic,FALSE);
3937 /* if bitfield then unpack the bits */
3938 if (IS_BITVAR(retype))
3939 genPackBits (retype,right,rname,POINTER);
3941 /* we have can just get the values */
3942 int size = AOP_SIZE(right);
3946 l = aopGet(AOP(right),offset);
3949 emitcode("mov","@%s,a",rname);
3951 emitcode("mov","@%s,%s",rname,l);
3953 emitcode("inc","%s",rname);
3958 /* now some housekeeping stuff */
3960 /* we had to allocate for this iCode */
3961 freeAsmop(NULL,aop,ic,TRUE);
3963 /* we did not allocate which means left
3964 already in a pointer register, then
3965 if size > 0 && this could be used again
3966 we have to point it back to where it
3968 if (AOP_SIZE(right) > 1 &&
3969 !OP_SYMBOL(result)->remat &&
3970 ( OP_SYMBOL(result)->liveTo > ic->seq ||
3972 int size = AOP_SIZE(right) - 1;
3974 emitcode("dec","%s",rname);
3979 freeAsmop(right,NULL,ic,TRUE);
3984 /*-----------------------------------------------------------------*/
3985 /* genPagedPointerSet - emitcode for Paged pointer put */
3986 /*-----------------------------------------------------------------*/
3987 static void genPagedPointerSet (operand *right,
3996 retype= getSpec(operandType(right));
3998 aopOp(result,ic,FALSE);
4000 /* if the value is already in a pointer register
4001 then don't need anything more */
4002 if (!AOP_INPREG(AOP(result))) {
4003 /* otherwise get a free pointer register */
4005 preg = getFreePtr(ic,&aop,FALSE,0);
4006 emitcode("mov","%s,%s",
4008 aopGet(AOP(result),0));
4009 rname = preg->name ;
4011 rname = aopGet(AOP(result),0);
4013 freeAsmop(result,NULL,ic,TRUE);
4014 aopOp (right,ic,FALSE);
4016 /* if bitfield then unpack the bits */
4017 if (IS_BITVAR(retype))
4018 genPackBits (retype,right,rname,PPOINTER);
4020 /* we have can just get the values */
4021 int size = AOP_SIZE(right);
4025 l = aopGet(AOP(right),offset);
4028 emitcode("movx","@%s,a",rname);
4031 emitcode("inc","%s",rname);
4037 /* now some housekeeping stuff */
4039 /* we had to allocate for this iCode */
4040 freeAsmop(NULL,aop,ic,TRUE);
4042 /* we did not allocate which means left
4043 already in a pointer register, then
4044 if size > 0 && this could be used again
4045 we have to point it back to where it
4047 if (AOP_SIZE(right) > 1 &&
4048 !OP_SYMBOL(result)->remat &&
4049 ( OP_SYMBOL(result)->liveTo > ic->seq ||
4051 int size = AOP_SIZE(right) - 1;
4053 emitcode("dec","%s",rname);
4058 freeAsmop(right,NULL,ic,TRUE);
4063 /*-----------------------------------------------------------------*/
4064 /* genFarPointerSet - set value from far space */
4065 /*-----------------------------------------------------------------*/
4066 static void genFarPointerSet (operand *right,
4067 operand *result, iCode *ic)
4070 link *retype = getSpec(operandType(right));
4072 aopOp(result,ic,FALSE);
4074 /* if the operand is already in dptr
4075 then we do nothing else we move the value to dptr */
4076 if (AOP_TYPE(result) != AOP_STR) {
4077 /* if this is remateriazable */
4078 if (AOP_TYPE(result) == AOP_IMMD)
4079 emitcode("mov","dptr,%s",aopGet(AOP(result),0));
4080 else { /* we need to get it byte by byte */
4081 emitcode("mov","dpl,%s",aopGet(AOP(result),0));
4082 emitcode("mov","dph,%s",aopGet(AOP(result),1));
4083 if (options.model == MODEL_FLAT24)
4085 emitcode("mov", "dpx,%s",aopGet(AOP(result),2));
4089 /* so dptr know contains the address */
4090 freeAsmop(result,NULL,ic,TRUE);
4091 aopOp(right,ic,FALSE);
4093 /* if bit then unpack */
4094 if (IS_BITVAR(retype))
4095 genPackBits(retype,right,"dptr",FPOINTER);
4097 size = AOP_SIZE(right);
4101 char *l = aopGet(AOP(right),offset++);
4103 emitcode("movx","@dptr,a");
4105 emitcode("inc","dptr");
4109 freeAsmop(right,NULL,ic,TRUE);
4112 /*-----------------------------------------------------------------*/
4113 /* genGenPointerSet - set value from generic pointer space */
4114 /*-----------------------------------------------------------------*/
4115 static void genGenPointerSet (operand *right,
4116 operand *result, iCode *ic)
4119 link *retype = getSpec(operandType(right));
4121 aopOp(result,ic,FALSE);
4123 /* if the operand is already in dptr
4124 then we do nothing else we move the value to dptr */
4125 if (AOP_TYPE(result) != AOP_STR) {
4126 /* if this is remateriazable */
4127 if (AOP_TYPE(result) == AOP_IMMD) {
4128 emitcode("mov","dptr,%s",aopGet(AOP(result),0));
4129 emitcode("mov","b,%s + 1",aopGet(AOP(result),0));
4131 else { /* we need to get it byte by byte */
4132 emitcode("mov","dpl,%s",aopGet(AOP(result),0));
4133 emitcode("mov","dph,%s",aopGet(AOP(result),1));
4134 if (options.model == MODEL_FLAT24)
4136 emitcode("mov", "dpx,%s",aopGet(AOP(result),2));
4137 emitcode("mov","b,%s",aopGet(AOP(result),3));
4141 emitcode("mov","b,%s",aopGet(AOP(result),2));
4145 /* so dptr know contains the address */
4146 freeAsmop(result,NULL,ic,TRUE);
4147 aopOp(right,ic,FALSE);
4149 /* if bit then unpack */
4150 if (IS_BITVAR(retype))
4151 genPackBits(retype,right,"dptr",GPOINTER);
4153 size = AOP_SIZE(right);
4157 char *l = aopGet(AOP(right),offset++);
4159 emitcode("lcall","__gptrput");
4161 emitcode("inc","dptr");
4165 freeAsmop(right,NULL,ic,TRUE);
4168 /*-----------------------------------------------------------------*/
4169 /* genPointerSet - stores the value into a pointer location */
4170 /*-----------------------------------------------------------------*/
4171 static void genPointerSet (iCode *ic)
4173 operand *right, *result ;
4177 right = IC_RIGHT(ic);
4178 result = IC_RESULT(ic) ;
4180 /* depending on the type of pointer we need to
4181 move it to the correct pointer register */
4182 type = operandType(result);
4183 etype = getSpec(type);
4184 /* if left is of type of pointer then it is simple */
4185 if (IS_PTR(type) && !IS_FUNC(type->next)) {
4186 p_type = DCL_TYPE(type);
4189 /* we have to go by the storage class */
4190 p_type = PTR_TYPE(SPEC_OCLS(etype));
4192 /* if (SPEC_OCLS(etype)->codesp ) { */
4193 /* p_type = CPOINTER ; */
4196 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
4197 /* p_type = FPOINTER ; */
4199 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
4200 /* p_type = PPOINTER ; */
4202 /* if (SPEC_OCLS(etype) == idata ) */
4203 /* p_type = IPOINTER ; */
4205 /* p_type = POINTER ; */
4208 /* now that we have the pointer type we assign
4209 the pointer values */
4214 genNearPointerSet (right,result,ic);
4218 genPagedPointerSet (right,result,ic);
4222 genFarPointerSet (right,result,ic);
4226 genGenPointerSet (right,result,ic);
4232 /*-----------------------------------------------------------------*/
4233 /* genIfx - generate code for Ifx statement */
4234 /*-----------------------------------------------------------------*/
4235 static void genIfx (iCode *ic, iCode *popIc)
4237 operand *cond = IC_COND(ic);
4240 aopOp(cond,ic,FALSE);
4242 /* get the value into acc */
4243 if (AOP_TYPE(cond) != AOP_CRY)
4244 toBoolean(cond,"",0);
4247 /* the result is now in the accumulator */
4248 freeAsmop(cond,NULL,ic,TRUE);
4250 /* if there was something to be popped then do it */
4254 /* if the condition is a bit variable */
4255 /* if (isbit && IS_ITEMP(cond) && SPIL_LOC(cond)) { */
4256 /* // genIfxJump(ic,SPIL_LOC(cond)->rname); */
4259 /* if (isbit && !IS_ITEMP(cond)) */
4260 /* // genIfxJump(ic,OP_SYMBOL(cond)->rname); */
4262 /* // genIfxJump(ic,"a"); */
4267 /*-----------------------------------------------------------------*/
4268 /* genAddrOf - generates code for address of */
4269 /*-----------------------------------------------------------------*/
4270 static void genAddrOf (iCode *ic)
4272 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
4275 aopOp(IC_RESULT(ic),ic,FALSE);
4277 /* if the operand is on the stack then we
4278 need to get the stack offset of this
4281 /* if it has an offset then we need to compute
4284 emitcode("mov","a,_bp");
4285 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
4286 aopPut(AOP(IC_RESULT(ic)),"a",0);
4288 /* we can just move _bp */
4289 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
4291 /* fill the result with zero */
4292 size = AOP_SIZE(IC_RESULT(ic)) - 1;
4295 if (options.stack10bit && size < (FPTRSIZE - 1))
4298 "*** warning: pointer to stack var truncated.\n");
4305 if (options.stack10bit && offset == 2)
4307 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
4311 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
4318 /* object not on stack then we need the name */
4319 size = AOP_SIZE(IC_RESULT(ic));
4323 char s[SDCC_NAME_MAX];
4325 sprintf(s,"#(%s >> %d)",
4329 sprintf(s,"#%s",sym->rname);
4330 aopPut(AOP(IC_RESULT(ic)),s,offset++);
4334 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
4338 /*-----------------------------------------------------------------*/
4339 /* genFarFarAssign - assignment when both are in far space */
4340 /*-----------------------------------------------------------------*/
4341 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
4343 int size = AOP_SIZE(right);
4346 /* first push the right side on to the stack */
4348 l = aopGet(AOP(right),offset++);
4350 emitcode ("push","acc");
4353 freeAsmop(right,NULL,ic,FALSE);
4354 /* now assign DPTR to result */
4355 aopOp(result,ic,FALSE);
4356 size = AOP_SIZE(result);
4358 emitcode ("pop","acc");
4359 aopPut(AOP(result),"a",--offset);
4361 freeAsmop(result,NULL,ic,FALSE);
4365 /*-----------------------------------------------------------------*/
4366 /* genAssign - generate code for assignment */
4367 /*-----------------------------------------------------------------*/
4368 static void genAssign (iCode *ic)
4370 operand *result, *right;
4372 unsigned long lit = 0L;
4374 result = IC_RESULT(ic);
4375 right = IC_RIGHT(ic) ;
4377 /* if they are the same */
4378 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
4381 aopOp(right,ic,FALSE);
4383 /* special case both in far space */
4384 if (AOP_TYPE(right) == AOP_DPTR &&
4385 IS_TRUE_SYMOP(result) &&
4386 isOperandInFarSpace(result)) {
4388 genFarFarAssign (result,right,ic);
4392 aopOp(result,ic,TRUE);
4394 /* if they are the same registers */
4395 if (sameRegs(AOP(right),AOP(result)))
4398 /* if the result is a bit */
4399 if (AOP_TYPE(result) == AOP_CRY) {
4401 /* if the right size is a literal then
4402 we know what the value is */
4403 if (AOP_TYPE(right) == AOP_LIT) {
4404 if (((int) operandLitValue(right)))
4405 aopPut(AOP(result),one,0);
4407 aopPut(AOP(result),zero,0);
4411 /* the right is also a bit variable */
4412 if (AOP_TYPE(right) == AOP_CRY) {
4413 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4414 aopPut(AOP(result),"c",0);
4419 toBoolean(right,"",0);
4420 aopPut(AOP(result),"a",0);
4424 /* bit variables done */
4426 size = AOP_SIZE(result);
4428 if(AOP_TYPE(right) == AOP_LIT)
4429 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4431 (AOP_TYPE(result) != AOP_REG) &&
4432 (AOP_TYPE(right) == AOP_LIT) &&
4433 !IS_FLOAT(operandType(right)) &&
4435 emitcode("clr","a");
4437 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
4438 aopPut(AOP(result),"a",size);
4441 aopGet(AOP(right),size),
4447 aopGet(AOP(right),offset),
4454 freeAsmop (right,NULL,ic,FALSE);
4455 freeAsmop (result,NULL,ic,TRUE);
4458 /*-----------------------------------------------------------------*/
4459 /* genJumpTab - genrates code for jump table */
4460 /*-----------------------------------------------------------------*/
4461 static void genJumpTab (iCode *ic)
4466 aopOp(IC_JTCOND(ic),ic,FALSE);
4467 /* get the condition into accumulator */
4468 l = aopGet(AOP(IC_JTCOND(ic)),0);
4470 /* multiply by three */
4471 emitcode("add","a,acc");
4472 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0));
4473 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
4475 jtab = newiTempLabel(NULL);
4476 emitcode("mov","dptr,#%05d$",jtab->key+100);
4477 emitcode("jmp","@a+dptr");
4478 emitcode("","%05d$:",jtab->key+100);
4479 /* now generate the jump labels */
4480 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
4481 jtab = setNextItem(IC_JTLABELS(ic)))
4482 emitcode("ljmp","%05d$",jtab->key+100);
4486 /*-----------------------------------------------------------------*/
4487 /* genCast - gen code for casting */
4488 /*-----------------------------------------------------------------*/
4489 static void genCast (iCode *ic)
4491 operand *result = IC_RESULT(ic);
4492 link *ctype = operandType(IC_LEFT(ic));
4493 link *rtype = operandType(IC_RIGHT(ic));
4494 operand *right = IC_RIGHT(ic);
4497 /* if they are equivalent then do nothing */
4498 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
4501 aopOp(right,ic,FALSE) ;
4502 aopOp(result,ic,FALSE);
4504 /* if the result is a bit */
4505 if (AOP_TYPE(result) == AOP_CRY) {
4506 /* if the right size is a literal then
4507 we know what the value is */
4508 if (AOP_TYPE(right) == AOP_LIT) {
4509 if (((int) operandLitValue(right)))
4510 aopPut(AOP(result),one,0);
4512 aopPut(AOP(result),zero,0);
4517 /* the right is also a bit variable */
4518 if (AOP_TYPE(right) == AOP_CRY) {
4519 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4520 aopPut(AOP(result),"c",0);
4525 toBoolean(right,"",0);
4526 aopPut(AOP(result),"a",0);
4530 /* if they are the same size : or less */
4531 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
4533 /* if they are in the same place */
4534 if (sameRegs(AOP(right),AOP(result)))
4537 /* if they in different places then copy */
4538 size = AOP_SIZE(result);
4542 aopGet(AOP(right),offset),
4550 /* if the result is of type pointer */
4551 if (IS_PTR(ctype)) {
4554 link *type = operandType(right);
4555 link *etype = getSpec(type);
4557 /* pointer to generic pointer */
4558 if (IS_GENPTR(ctype)) {
4562 p_type = DCL_TYPE(type);
4564 /* we have to go by the storage class */
4565 p_type = PTR_TYPE(SPEC_OCLS(etype));
4568 /* the first two bytes are known */
4569 size = GPTRSIZE - 1;
4573 aopGet(AOP(right),offset),
4577 /* the last byte depending on type */
4594 /* this should never happen */
4595 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
4596 "got unknown pointer type");
4599 aopPut(AOP(result),l, GPTRSIZE - 1);
4603 /* just copy the pointers */
4604 size = AOP_SIZE(result);
4608 aopGet(AOP(right),offset),
4615 /* so we now know that the size of destination is greater
4616 than the size of the source */
4617 /* we move to result for the size of source */
4618 size = AOP_SIZE(right);
4622 aopGet(AOP(right),offset),
4627 /* now depending on the sign of the source && destination */
4628 size = AOP_SIZE(result) - AOP_SIZE(right);
4629 /* if unsigned or not an integral type */
4630 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
4632 aopPut(AOP(result),zero,offset++);
4634 /* we need to extend the sign :{ */
4635 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1);
4637 emitcode("rlc","a");
4638 emitcode("subb","a,acc");
4640 aopPut(AOP(result),"a",offset++);
4643 /* we are done hurray !!!! */
4646 freeAsmop(right,NULL,ic,TRUE);
4647 freeAsmop(result,NULL,ic,TRUE);
4651 /*-----------------------------------------------------------------*/
4652 /* genDjnz - generate decrement & jump if not zero instrucion */
4653 /*-----------------------------------------------------------------*/
4654 static int genDjnz (iCode *ic, iCode *ifx)
4660 /* if the if condition has a false label
4661 then we cannot save */
4665 /* if the minus is not of the form
4667 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
4668 !IS_OP_LITERAL(IC_RIGHT(ic)))
4671 if (operandLitValue(IC_RIGHT(ic)) != 1)
4674 /* if the size of this greater than one then no
4676 if (getSize(operandType(IC_RESULT(ic))) > 1)
4679 /* otherwise we can save BIG */
4680 lbl = newiTempLabel(NULL);
4681 lbl1= newiTempLabel(NULL);
4683 aopOp(IC_RESULT(ic),ic,FALSE);
4685 if (IS_AOP_PREG(IC_RESULT(ic))) {
4686 emitcode("dec","%s",
4687 aopGet(AOP(IC_RESULT(ic)),0));
4688 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0));
4689 emitcode("jnz","%05d$",lbl->key+100);
4691 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0),
4694 emitcode ("sjmp","%05d$",lbl1->key+100);
4695 emitcode ("","%05d$:",lbl->key+100);
4696 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4697 emitcode ("","%05d$:",lbl1->key+100);
4699 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
4704 static char *recvregs[8] =
4706 "r16","r17","r18","r19","r20","r21","r22","r23"
4710 /*-----------------------------------------------------------------*/
4711 /* genReceive - generate code for a receive iCode */
4712 /*-----------------------------------------------------------------*/
4713 static void genReceive (iCode *ic)
4715 int size , offset =0;
4716 aopOp(IC_RESULT(ic),ic,FALSE);
4717 size = AOP_SIZE(IC_RESULT(ic));
4719 aopPut(AOP(IC_RESULT(ic)),recvregs[recvCnt++],offset);
4722 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
4725 /*-----------------------------------------------------------------*/
4726 /* gen51Code - generate code for 8051 based controllers */
4727 /*-----------------------------------------------------------------*/
4728 void genAVRCode (iCode *lic)
4733 lineHead = lineCurr = NULL;
4735 /* print the allocation information */
4737 printAllocInfo( currFunc, codeOutFile);
4738 /* if debug information required */
4739 /* if (options.debug && currFunc) { */
4741 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
4743 if (IS_STATIC(currFunc->etype))
4744 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
4746 emitcode("","G$%s$0$0 ==.",currFunc->name);
4749 /* stack pointer name */
4750 if (options.useXstack)
4756 for (ic = lic ; ic ; ic = ic->next ) {
4758 if ( cln != ic->lineno ) {
4759 if ( options.debug ) {
4761 emitcode("","C$%s$%d$%d$%d ==.",
4762 ic->filename,ic->lineno,
4763 ic->level,ic->block);
4766 emitcode(";","%s %d",ic->filename,ic->lineno);
4769 /* if the result is marked as
4770 spilt and rematerializable or code for
4771 this has already been generated then
4773 if (resultRemat(ic) || ic->generated )
4776 /* depending on the operation */
4795 /* IPOP happens only when trying to restore a
4796 spilt live range, if there is an ifx statement
4797 following this pop then the if statement might
4798 be using some of the registers being popped which
4799 would destory the contents of the register so
4800 we need to check for this condition and handle it */
4802 ic->next->op == IFX &&
4803 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
4804 genIfx (ic->next,ic);
4822 genEndFunction (ic);
4842 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
4859 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
4863 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
4867 genCmpLe (ic,ifxForOp(IC_RESULT(ic),ic));
4871 genCmpGe (ic,ifxForOp(IC_RESULT(ic),ic));
4875 genCmpNe (ic,ifxForOp(IC_RESULT(ic),ic));
4879 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
4891 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
4895 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
4899 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
4926 case GET_VALUE_AT_ADDRESS:
4931 if (POINTER_SET(ic))
4958 addSet(&_G.sendSet,ic);
4963 /* piCode(ic,stdout); */
4969 /* now we are ready to call the
4970 peep hole optimizer */
4971 if (!options.nopeep)
4972 peepHole (&lineHead);
4974 /* now do the actual printing */
4975 printLine (lineHead,codeOutFile);