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>
39 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
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 (sym_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 */
334 sym->aop = aop = newAsmop(0);
336 if (IN_CODESPACE(space))
339 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result,aop->code);
340 aop->size = getSize(sym->type);
341 emitcode ("ldi","%s,lo8(%s)",aop->aopu.aop_ptr->name,sym->rname);
342 emitcode ("ldi","%s,hi8(%s)",aop->aop_ptr2);
347 /*-----------------------------------------------------------------*/
348 /* aopForRemat - rematerialzes an object */
349 /*-----------------------------------------------------------------*/
350 static asmop *aopForRemat (symbol *sym)
352 iCode *ic = sym->rematiCode;
353 asmop *aop = newAsmop(AOP_IMMD);
358 val += operandLitValue(IC_RIGHT(ic));
359 else if (ic->op == '-')
360 val -= operandLitValue(IC_RIGHT(ic));
364 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
368 sprintf(buffer,"(%s %c 0x%04x)",
369 OP_SYMBOL(IC_LEFT(ic))->rname,
370 val >= 0 ? '+' : '-',
373 strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
375 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
376 strcpy(aop->aopu.aop_immd,buffer);
380 /*-----------------------------------------------------------------*/
381 /* regsInCommon - two operands have some registers in common */
382 /*-----------------------------------------------------------------*/
383 static bool regsInCommon (operand *op1, operand *op2)
388 /* if they have registers in common */
389 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
392 sym1 = OP_SYMBOL(op1);
393 sym2 = OP_SYMBOL(op2);
395 if (sym1->nRegs == 0 || sym2->nRegs == 0)
398 for (i = 0 ; i < sym1->nRegs ; i++) {
403 for (j = 0 ; j < sym2->nRegs ;j++ ) {
407 if (sym2->regs[j] == sym1->regs[i])
415 /*-----------------------------------------------------------------*/
416 /* operandsEqu - equivalent */
417 /*-----------------------------------------------------------------*/
418 static bool operandsEqu ( operand *op1, operand *op2)
422 /* if they not symbols */
423 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
426 sym1 = OP_SYMBOL(op1);
427 sym2 = OP_SYMBOL(op2);
429 /* if both are itemps & one is spilt
430 and the other is not then false */
431 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
432 sym1->isspilt != sym2->isspilt )
435 /* if they are the same */
439 if (strcmp(sym1->rname,sym2->rname) == 0)
443 /* if left is a tmp & right is not */
447 (sym1->usl.spillLoc == sym2))
454 (sym2->usl.spillLoc == sym1))
460 /*-----------------------------------------------------------------*/
461 /* sameRegs - two asmops have the same registers */
462 /*-----------------------------------------------------------------*/
463 static bool sameRegs (asmop *aop1, asmop *aop2 )
470 if (aop1->type != AOP_REG ||
471 aop2->type != AOP_REG )
474 if (aop1->size != aop2->size )
477 for (i = 0 ; i < aop1->size ; i++ )
478 if (aop1->aopu.aop_reg[i] !=
479 aop2->aopu.aop_reg[i] )
485 /*-----------------------------------------------------------------*/
486 /* isRegPair - for size 2 if this operand has a register pair */
487 /*-----------------------------------------------------------------*/
488 static int isRegPair (asmop *aop)
490 if (!aop || aop->size != 2) return 0;
491 if (aop->type == AOP_X || aop->type == AOP_Z) return 1;
492 if (aop->type != AOP_REG) return 0;
493 if ((aop->aopu.aop_reg[1]->rIdx -
494 aop->aopu.aop_reg[0]->rIdx) == 1) return 1;
498 /*-----------------------------------------------------------------*/
499 /* aopOp - allocates an asmop for an operand : */
500 /*-----------------------------------------------------------------*/
501 static void aopOp (operand *op, iCode *ic, bool result)
510 /* if this a literal */
511 if (IS_OP_LITERAL(op)) {
512 op->aop = aop = newAsmop(AOP_LIT);
513 aop->aopu.aop_lit = op->operand.valOperand;
514 aop->size = getSize(operandType(op));
518 /* if already has a asmop then continue */
522 /* if the underlying symbol has a aop */
523 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
524 op->aop = OP_SYMBOL(op)->aop;
528 /* if this is a true symbol */
529 if (IS_TRUE_SYMOP(op)) {
530 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
534 /* this is a temporary : this has
540 e) can be a return use only */
545 /* if the type is a conditional */
546 if (sym->regType == REG_CND) {
547 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
552 /* if it is spilt then two situations
554 b) has a spill location */
555 if (sym->isspilt || sym->nRegs == 0) {
557 /* rematerialize it NOW */
559 sym->aop = op->aop = aop =
561 aop->size = getSize(sym->type);
566 assert("ACC_USE cannot happen in AVR\n");
571 aop = op->aop = sym->aop = newAsmop(AOP_STR);
572 aop->size = getSize(sym->type);
573 for ( i = 0 ; i < fAVRReturnSize ; i++ )
574 aop->aopu.aop_str[i] = fAVRReturn[i];
578 /* else spill location */
579 sym->aop = op->aop = aop =
580 aopForSym(ic,sym->usl.spillLoc,result);
581 aop->size = getSize(sym->type);
585 /* must be in a register */
586 sym->aop = op->aop = aop = newAsmop(AOP_REG);
587 aop->size = sym->nRegs;
588 for ( i = 0 ; i < sym->nRegs ;i++)
589 aop->aopu.aop_reg[i] = sym->regs[i];
592 /*-----------------------------------------------------------------*/
593 /* freeAsmop - free up the asmop given to an operand */
594 /*----------------------------------------------------------------*/
595 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
612 /* depending on the asmop type only three cases need work AOP_RO
613 , AOP_R1 && AOP_STK */
618 emitcode ("pop","r26");
619 emitcode ("pop","r27");
623 bitVectUnSetBit(ic->rUsed,X_IDX);
629 emitcode ("pop","r30");
630 emitcode ("pop","r31");
634 bitVectUnSetBit(ic->rUsed,Z_IDX);
640 int stk = aop->aopu.aop_stk + aop->size;
641 bitVectUnSetBit(ic->rUsed,X_IDX);
642 bitVectUnSetBit(ic->rUsed,Z_IDX);
644 getFreePtr(ic,&aop,FALSE,0);
646 emitcode ("movw","%s,r28");
648 if (stk <= 63 && stk > 0) {
649 emitcode ("adiw","%s,0x%02x",aop->aopu.aop_ptr->name,stk+1);
651 emitcode ("subi","%s,lo8(%d)",aop->aopu.aop_ptr->name,-(stk+1));
652 emitcode ("sbci","%s,hi8(%d)",aop->aop_ptr2->name,-(stk+1));
657 emitcode("pop","r24");
658 emitcode("st","-%s,r24",aop->type == AOP_X ? "X" : "Z");
662 freeAsmop(op,NULL,ic,TRUE);
664 emitcode("pop","r26");
665 emitcode("pop","r27");
670 emitcode("pop","r30");
671 emitcode("pop","r31");
678 /* all other cases just dealloc */
682 OP_SYMBOL(op)->aop = NULL;
683 /* if the symbol has a spill */
685 SPIL_LOC(op)->aop = NULL;
690 /*-----------------------------------------------------------------*/
691 /* aopGet - for fetching value of the aop */
692 /*-----------------------------------------------------------------*/
693 static char *aopGet (asmop *aop, int offset)
698 /* offset is greater than
700 if (offset > (aop->size - 1) &&
701 aop->type != AOP_LIT)
704 /* depending on type */
708 if (offset > aop->coff) {
709 emitcode ("adiw","%s,%d",aop->aopu.aop_ptr->name,offset - aop->coff);
712 if (offset < aop->coff) {
713 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,aop->coff - offset);
717 emitcode("ld","%s,x",
718 (rs = ((offset & 1) ? "r25" : "r24")));
723 if (offset > aop->coff) {
724 emitcode("adiw","r30,%d",offset - aop->coff);
726 emitcode("sbiw","r30,%d",aop->coff - offset);
728 emitcode("lpm","%s,z",(rs = ((offset & 1) ? "r25" : "r24")));
731 if (offset > aop->coff) {
732 emitcode ("ldd","%s,z+%d",(rs = ((offset & 1) ? "r25" : "r24")),
735 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,aop->coff - offset);
737 emitcode ("ld","%s,z",(rs = ((offset & 1) ? "r25" : "r24")));
744 emitcode ("lds","%s,(%s)+%d",
745 (rs = ((offset & 1) ? "r25" : "r24")),
746 aop->aopu.aop_immd, offset);
750 emitcode ("lds","%s,(%s)+%d",
751 (rs = ((offset & 1) ? "r25" : "r24")),
752 aop->aopu.aop_dir, offset);
756 return aop->aopu.aop_reg[offset]->name;
759 assert("cannot be in bit space AOP_CRY\n");
763 s = aopLiteral(aop->aopu.aop_lit,offset);
764 emitcode("ldi","%s,lo8(%s)",(rs = ((offset & 1)?"r24" : "r25")),s);
769 return aop->aopu.aop_str[offset];
772 emitcode ("ldd","%s,Y+%d",
773 (rs = ((offset & 1) ? "r25" : "r24")),
774 aop->aopu.aop_stk+offset);
778 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
779 "aopget got unsupported aop->type");
782 /*-----------------------------------------------------------------*/
783 /* aopPut - puts a string for a aop */
784 /*-----------------------------------------------------------------*/
785 static void aopPut (asmop *aop, char *s, int offset)
789 if (aop->size && offset > ( aop->size - 1)) {
790 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
791 "aopPut got offset > aop->size");
795 /* will assign value to value */
796 /* depending on where it is ofcourse */
800 sprintf(d,"(%s)+%d", aop->aopu.aop_dir,offset);
803 sprintf(d,"%s",aop->aopu.aop_dir);
806 emitcode("sts","%s,%s",d,s);
810 if (toupper(*s) != 'R') {
812 emitcode("clr","%s",aop->aopu.aop_reg[offset]->name);
814 emitcode("ldi","r25,%s",s);
815 emitcode("mov","%s,r35",aop->aopu.aop_reg[offset]->name);
818 if (strcmp( aop->aopu.aop_reg[offset]->name,s)) {
819 emitcode("mov","%s,%s", aop->aopu.aop_reg[offset]->name,s);
825 if (offset > aop->coff) {
826 emitcode ("adiw","%s,%d",aop->aopu.aop_ptr->name,offset - aop->coff);
829 if (offset < aop->coff) {
830 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,aop->coff - offset);
834 emitcode("st","x,%s", s);
839 if (offset > aop->coff) {
840 emitcode("adiw","r30,%d",offset - aop->coff);
842 emitcode("sbiw","r30,%d",aop->coff - offset);
844 emitcode("lpm","%s,z",s);
847 if (offset > aop->coff) {
848 emitcode ("sdd","z+%d,%s",offset - aop->coff,s);
850 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,aop->coff - offset);
852 emitcode ("ld","%s,z",s);
858 emitcode("push","%s",s);
862 /* if used only for a condition code check */
863 assert(toupper(*s) == 'R');
865 emitcode("xrl","r0,r0");
866 emitcode("cpi","%s,0",s);
869 emitcode("cpc","r0,%s",s);
875 if (strcmp(aop->aopu.aop_str[offset],s))
876 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
880 emitcode ("std","y+%d,%s",offset,s);
884 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
885 "aopPut got unsupported aop->type");
891 /*-----------------------------------------------------------------*/
892 /* reAdjustPreg - points a register back to where it should */
893 /*-----------------------------------------------------------------*/
894 static void reAdjustPreg (asmop *aop)
899 if ((size = aop->size) <= 1)
905 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,size);
911 #define AOP(op) op->aop
912 #define AOP_TYPE(op) AOP(op)->type
913 #define AOP_SIZE(op) AOP(op)->size
914 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_X || \
915 AOP_TYPE(x) == AOP_Z))
916 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
917 (x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) || \
918 x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) )))
920 /*-----------------------------------------------------------------*/
921 /* genNotFloat - generates not for float operations */
922 /*-----------------------------------------------------------------*/
923 static void genNotFloat (operand *op, operand *res)
929 /* we will put 127 in the first byte of
931 aopPut(AOP(res),"127",0);
932 size = AOP_SIZE(op) - 1;
935 l = aopGet(op->aop,offset++);
939 emitcode("or","R0,%s", aopGet(op->aop, offset++));
941 tlbl = newiTempLabel(NULL);
943 tlbl = newiTempLabel(NULL);
944 aopPut(res->aop,zero,1);
945 emitcode("cpi","r0,0");
946 emitcode("breq","L%05d",tlbl->key);
947 aopPut(res->aop,one,1);
948 emitcode("","L%05d:",tlbl->key);
950 size = res->aop->size - 2;
952 /* put zeros in the rest */
954 aopPut(res->aop,zero,offset++);
957 /*-----------------------------------------------------------------*/
958 /* opIsGptr: returns non-zero if the passed operand is */
959 /* a generic pointer type. */
960 /*-----------------------------------------------------------------*/
961 static int opIsGptr(operand *op)
963 sym_link *type = operandType(op);
965 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
972 /*-----------------------------------------------------------------*/
973 /* getDataSize - get the operand data size */
974 /*-----------------------------------------------------------------*/
975 static int getDataSize(operand *op)
979 if (size == GPTRSIZE)
981 sym_link *type = operandType(op);
984 /* generic pointer; arithmetic operations
985 * should ignore the high byte (pointer type).
993 /*-----------------------------------------------------------------*/
994 /* outAcc - output Acc */
995 /*-----------------------------------------------------------------*/
996 static void outAcc(operand *result)
999 size = getDataSize(result);
1001 aopPut(AOP(result),"r0",0);
1004 /* unsigned or positive */
1006 aopPut(AOP(result),zero,offset++);
1011 /*-----------------------------------------------------------------*/
1012 /* outBitC - output a bit C */
1013 /*-----------------------------------------------------------------*/
1014 static void outBitC(operand *result)
1016 emitcode("clr","r0");
1017 emitcode("rol","r0");
1021 /*-----------------------------------------------------------------*/
1022 /* toBoolean - emit code for orl a,operator(sizeop) */
1023 /*-----------------------------------------------------------------*/
1024 static void toBoolean(operand *oper, char *r, bool clr)
1026 int size = AOP_SIZE(oper) ;
1028 if (clr) emitcode ("clr","%s",r);
1030 emitcode("or","%s,%s",r,aopGet(AOP(oper),offset++));
1034 /*-----------------------------------------------------------------*/
1035 /* genNot - generate code for ! operation */
1036 /*-----------------------------------------------------------------*/
1037 static void genNot (iCode *ic)
1040 sym_link *optype = operandType(IC_LEFT(ic));
1041 int size, offset = 1;
1043 /* assign asmOps to operand & result */
1044 aopOp (IC_LEFT(ic),ic,FALSE);
1045 aopOp (IC_RESULT(ic),ic,TRUE);
1047 /* if type float then do float */
1048 if (IS_FLOAT(optype)) {
1049 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1052 emitcode("clr","r0");
1053 tlbl = newiTempLabel(NULL);
1054 size = AOP_SIZE(IC_LEFT(ic));
1057 emitcode("cpse","%s,r0",aopGet(AOP(IC_LEFT(ic)),0));
1061 if (offset) emitcode("cpc","%s,r0",aopGet(AOP(IC_LEFT(ic)),offset));
1062 else emitcode("cpi","%s,0",aopGet(AOP(IC_LEFT(ic)),offset));
1065 emitcode("bne","L%05d",tlbl->key);
1067 emitcode("ldi","r0,1");
1068 emitcode("","L%05d:",tlbl->key);
1069 aopPut(AOP(IC_RESULT(ic)),"r0",0);
1070 size = AOP_SIZE(IC_RESULT(ic)) -1;
1072 while (size--) aopPut(AOP(IC_RESULT(ic)),zero,offset++);
1076 /* release the aops */
1077 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1078 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1082 /*-----------------------------------------------------------------*/
1083 /* genCpl - generate code for complement */
1084 /*-----------------------------------------------------------------*/
1085 static void genCpl (iCode *ic)
1091 /* assign asmOps to operand & result */
1092 aopOp (IC_LEFT(ic),ic,FALSE);
1093 aopOp (IC_RESULT(ic),ic,TRUE);
1094 samer = sameRegs(AOP(IC_LEFT(ic)),AOP(IC_RESULT(ic)));
1095 size = AOP_SIZE(IC_RESULT(ic));
1097 char *l = aopGet(AOP(IC_LEFT(ic)),offset);
1099 emitcode ("com","%s",l);
1101 aopPut(AOP(IC_RESULT(ic)),l,offset);
1102 emitcode ("com","%s",aopGet(AOP(IC_RESULT(ic)),offset));
1107 /* release the aops */
1108 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1109 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1112 /*-----------------------------------------------------------------*/
1113 /* genUminusFloat - unary minus for floating points */
1114 /*-----------------------------------------------------------------*/
1115 static void genUminusFloat(operand *op,operand *result)
1117 int size ,offset =0 ;
1119 /* for this we just need to flip the
1120 first it then copy the rest in place */
1121 size = AOP_SIZE(op) - 1;
1122 l = aopGet(AOP(op),3);
1124 emitcode("ldi","r24,0x80");
1125 if (sameRegs(AOP(op),AOP(result))) {
1126 emitcode("eor","%s,r24",l);
1128 aopPut(AOP(result),l,3);
1129 emitcode("eor","%s,r24",aopGet(AOP(result),3));
1132 aopPut(AOP(result), aopGet(AOP(op),offset), offset);
1137 /*-----------------------------------------------------------------*/
1138 /* genUminus - unary minus code generation */
1139 /*-----------------------------------------------------------------*/
1140 static void genUminus (iCode *ic)
1143 sym_link *optype, *rtype;
1147 aopOp(IC_LEFT(ic),ic,FALSE);
1148 aopOp(IC_RESULT(ic),ic,TRUE);
1150 optype = operandType(IC_LEFT(ic));
1151 rtype = operandType(IC_RESULT(ic));
1153 /* if float then do float stuff */
1154 if (IS_FLOAT(optype)) {
1155 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1159 /* otherwise subtract from zero */
1160 size = AOP_SIZE(IC_LEFT(ic));
1162 samer = sameRegs(AOP(IC_LEFT(ic)),AOP(IC_RESULT(ic)));
1165 emitcode("neg","%s",aopGet(AOP(IC_LEFT(ic)),0));
1167 aopPut(AOP(IC_RESULT(ic)),aopGet(AOP(IC_LEFT(ic)),0),0);
1168 emitcode("neg","%s",aopGet(AOP(IC_RESULT(ic)),0));
1173 char *l = aopGet(AOP(IC_LEFT(ic)),offset);
1175 aopPut(AOP(IC_RESULT(ic)),l,offset);
1176 l = aopGet(AOP(IC_RESULT(ic)),offset);
1178 if (offset) emitcode("com","%s",l);
1179 else emitcode("neg","%s",l);
1182 size = AOP_SIZE(IC_LEFT(ic)) -1;
1185 emitcode("sbci","%s,lo8(-1)",aopGet(AOP(IC_RESULT(ic)),offset++));
1189 /* if any remaining bytes in the result */
1190 /* we just need to propagate the sign */
1191 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1192 symbol *tlbl = newiTempLabel(NULL);
1193 emitcode("clr","r0");
1194 emitcode("brcc","L%05d",tlbl->key);
1195 emitcode("com","r0");
1196 emitcode("","L%05d:",tlbl->key);
1198 aopPut(AOP(IC_RESULT(ic)),"r0",offset++);
1202 /* release the aops */
1203 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1204 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1207 /*-----------------------------------------------------------------*/
1208 /* assignResultValue - */
1209 /*-----------------------------------------------------------------*/
1210 static void assignResultValue(operand * oper)
1213 int size = AOP_SIZE(oper);
1215 aopPut(AOP(oper),fAVRReturn[offset],offset);
1220 /*-----------------------------------------------------------------*/
1221 /* saveZreg - if indirect call then save z-pointer register */
1222 /*-----------------------------------------------------------------*/
1223 static void saveZreg (iCode *ic)
1225 /* only if live accross this call */
1226 if (ic->regsSaved == 0 &&
1227 (bitVectBitValue(ic->rMask,R30_IDX) ||
1228 bitVectBitValue(ic->rMask,R31_IDX))) {
1230 emitcode("push","r30");
1231 emitcode("push","r31");
1235 /*-----------------------------------------------------------------*/
1236 /* popZreg - restore values of zreg */
1237 /*-----------------------------------------------------------------*/
1238 static void popZreg (iCode *ic)
1240 if (ic->regsSaved) {
1241 emitcode ("pop","r31");
1242 emitcode ("pop","r30");
1246 /*-----------------------------------------------------------------*/
1247 /* genIpush - genrate code for pushing this gets a little complex */
1248 /*-----------------------------------------------------------------*/
1249 static void genIpush (iCode *ic)
1251 int size, offset = 0 ;
1255 if (!ic->parmPush) {
1256 /* and the item is spilt then do nothing */
1257 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1261 for (lic = ic->next ; lic ; lic = lic->next)
1262 if (lic->op == PCALL) break;
1263 if (lic) saveZreg(lic);
1266 /* this is a paramter push */
1267 aopOp(IC_LEFT(ic),ic,FALSE);
1268 size = AOP_SIZE(IC_LEFT(ic));
1270 l = aopGet(AOP(IC_LEFT(ic)),offset++);
1271 emitcode("push","%s",l);
1274 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1277 /*-----------------------------------------------------------------*/
1278 /* genIpop - recover the registers: can happen only for spilling */
1279 /*-----------------------------------------------------------------*/
1280 static void genIpop (iCode *ic)
1285 /* if the temp was not pushed then */
1286 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1289 aopOp(IC_LEFT(ic),ic,FALSE);
1290 size = AOP_SIZE(IC_LEFT(ic));
1293 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--));
1295 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1298 /*-----------------------------------------------------------------*/
1299 /* genCall - generates a call statement */
1300 /*-----------------------------------------------------------------*/
1301 static void genCall (iCode *ic)
1304 /* if send set is not empty the assign */
1308 for (sic = setFirstItem(_G.sendSet) ; sic ;
1309 sic = setNextItem(_G.sendSet)) {
1310 int size, offset = 0;
1311 aopOp(IC_LEFT(sic),sic,FALSE);
1312 size = AOP_SIZE(IC_LEFT(sic));
1314 char *l = aopGet(AOP(IC_LEFT(sic)),offset);
1316 sprintf(buffer,"r%d",rnum++);
1318 emitcode("mov","%s,%s",b,l);
1321 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1326 emitcode("call","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1327 OP_SYMBOL(IC_LEFT(ic))->rname :
1328 OP_SYMBOL(IC_LEFT(ic))->name));
1330 /* if we need assign a result value */
1331 if ((IS_ITEMP(IC_RESULT(ic)) &&
1332 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1333 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1334 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1336 aopOp(IC_RESULT(ic),ic,FALSE);
1337 assignResultValue(IC_RESULT(ic));
1338 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1341 /* adjust the stack for parameters if required */
1342 if (IC_LEFT(ic)->parmBytes) {
1343 if (IC_LEFT(ic)->parmBytes > 63) {
1344 emitcode("sbiw","r28,%d",IC_LEFT(ic)->parmBytes);
1346 emitcode("subi","r28,lo8(%d)",IC_LEFT(ic)->parmBytes);
1347 emitcode("sbci","r29,hi8(%d)",IC_LEFT(ic)->parmBytes);
1353 /*-----------------------------------------------------------------*/
1354 /* genPcall - generates a call by pointer statement */
1355 /*-----------------------------------------------------------------*/
1356 static void genPcall (iCode *ic)
1359 if (!ic->regsSaved) saveZreg(ic);
1361 aopOp(IC_LEFT(ic),ic,FALSE);
1362 emitcode("mov","r30",aopGet(AOP(IC_LEFT(ic)),0));
1363 emitcode("mov","r31",aopGet(AOP(IC_RIGHT(ic)),0));
1364 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1366 /* if send set is not empty the assign */
1370 for (sic = setFirstItem(_G.sendSet) ; sic ;
1371 sic = setNextItem(_G.sendSet)) {
1372 int size, offset = 0;
1373 aopOp(IC_LEFT(sic),sic,FALSE);
1374 size = AOP_SIZE(IC_LEFT(sic));
1376 char *l = aopGet(AOP(IC_LEFT(sic)),offset);
1378 sprintf(b,"r%d",rnum++);
1380 emitcode("mov","%s,%s",b,l);
1383 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1388 emitcode("icall","");
1390 /* if we need assign a result value */
1391 if ((IS_ITEMP(IC_RESULT(ic)) &&
1392 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1393 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
1394 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1396 aopOp(IC_RESULT(ic),ic,FALSE);
1398 assignResultValue(IC_RESULT(ic));
1399 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1402 /* adjust the stack for parameters if
1404 if (IC_LEFT(ic)->parmBytes) {
1406 if (IC_LEFT(ic)->parmBytes > 3) {
1407 emitcode("mov","a,%s",spname);
1408 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1409 emitcode("mov","%s,a",spname);
1411 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1412 emitcode("dec","%s",spname);
1416 /* adjust the stack for parameters if required */
1417 if (IC_LEFT(ic)->parmBytes) {
1418 if (IC_LEFT(ic)->parmBytes > 63) {
1419 emitcode("sbiw","r28,%d",IC_LEFT(ic)->parmBytes);
1421 emitcode("subi","r28,lo8(%d)",IC_LEFT(ic)->parmBytes);
1422 emitcode("sbci","r29,hi8(%d)",IC_LEFT(ic)->parmBytes);
1425 if (ic->regsSaved) popZreg(ic);
1428 /*-----------------------------------------------------------------*/
1429 /* resultRemat - result is rematerializable */
1430 /*-----------------------------------------------------------------*/
1431 static int resultRemat (iCode *ic)
1433 if (SKIP_IC(ic) || ic->op == IFX)
1436 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1437 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1438 if (sym->remat && !POINTER_SET(ic))
1445 #if defined(__BORLANDC__) || defined(_MSC_VER)
1446 #define STRCASECMP stricmp
1448 #define STRCASECMP strcasecmp
1451 /*-----------------------------------------------------------------*/
1452 /* inExcludeList - return 1 if the string is in exclude Reg list */
1453 /*-----------------------------------------------------------------*/
1454 static bool inExcludeList(char *s)
1458 if (options.excludeRegs[i] &&
1459 STRCASECMP(options.excludeRegs[i],"none") == 0)
1462 for ( i = 0 ; options.excludeRegs[i]; i++) {
1463 if (options.excludeRegs[i] &&
1464 STRCASECMP(s,options.excludeRegs[i]) == 0)
1470 /*-----------------------------------------------------------------*/
1471 /* genFunction - generated code for function entry */
1472 /*-----------------------------------------------------------------*/
1473 static void genFunction (iCode *ic)
1480 /* create the function header */
1481 emitcode(";","-----------------------------------------");
1482 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1483 emitcode(";","-----------------------------------------");
1485 emitcode("","%s:",sym->rname);
1486 fetype = getSpec(operandType(IC_LEFT(ic)));
1488 /* if critical function then turn interrupts off */
1489 if (SPEC_CRTCL(fetype))
1492 if (IS_ISR(sym->etype)) {
1495 /* save the preserved registers that are used in this function */
1496 for (i = R2_IDX ; i <= R15_IDX ; i++ ) {
1497 if (bitVectBitValue(sym->regsUsed,i)) {
1499 emitcode("push","%s",avr_regWithIdx(i)->name);
1502 /* now for the pointer registers */
1503 if (bitVectBitValue(sym->regsUsed,R26_IDX)) {
1505 emitcode("push","r26");
1507 if (bitVectBitValue(sym->regsUsed,R27_IDX)) {
1509 emitcode("push","r27");
1511 if (bitVectBitValue(sym->regsUsed,R30_IDX)) {
1513 emitcode("push","r30");
1515 if (bitVectBitValue(sym->regsUsed,R31_IDX)) {
1517 emitcode("push","r31");
1519 /* adjust the stack for the function */
1521 emitcode ("push","r28");
1522 emitcode ("push","r29");
1523 emitcode ("in","r28,__SP_L__");
1524 emitcode ("in","r29,__SP_H__");
1525 if (sym->stack <= 63) {
1526 emitcode("sbiw","r28,%d",sym->stack);
1528 emitcode ("subi","r28,lo8(%d)",sym->stack);
1529 emitcode ("sbci","r29,hi8(%d)",sym->stack);
1531 emitcode("out","__SP_L__,r28");
1532 emitcode("out","__SP_H__,r29");
1536 /*-----------------------------------------------------------------*/
1537 /* genEndFunction - generates epilogue for functions */
1538 /*-----------------------------------------------------------------*/
1539 static void genEndFunction (iCode *ic)
1541 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1544 /* restore stack pointer */
1546 if (sym->stack <= 63) {
1547 emitcode("adiw","r28,%d",sym->stack);
1549 emitcode ("subi","r28,lo8(-%d)",sym->stack);
1550 emitcode ("sbci","r29,hi8(-%d)",sym->stack);
1552 emitcode("out","__SP_L__,r28");
1553 emitcode("out","__SP_H__,r29");
1555 /* pop frame pointer */
1556 emitcode ("pop","r29");
1557 emitcode ("pop","r28");
1559 /* restore preserved registers */
1560 if (bitVectBitValue(sym->regsUsed,R31_IDX)) {
1562 emitcode("pop","r31");
1564 if (bitVectBitValue(sym->regsUsed,R30_IDX)) {
1566 emitcode("pop","r30");
1568 if (bitVectBitValue(sym->regsUsed,R27_IDX)) {
1570 emitcode("push","r27");
1572 if (bitVectBitValue(sym->regsUsed,R26_IDX)) {
1574 emitcode("push","r26");
1576 for (i = R15_IDX ; i >= R2_IDX ; i-- ) {
1577 if (bitVectBitValue(sym->regsUsed,i)) {
1579 emitcode("pop","%s",avr_regWithIdx(i)->name);
1583 if (SPEC_CRTCL(sym->etype))
1586 if (IS_ISR(sym->etype)) {
1594 /*-----------------------------------------------------------------*/
1595 /* genRet - generate code for return statement */
1596 /*-----------------------------------------------------------------*/
1597 static void genRet (iCode *ic)
1599 int size,offset = 0 ;
1601 /* if we have no return value then
1602 just generate the "ret" */
1606 /* we have something to return then
1607 move the return value into place */
1608 aopOp(IC_LEFT(ic),ic,FALSE);
1609 size = AOP_SIZE(IC_LEFT(ic));
1612 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
1613 emitcode("ldi","%s,%s(%d)",fAVRReturn[offset],larray[offset],
1614 (int)floatFromVal (AOP(IC_LEFT(ic))->aopu.aop_lit),offset);
1617 l = aopGet(AOP(IC_LEFT(ic)),offset);
1618 if (strcmp(fAVRReturn[offset],l))
1619 emitcode("mov","%s,%s",fAVRReturn[offset],l);
1624 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
1627 /* generate a jump to the return label
1628 if the next is not the return statement */
1629 if (!(ic->next && ic->next->op == LABEL &&
1630 IC_LABEL(ic->next) == returnLabel))
1632 emitcode("rjmp","L%05d",returnLabel->key);
1636 /*-----------------------------------------------------------------*/
1637 /* genLabel - generates a label */
1638 /*-----------------------------------------------------------------*/
1639 static void genLabel (iCode *ic)
1641 /* special case never generate */
1642 if (IC_LABEL(ic) == entryLabel)
1645 emitcode("","L%05d:",IC_LABEL(ic)->key);
1648 /*-----------------------------------------------------------------*/
1649 /* genGoto - generates a ljmp */
1650 /*-----------------------------------------------------------------*/
1651 static void genGoto (iCode *ic)
1653 emitcode ("rjmp","L%05d:",(IC_LABEL(ic)->key+100));
1656 /*-----------------------------------------------------------------*/
1657 /* findLabelBackwards: walks back through the iCode chain looking */
1658 /* for the given label. Returns number of iCode instructions */
1659 /* between that label and given ic. */
1660 /* Returns zero if label not found. */
1661 /*-----------------------------------------------------------------*/
1662 static int findLabelBackwards(iCode *ic, int key)
1671 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
1673 /* printf("findLabelBackwards = %d\n", count); */
1681 /*-----------------------------------------------------------------*/
1682 /* genPlusIncr :- does addition with increment if possible */
1683 /*-----------------------------------------------------------------*/
1684 static bool genPlusIncr (iCode *ic)
1686 unsigned int icount ;
1688 /* will try to generate an increment */
1689 /* if the right side is not a literal
1691 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1694 icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
1696 /* if the sizes are greater than 2 or they are not the same regs
1698 if (!sameRegs(AOP(IC_LEFT(ic)),AOP(IC_RESULT(ic))))
1701 /* so we know LEFT & RESULT in the same registers and add
1703 /* for short & char types */
1704 if (AOP_SIZE(IC_RESULT(ic)) < 2) {
1706 emitcode("inc","%s",aopGet(AOP(IC_LEFT(ic)),0));
1709 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_LEFT(ic)),0),-icount);
1713 if (AOP_SIZE(IC_RESULT(ic)) <= 3) {
1714 /* if register pair and starts with 26/30 then adiw */
1715 if (isRegPair(AOP(IC_RESULT(ic))) && icount > 0 && icount < 64 &&
1716 ( IS_REGIDX(AOP(IC_RESULT(ic)),R26_IDX) ||
1717 IS_REGIDX(AOP(IC_RESULT(ic)),R30_IDX) )) {
1718 emitcode("adiw","%s,%d",aopGet(AOP(IC_RESULT(ic)),0),icount);
1723 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_RESULT(ic)),0),-icount);
1724 emitcode("sbci","%s,hi8(%d)",aopGet(AOP(IC_RESULT(ic)),1),-icount);
1728 /* for 32 bit longs */
1729 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_RESULT(ic)),0),-icount);
1730 emitcode("sbci","%s,hi8(%d)",aopGet(AOP(IC_RESULT(ic)),1),-icount);
1731 emitcode("sbci","%s,hlo8(%d)",aopGet(AOP(IC_RESULT(ic)),2),-icount);
1732 emitcode("sbci","%s,hhi8(%d)",aopGet(AOP(IC_RESULT(ic)),3),-icount);
1737 /* This is the pure and virtuous version of this code.
1738 * I'm pretty certain it's right, but not enough to toss the old
1741 static void adjustArithmeticResult (iCode *ic)
1743 if (opIsGptr(IC_RESULT(ic)) &&
1744 opIsGptr(IC_LEFT(ic)) &&
1745 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1747 aopPut(AOP(IC_RESULT(ic)),
1748 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1),
1752 if (opIsGptr(IC_RESULT(ic)) &&
1753 opIsGptr(IC_RIGHT(ic)) &&
1754 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
1756 aopPut(AOP(IC_RESULT(ic)),
1757 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1),
1761 if (opIsGptr(IC_RESULT(ic)) &&
1762 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
1763 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
1764 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
1765 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
1767 sprintf(buffer,"%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
1768 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
1772 /*-----------------------------------------------------------------*/
1773 /* genPlus - generates code for addition */
1774 /*-----------------------------------------------------------------*/
1775 static void genPlus (iCode *ic)
1777 int size, offset = 0;
1781 /* special cases :- */
1783 aopOp (IC_LEFT(ic),ic,FALSE);
1784 aopOp (IC_RIGHT(ic),ic,FALSE);
1785 aopOp (IC_RESULT(ic),ic,TRUE);
1787 /* if I can do an increment instead
1788 of add then GOOD for ME */
1789 if (genPlusIncr (ic) == TRUE)
1792 size = getDataSize(IC_RESULT(ic));
1793 samer = sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic)));
1797 aopPut(AOP(IC_RESULT(ic)),aopGet(AOP(IC_LEFT(ic)),offset),offset);
1799 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
1801 if(offset == 0) l = "add";
1804 emitcode(l,"%s,%s",aopGet(AOP(IC_RESULT(ic)),offset),
1805 aopGet(AOP(IC_RIGHT(ic)),offset));
1807 if (offset == 0) l = "subi";
1810 emitcode(l,"%s,%s(-%d)",aopGet(AOP(IC_RESULT(ic)),offset),
1812 (int)floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
1817 adjustArithmeticResult(ic);
1820 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1821 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1822 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1825 /*-----------------------------------------------------------------*/
1826 /* genMinusDec :- does subtraction with deccrement if possible */
1827 /*-----------------------------------------------------------------*/
1828 static bool genMinusDec (iCode *ic)
1830 unsigned int icount ;
1832 /* will try to generate an increment */
1833 /* if the right side is not a literal
1835 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1838 icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
1840 /* if the sizes are greater than 2 or they are not the same regs
1842 if (!sameRegs(AOP(IC_LEFT(ic)),AOP(IC_RIGHT(ic))))
1845 /* so we know LEFT & RESULT in the same registers and add
1847 /* for short & char types */
1848 if (AOP_SIZE(IC_RESULT(ic)) < 2) {
1850 emitcode("dec","%s",aopGet(AOP(IC_LEFT(ic)),0));
1853 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_LEFT(ic)),0),icount);
1857 if (AOP_SIZE(IC_RESULT(ic)) <= 3) {
1858 /* if register pair and starts with 26/30 then adiw */
1859 if (isRegPair(AOP(IC_RESULT(ic))) && icount > 0 && icount < 64 &&
1860 ( IS_REGIDX(AOP(IC_RESULT(ic)),R26_IDX) ||
1861 IS_REGIDX(AOP(IC_RESULT(ic)),R30_IDX) )) {
1862 emitcode("sbiw","%s,%d",aopGet(AOP(IC_RESULT(ic)),0),icount);
1867 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_RESULT(ic)),0),icount);
1868 emitcode("sbci","%s,hi8(%d)",aopGet(AOP(IC_RESULT(ic)),1),icount);
1871 /* for 32 bit longs */
1872 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_RESULT(ic)),0),icount);
1873 emitcode("sbci","%s,hi8(%d)",aopGet(AOP(IC_RESULT(ic)),1),icount);
1874 emitcode("sbci","%s,hlo8(%d)",aopGet(AOP(IC_RESULT(ic)),2),icount);
1875 emitcode("sbci","%s,hhi8(%d)",aopGet(AOP(IC_RESULT(ic)),3),icount);
1880 /*-----------------------------------------------------------------*/
1881 /* addSign - complete with sign */
1882 /*-----------------------------------------------------------------*/
1883 static void addSign(operand *result, int offset, int sign)
1885 int size = (getDataSize(result) - offset);
1888 emitcode("rlc","a");
1889 emitcode("subb","a,acc");
1891 aopPut(AOP(result),"a",offset++);
1894 aopPut(AOP(result),zero,offset++);
1898 /*-----------------------------------------------------------------*/
1899 /* genMinus - generates code for subtraction */
1900 /*-----------------------------------------------------------------*/
1901 static void genMinus (iCode *ic)
1903 int size, offset = 0, samer;
1906 aopOp (IC_LEFT(ic),ic,FALSE);
1907 aopOp (IC_RIGHT(ic),ic,FALSE);
1908 aopOp (IC_RESULT(ic),ic,TRUE);
1910 /* if I can do an decrement instead
1911 of subtract then GOOD for ME */
1912 if (genMinusDec (ic) == TRUE)
1915 size = getDataSize(IC_RESULT(ic));
1916 samer = sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic)));
1919 aopPut(AOP(IC_RESULT(ic)),aopGet(AOP(IC_LEFT(ic)),offset),offset);
1921 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
1923 if(offset == 0) l = "sub";
1926 emitcode(l,"%s,%s",aopGet(AOP(IC_RESULT(ic)),offset),
1927 aopGet(AOP(IC_RIGHT(ic)),offset));
1929 if (offset == 0) l = "subi";
1932 emitcode(l,"%s,%s(%d)",aopGet(AOP(IC_RESULT(ic)),offset),
1934 (int)floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
1939 adjustArithmeticResult(ic);
1942 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1943 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1944 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1947 /*-----------------------------------------------------------------*/
1948 /* genMultOneByte : 8 bit multiplication & division */
1949 /*-----------------------------------------------------------------*/
1950 static void genMultOneByte (operand *left,
1954 sym_link *opetype = operandType(result);
1958 /* (if two literals, the value is computed before) */
1959 /* if one literal, literal on the right */
1960 if (AOP_TYPE(left) == AOP_LIT){
1966 size = AOP_SIZE(result);
1968 if (SPEC_USIGN(opetype)) {
1969 emitcode("mul","%s,%s", aopGet(AOP(left),0),aopGet(AOP(right),0));
1971 emitcode("muls","%s,%s", aopGet(AOP(left),0),
1972 aopGet(AOP(right),0));
1974 aopPut(AOP(result),"r0",0);
1976 aopPut(AOP(result),"r1",1);
1979 if (SPEC_USIGN(opetype)) {
1981 aopPut(AOP(result),zero,offset++);
1985 lbl = newiTempLabel(NULL);
1986 emitcode("ldi","r24,0");
1987 emitcode("brcc","L%05d",lbl->key);
1988 emitcode("ldi","r24,lo8(-1)");
1989 emitcode("","L%05d:",lbl->key);
1990 while (size--) aopPut(AOP(result),"r24",offset++);
1997 /*-----------------------------------------------------------------*/
1998 /* genMult - generates code for multiplication */
1999 /*-----------------------------------------------------------------*/
2000 static void genMult (iCode *ic)
2002 operand *left = IC_LEFT(ic);
2003 operand *right = IC_RIGHT(ic);
2004 operand *result= IC_RESULT(ic);
2006 /* assign the amsops */
2007 aopOp (left,ic,FALSE);
2008 aopOp (right,ic,FALSE);
2009 aopOp (result,ic,TRUE);
2011 /* if both are of size == 1 */
2012 if (AOP_SIZE(left) == 1 &&
2013 AOP_SIZE(right) == 1 ) {
2014 genMultOneByte(left,right,result);
2018 /* should have been converted to function call */
2022 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2023 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2024 freeAsmop(result,NULL,ic,TRUE);
2027 /*-----------------------------------------------------------------*/
2028 /* genDiv - generates code for division */
2029 /*-----------------------------------------------------------------*/
2030 static void genDiv (iCode *ic)
2032 /* should have been converted to function call */
2036 /*-----------------------------------------------------------------*/
2037 /* genMod - generates code for division */
2038 /*-----------------------------------------------------------------*/
2039 static void genMod (iCode *ic)
2041 /* should have been converted to function call */
2053 /*-----------------------------------------------------------------*/
2054 /* revavrcnd - reverse a conditional for avr */
2055 /*-----------------------------------------------------------------*/
2056 static int revavrcnd(int type)
2060 } rar[] = { { AVR_EQ, AVR_NE}, {AVR_LT, AVR_GE}};
2063 for (i = 0 ; i < (sizeof(rar)/sizeof(rar[0]));i++) {
2064 if (rar[i].type == type) return rar[i].rtype;
2065 if (rar[i].rtype== type) return rar[i].type;
2067 assert(1); /* cannot happen */
2068 return 0; /* makes the compiler happy */
2071 static char *br_name[4] = {"breq","brne","brlt","brge"};
2072 static char *br_uname[4]= {"breq","brne","brlo","brcc"};
2074 /*-----------------------------------------------------------------*/
2075 /* genBranch - generate the branch instruction */
2076 /*-----------------------------------------------------------------*/
2077 static void genBranch (iCode *ifx, int br_type, int sign)
2079 int tj = (IC_TRUE(ifx) ? 1 : 0) ;
2081 if (tj) { /* if true jump */
2082 char *nm = (sign ? br_name[br_type] : br_uname[br_type]);
2083 emitcode(nm,"L%05d",IC_TRUE(ifx)->key);
2084 } else { /* if false jump */
2085 int rtype = revavrcnd(br_type);
2086 char *nm = (sign ? br_name[rtype] : br_uname[rtype]);
2087 emitcode(nm,"L%05d",IC_FALSE(ifx)->key);
2092 /*-----------------------------------------------------------------*/
2093 /* genCmp - compare & jump */
2094 /*-----------------------------------------------------------------*/
2095 static void genCmp (iCode *ic, iCode *ifx, int br_type)
2097 operand *left, *right, *result;
2098 sym_link *letype , *retype;
2100 int sign, size, offset =0;
2103 right= IC_RIGHT(ic);
2104 result = IC_RESULT(ic);
2106 letype = getSpec(operandType(left));
2107 retype =getSpec(operandType(right));
2108 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2110 /* assign the amsops */
2111 aopOp (left,ic,FALSE);
2112 aopOp (right,ic,FALSE);
2113 aopOp (result,ic,TRUE);
2114 size = AOP_SIZE(left);
2118 if (AOP_TYPE(right) == AOP_LIT) {
2119 emitcode("cpi","%s,lo8(%d)",aopGet(AOP(left),0),
2120 (int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
2121 genBranch(ifx,br_type,sign);
2122 } else { /* right != literal */
2123 emitcode("cp","%s,%s",aopGet(AOP(left),0),aopGet(AOP(right),0));
2124 genBranch(ifx,br_type,sign);
2126 } else { /* size != 1 */
2129 emitcode("cp","%s,%s",aopGet(AOP(left),0),aopGet(AOP(right),0));
2131 emitcode("cpc","%s,%s",aopGet(AOP(left),offset),aopGet(AOP(right),offset));
2134 genBranch(ifx,br_type,sign);
2136 } else { /* no ifx */
2137 emitcode("clr","r0");
2140 emitcode("cp","%s,%s",aopGet(AOP(left),0),aopGet(AOP(right),0));
2142 emitcode("cpc","%s,%s",aopGet(AOP(left),offset),aopGet(AOP(right),offset));
2145 lbl = newiTempLabel(NULL);
2146 br_type = revavrcnd(br_type);
2147 if (sign) emitcode(br_uname[br_type],"L%05d",lbl->key);
2148 else emitcode(br_name[br_type],"L%05d",lbl->key);
2149 emitcode("inc","r0");
2150 emitcode("","L%05d:",lbl->key);
2151 aopPut(AOP(result),"r0",0);
2152 size = AOP_SIZE(result) - 1;
2154 while (size--) aopPut(AOP(result),zero,offset++);
2157 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2158 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2159 freeAsmop(result,NULL,ic,TRUE);
2162 /*-----------------------------------------------------------------*/
2163 /* genCmpGt :- greater than comparison */
2164 /*-----------------------------------------------------------------*/
2165 static void genCmpGt (iCode *ic, iCode *ifx)
2167 /* should have transformed by the parser */
2171 /*-----------------------------------------------------------------*/
2172 /* genCmpLt - less than comparisons */
2173 /*-----------------------------------------------------------------*/
2174 static void genCmpLt (iCode *ic, iCode *ifx)
2176 genCmp(ic,ifx,AVR_LT);
2179 /*-----------------------------------------------------------------*/
2180 /* genCmpEq - generates code for equal to */
2181 /*-----------------------------------------------------------------*/
2182 static void genCmpEq (iCode *ic, iCode *ifx)
2184 genCmp(ic,ifx,AVR_EQ);
2187 /*-----------------------------------------------------------------*/
2188 /* genCmpNe - generates code for not equal to */
2189 /*-----------------------------------------------------------------*/
2190 static void genCmpNe (iCode *ic, iCode *ifx)
2192 genCmp(ic,ifx,AVR_NE);
2195 /*-----------------------------------------------------------------*/
2196 /* genCmpGe - generates code for greater than equal to */
2197 /*-----------------------------------------------------------------*/
2198 static void genCmpGe (iCode *ic, iCode *ifx)
2200 genCmp(ic,ifx,AVR_GE);
2203 /*-----------------------------------------------------------------*/
2204 /* genCmpLe - generates code for less than equal to */
2205 /*-----------------------------------------------------------------*/
2206 static void genCmpLe (iCode *ic, iCode *ifx)
2208 operand *left = IC_LEFT(ic);
2209 operand *right= IC_RIGHT(ic);
2211 IC_RIGHT(ic) = left;
2212 IC_LEFT(ic) = right;
2213 genCmp(ic,ifx,AVR_GE);
2216 /*-----------------------------------------------------------------*/
2217 /* ifxForOp - returns the icode containing the ifx for operand */
2218 /*-----------------------------------------------------------------*/
2219 static iCode *ifxForOp ( operand *op, iCode *ic )
2221 /* if true symbol then needs to be assigned */
2222 if (IS_TRUE_SYMOP(op))
2225 /* if this has register type condition and
2226 the next instruction is ifx with the same operand
2227 and live to of the operand is upto the ifx only then */
2229 ic->next->op == IFX &&
2230 IC_COND(ic->next)->key == op->key &&
2231 OP_SYMBOL(op)->liveTo <= ic->next->seq )
2236 /*-----------------------------------------------------------------*/
2237 /* genAndOp - for && operation */
2238 /*-----------------------------------------------------------------*/
2239 static void genAndOp (iCode *ic)
2241 operand *left,*right, *result;
2245 /* note here that && operations that are in an
2246 if statement are taken away by backPatchLabels
2247 only those used in arthmetic operations remain */
2248 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2249 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2250 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2252 tlbl = newiTempLabel(NULL);
2253 toBoolean(left,"r0",TRUE);
2254 toBoolean(right,"r1",TRUE);
2255 emitcode("and","r0,r1");
2256 emitcode("ldi","r24,1");
2257 emitcode("breq","L%05d",tlbl->key);
2258 emitcode("dec","r24");
2259 emitcode("","L%05d:",tlbl->key);
2260 aopPut(AOP(result),"r24",0);
2261 size = AOP_SIZE(result) -1;
2263 while (size--) aopPut(AOP(result),zero,offset++);
2265 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2266 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2267 freeAsmop(result,NULL,ic,TRUE);
2271 /*-----------------------------------------------------------------*/
2272 /* genOrOp - for || operation */
2273 /*-----------------------------------------------------------------*/
2274 static void genOrOp (iCode *ic)
2276 operand *left,*right, *result;
2280 /* note here that || operations that are in an
2281 if statement are taken away by backPatchLabels
2282 only those used in arthmetic operations remain */
2283 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2284 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2285 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2287 tlbl = newiTempLabel(NULL);
2288 toBoolean(left,"r0",TRUE);
2289 toBoolean(right,"r0",FALSE);
2290 emitcode("ldi","r24,1");
2291 emitcode("breq","L%05d",tlbl->key);
2292 emitcode("dec","r24");
2293 emitcode("","L%05d:",tlbl->key);
2294 aopPut(AOP(result),"r24",0);
2295 size = AOP_SIZE(result) -1;
2297 while (size--) aopPut(AOP(result),zero,offset++);
2299 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2300 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2301 freeAsmop(result,NULL,ic,TRUE);
2304 /*-----------------------------------------------------------------*/
2305 /* isLiteralBit - test if lit == 2^n */
2306 /*-----------------------------------------------------------------*/
2307 static int isLiteralBit(unsigned long lit)
2309 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
2310 0x100L,0x200L,0x400L,0x800L,
2311 0x1000L,0x2000L,0x4000L,0x8000L,
2312 0x10000L,0x20000L,0x40000L,0x80000L,
2313 0x100000L,0x200000L,0x400000L,0x800000L,
2314 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
2315 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
2318 for(idx = 0; idx < 32; idx++)
2324 enum { AVR_AND = 0, AVR_OR, AVR_XOR };
2325 static char *bopnames_lit[] = {"andi","ori"};
2326 static char *bopnames[] = {"and","or","eor"};
2327 /*-----------------------------------------------------------------*/
2328 /* genBitWise - generate bitwise operations */
2329 /*-----------------------------------------------------------------*/
2330 static void genBitWise(iCode *ic, iCode *ifx, int bitop)
2332 operand *left, *right, *result;
2336 int samerl, samerr ;
2338 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2339 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2340 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2342 size = AOP_SIZE(left);
2344 if (ifx) { /* used only for jumps */
2345 if (AOP_TYPE(right) == AOP_LIT &&
2346 (bitop == AVR_AND || bitop == AVR_OR)) {
2347 int lit = (int) floatFromVal (AOP(right)->aopu.aop_lit);
2348 int p2 = powof2(lit);
2349 if (bitop == AVR_AND && p2) { /* right side is a power of 2 */
2350 l = aopGet(AOP(left),p2 / 8);
2352 emitcode("sbrc","%s,%d",l,(p2 % 8));
2353 emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2355 emitcode("sbrs","%s,%d",l,(p2 % 8));
2356 emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2358 } else { /* right not power of two */
2359 int eh = OP_SYMBOL(left)->liveTo <= ic->seq;
2362 emitcode(bopnames_lit[bitop],"%s,lo8(%d)",
2363 aopGet(AOP(IC_LEFT(ic)),0), lit);
2365 MOVR0(aopGet(AOP(IC_LEFT(ic)),0));
2366 emitcode(bopnames_lit[bitop],"r0,lo8(%d)",lit);
2368 lbl = newiTempLabel(NULL);
2370 emitcode("breq","L%05d",lbl->key);
2371 emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2373 emitcode("brne","L%05d",lbl->key);
2374 emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2376 emitcode("","L%05d:",lbl->key);
2377 } else if (size == 2) {
2378 emitcode("mov","r24,%s",aopGet(AOP(IC_LEFT(ic)),0));
2379 emitcode("mov","r25,%s",aopGet(AOP(IC_LEFT(ic)),1));
2380 emitcode(bopnames_lit[bitop],"r24,lo8(%d)",lit);
2381 emitcode(bopnames_lit[bitop],"r25,hi8(%d)",lit);
2382 emitcode("sbiw","r24,0");
2383 lbl = newiTempLabel(NULL);
2385 emitcode("breq","L%05d",lbl->key);
2386 emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2388 emitcode("brne","L%05d",lbl->key);
2389 emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2391 emitcode("","L%05d:",lbl->key);
2393 lbl = newiTempLabel(NULL);
2394 lbl1 = newiTempLabel(NULL);
2397 emitcode(bopnames_lit[bitop],"%s,lo8(%d)",
2398 aopGet(AOP(IC_LEFT(ic)),offset), lit);
2400 MOVR0(aopGet(AOP(IC_LEFT(ic)),offset));
2401 emitcode("andi","r0,lo8(%d)",lit);
2403 emitcode("brne","L%05d",lbl->key);
2407 if (IC_FALSE(ifx)) emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2408 else emitcode("rjmp","L%05d",lbl1->key);
2409 emitcode("","L%05d:",lbl->key);
2411 if (IC_TRUE(ifx)) emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2412 emitcode("","L%05d:",lbl1->key);
2416 } else { /* right is not a literal */
2417 int eh = OP_SYMBOL(left)->liveTo <= ic->seq;
2418 int reh = OP_SYMBOL(right)->liveTo <= ic->seq;
2421 emitcode(bopnames[bitop],"%s,%s",
2422 aopGet(AOP(IC_LEFT(ic)),0),
2423 aopGet(AOP(IC_RIGHT(ic)),0));
2425 emitcode(bopnames[bitop],"%s,%s",
2426 aopGet(AOP(IC_RIGHT(ic)),0),
2427 aopGet(AOP(IC_LEFT(ic)),0));
2429 MOVR0(aopGet(AOP(IC_LEFT(ic)),0));
2430 emitcode(bopnames[bitop],"r0,%s",aopGet(AOP(IC_RIGHT(ic)),0));
2432 lbl = newiTempLabel(NULL);
2434 emitcode("breq","L%05d",lbl->key);
2435 emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2437 emitcode("brne","L%05d",lbl->key);
2438 emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2440 emitcode("","L%05d:",lbl->key);
2441 } else if (size == 2) {
2442 emitcode("mov","r24,%s",aopGet(AOP(IC_LEFT(ic)),0));
2443 emitcode("mov","r25,%s",aopGet(AOP(IC_LEFT(ic)),1));
2444 emitcode(bopnames[bitop],"r24,%s",aopGet(AOP(IC_RIGHT(ic)),0));
2445 emitcode(bopnames[bitop],"r25,%s",aopGet(AOP(IC_RIGHT(ic)),1));
2446 emitcode("sbiw","r24,0");
2447 lbl = newiTempLabel(NULL);
2449 emitcode("breq","L%05d",lbl->key);
2450 emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2452 emitcode("brne","L%05d",lbl->key);
2453 emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2455 emitcode("","L%05d:",lbl->key);
2457 lbl = newiTempLabel(NULL);
2458 lbl1 = newiTempLabel(NULL);
2461 emitcode(bopnames[bitop],"%s,%s",
2462 aopGet(AOP(IC_LEFT(ic)),offset),
2463 aopGet(AOP(IC_RIGHT(ic)),offset));
2465 emitcode(bopnames[bitop],"%s,%s",
2466 aopGet(AOP(IC_RIGHT(ic)),offset),
2467 aopGet(AOP(IC_LEFT(ic)),offset));
2469 MOVR0(aopGet(AOP(IC_LEFT(ic)),offset));
2470 emitcode(bopnames[bitop],"r0,%s",aopGet(AOP(IC_RIGHT(ic)),offset));
2472 emitcode("brne","L%05d",lbl->key);
2476 if (IC_FALSE(ifx)) emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2477 else emitcode("rjmp","L%05d",lbl1->key);
2478 emitcode("","L%05d:",lbl->key);
2480 if (IC_TRUE(ifx)) emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2481 emitcode("","L%05d:",lbl1->key);
2488 /* result needs to go a register */
2489 samerl = sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic)));
2490 samerr = sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)));
2492 if (AOP_TYPE(right) == AOP_LIT) {
2493 unsigned int lit = (int) floatFromVal (AOP(right)->aopu.aop_lit);
2494 if (((lit >> (8*offset)) & 0xff) == 0) {
2495 if (bitop == AVR_AND) {
2496 aopPut(AOP(result),zero,offset++);
2498 } else if (bitop == AVR_OR) {
2500 aopPut(AOP(result),aopGet(AOP(left),offset),offset);
2507 if (AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT && (bitop == AVR_AND || bitop == AVR_OR)) {
2508 emitcode(bopnames_lit[bitop],"%s,%s(%d)",aopGet(AOP(IC_LEFT(ic)),offset),
2509 larray[offset],(int) floatFromVal (AOP(right)->aopu.aop_lit));
2511 emitcode(bopnames[bitop],"%s,%s",aopGet(AOP(IC_LEFT(ic)),offset),
2512 aopGet(AOP(IC_RIGHT(ic)),offset));
2514 } else if (samerr) {
2515 emitcode(bopnames[bitop],"%s,%s",aopGet(AOP(IC_RIGHT(ic)),offset),
2516 aopGet(AOP(IC_LEFT(ic)),offset));
2518 aopPut(AOP(IC_RESULT(ic)),aopGet(AOP(IC_LEFT(ic)),offset),offset);
2519 emitcode(bopnames[bitop],aopGet(AOP(IC_RESULT(ic)),offset),
2520 aopGet(AOP(IC_RIGHT(ic)),offset));
2525 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2526 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2527 freeAsmop(result,NULL,ic,TRUE);
2530 /*-----------------------------------------------------------------*/
2531 /* genAnd - code for and */
2532 /*-----------------------------------------------------------------*/
2533 static void genAnd (iCode *ic, iCode *ifx)
2535 genBitWise(ic,ifx,AVR_AND);
2538 /*-----------------------------------------------------------------*/
2539 /* genOr - code for or */
2540 /*-----------------------------------------------------------------*/
2541 static void genOr (iCode *ic, iCode *ifx)
2543 genBitWise(ic,ifx,AVR_OR);
2546 /*-----------------------------------------------------------------*/
2547 /* genXor - code for xclusive or */
2548 /*-----------------------------------------------------------------*/
2549 static void genXor (iCode *ic, iCode *ifx)
2551 genBitWise(ic,ifx,AVR_XOR);
2554 /*-----------------------------------------------------------------*/
2555 /* genInline - write the inline code out */
2556 /*-----------------------------------------------------------------*/
2557 static void genInline (iCode *ic)
2559 char buffer[MAX_INLINEASM];
2563 _G.inLine += (!options.asmpeep);
2564 strcpy(buffer,IC_INLINE(ic));
2566 /* emit each line as a code */
2585 /* emitcode("",buffer); */
2586 _G.inLine -= (!options.asmpeep);
2589 /*-----------------------------------------------------------------*/
2590 /* genRotC - rotate right/left with carry , lr = 1 rotate right */
2591 /*-----------------------------------------------------------------*/
2592 static void genRotC (iCode *ic, int lr)
2594 operand *left , *result ;
2595 int size, offset = 0;
2597 /* rotate right with carry */
2599 result=IC_RESULT(ic);
2600 aopOp (left,ic,FALSE);
2601 aopOp (result,ic,FALSE);
2603 /* move it to the result */
2604 size = AOP_SIZE(result);
2605 if (!sameRegs(AOP(left),AOP(result))) {
2609 aopGet(AOP(left),offset),
2613 size = AOP_SIZE(result);
2615 if (lr) offset = size - 1;
2619 emitcode ("sbrc","%s,%d",aopGet(AOP(result),offset),
2624 emitcode((lr ? "ror" : "rol"),"%s",aopGet(AOP(result),offset));
2628 freeAsmop(left,NULL,ic,TRUE);
2629 freeAsmop(result,NULL,ic,TRUE);
2632 /*-----------------------------------------------------------------*/
2633 /* genRRC - rotate right with carry */
2634 /*-----------------------------------------------------------------*/
2635 static void genRRC (iCode *ic)
2640 /*-----------------------------------------------------------------*/
2641 /* genRLC - generate code for rotate left with carry */
2642 /*-----------------------------------------------------------------*/
2643 static void genRLC (iCode *ic)
2648 /*-----------------------------------------------------------------*/
2649 /* genGetHbit - generates code get highest order bit */
2650 /*-----------------------------------------------------------------*/
2651 static void genGetHbit (iCode *ic)
2653 operand *left, *result;
2657 result=IC_RESULT(ic);
2658 aopOp (left,ic,FALSE);
2659 aopOp (result,ic,FALSE);
2661 size = AOP_SIZE(result);
2662 if (!sameRegs(AOP(left),AOP(result))) {
2663 emitcode("clr","%s",aopGet(AOP(result),size -1));
2664 emitcode("sbrc","%s,7",aopGet(AOP(left),size -1));
2665 emitcode("subi","%s,lo8(-1)",aopGet(AOP(result),size-1));
2667 emitcode("clr","r0");
2668 emitcode("sbrc","%s,7",aopGet(AOP(left),size-1));
2669 emitcode("subi","r0,lo8(-1)");
2670 aopPut(AOP(result),"r0",0);
2675 emitcode("clr",aopGet(AOP(result),offset++));
2677 freeAsmop(left,NULL,ic,TRUE);
2678 freeAsmop(result,NULL,ic,TRUE);
2681 /*-----------------------------------------------------------------*/
2682 /* genShiftLeftLit - shift left by a known amount */
2683 /*-----------------------------------------------------------------*/
2684 static void genShiftLeftLit (iCode *ic)
2686 operand *left,*right, *result;
2687 int size , shCount, offset =0;
2690 right = IC_RIGHT(ic);
2692 result = IC_RESULT(ic);
2694 aopOp(left,ic,FALSE);
2695 aopOp(result,ic,FALSE);
2696 size = AOP_SIZE(result);
2697 shCount = (int)floatFromVal (AOP(right)->aopu.aop_lit);
2699 if (shCount > (size*8 -1)) {
2700 while (size--) aopPut(AOP(result),zero,offset++);
2705 if (!sameRegs(AOP(left),AOP(result)))
2706 aopPut(AOP(result),aopGet(AOP(left),0),0);
2708 emitcode("swap","%s",aopGet(AOP(result),0));
2709 emitcode("andi","%s,0xf0");
2713 emitcode("add","%s,%s",aopGet(AOP(result),0),aopGet(AOP(result),0));
2717 emitcode("lsl","%s",aopGet(AOP(result),0));
2720 if (shCount >= 12) {
2721 aopPut(AOP(result),aopGet(AOP(left),0),1);
2722 aopPut(AOP(result),zero,0);
2723 emitcode("swap","%s",aopGet(AOP(result),1));
2724 emitcode("andi","%s,0xf0",aopGet(AOP(result),1));
2729 aopPut(AOP(result),aopGet(AOP(left),0),1);
2730 aopPut(AOP(result),zero,0);
2736 if (!sameRegs(AOP(left),AOP(result))) {
2737 aopPut(AOP(result),aopGet(AOP(left),0),0);
2738 aopPut(AOP(result),aopGet(AOP(left),1),1);
2740 emitcode("mov","r1,%s",aopGet(AOP(result),0));
2741 emitcode("swap","%s",aopGet(AOP(result),0));
2742 emitcode("andi","%s,0xf0",aopGet(AOP(result),0));
2743 emitcode("andi","r1,0x0f");
2744 emitcode("swap","%s",aopGet(AOP(result),1));
2745 emitcode("andi","%s,0xf0",aopGet(AOP(result),1));
2746 emitcode("or","%s,r1",aopGet(AOP(result),1));
2748 emitcode("lsl","%s",aopGet(AOP(result),0));
2749 emitcode("rol","%s",aopGet(AOP(result),1));
2752 if (!lByteZ && !sameRegs(AOP(result),AOP(left)) && shCount) {
2755 aopPut(AOP(result),aopGet(AOP(left),offset),offset);
2761 emitcode("lsl","%s",aopGet(AOP(result),1));
2763 emitcode("lsl","%s",aopGet(AOP(result),0));
2764 emitcode("rol","%s",aopGet(AOP(result),1));
2769 assert("shifting generic pointer ?\n");
2772 /* 32 bits we do only byte boundaries */
2773 if (shCount >= 24) {
2774 aopPut(AOP(result),aopGet(AOP(left),0),3);
2775 aopPut(AOP(result),zero,2);
2776 aopPut(AOP(result),zero,1);
2777 aopPut(AOP(result),zero,0);
2781 if (shCount >= 16) {
2782 aopPut(AOP(result),aopGet(AOP(left),0),3);
2783 aopPut(AOP(result),aopGet(AOP(left),1),2);
2784 aopPut(AOP(result),zero,1);
2785 aopPut(AOP(result),zero,0);
2790 aopPut(AOP(result),aopGet(AOP(left),0),3);
2791 aopPut(AOP(result),aopGet(AOP(left),1),2);
2792 aopPut(AOP(result),aopGet(AOP(left),2),1);
2793 aopPut(AOP(result),zero,0);
2797 if (!lByteZ && !sameRegs(AOP(left),AOP(right))) {
2800 aopPut(AOP(result),aopGet(AOP(left),offset),offset);
2804 size = AOP_SIZE(result);
2810 emitcode("lsl","%s",aopGet(AOP(result),0));
2811 emitcode("rol","%s",aopGet(AOP(result),1));
2812 emitcode("rol","%s",aopGet(AOP(result),2));
2813 emitcode("rol","%s",aopGet(AOP(result),3));
2818 emitcode("lsl","%s",aopGet(AOP(result),1));
2819 emitcode("rol","%s",aopGet(AOP(result),2));
2820 emitcode("rol","%s",aopGet(AOP(result),3));
2825 emitcode("lsl","%s",aopGet(AOP(result),2));
2826 emitcode("rol","%s",aopGet(AOP(result),3));
2831 emitcode("lsl","%s",aopGet(AOP(result),3));
2839 freeAsmop(left,NULL,ic,TRUE);
2840 freeAsmop(right,NULL,ic,TRUE);
2841 freeAsmop(result,NULL,ic,TRUE);
2844 /*-----------------------------------------------------------------*/
2845 /* genLeftShift - generates code for left shifting */
2846 /*-----------------------------------------------------------------*/
2847 static void genLeftShift (iCode *ic)
2849 operand *left,*right, *result;
2853 right = IC_RIGHT(ic);
2855 result = IC_RESULT(ic);
2857 aopOp(right,ic,FALSE);
2859 if (AOP_TYPE(right) == AOP_LIT) {
2860 genShiftLeftLit(ic);
2865 aopOp(left,ic,FALSE);
2866 aopOp(result,ic,FALSE);
2867 size = AOP_SIZE(result);
2869 if (AOP_SIZE(right) > 1) {
2870 if (isRegPair(AOP(right))) {
2871 emitcode("movw","r24,%s",aopGet(AOP(right),0));
2873 emitcode("mov","r24,%s",aopGet(AOP(right),0));
2874 emitcode("mov","r25,%s",aopGet(AOP(right),1));
2877 emitcode("mov","r24,%s",aopGet(AOP(right),0));
2879 if (!sameRegs(AOP(left),AOP(result))) {
2881 aopPut(AOP(result),aopGet(AOP(left),offset),offset);
2884 size = AOP_SIZE(result);
2886 tlbl = newiTempLabel(NULL);
2887 emitcode("","L%05d:",tlbl->key);
2890 if (offset) emitcode("rol","%s",aopGet(AOP(result),offset));
2891 else emitcode("lsl","%s",aopGet(AOP(result),0));
2894 if (AOP_SIZE(right) > 1) emitcode("sbiw","r24,1");
2895 else emitcode("dec","r24");
2896 emitcode("brne","L%05d",tlbl->key);
2898 freeAsmop(left,NULL,ic,TRUE);
2899 freeAsmop(right,NULL,ic,TRUE);
2900 freeAsmop(result,NULL,ic,TRUE);
2903 /*-----------------------------------------------------------------*/
2904 /* genShiftRightLit - generate for right shift with known count */
2905 /*-----------------------------------------------------------------*/
2906 static void genShiftRightLit (iCode *ic)
2908 operand *left = IC_LEFT(ic)
2909 ,*right= IC_RIGHT(ic)
2910 ,*result=IC_RESULT(ic);
2911 int size , shCount, offset =0;
2913 sym_link *letype = getSpec(operandType(left));
2914 int sign = !SPEC_USIGN(letype);
2916 right = IC_RIGHT(ic);
2918 result = IC_RESULT(ic);
2920 aopOp(left,ic,FALSE);
2921 aopOp(result,ic,FALSE);
2922 size = AOP_SIZE(result);
2923 shCount = (int)floatFromVal (AOP(right)->aopu.aop_lit);
2925 /* if signed then give up and use a loop to shift */
2928 if (!sameRegs(AOP(left),AOP(result))) {
2930 aopPut(AOP(result),aopGet(AOP(left),offset),offset);
2933 size = size = AOP_SIZE(result);
2936 /* be as economical as possible */
2941 size = AOP_SIZE(result);
2943 if (offset == (size-1))
2944 emitcode("asr","%s",aopGet(AOP(result),offset));
2946 emitcode("lsr","%s",aopGet(AOP(result),offset));
2951 emitcode("ldi","r24,lo8(%d)",shCount);
2952 tlbl = newiTempLabel(NULL);
2953 emitcode("","L%05d:",tlbl->key);
2956 if (offset == (size-1)) emitcode("asr","%s",aopGet(AOP(result),offset));
2957 else emitcode("lsr","%s",aopGet(AOP(result),offset));
2960 emitcode("dec","r24");
2961 emitcode("brne","L%05d",tlbl->key);
2965 if (shCount > (size*8 -1)) {
2966 while (size--) aopPut(AOP(result),zero,offset++);
2969 /* for unsigned we can much more efficient */
2972 if (!sameRegs(AOP(left),AOP(result)))
2973 aopPut(AOP(result),aopGet(AOP(left),0),0);
2975 emitcode("swap","%s",aopGet(AOP(result),0));
2976 emitcode("andi","%s,0x0f");
2980 emitcode("lsr","%s",aopGet(AOP(result),0));
2983 if (shCount >= 12) {
2984 aopPut(AOP(result),aopGet(AOP(left),1),0);
2985 aopPut(AOP(result),zero,1);
2986 emitcode("swap","%s",aopGet(AOP(result),0));
2987 emitcode("andi","%s,0x0f",aopGet(AOP(result),0));
2992 aopPut(AOP(result),aopGet(AOP(left),1),0);
2993 aopPut(AOP(result),zero,1);
2999 if (!sameRegs(AOP(left),AOP(result))) {
3000 aopPut(AOP(result),aopGet(AOP(left),0),0);
3001 aopPut(AOP(result),aopGet(AOP(left),1),1);
3003 emitcode("mov","r1,%s",aopGet(AOP(result),1));
3004 emitcode("swap","%s",aopGet(AOP(result),0));
3005 emitcode("andi","%s,0x0f",aopGet(AOP(result),0));
3006 emitcode("andi","r1,0xf0");
3007 emitcode("or","%s,r1",aopGet(AOP(result),0));
3008 emitcode("swap","%s",aopGet(AOP(result),1));
3009 emitcode("andi","%s,0x0f",aopGet(AOP(result),1));
3011 emitcode("lsr","%s",aopGet(AOP(result),1));
3012 emitcode("ror","%s",aopGet(AOP(result),0));
3016 if (!hByteZ && !sameRegs(AOP(result),AOP(left)) && shCount) {
3019 aopPut(AOP(result),aopGet(AOP(left),offset),offset);
3025 emitcode("lsr","%s",aopGet(AOP(result),0));
3027 emitcode("lsr","%s",aopGet(AOP(result),1));
3028 emitcode("ror","%s",aopGet(AOP(result),0));
3034 assert("shifting generic pointer ?\n");
3037 /* 32 bits we do only byte boundaries */
3038 if (shCount >= 24) {
3039 aopPut(AOP(result),aopGet(AOP(left),3),0);
3040 aopPut(AOP(result),zero,1);
3041 aopPut(AOP(result),zero,2);
3042 aopPut(AOP(result),zero,3);
3046 if (shCount >= 16) {
3047 aopPut(AOP(result),aopGet(AOP(left),3),1);
3048 aopPut(AOP(result),aopGet(AOP(left),2),0);
3049 aopPut(AOP(result),zero,2);
3050 aopPut(AOP(result),zero,3);
3055 aopPut(AOP(result),aopGet(AOP(left),1),0);
3056 aopPut(AOP(result),aopGet(AOP(left),2),1);
3057 aopPut(AOP(result),aopGet(AOP(left),3),2);
3058 aopPut(AOP(result),zero,3);
3062 if (!hByteZ && !sameRegs(AOP(left),AOP(right))) {
3065 aopPut(AOP(result),aopGet(AOP(left),offset),offset);
3069 size = AOP_SIZE(result);
3075 emitcode("lsr","%s",aopGet(AOP(result),3));
3076 emitcode("ror","%s",aopGet(AOP(result),2));
3077 emitcode("ror","%s",aopGet(AOP(result),1));
3078 emitcode("ror","%s",aopGet(AOP(result),0));
3083 emitcode("lsr","%s",aopGet(AOP(result),2));
3084 emitcode("ror","%s",aopGet(AOP(result),1));
3085 emitcode("ror","%s",aopGet(AOP(result),0));
3090 emitcode("lsr","%s",aopGet(AOP(result),1));
3091 emitcode("ror","%s",aopGet(AOP(result),0));
3096 emitcode("lsr","%s",aopGet(AOP(result),0));
3103 freeAsmop(left,NULL,ic,TRUE);
3104 freeAsmop(right,NULL,ic,TRUE);
3105 freeAsmop(result,NULL,ic,TRUE);
3108 /*-----------------------------------------------------------------*/
3109 /* genRightShift - generate code for right shifting */
3110 /*-----------------------------------------------------------------*/
3111 static void genRightShift (iCode *ic)
3113 operand *right, *left, *result;
3116 int sign = 0, first =1;
3119 aopOp(right=IC_RIGHT(ic),ic,FALSE);
3120 if (AOP_TYPE(right) == AOP_LIT) {
3121 genShiftRightLit(ic);
3125 if (AOP_SIZE(right) > 1) {
3126 if (isRegPair(AOP(right))) {
3127 emitcode("movw","r24,%s",aopGet(AOP(right),0));
3129 emitcode("mov","r24,%s",aopGet(AOP(right),0));
3130 emitcode("mov","r25,%s",aopGet(AOP(right),1));
3133 emitcode("mov","r24,%s",aopGet(AOP(right),0));
3135 aopOp(left=IC_LEFT(ic),ic,FALSE);
3136 aopOp(result=IC_RESULT(ic),ic,FALSE);
3137 size = AOP_SIZE(result);
3138 tlbl = newiTempLabel(NULL);
3139 emitcode("","L%05d:",tlbl->key);
3141 letype = getSpec(operandType(left));
3142 sign = !SPEC_USIGN(letype);
3143 if (!sameRegs(AOP(left),AOP(result))) {
3145 aopPut(AOP(result),aopGet(AOP(left),offset),offset);
3148 size = AOP_SIZE(result);
3150 size = AOP_SIZE(result);
3153 if (sign) emitcode("asr","%s",aopGet(AOP(result),offset));
3154 else emitcode("lsr","%s",aopGet(AOP(result),offset));
3157 else emitcode("ror","%s",aopGet(AOP(result),offset));
3160 if (AOP_SIZE(right) > 1) emitcode("sbiw","r24,1");
3161 else emitcode("dec","r24");
3162 emitcode("brne","L%05d",tlbl->key);
3164 freeAsmop(left,NULL,ic,TRUE);
3165 freeAsmop(result,NULL,ic,TRUE);
3168 /*-----------------------------------------------------------------*/
3169 /* R0Rsh - shift right r0 by known count */
3170 /*-----------------------------------------------------------------*/
3171 static void R0Rsh (int shCount)
3173 shCount &= 0x0007; // shCount : 0..7
3178 emitcode("lsr","r0");
3181 emitcode("lsr","r0");
3182 emitcode("lsr","r0");
3185 emitcode("swap","r0");
3186 emitcode("lsl","r0");
3189 emitcode("swap","r0");
3192 emitcode("swap","r0");
3193 emitcode("lsr","r0");
3196 emitcode("swap","r0");
3197 emitcode("lsr","r0");
3198 emitcode("lsr","r0");
3201 emitcode("swap","r0");
3202 emitcode("lsr","r0");
3203 emitcode("lsr","r0");
3204 emitcode("lsr","r0");
3209 /*-----------------------------------------------------------------*/
3210 /* genUnpackBits - generates code for unpacking bits */
3211 /*-----------------------------------------------------------------*/
3212 static void genUnpackBits (operand *result, char *rname, int ptype)
3219 etype = getSpec(operandType(result));
3221 /* read the first byte */
3228 emitcode("ld","r0,%s+",rname);
3232 emitcode("ldm","r0,%s+",rname);
3236 emitcode("call","__gptrget_pi");
3240 /* if we have bitdisplacement then it fits */
3241 /* into this byte completely or if length is */
3242 /* less than a byte */
3243 if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8)) {
3245 /* shift right r0 */
3247 emitcode("andi","r0,0x%02x",
3248 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
3250 aopPut(AOP(result),"r0",offset);
3254 /* bit field did not fit in a byte */
3255 rlen = SPEC_BLEN(etype) - 8;
3256 aopPut(AOP(result),"a",offset++);
3265 emitcode("ld","r0,%s+",rname);
3269 emitcode("ldm","r0,%s+",rname);
3273 emitcode("lcall","__gptrget_pi");
3278 /* if we are done */
3282 aopPut(AOP(result),"r0",offset++);
3287 emitcode("andi","r0,#0x%02x",((unsigned char)-1)>>(-rlen));
3288 aopPut(AOP(result),"r0",offset);
3295 /*-----------------------------------------------------------------*/
3296 /* genDataPointerGet - generates code when ptr offset is known */
3297 /*-----------------------------------------------------------------*/
3298 static void genDataPointerGet (operand *left,
3304 int size , offset = 0;
3305 aopOp(result,ic,TRUE);
3307 /* get the string representation of the name */
3308 l = aopGet(AOP(left),0);
3309 size = AOP_SIZE(result);
3312 sprintf(buffer,"(%s + %d)",l+1,offset);
3314 sprintf(buffer,"%s",l+1);
3315 emitcode("lds","%s,%s",aopGet(AOP(result),offset++),buffer);
3318 freeAsmop(left,NULL,ic,TRUE);
3319 freeAsmop(result,NULL,ic,TRUE);
3322 /*-----------------------------------------------------------------*/
3323 /* genNearPointerGet - emitcode for near pointer fetch */
3324 /*-----------------------------------------------------------------*/
3325 static void genNearPointerGet (operand *left,
3332 sym_link *rtype, *retype;
3333 sym_link *ltype = operandType(left);
3336 rtype = operandType(result);
3337 retype= getSpec(rtype);
3339 aopOp(left,ic,FALSE);
3341 /* if left is rematerialisable and
3342 result is not bit variable type and
3343 the left is pointer to data space i.e
3344 lower 128 bytes of space */
3345 if (AOP_TYPE(left) == AOP_IMMD &&
3346 !IS_BITVAR(retype) &&
3347 DCL_TYPE(ltype) == POINTER) {
3348 genDataPointerGet (left,result,ic);
3352 /* if the value is already in a pointer register
3353 then don't need anything more */
3354 if (!AOP_INPREG(AOP(left))) {
3355 /* otherwise get a free pointer register */
3357 preg = getFreePtr(ic,&aop,FALSE,0);
3358 emitcode("mov","%s,%s",
3360 aopGet(AOP(left),0));
3361 rname = preg->name ;
3363 rname = aopGet(AOP(left),0);
3365 freeAsmop(left,NULL,ic,TRUE);
3366 aopOp (result,ic,FALSE);
3368 /* if bitfield then unpack the bits */
3369 if (IS_BITVAR(retype))
3370 genUnpackBits (result,rname,POINTER);
3372 /* we have can just get the values */
3373 int size = AOP_SIZE(result);
3377 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
3379 emitcode("mov","a,@%s",rname);
3380 aopPut(AOP(result),"a",offset);
3382 sprintf(buffer,"@%s",rname);
3383 aopPut(AOP(result),buffer,offset);
3387 emitcode("inc","%s",rname);
3391 /* now some housekeeping stuff */
3393 /* we had to allocate for this iCode */
3394 freeAsmop(NULL,aop,ic,TRUE);
3396 /* we did not allocate which means left
3397 already in a pointer register, then
3398 if size > 0 && this could be used again
3399 we have to point it back to where it
3401 if (AOP_SIZE(result) > 1 &&
3402 !OP_SYMBOL(left)->remat &&
3403 ( OP_SYMBOL(left)->liveTo > ic->seq ||
3405 int size = AOP_SIZE(result) - 1;
3407 emitcode("dec","%s",rname);
3412 freeAsmop(result,NULL,ic,TRUE);
3416 /*-----------------------------------------------------------------*/
3417 /* genPagedPointerGet - emitcode for paged pointer fetch */
3418 /*-----------------------------------------------------------------*/
3419 static void genPagedPointerGet (operand *left,
3426 sym_link *rtype, *retype;
3428 rtype = operandType(result);
3429 retype= getSpec(rtype);
3431 aopOp(left,ic,FALSE);
3433 /* if the value is already in a pointer register
3434 then don't need anything more */
3435 if (!AOP_INPREG(AOP(left))) {
3436 /* otherwise get a free pointer register */
3438 preg = getFreePtr(ic,&aop,FALSE,0);
3439 emitcode("mov","%s,%s",
3441 aopGet(AOP(left),0));
3442 rname = preg->name ;
3444 rname = aopGet(AOP(left),0);
3446 freeAsmop(left,NULL,ic,TRUE);
3447 aopOp (result,ic,FALSE);
3449 /* if bitfield then unpack the bits */
3450 if (IS_BITVAR(retype))
3451 genUnpackBits (result,rname,PPOINTER);
3453 /* we have can just get the values */
3454 int size = AOP_SIZE(result);
3459 emitcode("movx","a,@%s",rname);
3460 aopPut(AOP(result),"a",offset);
3465 emitcode("inc","%s",rname);
3469 /* now some housekeeping stuff */
3471 /* we had to allocate for this iCode */
3472 freeAsmop(NULL,aop,ic,TRUE);
3474 /* we did not allocate which means left
3475 already in a pointer register, then
3476 if size > 0 && this could be used again
3477 we have to point it back to where it
3479 if (AOP_SIZE(result) > 1 &&
3480 !OP_SYMBOL(left)->remat &&
3481 ( OP_SYMBOL(left)->liveTo > ic->seq ||
3483 int size = AOP_SIZE(result) - 1;
3485 emitcode("dec","%s",rname);
3490 freeAsmop(result,NULL,ic,TRUE);
3495 /*-----------------------------------------------------------------*/
3496 /* genFarPointerGet - gget value from far space */
3497 /*-----------------------------------------------------------------*/
3498 static void genFarPointerGet (operand *left,
3499 operand *result, iCode *ic)
3502 sym_link *retype = getSpec(operandType(result));
3504 aopOp(left,ic,FALSE);
3506 /* if the operand is already in dptr
3507 then we do nothing else we move the value to dptr */
3508 if (AOP_TYPE(left) != AOP_STR) {
3509 /* if this is remateriazable */
3510 if (AOP_TYPE(left) == AOP_IMMD)
3511 emitcode("mov","dptr,%s",aopGet(AOP(left),0));
3512 else { /* we need to get it byte by byte */
3513 emitcode("mov","dpl,%s",aopGet(AOP(left),0));
3514 emitcode("mov","dph,%s",aopGet(AOP(left),1));
3515 if (options.model == MODEL_FLAT24)
3517 emitcode("mov", "dpx,%s",aopGet(AOP(left),2));
3521 /* so dptr know contains the address */
3522 freeAsmop(left,NULL,ic,TRUE);
3523 aopOp(result,ic,FALSE);
3525 /* if bit then unpack */
3526 if (IS_BITVAR(retype))
3527 genUnpackBits(result,"dptr",FPOINTER);
3529 size = AOP_SIZE(result);
3533 emitcode("movx","a,@dptr");
3534 aopPut(AOP(result),"a",offset++);
3536 emitcode("inc","dptr");
3540 freeAsmop(result,NULL,ic,TRUE);
3543 /*-----------------------------------------------------------------*/
3544 /* emitcodePointerGet - gget value from code space */
3545 /*-----------------------------------------------------------------*/
3546 static void emitcodePointerGet (operand *left,
3547 operand *result, iCode *ic)
3550 sym_link *retype = getSpec(operandType(result));
3552 aopOp(left,ic,FALSE);
3554 /* if the operand is already in dptr
3555 then we do nothing else we move the value to dptr */
3556 if (AOP_TYPE(left) != AOP_STR) {
3557 /* if this is remateriazable */
3558 if (AOP_TYPE(left) == AOP_IMMD)
3559 emitcode("mov","dptr,%s",aopGet(AOP(left),0));
3560 else { /* we need to get it byte by byte */
3561 emitcode("mov","dpl,%s",aopGet(AOP(left),0));
3562 emitcode("mov","dph,%s",aopGet(AOP(left),1));
3563 if (options.model == MODEL_FLAT24)
3565 emitcode("mov", "dpx,%s",aopGet(AOP(left),2));
3569 /* so dptr know contains the address */
3570 freeAsmop(left,NULL,ic,TRUE);
3571 aopOp(result,ic,FALSE);
3573 /* if bit then unpack */
3574 if (IS_BITVAR(retype))
3575 genUnpackBits(result,"dptr",CPOINTER);
3577 size = AOP_SIZE(result);
3581 emitcode("clr","a");
3582 emitcode("movc","a,@a+dptr");
3583 aopPut(AOP(result),"a",offset++);
3585 emitcode("inc","dptr");
3589 freeAsmop(result,NULL,ic,TRUE);
3592 /*-----------------------------------------------------------------*/
3593 /* genGenPointerGet - gget value from generic pointer space */
3594 /*-----------------------------------------------------------------*/
3595 static void genGenPointerGet (operand *left,
3596 operand *result, iCode *ic)
3599 sym_link *retype = getSpec(operandType(result));
3601 aopOp(left,ic,FALSE);
3603 /* if the operand is already in dptr
3604 then we do nothing else we move the value to dptr */
3605 if (AOP_TYPE(left) != AOP_STR) {
3606 /* if this is remateriazable */
3607 if (AOP_TYPE(left) == AOP_IMMD) {
3608 emitcode("mov","dptr,%s",aopGet(AOP(left),0));
3609 emitcode("mov","b,#%d",pointerCode(retype));
3611 else { /* we need to get it byte by byte */
3612 emitcode("mov","dpl,%s",aopGet(AOP(left),0));
3613 emitcode("mov","dph,%s",aopGet(AOP(left),1));
3614 if (options.model == MODEL_FLAT24)
3616 emitcode("mov", "dpx,%s",aopGet(AOP(left),2));
3617 emitcode("mov","b,%s",aopGet(AOP(left),3));
3621 emitcode("mov","b,%s",aopGet(AOP(left),2));
3625 /* so dptr know contains the address */
3626 freeAsmop(left,NULL,ic,TRUE);
3627 aopOp(result,ic,FALSE);
3629 /* if bit then unpack */
3630 if (IS_BITVAR(retype))
3631 genUnpackBits(result,"dptr",GPOINTER);
3633 size = AOP_SIZE(result);
3637 emitcode("lcall","__gptrget");
3638 aopPut(AOP(result),"a",offset++);
3640 emitcode("inc","dptr");
3644 freeAsmop(result,NULL,ic,TRUE);
3647 /*-----------------------------------------------------------------*/
3648 /* genPointerGet - generate code for pointer get */
3649 /*-----------------------------------------------------------------*/
3650 static void genPointerGet (iCode *ic)
3652 operand *left, *result ;
3653 sym_link *type, *etype;
3657 result = IC_RESULT(ic) ;
3659 /* depending on the type of pointer we need to
3660 move it to the correct pointer register */
3661 type = operandType(left);
3662 etype = getSpec(type);
3663 /* if left is of type of pointer then it is simple */
3664 if (IS_PTR(type) && !IS_FUNC(type->next))
3665 p_type = DCL_TYPE(type);
3667 /* we have to go by the storage class */
3668 p_type = PTR_TYPE(SPEC_OCLS(etype));
3670 /* if (SPEC_OCLS(etype)->codesp ) { */
3671 /* p_type = CPOINTER ; */
3674 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
3675 /* p_type = FPOINTER ; */
3677 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
3678 /* p_type = PPOINTER; */
3680 /* if (SPEC_OCLS(etype) == idata ) */
3681 /* p_type = IPOINTER; */
3683 /* p_type = POINTER ; */
3686 /* now that we have the pointer type we assign
3687 the pointer values */
3692 genNearPointerGet (left,result,ic);
3696 genPagedPointerGet(left,result,ic);
3700 genFarPointerGet (left,result,ic);
3704 emitcodePointerGet (left,result,ic);
3708 genGenPointerGet (left,result,ic);
3714 /*-----------------------------------------------------------------*/
3715 /* genPackBits - generates code for packed bit storage */
3716 /*-----------------------------------------------------------------*/
3717 static void genPackBits (sym_link *etype ,
3719 char *rname, int p_type)
3727 blen = SPEC_BLEN(etype);
3728 bstr = SPEC_BSTR(etype);
3730 l = aopGet(AOP(right),offset++);
3733 /* if the bit lenth is less than or */
3734 /* it exactly fits a byte then */
3735 if (SPEC_BLEN(etype) <= 8 ) {
3736 shCount = SPEC_BSTR(etype) ;
3738 /* shift left acc */
3741 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
3746 emitcode ("mov","b,a");
3747 emitcode("mov","a,@%s",rname);
3751 emitcode ("mov","b,a");
3752 emitcode("movx","a,@dptr");
3756 emitcode ("push","b");
3757 emitcode ("push","acc");
3758 emitcode ("lcall","__gptrget");
3759 emitcode ("pop","b");
3763 emitcode ("anl","a,#0x%02x",(unsigned char)
3764 ((unsigned char)(0xFF << (blen+bstr)) |
3765 (unsigned char)(0xFF >> (8-bstr)) ) );
3766 emitcode ("orl","a,b");
3767 if (p_type == GPOINTER)
3768 emitcode("pop","b");
3774 emitcode("mov","@%s,a",rname);
3778 emitcode("movx","@dptr,a");
3782 emitcode("lcall","__gptrput");
3787 if ( SPEC_BLEN(etype) <= 8 )
3790 emitcode("inc","%s",rname);
3791 rLen = SPEC_BLEN(etype) ;
3793 /* now generate for lengths greater than one byte */
3796 l = aopGet(AOP(right),offset++);
3806 emitcode("mov","@%s,a",rname);
3808 emitcode("mov","@%s,%s",rname,l);
3813 emitcode("movx","@dptr,a");
3818 emitcode("lcall","__gptrput");
3821 emitcode ("inc","%s",rname);
3826 /* last last was not complete */
3828 /* save the byte & read byte */
3831 emitcode ("mov","b,a");
3832 emitcode("mov","a,@%s",rname);
3836 emitcode ("mov","b,a");
3837 emitcode("movx","a,@dptr");
3841 emitcode ("push","b");
3842 emitcode ("push","acc");
3843 emitcode ("lcall","__gptrget");
3844 emitcode ("pop","b");
3848 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
3849 emitcode ("orl","a,b");
3852 if (p_type == GPOINTER)
3853 emitcode("pop","b");
3858 emitcode("mov","@%s,a",rname);
3862 emitcode("movx","@dptr,a");
3866 emitcode("lcall","__gptrput");
3870 /*-----------------------------------------------------------------*/
3871 /* genDataPointerSet - remat pointer to data space */
3872 /*-----------------------------------------------------------------*/
3873 static void genDataPointerSet(operand *right,
3877 int size, offset = 0 ;
3878 char *l, buffer[256];
3880 aopOp(right,ic,FALSE);
3882 l = aopGet(AOP(result),0);
3883 size = AOP_SIZE(right);
3886 sprintf(buffer,"(%s + %d)",l+1,offset);
3888 sprintf(buffer,"%s",l+1);
3889 emitcode("mov","%s,%s",buffer,
3890 aopGet(AOP(right),offset++));
3893 freeAsmop(right,NULL,ic,TRUE);
3894 freeAsmop(result,NULL,ic,TRUE);
3897 /*-----------------------------------------------------------------*/
3898 /* genNearPointerSet - emitcode for near pointer put */
3899 /*-----------------------------------------------------------------*/
3900 static void genNearPointerSet (operand *right,
3908 sym_link *ptype = operandType(result);
3910 retype= getSpec(operandType(right));
3912 aopOp(result,ic,FALSE);
3914 /* if the result is rematerializable &
3915 in data space & not a bit variable */
3916 if (AOP_TYPE(result) == AOP_IMMD &&
3917 DCL_TYPE(ptype) == POINTER &&
3918 !IS_BITVAR(retype)) {
3919 genDataPointerSet (right,result,ic);
3923 /* if the value is already in a pointer register
3924 then don't need anything more */
3925 if (!AOP_INPREG(AOP(result))) {
3926 /* otherwise get a free pointer register */
3928 preg = getFreePtr(ic,&aop,FALSE,0);
3929 emitcode("mov","%s,%s",
3931 aopGet(AOP(result),0));
3932 rname = preg->name ;
3934 rname = aopGet(AOP(result),0);
3936 freeAsmop(result,NULL,ic,TRUE);
3937 aopOp (right,ic,FALSE);
3939 /* if bitfield then unpack the bits */
3940 if (IS_BITVAR(retype))
3941 genPackBits (retype,right,rname,POINTER);
3943 /* we have can just get the values */
3944 int size = AOP_SIZE(right);
3948 l = aopGet(AOP(right),offset);
3951 emitcode("mov","@%s,a",rname);
3953 emitcode("mov","@%s,%s",rname,l);
3955 emitcode("inc","%s",rname);
3960 /* now some housekeeping stuff */
3962 /* we had to allocate for this iCode */
3963 freeAsmop(NULL,aop,ic,TRUE);
3965 /* we did not allocate which means left
3966 already in a pointer register, then
3967 if size > 0 && this could be used again
3968 we have to point it back to where it
3970 if (AOP_SIZE(right) > 1 &&
3971 !OP_SYMBOL(result)->remat &&
3972 ( OP_SYMBOL(result)->liveTo > ic->seq ||
3974 int size = AOP_SIZE(right) - 1;
3976 emitcode("dec","%s",rname);
3981 freeAsmop(right,NULL,ic,TRUE);
3986 /*-----------------------------------------------------------------*/
3987 /* genPagedPointerSet - emitcode for Paged pointer put */
3988 /*-----------------------------------------------------------------*/
3989 static void genPagedPointerSet (operand *right,
3998 retype= getSpec(operandType(right));
4000 aopOp(result,ic,FALSE);
4002 /* if the value is already in a pointer register
4003 then don't need anything more */
4004 if (!AOP_INPREG(AOP(result))) {
4005 /* otherwise get a free pointer register */
4007 preg = getFreePtr(ic,&aop,FALSE,0);
4008 emitcode("mov","%s,%s",
4010 aopGet(AOP(result),0));
4011 rname = preg->name ;
4013 rname = aopGet(AOP(result),0);
4015 freeAsmop(result,NULL,ic,TRUE);
4016 aopOp (right,ic,FALSE);
4018 /* if bitfield then unpack the bits */
4019 if (IS_BITVAR(retype))
4020 genPackBits (retype,right,rname,PPOINTER);
4022 /* we have can just get the values */
4023 int size = AOP_SIZE(right);
4027 l = aopGet(AOP(right),offset);
4030 emitcode("movx","@%s,a",rname);
4033 emitcode("inc","%s",rname);
4039 /* now some housekeeping stuff */
4041 /* we had to allocate for this iCode */
4042 freeAsmop(NULL,aop,ic,TRUE);
4044 /* we did not allocate which means left
4045 already in a pointer register, then
4046 if size > 0 && this could be used again
4047 we have to point it back to where it
4049 if (AOP_SIZE(right) > 1 &&
4050 !OP_SYMBOL(result)->remat &&
4051 ( OP_SYMBOL(result)->liveTo > ic->seq ||
4053 int size = AOP_SIZE(right) - 1;
4055 emitcode("dec","%s",rname);
4060 freeAsmop(right,NULL,ic,TRUE);
4065 /*-----------------------------------------------------------------*/
4066 /* genFarPointerSet - set value from far space */
4067 /*-----------------------------------------------------------------*/
4068 static void genFarPointerSet (operand *right,
4069 operand *result, iCode *ic)
4072 sym_link *retype = getSpec(operandType(right));
4074 aopOp(result,ic,FALSE);
4076 /* if the operand is already in dptr
4077 then we do nothing else we move the value to dptr */
4078 if (AOP_TYPE(result) != AOP_STR) {
4079 /* if this is remateriazable */
4080 if (AOP_TYPE(result) == AOP_IMMD)
4081 emitcode("mov","dptr,%s",aopGet(AOP(result),0));
4082 else { /* we need to get it byte by byte */
4083 emitcode("mov","dpl,%s",aopGet(AOP(result),0));
4084 emitcode("mov","dph,%s",aopGet(AOP(result),1));
4085 if (options.model == MODEL_FLAT24)
4087 emitcode("mov", "dpx,%s",aopGet(AOP(result),2));
4091 /* so dptr know contains the address */
4092 freeAsmop(result,NULL,ic,TRUE);
4093 aopOp(right,ic,FALSE);
4095 /* if bit then unpack */
4096 if (IS_BITVAR(retype))
4097 genPackBits(retype,right,"dptr",FPOINTER);
4099 size = AOP_SIZE(right);
4103 char *l = aopGet(AOP(right),offset++);
4105 emitcode("movx","@dptr,a");
4107 emitcode("inc","dptr");
4111 freeAsmop(right,NULL,ic,TRUE);
4114 /*-----------------------------------------------------------------*/
4115 /* genGenPointerSet - set value from generic pointer space */
4116 /*-----------------------------------------------------------------*/
4117 static void genGenPointerSet (operand *right,
4118 operand *result, iCode *ic)
4121 sym_link *retype = getSpec(operandType(right));
4123 aopOp(result,ic,FALSE);
4125 /* if the operand is already in dptr
4126 then we do nothing else we move the value to dptr */
4127 if (AOP_TYPE(result) != AOP_STR) {
4128 /* if this is remateriazable */
4129 if (AOP_TYPE(result) == AOP_IMMD) {
4130 emitcode("mov","dptr,%s",aopGet(AOP(result),0));
4131 emitcode("mov","b,%s + 1",aopGet(AOP(result),0));
4133 else { /* we need to get it byte by byte */
4134 emitcode("mov","dpl,%s",aopGet(AOP(result),0));
4135 emitcode("mov","dph,%s",aopGet(AOP(result),1));
4136 if (options.model == MODEL_FLAT24)
4138 emitcode("mov", "dpx,%s",aopGet(AOP(result),2));
4139 emitcode("mov","b,%s",aopGet(AOP(result),3));
4143 emitcode("mov","b,%s",aopGet(AOP(result),2));
4147 /* so dptr know contains the address */
4148 freeAsmop(result,NULL,ic,TRUE);
4149 aopOp(right,ic,FALSE);
4151 /* if bit then unpack */
4152 if (IS_BITVAR(retype))
4153 genPackBits(retype,right,"dptr",GPOINTER);
4155 size = AOP_SIZE(right);
4159 char *l = aopGet(AOP(right),offset++);
4161 emitcode("lcall","__gptrput");
4163 emitcode("inc","dptr");
4167 freeAsmop(right,NULL,ic,TRUE);
4170 /*-----------------------------------------------------------------*/
4171 /* genPointerSet - stores the value into a pointer location */
4172 /*-----------------------------------------------------------------*/
4173 static void genPointerSet (iCode *ic)
4175 operand *right, *result ;
4176 sym_link *type, *etype;
4179 right = IC_RIGHT(ic);
4180 result = IC_RESULT(ic) ;
4182 /* depending on the type of pointer we need to
4183 move it to the correct pointer register */
4184 type = operandType(result);
4185 etype = getSpec(type);
4186 /* if left is of type of pointer then it is simple */
4187 if (IS_PTR(type) && !IS_FUNC(type->next)) {
4188 p_type = DCL_TYPE(type);
4191 /* we have to go by the storage class */
4192 p_type = PTR_TYPE(SPEC_OCLS(etype));
4194 /* if (SPEC_OCLS(etype)->codesp ) { */
4195 /* p_type = CPOINTER ; */
4198 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
4199 /* p_type = FPOINTER ; */
4201 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
4202 /* p_type = PPOINTER ; */
4204 /* if (SPEC_OCLS(etype) == idata ) */
4205 /* p_type = IPOINTER ; */
4207 /* p_type = POINTER ; */
4210 /* now that we have the pointer type we assign
4211 the pointer values */
4216 genNearPointerSet (right,result,ic);
4220 genPagedPointerSet (right,result,ic);
4224 genFarPointerSet (right,result,ic);
4228 genGenPointerSet (right,result,ic);
4234 /*-----------------------------------------------------------------*/
4235 /* genIfx - generate code for Ifx statement */
4236 /*-----------------------------------------------------------------*/
4237 static void genIfx (iCode *ic, iCode *popIc)
4239 operand *cond = IC_COND(ic);
4242 aopOp(cond,ic,FALSE);
4244 /* get the value into acc */
4245 if (AOP_TYPE(cond) != AOP_CRY)
4246 toBoolean(cond,"",0);
4249 /* the result is now in the accumulator */
4250 freeAsmop(cond,NULL,ic,TRUE);
4252 /* if there was something to be popped then do it */
4256 /* if the condition is a bit variable */
4257 /* if (isbit && IS_ITEMP(cond) && SPIL_LOC(cond)) { */
4258 /* // genIfxJump(ic,SPIL_LOC(cond)->rname); */
4261 /* if (isbit && !IS_ITEMP(cond)) */
4262 /* // genIfxJump(ic,OP_SYMBOL(cond)->rname); */
4264 /* // genIfxJump(ic,"a"); */
4269 /*-----------------------------------------------------------------*/
4270 /* genAddrOf - generates code for address of */
4271 /*-----------------------------------------------------------------*/
4272 static void genAddrOf (iCode *ic)
4274 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
4277 aopOp(IC_RESULT(ic),ic,FALSE);
4279 /* if the operand is on the stack then we
4280 need to get the stack offset of this
4283 /* if it has an offset then we need to compute
4286 emitcode("mov","a,_bp");
4287 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
4288 aopPut(AOP(IC_RESULT(ic)),"a",0);
4290 /* we can just move _bp */
4291 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
4293 /* fill the result with zero */
4294 size = AOP_SIZE(IC_RESULT(ic)) - 1;
4297 if (options.stack10bit && size < (FPTRSIZE - 1))
4300 "*** warning: pointer to stack var truncated.\n");
4307 if (options.stack10bit && offset == 2)
4309 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
4313 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
4320 /* object not on stack then we need the name */
4321 size = AOP_SIZE(IC_RESULT(ic));
4325 char s[SDCC_NAME_MAX];
4327 sprintf(s,"#(%s >> %d)",
4331 sprintf(s,"#%s",sym->rname);
4332 aopPut(AOP(IC_RESULT(ic)),s,offset++);
4336 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
4340 /*-----------------------------------------------------------------*/
4341 /* genFarFarAssign - assignment when both are in far space */
4342 /*-----------------------------------------------------------------*/
4343 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
4345 int size = AOP_SIZE(right);
4348 /* first push the right side on to the stack */
4350 l = aopGet(AOP(right),offset++);
4352 emitcode ("push","acc");
4355 freeAsmop(right,NULL,ic,FALSE);
4356 /* now assign DPTR to result */
4357 aopOp(result,ic,FALSE);
4358 size = AOP_SIZE(result);
4360 emitcode ("pop","acc");
4361 aopPut(AOP(result),"a",--offset);
4363 freeAsmop(result,NULL,ic,FALSE);
4367 /*-----------------------------------------------------------------*/
4368 /* genAssign - generate code for assignment */
4369 /*-----------------------------------------------------------------*/
4370 static void genAssign (iCode *ic)
4372 operand *result, *right;
4374 unsigned long lit = 0L;
4376 result = IC_RESULT(ic);
4377 right = IC_RIGHT(ic) ;
4379 /* if they are the same */
4380 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
4383 aopOp(right,ic,FALSE);
4385 /* special case both in far space */
4386 if (AOP_TYPE(right) == AOP_DPTR &&
4387 IS_TRUE_SYMOP(result) &&
4388 isOperandInFarSpace(result)) {
4390 genFarFarAssign (result,right,ic);
4394 aopOp(result,ic,TRUE);
4396 /* if they are the same registers */
4397 if (sameRegs(AOP(right),AOP(result)))
4400 /* if the result is a bit */
4401 if (AOP_TYPE(result) == AOP_CRY) {
4403 /* if the right size is a literal then
4404 we know what the value is */
4405 if (AOP_TYPE(right) == AOP_LIT) {
4406 if (((int) operandLitValue(right)))
4407 aopPut(AOP(result),one,0);
4409 aopPut(AOP(result),zero,0);
4413 /* the right is also a bit variable */
4414 if (AOP_TYPE(right) == AOP_CRY) {
4415 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4416 aopPut(AOP(result),"c",0);
4421 toBoolean(right,"",0);
4422 aopPut(AOP(result),"a",0);
4426 /* bit variables done */
4428 size = AOP_SIZE(result);
4430 if(AOP_TYPE(right) == AOP_LIT)
4431 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4433 (AOP_TYPE(result) != AOP_REG) &&
4434 (AOP_TYPE(right) == AOP_LIT) &&
4435 !IS_FLOAT(operandType(right)) &&
4437 emitcode("clr","a");
4439 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
4440 aopPut(AOP(result),"a",size);
4443 aopGet(AOP(right),size),
4449 aopGet(AOP(right),offset),
4456 freeAsmop (right,NULL,ic,FALSE);
4457 freeAsmop (result,NULL,ic,TRUE);
4460 /*-----------------------------------------------------------------*/
4461 /* genJumpTab - genrates code for jump table */
4462 /*-----------------------------------------------------------------*/
4463 static void genJumpTab (iCode *ic)
4468 aopOp(IC_JTCOND(ic),ic,FALSE);
4469 /* get the condition into accumulator */
4470 l = aopGet(AOP(IC_JTCOND(ic)),0);
4472 /* multiply by three */
4473 emitcode("add","a,acc");
4474 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0));
4475 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
4477 jtab = newiTempLabel(NULL);
4478 emitcode("mov","dptr,#%05d$",jtab->key+100);
4479 emitcode("jmp","@a+dptr");
4480 emitcode("","%05d$:",jtab->key+100);
4481 /* now generate the jump labels */
4482 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
4483 jtab = setNextItem(IC_JTLABELS(ic)))
4484 emitcode("ljmp","%05d$",jtab->key+100);
4488 /*-----------------------------------------------------------------*/
4489 /* genCast - gen code for casting */
4490 /*-----------------------------------------------------------------*/
4491 static void genCast (iCode *ic)
4493 operand *result = IC_RESULT(ic);
4494 sym_link *ctype = operandType(IC_LEFT(ic));
4495 sym_link *rtype = operandType(IC_RIGHT(ic));
4496 operand *right = IC_RIGHT(ic);
4499 /* if they are equivalent then do nothing */
4500 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
4503 aopOp(right,ic,FALSE) ;
4504 aopOp(result,ic,FALSE);
4506 /* if the result is a bit */
4507 if (AOP_TYPE(result) == AOP_CRY) {
4508 /* if the right size is a literal then
4509 we know what the value is */
4510 if (AOP_TYPE(right) == AOP_LIT) {
4511 if (((int) operandLitValue(right)))
4512 aopPut(AOP(result),one,0);
4514 aopPut(AOP(result),zero,0);
4519 /* the right is also a bit variable */
4520 if (AOP_TYPE(right) == AOP_CRY) {
4521 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4522 aopPut(AOP(result),"c",0);
4527 toBoolean(right,"",0);
4528 aopPut(AOP(result),"a",0);
4532 /* if they are the same size : or less */
4533 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
4535 /* if they are in the same place */
4536 if (sameRegs(AOP(right),AOP(result)))
4539 /* if they in different places then copy */
4540 size = AOP_SIZE(result);
4544 aopGet(AOP(right),offset),
4552 /* if the result is of type pointer */
4553 if (IS_PTR(ctype)) {
4556 sym_link *type = operandType(right);
4557 sym_link *etype = getSpec(type);
4559 /* pointer to generic pointer */
4560 if (IS_GENPTR(ctype)) {
4564 p_type = DCL_TYPE(type);
4566 /* we have to go by the storage class */
4567 p_type = PTR_TYPE(SPEC_OCLS(etype));
4570 /* the first two bytes are known */
4571 size = GPTRSIZE - 1;
4575 aopGet(AOP(right),offset),
4579 /* the last byte depending on type */
4596 /* this should never happen */
4597 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
4598 "got unknown pointer type");
4601 aopPut(AOP(result),l, GPTRSIZE - 1);
4605 /* just copy the pointers */
4606 size = AOP_SIZE(result);
4610 aopGet(AOP(right),offset),
4617 /* so we now know that the size of destination is greater
4618 than the size of the source */
4619 /* we move to result for the size of source */
4620 size = AOP_SIZE(right);
4624 aopGet(AOP(right),offset),
4629 /* now depending on the sign of the source && destination */
4630 size = AOP_SIZE(result) - AOP_SIZE(right);
4631 /* if unsigned or not an integral type */
4632 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
4634 aopPut(AOP(result),zero,offset++);
4636 /* we need to extend the sign :{ */
4637 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1);
4639 emitcode("rlc","a");
4640 emitcode("subb","a,acc");
4642 aopPut(AOP(result),"a",offset++);
4645 /* we are done hurray !!!! */
4648 freeAsmop(right,NULL,ic,TRUE);
4649 freeAsmop(result,NULL,ic,TRUE);
4653 /*-----------------------------------------------------------------*/
4654 /* genDjnz - generate decrement & jump if not zero instrucion */
4655 /*-----------------------------------------------------------------*/
4656 static int genDjnz (iCode *ic, iCode *ifx)
4662 /* if the if condition has a false label
4663 then we cannot save */
4667 /* if the minus is not of the form
4669 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
4670 !IS_OP_LITERAL(IC_RIGHT(ic)))
4673 if (operandLitValue(IC_RIGHT(ic)) != 1)
4676 /* if the size of this greater than one then no
4678 if (getSize(operandType(IC_RESULT(ic))) > 1)
4681 /* otherwise we can save BIG */
4682 lbl = newiTempLabel(NULL);
4683 lbl1= newiTempLabel(NULL);
4685 aopOp(IC_RESULT(ic),ic,FALSE);
4687 if (IS_AOP_PREG(IC_RESULT(ic))) {
4688 emitcode("dec","%s",
4689 aopGet(AOP(IC_RESULT(ic)),0));
4690 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0));
4691 emitcode("jnz","%05d$",lbl->key+100);
4693 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0),
4696 emitcode ("sjmp","%05d$",lbl1->key+100);
4697 emitcode ("","%05d$:",lbl->key+100);
4698 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4699 emitcode ("","%05d$:",lbl1->key+100);
4701 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
4706 static char *recvregs[8] =
4708 "r16","r17","r18","r19","r20","r21","r22","r23"
4712 /*-----------------------------------------------------------------*/
4713 /* genReceive - generate code for a receive iCode */
4714 /*-----------------------------------------------------------------*/
4715 static void genReceive (iCode *ic)
4717 int size , offset =0;
4718 aopOp(IC_RESULT(ic),ic,FALSE);
4719 size = AOP_SIZE(IC_RESULT(ic));
4721 aopPut(AOP(IC_RESULT(ic)),recvregs[recvCnt++],offset);
4724 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
4727 /*-----------------------------------------------------------------*/
4728 /* gen51Code - generate code for 8051 based controllers */
4729 /*-----------------------------------------------------------------*/
4730 void genAVRCode (iCode *lic)
4735 lineHead = lineCurr = NULL;
4737 /* print the allocation information */
4739 printAllocInfo( currFunc, codeOutFile);
4740 /* if debug information required */
4741 /* if (options.debug && currFunc) { */
4743 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
4745 if (IS_STATIC(currFunc->etype))
4746 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
4748 emitcode("","G$%s$0$0 ==.",currFunc->name);
4751 /* stack pointer name */
4752 if (options.useXstack)
4758 for (ic = lic ; ic ; ic = ic->next ) {
4760 if ( cln != ic->lineno ) {
4761 if ( options.debug ) {
4763 emitcode("","C$%s$%d$%d$%d ==.",
4764 ic->filename,ic->lineno,
4765 ic->level,ic->block);
4768 emitcode(";","%s %d",ic->filename,ic->lineno);
4771 /* if the result is marked as
4772 spilt and rematerializable or code for
4773 this has already been generated then
4775 if (resultRemat(ic) || ic->generated )
4778 /* depending on the operation */
4797 /* IPOP happens only when trying to restore a
4798 spilt live range, if there is an ifx statement
4799 following this pop then the if statement might
4800 be using some of the registers being popped which
4801 would destory the contents of the register so
4802 we need to check for this condition and handle it */
4804 ic->next->op == IFX &&
4805 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
4806 genIfx (ic->next,ic);
4824 genEndFunction (ic);
4844 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
4861 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
4865 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
4869 genCmpLe (ic,ifxForOp(IC_RESULT(ic),ic));
4873 genCmpGe (ic,ifxForOp(IC_RESULT(ic),ic));
4877 genCmpNe (ic,ifxForOp(IC_RESULT(ic),ic));
4881 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
4893 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
4897 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
4901 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
4928 case GET_VALUE_AT_ADDRESS:
4933 if (POINTER_SET(ic))
4960 addSet(&_G.sendSet,ic);
4965 /* piCode(ic,stdout); */
4971 /* now we are ready to call the
4972 peep hole optimizer */
4973 if (!options.nopeep)
4974 peepHole (&lineHead);
4976 /* now do the actual printing */
4977 printLine (lineHead,codeOutFile);