1 /*-------------------------------------------------------------------------
2 avrgen.c - source file for code generation for ATMEL AVR
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (2000)
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding!
25 -------------------------------------------------------------------------*/
31 #include "SDCCglobl.h"
33 #ifdef HAVE_SYS_ISA_DEFS_H
34 #include <sys/isa_defs.h>
40 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
41 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
47 #include "SDCCpeeph.h"
51 char *aopLiteral (value *val, int offset);
54 /* this is the down and dirty file with all kinds of
55 kludgy & hacky stuff. This is what it is all about
56 CODE GENERATION for a specific MCU . some of the
57 routines may be reusable, will have to see */
59 static char *zero = "0x00";
60 static char *one = "0x01";
63 char *fReturnAVR[] = {"r16","r17","r18","r19" };
64 unsigned fAVRReturnSize = 4; /* shared with ralloc.c */
65 char **fAVRReturn = fReturnAVR;
67 static short rbank = -1;
68 static char *larray[4] = {"lo8","hi8","hlo8","hhi8"};
69 static char *tscr[4] = {"r0","r1","r24","r25"};
80 extern int avr_ptrRegReq ;
82 extern FILE *codeOutFile;
83 static void saverbank (int, iCode *,bool);
84 #define RESULTONSTACK(x) \
85 (IC_RESULT(x) && IC_RESULT(x)->aop && \
86 IC_RESULT(x)->aop->type == AOP_STK )
88 #define MOVR0(x) if (strcmp(x,"r0")) emitcode("mov","r0,%s",x);
89 #define CLRC emitcode("clc","")
90 #define SETC emitcode("stc","")
92 #define IS_REGIDX(a,r) (a->type == AOP_REG && a->aopu.aop_reg[0]->rIdx == r)
94 static lineNode *lineHead = NULL;
95 static lineNode *lineCurr = NULL;
97 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
98 0xE0, 0xC0, 0x80, 0x00};
99 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
100 0x07, 0x03, 0x01, 0x00};
107 /*-----------------------------------------------------------------*/
108 /* emitcode - writes the code into a file : for now it is simple */
109 /*-----------------------------------------------------------------*/
110 static void emitcode (char *inst,char *fmt, ...)
113 char lb[MAX_INLINEASM];
120 sprintf(lb,"%s\t",inst);
122 sprintf(lb,"%s",inst);
123 vsprintf(lb+(strlen(lb)),fmt,ap);
127 while (isspace(*lbp)) lbp++;
130 lineCurr = (lineCurr ?
131 connectLine(lineCurr,newLineNode(lb)) :
132 (lineHead = newLineNode(lb)));
133 lineCurr->isInline = _G.inLine;
134 lineCurr->isDebug = _G.debugLine;
138 /*-----------------------------------------------------------------*/
139 /* getFreePtr - returns X or Z whichever is free or can be pushed */
140 /*-----------------------------------------------------------------*/
141 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result, bool zonly)
143 bool xiu = FALSE , ziu = FALSE;
144 bool xou = FALSE , zou = FALSE;
146 /* the logic: if x & z used in the instruction
147 then we are in trouble otherwise */
149 /* first check if x & z are used by this
150 instruction, in which case we are in trouble */
151 if ((xiu = bitVectBitValue(ic->rUsed,X_IDX)) &&
152 (ziu = bitVectBitValue(ic->rUsed,Z_IDX)))
157 xou = bitVectBitValue(ic->rMask,X_IDX);
158 zou = bitVectBitValue(ic->rMask,Z_IDX);
160 /* if no usage of Z then return it */
162 ic->rUsed = bitVectSetBit(ic->rUsed,Z_IDX);
163 (*aopp)->type = AOP_Z;
165 (*aopp)->aop_ptr2 = avr_regWithIdx(R31_IDX);
166 return (*aopp)->aopu.aop_ptr = avr_regWithIdx(R30_IDX);
169 /* if no usage of X then return it */
170 if (!xiu && !xou && !zonly) {
171 ic->rUsed = bitVectSetBit(ic->rUsed,X_IDX);
172 (*aopp)->type = AOP_X;
174 (*aopp)->aop_ptr2 = avr_regWithIdx(R27_IDX);
175 return (*aopp)->aopu.aop_ptr = avr_regWithIdx(R26_IDX);
178 /* if z not used then */
181 /* push it if not already pushed */
183 emitcode ("push","%s",
184 avr_regWithIdx(R30_IDX)->dname);
185 emitcode ("push","%s",
186 avr_regWithIdx(R31_IDX)->dname);
190 ic->rUsed = bitVectSetBit(ic->rUsed,Z_IDX);
191 (*aopp)->type = AOP_Z;
192 (*aopp)->aop_ptr2 = avr_regWithIdx(R31_IDX);
193 return (*aopp)->aopu.aop_ptr = avr_regWithIdx(R30_IDX);
196 /* now we know they both have usage */
197 /* if x not used in this instruction */
198 if (!xiu && !zonly) {
199 /* push it if not already pushed */
201 emitcode ("push","%s",
202 avr_regWithIdx(R26_IDX)->dname);
203 emitcode ("push","%s",
204 avr_regWithIdx(R27_IDX)->dname);
208 ic->rUsed = bitVectSetBit(ic->rUsed,X_IDX);
209 (*aopp)->type = AOP_X;
211 (*aopp)->aop_ptr2 = avr_regWithIdx(R27_IDX);
212 return (*aopp)->aopu.aop_ptr = avr_regWithIdx(R26_IDX);
217 /* I said end of world but not quite end of world yet */
218 /* if this is a result then we can push it on the stack*/
220 (*aopp)->type = AOP_STK;
225 /* other wise this is true end of the world */
226 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
227 "getFreePtr should never reach here");
231 /*-----------------------------------------------------------------*/
232 /* newAsmop - creates a new asmOp */
233 /*-----------------------------------------------------------------*/
234 static asmop *newAsmop (short type)
238 ALLOC(aop,sizeof(asmop));
243 /*-----------------------------------------------------------------*/
244 /* pointerCode - returns the code for a pointer type */
245 /*-----------------------------------------------------------------*/
246 static int pointerCode (link *etype)
249 return PTR_TYPE(SPEC_OCLS(etype));
253 /*-----------------------------------------------------------------*/
254 /* aopForSym - for a true symbol */
255 /*-----------------------------------------------------------------*/
256 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
259 memmap *space= SPEC_OCLS(sym->etype);
261 /* if already has one */
265 /* assign depending on the storage class */
266 /* if it is on the stack */
268 sym->aop = aop = newAsmop(0);
269 aop->size = getSize(sym->type);
271 /* we can use std / ldd instruction */
272 if (sym->stack > 0 && (sym->stack + getSize(sym->type) - 1) <= 63) {
273 aop->type = AOP_STK_D;
274 aop->aopu.aop_stk = sym->stack;
278 /* otherwise get a free pointer register X/Z */
279 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result,FALSE);
281 /* now assign the address of the variable to
282 the pointer register */
283 if (aop->type != AOP_STK) {
284 emitcode("movw","%s,r28",aop->aopu.aop_ptr->name);
285 if (sym->stack < 0) {
286 if ((sym->stack - _G.nRegsSaved) > -63) {
287 emitcode("sbiw","%s,0x%02x",
288 aop->aopu.aop_ptr->name,
289 (sym->stack - _G.nRegsSaved));
291 emitcode("subi","%s,lo8(%d)", aop->aopu.aop_ptr->name,
292 sym->stack - _G.nRegsSaved);
293 emitcode("sbci","%s,hi8(%d)",aop->aop_ptr2->name,
294 sym->stack - _G.nRegsSaved);
297 if (sym->stack <= 63) {
298 emitcode("adiw","%s,0x%02x",aop->aopu.aop_ptr->name,sym->stack);
300 emitcode("subi","%s,lo8(-%d)",aop->aopu.aop_ptr->name,sym->stack);
301 emitcode("sbci","%s,hi8(-%d)",aop->aop_ptr2->name,sym->stack);
308 /* if in bit space */
309 if (IN_BITSPACE(space)) {
310 sym->aop = aop = newAsmop (AOP_CRY);
311 aop->aopu.aop_dir = sym->rname ;
312 aop->size = getSize(sym->type);
315 /* if it is in direct space */
316 if (IN_DIRSPACE(space)) {
317 sym->aop = aop = newAsmop (AOP_DIR);
318 aop->aopu.aop_dir = sym->rname ;
319 aop->size = getSize(sym->type);
323 /* special case for a function */
324 if (IS_FUNC(sym->type)) {
325 sym->aop = aop = newAsmop(AOP_IMMD);
326 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
327 strcpy(aop->aopu.aop_immd,sym->rname);
328 aop->size = FPTRSIZE;
332 /* only remaining is code / eeprom which will need pointer reg */
333 /* if it is in code space */
334 if (IN_CODESPACE(space))
337 sym->aop = aop = newAsmop(0);
338 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result,aop->code);
339 aop->size = getSize(sym->type);
340 emitcode ("ldi","%s,lo8(%s)",aop->aopu.aop_ptr->name,sym->rname);
341 emitcode ("ldi","%s,hi8(%s)",aop->aop_ptr2);
346 /*-----------------------------------------------------------------*/
347 /* aopForRemat - rematerialzes an object */
348 /*-----------------------------------------------------------------*/
349 static asmop *aopForRemat (symbol *sym)
351 iCode *ic = sym->rematiCode;
352 asmop *aop = newAsmop(AOP_IMMD);
357 val += operandLitValue(IC_RIGHT(ic));
358 else if (ic->op == '-')
359 val -= operandLitValue(IC_RIGHT(ic));
363 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
367 sprintf(buffer,"(%s %c 0x%04x)",
368 OP_SYMBOL(IC_LEFT(ic))->rname,
369 val >= 0 ? '+' : '-',
372 strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
374 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
375 strcpy(aop->aopu.aop_immd,buffer);
379 /*-----------------------------------------------------------------*/
380 /* regsInCommon - two operands have some registers in common */
381 /*-----------------------------------------------------------------*/
382 static bool regsInCommon (operand *op1, operand *op2)
387 /* if they have registers in common */
388 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
391 sym1 = OP_SYMBOL(op1);
392 sym2 = OP_SYMBOL(op2);
394 if (sym1->nRegs == 0 || sym2->nRegs == 0)
397 for (i = 0 ; i < sym1->nRegs ; i++) {
402 for (j = 0 ; j < sym2->nRegs ;j++ ) {
406 if (sym2->regs[j] == sym1->regs[i])
414 /*-----------------------------------------------------------------*/
415 /* operandsEqu - equivalent */
416 /*-----------------------------------------------------------------*/
417 static bool operandsEqu ( operand *op1, operand *op2)
421 /* if they not symbols */
422 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
425 sym1 = OP_SYMBOL(op1);
426 sym2 = OP_SYMBOL(op2);
428 /* if both are itemps & one is spilt
429 and the other is not then false */
430 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
431 sym1->isspilt != sym2->isspilt )
434 /* if they are the same */
438 if (strcmp(sym1->rname,sym2->rname) == 0)
442 /* if left is a tmp & right is not */
446 (sym1->usl.spillLoc == sym2))
453 (sym2->usl.spillLoc == sym1))
459 /*-----------------------------------------------------------------*/
460 /* sameRegs - two asmops have the same registers */
461 /*-----------------------------------------------------------------*/
462 static bool sameRegs (asmop *aop1, asmop *aop2 )
469 if (aop1->type != AOP_REG ||
470 aop2->type != AOP_REG )
473 if (aop1->size != aop2->size )
476 for (i = 0 ; i < aop1->size ; i++ )
477 if (aop1->aopu.aop_reg[i] !=
478 aop2->aopu.aop_reg[i] )
484 /*-----------------------------------------------------------------*/
485 /* isRegPair - for size 2 if this operand has a register pair */
486 /*-----------------------------------------------------------------*/
487 static int isRegPair (asmop *aop)
489 if (!aop || aop->size != 2) return 0;
490 if (aop->type == AOP_X || aop->type == AOP_Z) return 1;
491 if (aop->type != AOP_REG) return 0;
492 if ((aop->aopu.aop_reg[1]->rIdx -
493 aop->aopu.aop_reg[0]->rIdx) == 1) return 1;
497 /*-----------------------------------------------------------------*/
498 /* aopOp - allocates an asmop for an operand : */
499 /*-----------------------------------------------------------------*/
500 static void aopOp (operand *op, iCode *ic, bool result)
509 /* if this a literal */
510 if (IS_OP_LITERAL(op)) {
511 op->aop = aop = newAsmop(AOP_LIT);
512 aop->aopu.aop_lit = op->operand.valOperand;
513 aop->size = getSize(operandType(op));
517 /* if already has a asmop then continue */
521 /* if the underlying symbol has a aop */
522 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
523 op->aop = OP_SYMBOL(op)->aop;
527 /* if this is a true symbol */
528 if (IS_TRUE_SYMOP(op)) {
529 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
533 /* this is a temporary : this has
539 e) can be a return use only */
544 /* if the type is a conditional */
545 if (sym->regType == REG_CND) {
546 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
551 /* if it is spilt then two situations
553 b) has a spill location */
554 if (sym->isspilt || sym->nRegs == 0) {
556 /* rematerialize it NOW */
558 sym->aop = op->aop = aop =
560 aop->size = getSize(sym->type);
565 assert("ACC_USE cannot happen in AVR\n");
570 aop = op->aop = sym->aop = newAsmop(AOP_STR);
571 aop->size = getSize(sym->type);
572 for ( i = 0 ; i < fAVRReturnSize ; i++ )
573 aop->aopu.aop_str[i] = fAVRReturn[i];
577 /* else spill location */
578 sym->aop = op->aop = aop =
579 aopForSym(ic,sym->usl.spillLoc,result);
580 aop->size = getSize(sym->type);
584 /* must be in a register */
585 sym->aop = op->aop = aop = newAsmop(AOP_REG);
586 aop->size = sym->nRegs;
587 for ( i = 0 ; i < sym->nRegs ;i++)
588 aop->aopu.aop_reg[i] = sym->regs[i];
591 /*-----------------------------------------------------------------*/
592 /* freeAsmop - free up the asmop given to an operand */
593 /*----------------------------------------------------------------*/
594 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
611 /* depending on the asmop type only three cases need work AOP_RO
612 , AOP_R1 && AOP_STK */
617 emitcode ("pop","r26");
618 emitcode ("pop","r27");
622 bitVectUnSetBit(ic->rUsed,X_IDX);
628 emitcode ("pop","r30");
629 emitcode ("pop","r31");
633 bitVectUnSetBit(ic->rUsed,Z_IDX);
639 int stk = aop->aopu.aop_stk + aop->size;
640 bitVectUnSetBit(ic->rUsed,X_IDX);
641 bitVectUnSetBit(ic->rUsed,Z_IDX);
643 getFreePtr(ic,&aop,FALSE,0);
645 emitcode ("movw","%s,r28");
647 if (stk <= 63 && stk > 0) {
648 emitcode ("adiw","%s,0x%02x",aop->aopu.aop_ptr->name,stk+1);
650 emitcode ("subi","%s,lo8(%d)",aop->aopu.aop_ptr->name,-(stk+1));
651 emitcode ("sbci","%s,hi8(%d)",aop->aop_ptr2->name,-(stk+1));
656 emitcode("pop","r24");
657 emitcode("st","-%s,r24",aop->type == AOP_X ? "X" : "Z");
661 freeAsmop(op,NULL,ic,TRUE);
663 emitcode("pop","r26");
664 emitcode("pop","r27");
669 emitcode("pop","r30");
670 emitcode("pop","r31");
677 /* all other cases just dealloc */
681 OP_SYMBOL(op)->aop = NULL;
682 /* if the symbol has a spill */
684 SPIL_LOC(op)->aop = NULL;
689 /*-----------------------------------------------------------------*/
690 /* aopGet - for fetching value of the aop */
691 /*-----------------------------------------------------------------*/
692 static char *aopGet (asmop *aop, int offset)
697 /* offset is greater than
699 if (offset > (aop->size - 1) &&
700 aop->type != AOP_LIT)
703 /* depending on type */
707 if (offset > aop->coff) {
708 emitcode ("adiw","%s,%d",aop->aopu.aop_ptr->name,offset - aop->coff);
711 if (offset < aop->coff) {
712 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,aop->coff - offset);
716 emitcode("ld","%s,x",
717 (rs = ((offset & 1) ? "r25" : "r24")));
722 if (offset > aop->coff) {
723 emitcode("adiw","r30,%d",offset - aop->coff);
725 emitcode("sbiw","r30,%d",aop->coff - offset);
727 emitcode("lpm","%s,z",(rs = ((offset & 1) ? "r25" : "r24")));
730 if (offset > aop->coff) {
731 emitcode ("ldd","%s,z+%d",(rs = ((offset & 1) ? "r25" : "r24")),
734 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,aop->coff - offset);
736 emitcode ("ld","%s,z",(rs = ((offset & 1) ? "r25" : "r24")));
743 emitcode ("lds","%s,(%s)+%d",
744 (rs = ((offset & 1) ? "r25" : "r24")),
745 aop->aopu.aop_immd, offset);
749 emitcode ("lds","%s,(%s)+%d",
750 (rs = ((offset & 1) ? "r25" : "r24")),
751 aop->aopu.aop_dir, offset);
755 return aop->aopu.aop_reg[offset]->name;
758 assert("cannot be in bit space AOP_CRY\n");
762 s = aopLiteral(aop->aopu.aop_lit,offset);
763 emitcode("ldi","%s,lo8(%s)",(rs = ((offset & 1)?"r24" : "r25")),s);
768 return aop->aopu.aop_str[offset];
771 emitcode ("ldd","%s,Y+%d",
772 (rs = ((offset & 1) ? "r25" : "r24")),
773 aop->aopu.aop_stk+offset);
777 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
778 "aopget got unsupported aop->type");
781 /*-----------------------------------------------------------------*/
782 /* aopPut - puts a string for a aop */
783 /*-----------------------------------------------------------------*/
784 static void aopPut (asmop *aop, char *s, int offset)
788 if (aop->size && offset > ( aop->size - 1)) {
789 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
790 "aopPut got offset > aop->size");
794 /* will assign value to value */
795 /* depending on where it is ofcourse */
799 sprintf(d,"(%s)+%d", aop->aopu.aop_dir,offset);
802 sprintf(d,"%s",aop->aopu.aop_dir);
805 emitcode("sts","%s,%s",d,s);
809 if (toupper(*s) != 'R') {
811 emitcode("clr","%s",aop->aopu.aop_reg[offset]->name);
813 emitcode("ldi","r25,%s",s);
814 emitcode("mov","%s,r35",aop->aopu.aop_reg[offset]->name);
817 if (strcmp( aop->aopu.aop_reg[offset]->name,s)) {
818 emitcode("mov","%s,%s", aop->aopu.aop_reg[offset]->name,s);
824 if (offset > aop->coff) {
825 emitcode ("adiw","%s,%d",aop->aopu.aop_ptr->name,offset - aop->coff);
828 if (offset < aop->coff) {
829 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,aop->coff - offset);
833 emitcode("st","x,%s", s);
838 if (offset > aop->coff) {
839 emitcode("adiw","r30,%d",offset - aop->coff);
841 emitcode("sbiw","r30,%d",aop->coff - offset);
843 emitcode("lpm","%s,z",s);
846 if (offset > aop->coff) {
847 emitcode ("sdd","z+%d,%s",offset - aop->coff,s);
849 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,aop->coff - offset);
851 emitcode ("ld","%s,z",s);
857 emitcode("push","%s",s);
861 /* if used only for a condition code check */
862 assert(toupper(*s) == 'R');
864 emitcode("xrl","r0,r0");
865 emitcode("cpi","%s,0",s);
868 emitcode("cpc","r0,%s",s);
874 if (strcmp(aop->aopu.aop_str[offset],s))
875 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
879 emitcode ("std","y+%d,%s",offset,s);
883 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
884 "aopPut got unsupported aop->type");
890 /*-----------------------------------------------------------------*/
891 /* reAdjustPreg - points a register back to where it should */
892 /*-----------------------------------------------------------------*/
893 static void reAdjustPreg (asmop *aop)
898 if ((size = aop->size) <= 1)
904 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,size);
910 #define AOP(op) op->aop
911 #define AOP_TYPE(op) AOP(op)->type
912 #define AOP_SIZE(op) AOP(op)->size
913 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_X || \
914 AOP_TYPE(x) == AOP_Z))
915 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
916 (x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) || \
917 x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) )))
919 /*-----------------------------------------------------------------*/
920 /* genNotFloat - generates not for float operations */
921 /*-----------------------------------------------------------------*/
922 static void genNotFloat (operand *op, operand *res)
928 /* we will put 127 in the first byte of
930 aopPut(AOP(res),"127",0);
931 size = AOP_SIZE(op) - 1;
934 l = aopGet(op->aop,offset++);
938 emitcode("or","R0,%s", aopGet(op->aop, offset++));
940 tlbl = newiTempLabel(NULL);
942 tlbl = newiTempLabel(NULL);
943 aopPut(res->aop,zero,1);
944 emitcode("cpi","r0,0");
945 emitcode("breq","L%05d",tlbl->key);
946 aopPut(res->aop,one,1);
947 emitcode("","L%05d:",tlbl->key);
949 size = res->aop->size - 2;
951 /* put zeros in the rest */
953 aopPut(res->aop,zero,offset++);
956 /*-----------------------------------------------------------------*/
957 /* opIsGptr: returns non-zero if the passed operand is */
958 /* a generic pointer type. */
959 /*-----------------------------------------------------------------*/
960 static int opIsGptr(operand *op)
962 link *type = operandType(op);
964 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
971 /*-----------------------------------------------------------------*/
972 /* getDataSize - get the operand data size */
973 /*-----------------------------------------------------------------*/
974 static int getDataSize(operand *op)
978 if (size == GPTRSIZE)
980 link *type = operandType(op);
983 /* generic pointer; arithmetic operations
984 * should ignore the high byte (pointer type).
992 /*-----------------------------------------------------------------*/
993 /* outAcc - output Acc */
994 /*-----------------------------------------------------------------*/
995 static void outAcc(operand *result)
998 size = getDataSize(result);
1000 aopPut(AOP(result),"r0",0);
1003 /* unsigned or positive */
1005 aopPut(AOP(result),zero,offset++);
1010 /*-----------------------------------------------------------------*/
1011 /* outBitC - output a bit C */
1012 /*-----------------------------------------------------------------*/
1013 static void outBitC(operand *result)
1015 emitcode("clr","r0");
1016 emitcode("rol","r0");
1020 /*-----------------------------------------------------------------*/
1021 /* toBoolean - emit code for orl a,operator(sizeop) */
1022 /*-----------------------------------------------------------------*/
1023 static void toBoolean(operand *oper, char *r, bool clr)
1025 int size = AOP_SIZE(oper) ;
1027 if (clr) emitcode ("clr","%s",r);
1029 emitcode("or","%s,%s",r,aopGet(AOP(oper),offset++));
1033 /*-----------------------------------------------------------------*/
1034 /* genNot - generate code for ! operation */
1035 /*-----------------------------------------------------------------*/
1036 static void genNot (iCode *ic)
1039 link *optype = operandType(IC_LEFT(ic));
1040 int size, offset = 1;
1042 /* assign asmOps to operand & result */
1043 aopOp (IC_LEFT(ic),ic,FALSE);
1044 aopOp (IC_RESULT(ic),ic,TRUE);
1046 /* if type float then do float */
1047 if (IS_FLOAT(optype)) {
1048 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1051 emitcode("clr","r0");
1052 tlbl = newiTempLabel(NULL);
1053 size = AOP_SIZE(IC_LEFT(ic));
1056 emitcode("cpse","%s,r0",aopGet(AOP(IC_LEFT(ic)),0));
1060 if (offset) emitcode("cpc","%s,r0",aopGet(AOP(IC_LEFT(ic)),offset));
1061 else emitcode("cpi","%s,0",aopGet(AOP(IC_LEFT(ic)),offset));
1064 emitcode("bne","L%05d",tlbl->key);
1066 emitcode("ldi","r0,1");
1067 emitcode("","L%05d:",tlbl->key);
1068 aopPut(AOP(IC_RESULT(ic)),"r0",0);
1069 size = AOP_SIZE(IC_RESULT(ic)) -1;
1071 while (size--) aopPut(AOP(IC_RESULT(ic)),zero,offset++);
1075 /* release the aops */
1076 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1077 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1081 /*-----------------------------------------------------------------*/
1082 /* genCpl - generate code for complement */
1083 /*-----------------------------------------------------------------*/
1084 static void genCpl (iCode *ic)
1090 /* assign asmOps to operand & result */
1091 aopOp (IC_LEFT(ic),ic,FALSE);
1092 aopOp (IC_RESULT(ic),ic,TRUE);
1093 samer = sameRegs(AOP(IC_LEFT(ic)),AOP(IC_RESULT(ic)));
1094 size = AOP_SIZE(IC_RESULT(ic));
1096 char *l = aopGet(AOP(IC_LEFT(ic)),offset);
1098 emitcode ("com","%s",l);
1100 aopPut(AOP(IC_RESULT(ic)),l,offset);
1101 emitcode ("com","%s",aopGet(AOP(IC_RESULT(ic)),offset));
1106 /* release the aops */
1107 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1108 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1111 /*-----------------------------------------------------------------*/
1112 /* genUminusFloat - unary minus for floating points */
1113 /*-----------------------------------------------------------------*/
1114 static void genUminusFloat(operand *op,operand *result)
1116 int size ,offset =0 ;
1118 /* for this we just need to flip the
1119 first it then copy the rest in place */
1120 size = AOP_SIZE(op) - 1;
1121 l = aopGet(AOP(op),3);
1123 emitcode("ldi","r24,0x80");
1124 if (sameRegs(AOP(op),AOP(result))) {
1125 emitcode("eor","%s,r24",l);
1127 aopPut(AOP(result),l,3);
1128 emitcode("eor","%s,r24",aopGet(AOP(result),3));
1131 aopPut(AOP(result), aopGet(AOP(op),offset), offset);
1136 /*-----------------------------------------------------------------*/
1137 /* genUminus - unary minus code generation */
1138 /*-----------------------------------------------------------------*/
1139 static void genUminus (iCode *ic)
1142 link *optype, *rtype;
1146 aopOp(IC_LEFT(ic),ic,FALSE);
1147 aopOp(IC_RESULT(ic),ic,TRUE);
1149 optype = operandType(IC_LEFT(ic));
1150 rtype = operandType(IC_RESULT(ic));
1152 /* if float then do float stuff */
1153 if (IS_FLOAT(optype)) {
1154 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1158 /* otherwise subtract from zero */
1159 size = AOP_SIZE(IC_LEFT(ic));
1161 samer = sameRegs(AOP(IC_LEFT(ic)),AOP(IC_RESULT(ic)));
1164 emitcode("neg","%s",aopGet(AOP(IC_LEFT(ic)),0));
1166 aopPut(AOP(IC_RESULT(ic)),aopGet(AOP(IC_LEFT(ic)),0),0);
1167 emitcode("neg","%s",aopGet(AOP(IC_RESULT(ic)),0));
1172 char *l = aopGet(AOP(IC_LEFT(ic)),offset);
1174 aopPut(AOP(IC_RESULT(ic)),l,offset);
1175 l = aopGet(AOP(IC_RESULT(ic)),offset);
1177 if (offset) emitcode("com","%s",l);
1178 else emitcode("neg","%s",l);
1181 size = AOP_SIZE(IC_LEFT(ic)) -1;
1184 emitcode("sbci","%s,lo8(-1)",aopGet(AOP(IC_RESULT(ic)),offset++));
1188 /* if any remaining bytes in the result */
1189 /* we just need to propagate the sign */
1190 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1191 symbol *tlbl = newiTempLabel(NULL);
1192 emitcode("clr","r0");
1193 emitcode("brcc","L%05d",tlbl->key);
1194 emitcode("com","r0");
1195 emitcode("","L%05d:",tlbl->key);
1197 aopPut(AOP(IC_RESULT(ic)),"r0",offset++);
1201 /* release the aops */
1202 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1203 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1206 /*-----------------------------------------------------------------*/
1207 /* assignResultValue - */
1208 /*-----------------------------------------------------------------*/
1209 static void assignResultValue(operand * oper)
1212 int size = AOP_SIZE(oper);
1214 aopPut(AOP(oper),fAVRReturn[offset],offset);
1219 /*-----------------------------------------------------------------*/
1220 /* saveZreg - if indirect call then save z-pointer register */
1221 /*-----------------------------------------------------------------*/
1222 static void saveZreg (iCode *ic)
1224 /* only if live accross this call */
1225 if (ic->regsSaved == 0 &&
1226 (bitVectBitValue(ic->rMask,R30_IDX) ||
1227 bitVectBitValue(ic->rMask,R31_IDX))) {
1229 emitcode("push","r30");
1230 emitcode("push","r31");
1234 /*-----------------------------------------------------------------*/
1235 /* popZreg - restore values of zreg */
1236 /*-----------------------------------------------------------------*/
1237 static void popZreg (iCode *ic)
1239 if (ic->regsSaved) {
1240 emitcode ("pop","r31");
1241 emitcode ("pop","r30");
1245 /*-----------------------------------------------------------------*/
1246 /* genIpush - genrate code for pushing this gets a little complex */
1247 /*-----------------------------------------------------------------*/
1248 static void genIpush (iCode *ic)
1250 int size, offset = 0 ;
1254 if (!ic->parmPush) {
1255 /* and the item is spilt then do nothing */
1256 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1260 for (lic = ic->next ; lic ; lic = lic->next)
1261 if (lic->op == PCALL) break;
1262 if (lic) saveZreg(lic);
1265 /* this is a paramter push */
1266 aopOp(IC_LEFT(ic),ic,FALSE);
1267 size = AOP_SIZE(IC_LEFT(ic));
1269 l = aopGet(AOP(IC_LEFT(ic)),offset++);
1270 emitcode("push","%s",l);
1273 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1276 /*-----------------------------------------------------------------*/
1277 /* genIpop - recover the registers: can happen only for spilling */
1278 /*-----------------------------------------------------------------*/
1279 static void genIpop (iCode *ic)
1284 /* if the temp was not pushed then */
1285 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1288 aopOp(IC_LEFT(ic),ic,FALSE);
1289 size = AOP_SIZE(IC_LEFT(ic));
1292 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--));
1294 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1297 /*-----------------------------------------------------------------*/
1298 /* genCall - generates a call statement */
1299 /*-----------------------------------------------------------------*/
1300 static void genCall (iCode *ic)
1303 /* if send set is not empty the assign */
1307 for (sic = setFirstItem(_G.sendSet) ; sic ;
1308 sic = setNextItem(_G.sendSet)) {
1309 int size, offset = 0;
1310 aopOp(IC_LEFT(sic),sic,FALSE);
1311 size = AOP_SIZE(IC_LEFT(sic));
1313 char *l = aopGet(AOP(IC_LEFT(sic)),offset);
1314 if (strcmp(l,fAVRReturn[offset]))
1315 emitcode("mov","%s,%s",
1320 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1325 emitcode("call","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1326 OP_SYMBOL(IC_LEFT(ic))->rname :
1327 OP_SYMBOL(IC_LEFT(ic))->name));
1329 /* if we need assign a result value */
1330 if ((IS_ITEMP(IC_RESULT(ic)) &&
1331 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1332 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1333 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1335 aopOp(IC_RESULT(ic),ic,FALSE);
1336 assignResultValue(IC_RESULT(ic));
1337 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1340 /* adjust the stack for parameters if required */
1341 if (IC_LEFT(ic)->parmBytes) {
1342 if (IC_LEFT(ic)->parmBytes > 63) {
1343 emitcode("sbiw","r28,%d",IC_LEFT(ic)->parmBytes);
1345 emitcode("subi","r28,lo8(%d)",IC_LEFT(ic)->parmBytes);
1346 emitcode("sbci","r29,hi8(%d)",IC_LEFT(ic)->parmBytes);
1352 /*-----------------------------------------------------------------*/
1353 /* genPcall - generates a call by pointer statement */
1354 /*-----------------------------------------------------------------*/
1355 static void genPcall (iCode *ic)
1358 if (!ic->regsSaved) saveZreg(ic);
1360 aopOp(IC_LEFT(ic),ic,FALSE);
1361 emitcode("mov","r30",aopGet(AOP(IC_LEFT(ic)),0));
1362 emitcode("mov","r31",aopGet(AOP(IC_RIGHT(ic)),0));
1363 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1365 /* if send set is not empty the assign */
1369 for (sic = setFirstItem(_G.sendSet) ; sic ;
1370 sic = setNextItem(_G.sendSet)) {
1371 int size, offset = 0;
1372 aopOp(IC_LEFT(sic),sic,FALSE);
1373 size = AOP_SIZE(IC_LEFT(sic));
1375 char *l = aopGet(AOP(IC_LEFT(sic)),offset);
1376 if (strcmp(l,fAVRReturn[offset]))
1377 emitcode("mov","%s,%s",
1382 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1387 emitcode("icall","");
1389 /* if we need assign a result value */
1390 if ((IS_ITEMP(IC_RESULT(ic)) &&
1391 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1392 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
1393 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1395 aopOp(IC_RESULT(ic),ic,FALSE);
1397 assignResultValue(IC_RESULT(ic));
1398 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1401 /* adjust the stack for parameters if
1403 if (IC_LEFT(ic)->parmBytes) {
1405 if (IC_LEFT(ic)->parmBytes > 3) {
1406 emitcode("mov","a,%s",spname);
1407 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1408 emitcode("mov","%s,a",spname);
1410 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1411 emitcode("dec","%s",spname);
1415 /* adjust the stack for parameters if required */
1416 if (IC_LEFT(ic)->parmBytes) {
1417 if (IC_LEFT(ic)->parmBytes > 63) {
1418 emitcode("sbiw","r28,%d",IC_LEFT(ic)->parmBytes);
1420 emitcode("subi","r28,lo8(%d)",IC_LEFT(ic)->parmBytes);
1421 emitcode("sbci","r29,hi8(%d)",IC_LEFT(ic)->parmBytes);
1424 if (ic->regsSaved) popZreg(ic);
1427 /*-----------------------------------------------------------------*/
1428 /* resultRemat - result is rematerializable */
1429 /*-----------------------------------------------------------------*/
1430 static int resultRemat (iCode *ic)
1432 if (SKIP_IC(ic) || ic->op == IFX)
1435 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1436 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1437 if (sym->remat && !POINTER_SET(ic))
1445 #define STRCASECMP stricmp
1447 #define STRCASECMP strcasecmp
1450 /*-----------------------------------------------------------------*/
1451 /* inExcludeList - return 1 if the string is in exclude Reg list */
1452 /*-----------------------------------------------------------------*/
1453 static bool inExcludeList(char *s)
1457 if (options.excludeRegs[i] &&
1458 STRCASECMP(options.excludeRegs[i],"none") == 0)
1461 for ( i = 0 ; options.excludeRegs[i]; i++) {
1462 if (options.excludeRegs[i] &&
1463 STRCASECMP(s,options.excludeRegs[i]) == 0)
1469 /*-----------------------------------------------------------------*/
1470 /* genFunction - generated code for function entry */
1471 /*-----------------------------------------------------------------*/
1472 static void genFunction (iCode *ic)
1479 /* create the function header */
1480 emitcode(";","-----------------------------------------");
1481 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1482 emitcode(";","-----------------------------------------");
1484 emitcode("","%s:",sym->rname);
1485 fetype = getSpec(operandType(IC_LEFT(ic)));
1487 /* if critical function then turn interrupts off */
1488 if (SPEC_CRTCL(fetype))
1491 if (IS_ISR(sym->etype)) {
1494 /* save the preserved registers that are used in this function */
1495 for (i = R2_IDX ; i <= R15_IDX ; i++ ) {
1496 if (bitVectBitValue(sym->regsUsed,i)) {
1498 emitcode("push","%s",avr_regWithIdx(i)->name);
1501 /* now for the pointer registers */
1502 if (bitVectBitValue(sym->regsUsed,R26_IDX)) {
1504 emitcode("push","r26");
1506 if (bitVectBitValue(sym->regsUsed,R27_IDX)) {
1508 emitcode("push","r27");
1510 if (bitVectBitValue(sym->regsUsed,R30_IDX)) {
1512 emitcode("push","r30");
1514 if (bitVectBitValue(sym->regsUsed,R31_IDX)) {
1516 emitcode("push","r31");
1518 /* adjust the stack for the function */
1520 emitcode ("push","r28");
1521 emitcode ("push","r29");
1522 emitcode ("in","r28,__SP_L__");
1523 emitcode ("in","r29,__SP_H__");
1524 if (sym->stack <= 63) {
1525 emitcode("sbiw","r28,%d",sym->stack);
1527 emitcode ("subi","r28,lo8(%d)",sym->stack);
1528 emitcode ("sbci","r29,hi8(%d)",sym->stack);
1530 emitcode("out","__SP_L__,r28");
1531 emitcode("out","__SP_H__,r29");
1535 /*-----------------------------------------------------------------*/
1536 /* genEndFunction - generates epilogue for functions */
1537 /*-----------------------------------------------------------------*/
1538 static void genEndFunction (iCode *ic)
1540 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1543 /* restore stack pointer */
1545 if (sym->stack <= 63) {
1546 emitcode("adiw","r28,%d",sym->stack);
1548 emitcode ("subi","r28,lo8(-%d)",sym->stack);
1549 emitcode ("sbci","r29,hi8(-%d)",sym->stack);
1551 emitcode("out","__SP_L__,r28");
1552 emitcode("out","__SP_H__,r29");
1554 /* pop frame pointer */
1555 emitcode ("pop","r29");
1556 emitcode ("pop","r28");
1558 /* restore preserved registers */
1559 if (bitVectBitValue(sym->regsUsed,R31_IDX)) {
1561 emitcode("pop","r31");
1563 if (bitVectBitValue(sym->regsUsed,R30_IDX)) {
1565 emitcode("pop","r30");
1567 if (bitVectBitValue(sym->regsUsed,R27_IDX)) {
1569 emitcode("push","r27");
1571 if (bitVectBitValue(sym->regsUsed,R26_IDX)) {
1573 emitcode("push","r26");
1575 for (i = R15_IDX ; i >= R2_IDX ; i-- ) {
1576 if (bitVectBitValue(sym->regsUsed,i)) {
1578 emitcode("pop","%s",avr_regWithIdx(i)->name);
1582 if (SPEC_CRTCL(sym->etype))
1585 if (IS_ISR(sym->etype)) {
1593 /*-----------------------------------------------------------------*/
1594 /* genRet - generate code for return statement */
1595 /*-----------------------------------------------------------------*/
1596 static void genRet (iCode *ic)
1598 int size,offset = 0 ;
1600 /* if we have no return value then
1601 just generate the "ret" */
1605 /* we have something to return then
1606 move the return value into place */
1607 aopOp(IC_LEFT(ic),ic,FALSE);
1608 size = AOP_SIZE(IC_LEFT(ic));
1611 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
1612 emitcode("ldi","%s,%s(%d)",fAVRReturn[offset],larray[offset],
1613 (int)floatFromVal (AOP(IC_LEFT(ic))->aopu.aop_lit),offset);
1616 l = aopGet(AOP(IC_LEFT(ic)),offset);
1617 if (strcmp(fAVRReturn[offset],l))
1618 emitcode("mov","%s,%s",fAVRReturn[offset],l);
1623 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
1626 /* generate a jump to the return label
1627 if the next is not the return statement */
1628 if (!(ic->next && ic->next->op == LABEL &&
1629 IC_LABEL(ic->next) == returnLabel))
1631 emitcode("rjmp","L%05d",returnLabel->key);
1635 /*-----------------------------------------------------------------*/
1636 /* genLabel - generates a label */
1637 /*-----------------------------------------------------------------*/
1638 static void genLabel (iCode *ic)
1640 /* special case never generate */
1641 if (IC_LABEL(ic) == entryLabel)
1644 emitcode("","L%05d:",IC_LABEL(ic)->key);
1647 /*-----------------------------------------------------------------*/
1648 /* genGoto - generates a ljmp */
1649 /*-----------------------------------------------------------------*/
1650 static void genGoto (iCode *ic)
1652 emitcode ("rjmp","L%05d:",(IC_LABEL(ic)->key+100));
1655 /*-----------------------------------------------------------------*/
1656 /* findLabelBackwards: walks back through the iCode chain looking */
1657 /* for the given label. Returns number of iCode instructions */
1658 /* between that label and given ic. */
1659 /* Returns zero if label not found. */
1660 /*-----------------------------------------------------------------*/
1661 static int findLabelBackwards(iCode *ic, int key)
1670 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
1672 /* printf("findLabelBackwards = %d\n", count); */
1680 /*-----------------------------------------------------------------*/
1681 /* genPlusIncr :- does addition with increment if possible */
1682 /*-----------------------------------------------------------------*/
1683 static bool genPlusIncr (iCode *ic)
1685 unsigned int icount ;
1687 /* will try to generate an increment */
1688 /* if the right side is not a literal
1690 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1693 icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
1695 /* if the sizes are greater than 2 or they are not the same regs
1697 if (!sameRegs(AOP(IC_LEFT(ic)),AOP(IC_RESULT(ic))))
1700 /* so we know LEFT & RESULT in the same registers and add
1702 /* for short & char types */
1703 if (AOP_SIZE(IC_RESULT(ic)) < 2) {
1705 emitcode("inc","%s",aopGet(AOP(IC_LEFT(ic)),0));
1708 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_LEFT(ic)),0),-icount);
1712 if (AOP_SIZE(IC_RESULT(ic)) <= 3) {
1713 /* if register pair and starts with 26/30 then adiw */
1714 if (isRegPair(AOP(IC_RESULT(ic))) && icount > 0 && icount < 64 &&
1715 ( IS_REGIDX(AOP(IC_RESULT(ic)),R26_IDX) ||
1716 IS_REGIDX(AOP(IC_RESULT(ic)),R30_IDX) )) {
1717 emitcode("adiw","%s,%d",aopGet(AOP(IC_RESULT(ic)),0),icount);
1722 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_RESULT(ic)),0),-icount);
1723 emitcode("sbci","%s,hi8(%d)",aopGet(AOP(IC_RESULT(ic)),1),-icount);
1727 /* for 32 bit longs */
1728 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_RESULT(ic)),0),-icount);
1729 emitcode("sbci","%s,hi8(%d)",aopGet(AOP(IC_RESULT(ic)),1),-icount);
1730 emitcode("sbci","%s,hlo8(%d)",aopGet(AOP(IC_RESULT(ic)),2),-icount);
1731 emitcode("sbci","%s,hhi8(%d)",aopGet(AOP(IC_RESULT(ic)),3),-icount);
1736 /* This is the pure and virtuous version of this code.
1737 * I'm pretty certain it's right, but not enough to toss the old
1740 static void adjustArithmeticResult (iCode *ic)
1742 if (opIsGptr(IC_RESULT(ic)) &&
1743 opIsGptr(IC_LEFT(ic)) &&
1744 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1746 aopPut(AOP(IC_RESULT(ic)),
1747 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1),
1751 if (opIsGptr(IC_RESULT(ic)) &&
1752 opIsGptr(IC_RIGHT(ic)) &&
1753 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
1755 aopPut(AOP(IC_RESULT(ic)),
1756 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1),
1760 if (opIsGptr(IC_RESULT(ic)) &&
1761 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
1762 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
1763 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
1764 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
1766 sprintf(buffer,"%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
1767 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
1771 /*-----------------------------------------------------------------*/
1772 /* genPlus - generates code for addition */
1773 /*-----------------------------------------------------------------*/
1774 static void genPlus (iCode *ic)
1776 int size, offset = 0;
1780 /* special cases :- */
1782 aopOp (IC_LEFT(ic),ic,FALSE);
1783 aopOp (IC_RIGHT(ic),ic,FALSE);
1784 aopOp (IC_RESULT(ic),ic,TRUE);
1786 /* if I can do an increment instead
1787 of add then GOOD for ME */
1788 if (genPlusIncr (ic) == TRUE)
1791 size = getDataSize(IC_RESULT(ic));
1792 samer = sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic)));
1796 aopPut(AOP(IC_RESULT(ic)),aopGet(AOP(IC_LEFT(ic)),offset),offset);
1798 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
1800 if(offset == 0) l = "add";
1803 emitcode(l,"%s,%s",aopGet(AOP(IC_RESULT(ic)),offset),
1804 aopGet(AOP(IC_RIGHT(ic)),offset));
1806 if (offset == 0) l = "subi";
1809 emitcode(l,"%s,%s(-%d)",aopGet(AOP(IC_RESULT(ic)),offset),
1811 (int)floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
1816 adjustArithmeticResult(ic);
1819 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1820 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1821 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1824 /*-----------------------------------------------------------------*/
1825 /* genMinusDec :- does subtraction with deccrement if possible */
1826 /*-----------------------------------------------------------------*/
1827 static bool genMinusDec (iCode *ic)
1829 unsigned int icount ;
1831 /* will try to generate an increment */
1832 /* if the right side is not a literal
1834 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1837 icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
1839 /* if the sizes are greater than 2 or they are not the same regs
1841 if (!sameRegs(AOP(IC_LEFT(ic)),AOP(IC_RIGHT(ic))))
1844 /* so we know LEFT & RESULT in the same registers and add
1846 /* for short & char types */
1847 if (AOP_SIZE(IC_RESULT(ic)) < 2) {
1849 emitcode("dec","%s",aopGet(AOP(IC_LEFT(ic)),0));
1852 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_LEFT(ic)),0),icount);
1856 if (AOP_SIZE(IC_RESULT(ic)) <= 3) {
1857 /* if register pair and starts with 26/30 then adiw */
1858 if (isRegPair(AOP(IC_RESULT(ic))) && icount > 0 && icount < 64 &&
1859 ( IS_REGIDX(AOP(IC_RESULT(ic)),R26_IDX) ||
1860 IS_REGIDX(AOP(IC_RESULT(ic)),R30_IDX) )) {
1861 emitcode("sbiw","%s,%d",aopGet(AOP(IC_RESULT(ic)),0),icount);
1866 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_RESULT(ic)),0),icount);
1867 emitcode("sbci","%s,hi8(%d)",aopGet(AOP(IC_RESULT(ic)),1),icount);
1870 /* for 32 bit longs */
1871 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_RESULT(ic)),0),icount);
1872 emitcode("sbci","%s,hi8(%d)",aopGet(AOP(IC_RESULT(ic)),1),icount);
1873 emitcode("sbci","%s,hlo8(%d)",aopGet(AOP(IC_RESULT(ic)),2),icount);
1874 emitcode("sbci","%s,hhi8(%d)",aopGet(AOP(IC_RESULT(ic)),3),icount);
1879 /*-----------------------------------------------------------------*/
1880 /* addSign - complete with sign */
1881 /*-----------------------------------------------------------------*/
1882 static void addSign(operand *result, int offset, int sign)
1884 int size = (getDataSize(result) - offset);
1887 emitcode("rlc","a");
1888 emitcode("subb","a,acc");
1890 aopPut(AOP(result),"a",offset++);
1893 aopPut(AOP(result),zero,offset++);
1897 /*-----------------------------------------------------------------*/
1898 /* genMinus - generates code for subtraction */
1899 /*-----------------------------------------------------------------*/
1900 static void genMinus (iCode *ic)
1902 int size, offset = 0, samer;
1905 aopOp (IC_LEFT(ic),ic,FALSE);
1906 aopOp (IC_RIGHT(ic),ic,FALSE);
1907 aopOp (IC_RESULT(ic),ic,TRUE);
1909 /* if I can do an decrement instead
1910 of subtract then GOOD for ME */
1911 if (genMinusDec (ic) == TRUE)
1914 size = getDataSize(IC_RESULT(ic));
1915 samer = sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic)));
1918 aopPut(AOP(IC_RESULT(ic)),aopGet(AOP(IC_LEFT(ic)),offset),offset);
1920 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
1922 if(offset == 0) l = "sub";
1925 emitcode(l,"%s,%s",aopGet(AOP(IC_RESULT(ic)),offset),
1926 aopGet(AOP(IC_RIGHT(ic)),offset));
1928 if (offset == 0) l = "subi";
1931 emitcode(l,"%s,%s(%d)",aopGet(AOP(IC_RESULT(ic)),offset),
1933 (int)floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
1938 adjustArithmeticResult(ic);
1941 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1942 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1943 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1946 /*-----------------------------------------------------------------*/
1947 /* genMultOneByte : 8 bit multiplication & division */
1948 /*-----------------------------------------------------------------*/
1949 static void genMultOneByte (operand *left,
1953 link *opetype = operandType(result);
1957 /* (if two literals, the value is computed before) */
1958 /* if one literal, literal on the right */
1959 if (AOP_TYPE(left) == AOP_LIT){
1965 size = AOP_SIZE(result);
1967 if (SPEC_USIGN(opetype)) {
1968 emitcode("mul","%s,%s", aopGet(AOP(left),0),aopGet(AOP(right),0));
1970 emitcode("muls","%s,%s", aopGet(AOP(left),0),
1971 aopGet(AOP(right),0));
1973 aopPut(AOP(result),"r0",0);
1975 aopPut(AOP(result),"r1",1);
1978 if (SPEC_USIGN(opetype)) {
1980 aopPut(AOP(result),zero,offset++);
1984 lbl = newiTempLabel(NULL);
1985 emitcode("ldi","r24,0");
1986 emitcode("brcc","L%05d",lbl->key);
1987 emitcode("ldi","r24,lo8(-1)");
1988 emitcode("","L%05d:",lbl->key);
1989 while (size--) aopPut(AOP(result),"r24",offset++);
1996 /*-----------------------------------------------------------------*/
1997 /* genMult - generates code for multiplication */
1998 /*-----------------------------------------------------------------*/
1999 static void genMult (iCode *ic)
2001 operand *left = IC_LEFT(ic);
2002 operand *right = IC_RIGHT(ic);
2003 operand *result= IC_RESULT(ic);
2005 /* assign the amsops */
2006 aopOp (left,ic,FALSE);
2007 aopOp (right,ic,FALSE);
2008 aopOp (result,ic,TRUE);
2010 /* if both are of size == 1 */
2011 if (AOP_SIZE(left) == 1 &&
2012 AOP_SIZE(right) == 1 ) {
2013 genMultOneByte(left,right,result);
2017 /* should have been converted to function call */
2021 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2022 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2023 freeAsmop(result,NULL,ic,TRUE);
2026 /*-----------------------------------------------------------------*/
2027 /* genDiv - generates code for division */
2028 /*-----------------------------------------------------------------*/
2029 static void genDiv (iCode *ic)
2031 /* should have been converted to function call */
2035 /*-----------------------------------------------------------------*/
2036 /* genMod - generates code for division */
2037 /*-----------------------------------------------------------------*/
2038 static void genMod (iCode *ic)
2040 /* should have been converted to function call */
2052 /*-----------------------------------------------------------------*/
2053 /* revavrcnd - reverse a conditional for avr */
2054 /*-----------------------------------------------------------------*/
2055 static int revavrcnd(int type)
2059 } rar[] = { { AVR_EQ, AVR_NE}, {AVR_LT, AVR_GE}};
2062 for (i = 0 ; i < (sizeof(rar)/sizeof(rar[0]));i++) {
2063 if (rar[i].type == type) return rar[i].rtype;
2064 if (rar[i].rtype== type) return rar[i].type;
2066 assert(1); /* cannot happen */
2069 static char *br_name[4] = {"breq","brne","brlt","brge"};
2070 static char *br_uname[4]= {"breq","brne","brlo","brcc"};
2072 /*-----------------------------------------------------------------*/
2073 /* genBranch - generate the branch instruction */
2074 /*-----------------------------------------------------------------*/
2075 static void genBranch (iCode *ifx, int br_type, int sign)
2077 int tj = (IC_TRUE(ifx) ? 1 : 0) ;
2079 if (tj) { /* if true jump */
2080 char *nm = (sign ? br_name[br_type] : br_uname[br_type]);
2081 emitcode(nm,"L%05d",IC_TRUE(ifx)->key);
2082 } else { /* if false jump */
2083 int rtype = revavrcnd(br_type);
2084 char *nm = (sign ? br_name[rtype] : br_uname[rtype]);
2085 emitcode(nm,"L%05d",IC_FALSE(ifx)->key);
2090 /*-----------------------------------------------------------------*/
2091 /* genCmp - compare & jump */
2092 /*-----------------------------------------------------------------*/
2093 static void genCmp (iCode *ic, iCode *ifx, int br_type)
2095 operand *left, *right, *result;
2096 link *letype , *retype;
2098 int sign, size, offset =0;
2101 right= IC_RIGHT(ic);
2102 result = IC_RESULT(ic);
2104 letype = getSpec(operandType(left));
2105 retype =getSpec(operandType(right));
2106 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2108 /* assign the amsops */
2109 aopOp (left,ic,FALSE);
2110 aopOp (right,ic,FALSE);
2111 aopOp (result,ic,TRUE);
2112 size = AOP_SIZE(left);
2116 if (AOP_TYPE(right) == AOP_LIT) {
2117 emitcode("cpi","%s,lo8(%d)",aopGet(AOP(left),0),
2118 (int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
2119 genBranch(ifx,br_type,sign);
2120 } else { /* right != literal */
2121 emitcode("cp","%s,%s",aopGet(AOP(left),0),aopGet(AOP(right),0));
2122 genBranch(ifx,br_type,sign);
2124 } else { /* size != 1 */
2127 emitcode("cp","%s,%s",aopGet(AOP(left),0),aopGet(AOP(right),0));
2129 emitcode("cpc","%s,%s",aopGet(AOP(left),offset),aopGet(AOP(right),offset));
2132 genBranch(ifx,br_type,sign);
2134 } else { /* no ifx */
2135 emitcode("clr","r0");
2138 emitcode("cp","%s,%s",aopGet(AOP(left),0),aopGet(AOP(right),0));
2140 emitcode("cpc","%s,%s",aopGet(AOP(left),offset),aopGet(AOP(right),offset));
2143 lbl = newiTempLabel(NULL);
2144 br_type = revavrcnd(br_type);
2145 if (sign) emitcode(br_uname[br_type],"L%05d",lbl->key);
2146 else emitcode(br_name[br_type],"L%05d",lbl->key);
2147 emitcode("inc","r0");
2148 emitcode("","L%05d:",lbl->key);
2149 aopPut(AOP(result),"r0",0);
2150 size = AOP_SIZE(result) - 1;
2152 while (size--) aopPut(AOP(result),zero,offset++);
2155 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2156 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2157 freeAsmop(result,NULL,ic,TRUE);
2160 /*-----------------------------------------------------------------*/
2161 /* genCmpGt :- greater than comparison */
2162 /*-----------------------------------------------------------------*/
2163 static void genCmpGt (iCode *ic, iCode *ifx)
2165 /* should have transformed by the parser */
2169 /*-----------------------------------------------------------------*/
2170 /* genCmpLt - less than comparisons */
2171 /*-----------------------------------------------------------------*/
2172 static void genCmpLt (iCode *ic, iCode *ifx)
2174 genCmp(ic,ifx,AVR_LT);
2177 /*-----------------------------------------------------------------*/
2178 /* genCmpEq - generates code for equal to */
2179 /*-----------------------------------------------------------------*/
2180 static void genCmpEq (iCode *ic, iCode *ifx)
2182 genCmp(ic,ifx,AVR_EQ);
2185 /*-----------------------------------------------------------------*/
2186 /* genCmpNe - generates code for not equal to */
2187 /*-----------------------------------------------------------------*/
2188 static void genCmpNe (iCode *ic, iCode *ifx)
2190 genCmp(ic,ifx,AVR_NE);
2193 /*-----------------------------------------------------------------*/
2194 /* genCmpGe - generates code for greater than equal to */
2195 /*-----------------------------------------------------------------*/
2196 static void genCmpGe (iCode *ic, iCode *ifx)
2198 genCmp(ic,ifx,AVR_GE);
2201 /*-----------------------------------------------------------------*/
2202 /* genCmpLe - generates code for less than equal to */
2203 /*-----------------------------------------------------------------*/
2204 static void genCmpLe (iCode *ic, iCode *ifx)
2206 operand *left = IC_LEFT(ic);
2207 operand *right= IC_RIGHT(ic);
2209 IC_RIGHT(ic) = left;
2210 IC_LEFT(ic) = right;
2211 genCmp(ic,ifx,AVR_GE);
2214 /*-----------------------------------------------------------------*/
2215 /* ifxForOp - returns the icode containing the ifx for operand */
2216 /*-----------------------------------------------------------------*/
2217 static iCode *ifxForOp ( operand *op, iCode *ic )
2219 /* if true symbol then needs to be assigned */
2220 if (IS_TRUE_SYMOP(op))
2223 /* if this has register type condition and
2224 the next instruction is ifx with the same operand
2225 and live to of the operand is upto the ifx only then */
2227 ic->next->op == IFX &&
2228 IC_COND(ic->next)->key == op->key &&
2229 OP_SYMBOL(op)->liveTo <= ic->next->seq )
2234 /*-----------------------------------------------------------------*/
2235 /* genAndOp - for && operation */
2236 /*-----------------------------------------------------------------*/
2237 static void genAndOp (iCode *ic)
2239 operand *left,*right, *result;
2243 /* note here that && operations that are in an
2244 if statement are taken away by backPatchLabels
2245 only those used in arthmetic operations remain */
2246 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2247 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2248 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2250 tlbl = newiTempLabel(NULL);
2251 toBoolean(left,"r0",TRUE);
2252 toBoolean(right,"r1",TRUE);
2253 emitcode("and","r0,r1");
2254 emitcode("ldi","r24,1");
2255 emitcode("breq","L%05d",tlbl->key);
2256 emitcode("dec","r24");
2257 emitcode("","L%05d:",tlbl->key);
2258 aopPut(AOP(result),"r24",0);
2259 size = AOP_SIZE(result) -1;
2261 while (size--) aopPut(AOP(result),zero,offset++);
2263 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2264 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2265 freeAsmop(result,NULL,ic,TRUE);
2269 /*-----------------------------------------------------------------*/
2270 /* genOrOp - for || operation */
2271 /*-----------------------------------------------------------------*/
2272 static void genOrOp (iCode *ic)
2274 operand *left,*right, *result;
2278 /* note here that || operations that are in an
2279 if statement are taken away by backPatchLabels
2280 only those used in arthmetic operations remain */
2281 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2282 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2283 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2285 tlbl = newiTempLabel(NULL);
2286 toBoolean(left,"r0",TRUE);
2287 toBoolean(right,"r0",FALSE);
2288 emitcode("ldi","r24,1");
2289 emitcode("breq","L%05d",tlbl->key);
2290 emitcode("dec","r24");
2291 emitcode("","L%05d:",tlbl->key);
2292 aopPut(AOP(result),"r24",0);
2293 size = AOP_SIZE(result) -1;
2295 while (size--) aopPut(AOP(result),zero,offset++);
2297 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2298 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2299 freeAsmop(result,NULL,ic,TRUE);
2302 /*-----------------------------------------------------------------*/
2303 /* isLiteralBit - test if lit == 2^n */
2304 /*-----------------------------------------------------------------*/
2305 static int isLiteralBit(unsigned long lit)
2307 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
2308 0x100L,0x200L,0x400L,0x800L,
2309 0x1000L,0x2000L,0x4000L,0x8000L,
2310 0x10000L,0x20000L,0x40000L,0x80000L,
2311 0x100000L,0x200000L,0x400000L,0x800000L,
2312 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
2313 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
2316 for(idx = 0; idx < 32; idx++)
2322 enum { AVR_AND = 0, AVR_OR, AVR_XOR };
2323 static char *bopnames_lit[] = {"andi","ori"};
2324 static char *bopnames[] = {"and","or","eor"};
2325 /*-----------------------------------------------------------------*/
2326 /* genBitWise - generate bitwise operations */
2327 /*-----------------------------------------------------------------*/
2328 static void genBitWise(iCode *ic, iCode *ifx, int bitop)
2330 operand *left, *right, *result;
2334 int samerl, samerr ;
2336 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2337 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2338 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2340 size = AOP_SIZE(left);
2342 if (ifx) { /* used only for jumps */
2343 if (AOP_TYPE(right) == AOP_LIT &&
2344 (bitop == AVR_AND || bitop == AVR_OR)) {
2345 int lit = (int) floatFromVal (AOP(right)->aopu.aop_lit);
2346 int p2 = powof2(lit);
2347 if (bitop == AVR_AND && p2) { /* right side is a power of 2 */
2348 l = aopGet(AOP(left),p2 / 8);
2350 emitcode("sbrc","%s,%d",l,(p2 % 8));
2351 emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2353 emitcode("sbrs","%s,%d",l,(p2 % 8));
2354 emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2356 } else { /* right not power of two */
2357 int eh = OP_SYMBOL(left)->liveTo <= ic->seq;
2360 emitcode(bopnames_lit[bitop],"%s,lo8(%d)",
2361 aopGet(AOP(IC_LEFT(ic)),0), lit);
2363 MOVR0(aopGet(AOP(IC_LEFT(ic)),0));
2364 emitcode(bopnames_lit[bitop],"r0,lo8(%d)",lit);
2366 lbl = newiTempLabel(NULL);
2368 emitcode("breq","L%05d",lbl->key);
2369 emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2371 emitcode("brne","L%05d",lbl->key);
2372 emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2374 emitcode("","L%05d:",lbl->key);
2375 } else if (size == 2) {
2376 emitcode("mov","r24,%s",aopGet(AOP(IC_LEFT(ic)),0));
2377 emitcode("mov","r25,%s",aopGet(AOP(IC_LEFT(ic)),1));
2378 emitcode(bopnames_lit[bitop],"r24,lo8(%d)",lit);
2379 emitcode(bopnames_lit[bitop],"r25,hi8(%d)",lit);
2380 emitcode("sbiw","r24,0");
2381 lbl = newiTempLabel(NULL);
2383 emitcode("breq","L%05d",lbl->key);
2384 emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2386 emitcode("brne","L%05d",lbl->key);
2387 emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2389 emitcode("","L%05d:",lbl->key);
2391 lbl = newiTempLabel(NULL);
2392 lbl1 = newiTempLabel(NULL);
2395 emitcode(bopnames_lit[bitop],"%s,lo8(%d)",
2396 aopGet(AOP(IC_LEFT(ic)),offset), lit);
2398 MOVR0(aopGet(AOP(IC_LEFT(ic)),offset));
2399 emitcode("andi","r0,lo8(%d)",lit);
2401 emitcode("brne","L%05d",lbl->key);
2405 if (IC_FALSE(ifx)) emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2406 else emitcode("rjmp","L%05d",lbl1->key);
2407 emitcode("","L%05d:",lbl->key);
2409 if (IC_TRUE(ifx)) emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2410 emitcode("","L%05d:",lbl1->key);
2414 } else { /* right is not a literal */
2415 int eh = OP_SYMBOL(left)->liveTo <= ic->seq;
2416 int reh = OP_SYMBOL(right)->liveTo <= ic->seq;
2419 emitcode(bopnames[bitop],"%s,%s",
2420 aopGet(AOP(IC_LEFT(ic)),0),
2421 aopGet(AOP(IC_RIGHT(ic)),0));
2423 emitcode(bopnames[bitop],"%s,%s",
2424 aopGet(AOP(IC_RIGHT(ic)),0),
2425 aopGet(AOP(IC_LEFT(ic)),0));
2427 MOVR0(aopGet(AOP(IC_LEFT(ic)),0));
2428 emitcode(bopnames[bitop],"r0,%s",aopGet(AOP(IC_RIGHT(ic)),0));
2430 lbl = newiTempLabel(NULL);
2432 emitcode("breq","L%05d",lbl->key);
2433 emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2435 emitcode("brne","L%05d",lbl->key);
2436 emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2438 emitcode("","L%05d:",lbl->key);
2439 } else if (size == 2) {
2440 emitcode("mov","r24,%s",aopGet(AOP(IC_LEFT(ic)),0));
2441 emitcode("mov","r25,%s",aopGet(AOP(IC_LEFT(ic)),1));
2442 emitcode(bopnames[bitop],"r24,%s",aopGet(AOP(IC_RIGHT(ic)),0));
2443 emitcode(bopnames[bitop],"r25,%s",aopGet(AOP(IC_RIGHT(ic)),1));
2444 emitcode("sbiw","r24,0");
2445 lbl = newiTempLabel(NULL);
2447 emitcode("breq","L%05d",lbl->key);
2448 emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2450 emitcode("brne","L%05d",lbl->key);
2451 emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2453 emitcode("","L%05d:",lbl->key);
2455 lbl = newiTempLabel(NULL);
2456 lbl1 = newiTempLabel(NULL);
2459 emitcode(bopnames[bitop],"%s,%s",
2460 aopGet(AOP(IC_LEFT(ic)),offset),
2461 aopGet(AOP(IC_RIGHT(ic)),offset));
2463 emitcode(bopnames[bitop],"%s,%s",
2464 aopGet(AOP(IC_RIGHT(ic)),offset),
2465 aopGet(AOP(IC_LEFT(ic)),offset));
2467 MOVR0(aopGet(AOP(IC_LEFT(ic)),offset));
2468 emitcode(bopnames[bitop],"r0,%s",aopGet(AOP(IC_RIGHT(ic)),offset));
2470 emitcode("brne","L%05d",lbl->key);
2474 if (IC_FALSE(ifx)) emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2475 else emitcode("rjmp","L%05d",lbl1->key);
2476 emitcode("","L%05d:",lbl->key);
2478 if (IC_TRUE(ifx)) emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2479 emitcode("","L%05d:",lbl1->key);
2486 /* result needs to go a register */
2487 samerl = sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic)));
2488 samerr = sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)));
2491 if (AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT && (bitop == AVR_AND || bitop == AVR_OR)) {
2492 emitcode(bopnames_lit[bitop],"%s,%s(%d)",aopGet(AOP(IC_LEFT(ic)),offset),
2493 larray[offset],(int) floatFromVal (AOP(right)->aopu.aop_lit));
2495 emitcode(bopnames[bitop],"%s,%s",aopGet(AOP(IC_LEFT(ic)),offset),
2496 aopGet(AOP(IC_RIGHT(ic)),offset));
2498 } else if (samerr) {
2499 emitcode(bopnames[bitop],"%s,%s",aopGet(AOP(IC_RIGHT(ic)),offset),
2500 aopGet(AOP(IC_LEFT(ic)),offset));
2502 aopPut(AOP(IC_RESULT(ic)),aopGet(AOP(IC_LEFT(ic)),offset),offset);
2503 emitcode(bopnames[bitop],aopGet(AOP(IC_RESULT(ic)),offset),
2504 aopGet(AOP(IC_RIGHT(ic)),offset));
2509 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2510 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2511 freeAsmop(result,NULL,ic,TRUE);
2514 /*-----------------------------------------------------------------*/
2515 /* genAnd - code for and */
2516 /*-----------------------------------------------------------------*/
2517 static void genAnd (iCode *ic, iCode *ifx)
2519 genBitWise(ic,ifx,AVR_AND);
2522 /*-----------------------------------------------------------------*/
2523 /* genOr - code for or */
2524 /*-----------------------------------------------------------------*/
2525 static void genOr (iCode *ic, iCode *ifx)
2527 genBitWise(ic,ifx,AVR_OR);
2530 /*-----------------------------------------------------------------*/
2531 /* genXor - code for xclusive or */
2532 /*-----------------------------------------------------------------*/
2533 static void genXor (iCode *ic, iCode *ifx)
2535 genBitWise(ic,ifx,AVR_XOR);
2538 /*-----------------------------------------------------------------*/
2539 /* genInline - write the inline code out */
2540 /*-----------------------------------------------------------------*/
2541 static void genInline (iCode *ic)
2543 char buffer[MAX_INLINEASM];
2547 _G.inLine += (!options.asmpeep);
2548 strcpy(buffer,IC_INLINE(ic));
2550 /* emit each line as a code */
2569 /* emitcode("",buffer); */
2570 _G.inLine -= (!options.asmpeep);
2573 /*-----------------------------------------------------------------*/
2574 /* genRotC - rotate right/left with carry , lr = 1 rotate right */
2575 /*-----------------------------------------------------------------*/
2576 static void genRotC (iCode *ic, int lr)
2578 operand *left , *result ;
2579 int size, offset = 0;
2582 /* rotate right with carry */
2584 result=IC_RESULT(ic);
2585 aopOp (left,ic,FALSE);
2586 aopOp (result,ic,FALSE);
2588 /* move it to the result */
2589 size = AOP_SIZE(result);
2590 if (!sameRegs(AOP(left),AOP(result))) {
2594 aopGet(AOP(left),offset),
2598 size = AOP_SIZE(result);
2600 if (lr) offset = size - 1;
2604 emitcode ("sbrc","%s,%d",aopGet(AOP(result),offset),
2609 emitcode((lr ? "ror" : "rol"),"%s",aopGet(AOP(result),offset));
2613 freeAsmop(left,NULL,ic,TRUE);
2614 freeAsmop(result,NULL,ic,TRUE);
2617 /*-----------------------------------------------------------------*/
2618 /* genRRC - rotate right with carry */
2619 /*-----------------------------------------------------------------*/
2620 static void genRRC (iCode *ic)
2625 /*-----------------------------------------------------------------*/
2626 /* genRLC - generate code for rotate left with carry */
2627 /*-----------------------------------------------------------------*/
2628 static void genRLC (iCode *ic)
2633 /*-----------------------------------------------------------------*/
2634 /* genGetHbit - generates code get highest order bit */
2635 /*-----------------------------------------------------------------*/
2636 static void genGetHbit (iCode *ic)
2638 operand *left, *result;
2642 result=IC_RESULT(ic);
2643 aopOp (left,ic,FALSE);
2644 aopOp (result,ic,FALSE);
2646 size = AOP_SIZE(result);
2647 if (!sameRegs(AOP(left),AOP(result))) {
2648 emitcode("clr","%s",aopGet(AOP(result),size -1));
2649 emitcode("sbrc","%s,7",aopGet(AOP(left),size -1));
2650 emitcode("subi","%s,lo8(-1)",aopGet(AOP(result),size-1));
2652 emitcode("clr","r0");
2653 emitcode("sbrc","%s,7",aopGet(AOP(left),size-1));
2654 emitcode("subi","r0,lo8(-1)");
2655 aopPut(AOP(result),"r0",0);
2660 emitcode("clr",aopGet(AOP(result),offset++));
2662 freeAsmop(left,NULL,ic,TRUE);
2663 freeAsmop(result,NULL,ic,TRUE);
2666 /*-----------------------------------------------------------------*/
2667 /* genShiftLeftLit - shift left by a known amount */
2668 /*-----------------------------------------------------------------*/
2669 static void genShiftLeftLit (iCode *ic)
2671 operand *left,*right, *result;
2672 int size , shCount, offset =0;
2675 right = IC_RIGHT(ic);
2677 result = IC_RESULT(ic);
2679 aopOp(left,ic,FALSE);
2680 aopOp(result,ic,FALSE);
2681 size = AOP_SIZE(result);
2682 shCount = (int)floatFromVal (AOP(right)->aopu.aop_lit);
2684 if (shCount > (size*8 -1)) {
2685 while (size--) aopPut(AOP(result),zero,offset++);
2690 if (!sameRegs(AOP(left),AOP(result)))
2691 aopPut(AOP(result),aopGet(AOP(left),0),0);
2693 emitcode("swap","%s",aopGet(AOP(result),0));
2694 emitcode("andi","%s,0xf0");
2698 emitcode("add","%s,%s",aopGet(AOP(result),0),aopGet(AOP(result),0));
2702 emitcode("lsl","%s",aopGet(AOP(result),0));
2705 if (shCount >= 12) {
2706 aopPut(AOP(result),aopGet(AOP(left),0),1);
2707 aopPut(AOP(result),zero,0);
2708 emitcode("swap","%s",aopGet(AOP(result),1));
2709 emitcode("andi","%s,0xf0",aopGet(AOP(result),1));
2714 aopPut(AOP(result),aopGet(AOP(left),0),1);
2715 aopPut(AOP(result),zero,0);
2721 emitcode("swap","%s",aopGet(AOP(result),1));
2722 emitcode("andi","%s,0xf0",aopGet(AOP(result),1));
2728 if (sameRegs(AOP(left),AOP(result))) {
2729 emitcode("mov","r1,%s",aopGet(AOP(left),0));
2730 emitcode("swap","%s",aopGet(AOP(left),0));
2731 emitcode("andi","%s,0xf0",aopGet(AOP(left),0));
2732 emitcode("andi","r1,0x0f");
2734 emitcode("lsl","%s",aopGet(AOP(left),0));
2735 emitcode("lsl","r1");
2737 emitcode("swap","%s",aopGet(AOP(result),1));
2738 emitcode("andi","%s,0xf0",aopGet(AOP(result),1));
2739 while (ssh--) emitcode("lsl","%s",aopGet(AOP(result),1));
2740 emitcode("or","%s,r1",aopGet(AOP(result),1));
2743 MOVR0(aopGet(AOP(left),0));
2744 emitcode("mov","r1,r0");
2745 emitcode("swap","r0");
2746 emitcode("andi","r0,0xf0");
2747 emitcode("andi","r1,0x0f");
2749 emitcode("lsl","r0");
2750 emitcode("lsl","r1");
2752 aopPut(AOP(result),"r0",0);
2753 aopPut(AOP(result),aopGet(AOP(left),1),1);
2754 emitcode("swap","%s",aopGet(AOP(result),1));
2755 emitcode("andi","%s,0xf0",aopGet(AOP(result),1));
2756 while (ssh--) emitcode("lsl","%s",aopGet(AOP(result),1));
2757 emitcode("or","%s,r1",aopGet(AOP(result),1));
2762 if (!lByteZ && !sameRegs(AOP(result),AOP(left)) && shCount) {
2765 aopPut(AOP(result),aopGet(AOP(left),offset),offset);
2771 emitcode("lsl","%s",aopGet(AOP(result),1));
2773 emitcode("lsl","%s",aopGet(AOP(result),0));
2774 emitcode("rol","%s",aopGet(AOP(result),1));
2779 assert("shifting generic pointer ?\n");
2782 /* 32 bits we do only byte boundaries */
2783 if (shCount >= 24) {
2784 aopPut(AOP(result),aopGet(AOP(left),0),3);
2785 aopPut(AOP(result),zero,2);
2786 aopPut(AOP(result),zero,1);
2787 aopPut(AOP(result),zero,0);
2791 if (shCount >= 16) {
2792 aopPut(AOP(result),aopGet(AOP(left),0),3);
2793 aopPut(AOP(result),aopGet(AOP(left),1),2);
2794 aopPut(AOP(result),zero,1);
2795 aopPut(AOP(result),zero,0);
2800 aopPut(AOP(result),aopGet(AOP(left),0),3);
2801 aopPut(AOP(result),aopGet(AOP(left),1),2);
2802 aopPut(AOP(result),aopGet(AOP(left),2),1);
2803 aopPut(AOP(result),zero,0);
2807 if (!lByteZ && !sameRegs(AOP(left),AOP(right))) {
2810 aopPut(AOP(result),aopGet(AOP(left),offset),offset);
2814 size = AOP_SIZE(result);
2820 emitcode("lsl","%s",aopGet(AOP(result),0));
2821 emitcode("rol","%s",aopGet(AOP(result),1));
2822 emitcode("rol","%s",aopGet(AOP(result),2));
2823 emitcode("rol","%s",aopGet(AOP(result),3));
2828 emitcode("lsl","%s",aopGet(AOP(result),1));
2829 emitcode("rol","%s",aopGet(AOP(result),2));
2830 emitcode("rol","%s",aopGet(AOP(result),3));
2835 emitcode("lsl","%s",aopGet(AOP(result),2));
2836 emitcode("rol","%s",aopGet(AOP(result),3));
2841 emitcode("lsl","%s",aopGet(AOP(result),3));
2850 freeAsmop(left,NULL,ic,TRUE);
2851 freeAsmop(right,NULL,ic,TRUE);
2852 freeAsmop(result,NULL,ic,TRUE);
2855 /*-----------------------------------------------------------------*/
2856 /* genLeftShift - generates code for left shifting */
2857 /*-----------------------------------------------------------------*/
2858 static void genLeftShift (iCode *ic)
2860 operand *left,*right, *result;
2863 symbol *tlbl , *tlbl1;
2865 right = IC_RIGHT(ic);
2867 result = IC_RESULT(ic);
2869 aopOp(right,ic,FALSE);
2871 if (AOP_TYPE(right) == AOP_LIT) {
2872 genShiftLeftLit(ic);
2877 aopOp(left,ic,FALSE);
2878 aopOp(result,ic,FALSE);
2879 size = AOP_SIZE(result);
2881 if (AOP_SIZE(right) > 1) {
2882 if (isRegPair(AOP(right))) {
2883 emitcode("movw","r24,%s",aopGet(AOP(right),0));
2885 emitcode("mov","r24,%s",aopGet(AOP(right),0));
2886 emitcode("mov","r25,%s",aopGet(AOP(right),1));
2889 emitcode("mov","r24,%s",aopGet(AOP(right),0));
2891 if (!sameRegs(AOP(left),AOP(result))) {
2893 aopPut(AOP(result),aopGet(AOP(left),offset),offset);
2896 size = AOP_SIZE(result);
2898 tlbl = newiTempLabel(NULL);
2899 emitcode("","L%05d:",tlbl->key);
2902 if (offset) emitcode("rol","%s",aopGet(AOP(result),offset));
2903 else emitcode("lsl","%s",aopGet(AOP(result),0));
2906 if (AOP_SIZE(right) > 1) emitcode("sbiw","r24,1");
2907 else emitcode("dec","r24");
2908 emitcode("brne","L%05d",tlbl->key);
2911 freeAsmop(left,NULL,ic,TRUE);
2912 freeAsmop(right,NULL,ic,TRUE);
2913 freeAsmop(result,NULL,ic,TRUE);
2916 /*-----------------------------------------------------------------*/
2917 /* genRightShift - generate code for right shifting */
2918 /*-----------------------------------------------------------------*/
2919 static void genRightShift (iCode *ic)
2921 operand *right, *left, *result;
2925 symbol *tlbl, *tlbl1 ;
2929 freeAsmop(left,NULL,ic,TRUE);
2930 freeAsmop(result,NULL,ic,TRUE);
2933 /*-----------------------------------------------------------------*/
2934 /* genUnpackBits - generates code for unpacking bits */
2935 /*-----------------------------------------------------------------*/
2936 static void genUnpackBits (operand *result, char *rname, int ptype)
2943 etype = getSpec(operandType(result));
2945 /* read the first byte */
2950 emitcode("mov","a,@%s",rname);
2954 emitcode("movx","a,@%s",rname);
2958 emitcode("movx","a,@dptr");
2962 emitcode("clr","a");
2963 emitcode("movc","a","@a+dptr");
2967 emitcode("lcall","__gptrget");
2971 /* if we have bitdisplacement then it fits */
2972 /* into this byte completely or if length is */
2973 /* less than a byte */
2974 if ((shCnt = SPEC_BSTR(etype)) ||
2975 (SPEC_BLEN(etype) <= 8)) {
2977 /* shift right acc */
2980 emitcode("anl","a,#0x%02x",
2981 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
2982 aopPut(AOP(result),"a",offset);
2986 /* bit field did not fit in a byte */
2987 rlen = SPEC_BLEN(etype) - 8;
2988 aopPut(AOP(result),"a",offset++);
2995 emitcode("inc","%s",rname);
2996 emitcode("mov","a,@%s",rname);
3000 emitcode("inc","%s",rname);
3001 emitcode("movx","a,@%s",rname);
3005 emitcode("inc","dptr");
3006 emitcode("movx","a,@dptr");
3010 emitcode("clr","a");
3011 emitcode("inc","dptr");
3012 emitcode("movc","a","@a+dptr");
3016 emitcode("inc","dptr");
3017 emitcode("lcall","__gptrget");
3022 /* if we are done */
3026 aopPut(AOP(result),"a",offset++);
3031 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
3032 aopPut(AOP(result),"a",offset);
3039 /*-----------------------------------------------------------------*/
3040 /* genDataPointerGet - generates code when ptr offset is known */
3041 /*-----------------------------------------------------------------*/
3042 static void genDataPointerGet (operand *left,
3048 int size , offset = 0;
3049 aopOp(result,ic,TRUE);
3051 /* get the string representation of the name */
3052 l = aopGet(AOP(left),0);
3053 size = AOP_SIZE(result);
3056 sprintf(buffer,"(%s + %d)",l+1,offset);
3058 sprintf(buffer,"%s",l+1);
3059 aopPut(AOP(result),buffer,offset++);
3062 freeAsmop(left,NULL,ic,TRUE);
3063 freeAsmop(result,NULL,ic,TRUE);
3066 /*-----------------------------------------------------------------*/
3067 /* genNearPointerGet - emitcode for near pointer fetch */
3068 /*-----------------------------------------------------------------*/
3069 static void genNearPointerGet (operand *left,
3076 link *rtype, *retype;
3077 link *ltype = operandType(left);
3080 rtype = operandType(result);
3081 retype= getSpec(rtype);
3083 aopOp(left,ic,FALSE);
3085 /* if left is rematerialisable and
3086 result is not bit variable type and
3087 the left is pointer to data space i.e
3088 lower 128 bytes of space */
3089 if (AOP_TYPE(left) == AOP_IMMD &&
3090 !IS_BITVAR(retype) &&
3091 DCL_TYPE(ltype) == POINTER) {
3092 genDataPointerGet (left,result,ic);
3096 /* if the value is already in a pointer register
3097 then don't need anything more */
3098 if (!AOP_INPREG(AOP(left))) {
3099 /* otherwise get a free pointer register */
3101 preg = getFreePtr(ic,&aop,FALSE,0);
3102 emitcode("mov","%s,%s",
3104 aopGet(AOP(left),0));
3105 rname = preg->name ;
3107 rname = aopGet(AOP(left),0);
3109 freeAsmop(left,NULL,ic,TRUE);
3110 aopOp (result,ic,FALSE);
3112 /* if bitfield then unpack the bits */
3113 if (IS_BITVAR(retype))
3114 genUnpackBits (result,rname,POINTER);
3116 /* we have can just get the values */
3117 int size = AOP_SIZE(result);
3121 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
3123 emitcode("mov","a,@%s",rname);
3124 aopPut(AOP(result),"a",offset);
3126 sprintf(buffer,"@%s",rname);
3127 aopPut(AOP(result),buffer,offset);
3131 emitcode("inc","%s",rname);
3135 /* now some housekeeping stuff */
3137 /* we had to allocate for this iCode */
3138 freeAsmop(NULL,aop,ic,TRUE);
3140 /* we did not allocate which means left
3141 already in a pointer register, then
3142 if size > 0 && this could be used again
3143 we have to point it back to where it
3145 if (AOP_SIZE(result) > 1 &&
3146 !OP_SYMBOL(left)->remat &&
3147 ( OP_SYMBOL(left)->liveTo > ic->seq ||
3149 int size = AOP_SIZE(result) - 1;
3151 emitcode("dec","%s",rname);
3156 freeAsmop(result,NULL,ic,TRUE);
3160 /*-----------------------------------------------------------------*/
3161 /* genPagedPointerGet - emitcode for paged pointer fetch */
3162 /*-----------------------------------------------------------------*/
3163 static void genPagedPointerGet (operand *left,
3170 link *rtype, *retype;
3172 rtype = operandType(result);
3173 retype= getSpec(rtype);
3175 aopOp(left,ic,FALSE);
3177 /* if the value is already in a pointer register
3178 then don't need anything more */
3179 if (!AOP_INPREG(AOP(left))) {
3180 /* otherwise get a free pointer register */
3182 preg = getFreePtr(ic,&aop,FALSE,0);
3183 emitcode("mov","%s,%s",
3185 aopGet(AOP(left),0));
3186 rname = preg->name ;
3188 rname = aopGet(AOP(left),0);
3190 freeAsmop(left,NULL,ic,TRUE);
3191 aopOp (result,ic,FALSE);
3193 /* if bitfield then unpack the bits */
3194 if (IS_BITVAR(retype))
3195 genUnpackBits (result,rname,PPOINTER);
3197 /* we have can just get the values */
3198 int size = AOP_SIZE(result);
3203 emitcode("movx","a,@%s",rname);
3204 aopPut(AOP(result),"a",offset);
3209 emitcode("inc","%s",rname);
3213 /* now some housekeeping stuff */
3215 /* we had to allocate for this iCode */
3216 freeAsmop(NULL,aop,ic,TRUE);
3218 /* we did not allocate which means left
3219 already in a pointer register, then
3220 if size > 0 && this could be used again
3221 we have to point it back to where it
3223 if (AOP_SIZE(result) > 1 &&
3224 !OP_SYMBOL(left)->remat &&
3225 ( OP_SYMBOL(left)->liveTo > ic->seq ||
3227 int size = AOP_SIZE(result) - 1;
3229 emitcode("dec","%s",rname);
3234 freeAsmop(result,NULL,ic,TRUE);
3239 /*-----------------------------------------------------------------*/
3240 /* genFarPointerGet - gget value from far space */
3241 /*-----------------------------------------------------------------*/
3242 static void genFarPointerGet (operand *left,
3243 operand *result, iCode *ic)
3246 link *retype = getSpec(operandType(result));
3248 aopOp(left,ic,FALSE);
3250 /* if the operand is already in dptr
3251 then we do nothing else we move the value to dptr */
3252 if (AOP_TYPE(left) != AOP_STR) {
3253 /* if this is remateriazable */
3254 if (AOP_TYPE(left) == AOP_IMMD)
3255 emitcode("mov","dptr,%s",aopGet(AOP(left),0));
3256 else { /* we need to get it byte by byte */
3257 emitcode("mov","dpl,%s",aopGet(AOP(left),0));
3258 emitcode("mov","dph,%s",aopGet(AOP(left),1));
3259 if (options.model == MODEL_FLAT24)
3261 emitcode("mov", "dpx,%s",aopGet(AOP(left),2));
3265 /* so dptr know contains the address */
3266 freeAsmop(left,NULL,ic,TRUE);
3267 aopOp(result,ic,FALSE);
3269 /* if bit then unpack */
3270 if (IS_BITVAR(retype))
3271 genUnpackBits(result,"dptr",FPOINTER);
3273 size = AOP_SIZE(result);
3277 emitcode("movx","a,@dptr");
3278 aopPut(AOP(result),"a",offset++);
3280 emitcode("inc","dptr");
3284 freeAsmop(result,NULL,ic,TRUE);
3287 /*-----------------------------------------------------------------*/
3288 /* emitcodePointerGet - gget value from code space */
3289 /*-----------------------------------------------------------------*/
3290 static void emitcodePointerGet (operand *left,
3291 operand *result, iCode *ic)
3294 link *retype = getSpec(operandType(result));
3296 aopOp(left,ic,FALSE);
3298 /* if the operand is already in dptr
3299 then we do nothing else we move the value to dptr */
3300 if (AOP_TYPE(left) != AOP_STR) {
3301 /* if this is remateriazable */
3302 if (AOP_TYPE(left) == AOP_IMMD)
3303 emitcode("mov","dptr,%s",aopGet(AOP(left),0));
3304 else { /* we need to get it byte by byte */
3305 emitcode("mov","dpl,%s",aopGet(AOP(left),0));
3306 emitcode("mov","dph,%s",aopGet(AOP(left),1));
3307 if (options.model == MODEL_FLAT24)
3309 emitcode("mov", "dpx,%s",aopGet(AOP(left),2));
3313 /* so dptr know contains the address */
3314 freeAsmop(left,NULL,ic,TRUE);
3315 aopOp(result,ic,FALSE);
3317 /* if bit then unpack */
3318 if (IS_BITVAR(retype))
3319 genUnpackBits(result,"dptr",CPOINTER);
3321 size = AOP_SIZE(result);
3325 emitcode("clr","a");
3326 emitcode("movc","a,@a+dptr");
3327 aopPut(AOP(result),"a",offset++);
3329 emitcode("inc","dptr");
3333 freeAsmop(result,NULL,ic,TRUE);
3336 /*-----------------------------------------------------------------*/
3337 /* genGenPointerGet - gget value from generic pointer space */
3338 /*-----------------------------------------------------------------*/
3339 static void genGenPointerGet (operand *left,
3340 operand *result, iCode *ic)
3343 link *retype = getSpec(operandType(result));
3345 aopOp(left,ic,FALSE);
3347 /* if the operand is already in dptr
3348 then we do nothing else we move the value to dptr */
3349 if (AOP_TYPE(left) != AOP_STR) {
3350 /* if this is remateriazable */
3351 if (AOP_TYPE(left) == AOP_IMMD) {
3352 emitcode("mov","dptr,%s",aopGet(AOP(left),0));
3353 emitcode("mov","b,#%d",pointerCode(retype));
3355 else { /* we need to get it byte by byte */
3356 emitcode("mov","dpl,%s",aopGet(AOP(left),0));
3357 emitcode("mov","dph,%s",aopGet(AOP(left),1));
3358 if (options.model == MODEL_FLAT24)
3360 emitcode("mov", "dpx,%s",aopGet(AOP(left),2));
3361 emitcode("mov","b,%s",aopGet(AOP(left),3));
3365 emitcode("mov","b,%s",aopGet(AOP(left),2));
3369 /* so dptr know contains the address */
3370 freeAsmop(left,NULL,ic,TRUE);
3371 aopOp(result,ic,FALSE);
3373 /* if bit then unpack */
3374 if (IS_BITVAR(retype))
3375 genUnpackBits(result,"dptr",GPOINTER);
3377 size = AOP_SIZE(result);
3381 emitcode("lcall","__gptrget");
3382 aopPut(AOP(result),"a",offset++);
3384 emitcode("inc","dptr");
3388 freeAsmop(result,NULL,ic,TRUE);
3391 /*-----------------------------------------------------------------*/
3392 /* genPointerGet - generate code for pointer get */
3393 /*-----------------------------------------------------------------*/
3394 static void genPointerGet (iCode *ic)
3396 operand *left, *result ;
3401 result = IC_RESULT(ic) ;
3403 /* depending on the type of pointer we need to
3404 move it to the correct pointer register */
3405 type = operandType(left);
3406 etype = getSpec(type);
3407 /* if left is of type of pointer then it is simple */
3408 if (IS_PTR(type) && !IS_FUNC(type->next))
3409 p_type = DCL_TYPE(type);
3411 /* we have to go by the storage class */
3412 p_type = PTR_TYPE(SPEC_OCLS(etype));
3414 /* if (SPEC_OCLS(etype)->codesp ) { */
3415 /* p_type = CPOINTER ; */
3418 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
3419 /* p_type = FPOINTER ; */
3421 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
3422 /* p_type = PPOINTER; */
3424 /* if (SPEC_OCLS(etype) == idata ) */
3425 /* p_type = IPOINTER; */
3427 /* p_type = POINTER ; */
3430 /* now that we have the pointer type we assign
3431 the pointer values */
3436 genNearPointerGet (left,result,ic);
3440 genPagedPointerGet(left,result,ic);
3444 genFarPointerGet (left,result,ic);
3448 emitcodePointerGet (left,result,ic);
3452 genGenPointerGet (left,result,ic);
3458 /*-----------------------------------------------------------------*/
3459 /* genPackBits - generates code for packed bit storage */
3460 /*-----------------------------------------------------------------*/
3461 static void genPackBits (link *etype ,
3463 char *rname, int p_type)
3471 blen = SPEC_BLEN(etype);
3472 bstr = SPEC_BSTR(etype);
3474 l = aopGet(AOP(right),offset++);
3477 /* if the bit lenth is less than or */
3478 /* it exactly fits a byte then */
3479 if (SPEC_BLEN(etype) <= 8 ) {
3480 shCount = SPEC_BSTR(etype) ;
3482 /* shift left acc */
3485 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
3490 emitcode ("mov","b,a");
3491 emitcode("mov","a,@%s",rname);
3495 emitcode ("mov","b,a");
3496 emitcode("movx","a,@dptr");
3500 emitcode ("push","b");
3501 emitcode ("push","acc");
3502 emitcode ("lcall","__gptrget");
3503 emitcode ("pop","b");
3507 emitcode ("anl","a,#0x%02x",(unsigned char)
3508 ((unsigned char)(0xFF << (blen+bstr)) |
3509 (unsigned char)(0xFF >> (8-bstr)) ) );
3510 emitcode ("orl","a,b");
3511 if (p_type == GPOINTER)
3512 emitcode("pop","b");
3518 emitcode("mov","@%s,a",rname);
3522 emitcode("movx","@dptr,a");
3526 emitcode("lcall","__gptrput");
3531 if ( SPEC_BLEN(etype) <= 8 )
3534 emitcode("inc","%s",rname);
3535 rLen = SPEC_BLEN(etype) ;
3537 /* now generate for lengths greater than one byte */
3540 l = aopGet(AOP(right),offset++);
3550 emitcode("mov","@%s,a",rname);
3552 emitcode("mov","@%s,%s",rname,l);
3557 emitcode("movx","@dptr,a");
3562 emitcode("lcall","__gptrput");
3565 emitcode ("inc","%s",rname);
3570 /* last last was not complete */
3572 /* save the byte & read byte */
3575 emitcode ("mov","b,a");
3576 emitcode("mov","a,@%s",rname);
3580 emitcode ("mov","b,a");
3581 emitcode("movx","a,@dptr");
3585 emitcode ("push","b");
3586 emitcode ("push","acc");
3587 emitcode ("lcall","__gptrget");
3588 emitcode ("pop","b");
3592 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
3593 emitcode ("orl","a,b");
3596 if (p_type == GPOINTER)
3597 emitcode("pop","b");
3602 emitcode("mov","@%s,a",rname);
3606 emitcode("movx","@dptr,a");
3610 emitcode("lcall","__gptrput");
3614 /*-----------------------------------------------------------------*/
3615 /* genDataPointerSet - remat pointer to data space */
3616 /*-----------------------------------------------------------------*/
3617 static void genDataPointerSet(operand *right,
3621 int size, offset = 0 ;
3622 char *l, buffer[256];
3624 aopOp(right,ic,FALSE);
3626 l = aopGet(AOP(result),0);
3627 size = AOP_SIZE(right);
3630 sprintf(buffer,"(%s + %d)",l+1,offset);
3632 sprintf(buffer,"%s",l+1);
3633 emitcode("mov","%s,%s",buffer,
3634 aopGet(AOP(right),offset++));
3637 freeAsmop(right,NULL,ic,TRUE);
3638 freeAsmop(result,NULL,ic,TRUE);
3641 /*-----------------------------------------------------------------*/
3642 /* genNearPointerSet - emitcode for near pointer put */
3643 /*-----------------------------------------------------------------*/
3644 static void genNearPointerSet (operand *right,
3652 link *ptype = operandType(result);
3654 retype= getSpec(operandType(right));
3656 aopOp(result,ic,FALSE);
3658 /* if the result is rematerializable &
3659 in data space & not a bit variable */
3660 if (AOP_TYPE(result) == AOP_IMMD &&
3661 DCL_TYPE(ptype) == POINTER &&
3662 !IS_BITVAR(retype)) {
3663 genDataPointerSet (right,result,ic);
3667 /* if the value is already in a pointer register
3668 then don't need anything more */
3669 if (!AOP_INPREG(AOP(result))) {
3670 /* otherwise get a free pointer register */
3672 preg = getFreePtr(ic,&aop,FALSE,0);
3673 emitcode("mov","%s,%s",
3675 aopGet(AOP(result),0));
3676 rname = preg->name ;
3678 rname = aopGet(AOP(result),0);
3680 freeAsmop(result,NULL,ic,TRUE);
3681 aopOp (right,ic,FALSE);
3683 /* if bitfield then unpack the bits */
3684 if (IS_BITVAR(retype))
3685 genPackBits (retype,right,rname,POINTER);
3687 /* we have can just get the values */
3688 int size = AOP_SIZE(right);
3692 l = aopGet(AOP(right),offset);
3695 emitcode("mov","@%s,a",rname);
3697 emitcode("mov","@%s,%s",rname,l);
3699 emitcode("inc","%s",rname);
3704 /* now some housekeeping stuff */
3706 /* we had to allocate for this iCode */
3707 freeAsmop(NULL,aop,ic,TRUE);
3709 /* we did not allocate which means left
3710 already in a pointer register, then
3711 if size > 0 && this could be used again
3712 we have to point it back to where it
3714 if (AOP_SIZE(right) > 1 &&
3715 !OP_SYMBOL(result)->remat &&
3716 ( OP_SYMBOL(result)->liveTo > ic->seq ||
3718 int size = AOP_SIZE(right) - 1;
3720 emitcode("dec","%s",rname);
3725 freeAsmop(right,NULL,ic,TRUE);
3730 /*-----------------------------------------------------------------*/
3731 /* genPagedPointerSet - emitcode for Paged pointer put */
3732 /*-----------------------------------------------------------------*/
3733 static void genPagedPointerSet (operand *right,
3742 retype= getSpec(operandType(right));
3744 aopOp(result,ic,FALSE);
3746 /* if the value is already in a pointer register
3747 then don't need anything more */
3748 if (!AOP_INPREG(AOP(result))) {
3749 /* otherwise get a free pointer register */
3751 preg = getFreePtr(ic,&aop,FALSE,0);
3752 emitcode("mov","%s,%s",
3754 aopGet(AOP(result),0));
3755 rname = preg->name ;
3757 rname = aopGet(AOP(result),0);
3759 freeAsmop(result,NULL,ic,TRUE);
3760 aopOp (right,ic,FALSE);
3762 /* if bitfield then unpack the bits */
3763 if (IS_BITVAR(retype))
3764 genPackBits (retype,right,rname,PPOINTER);
3766 /* we have can just get the values */
3767 int size = AOP_SIZE(right);
3771 l = aopGet(AOP(right),offset);
3774 emitcode("movx","@%s,a",rname);
3777 emitcode("inc","%s",rname);
3783 /* now some housekeeping stuff */
3785 /* we had to allocate for this iCode */
3786 freeAsmop(NULL,aop,ic,TRUE);
3788 /* we did not allocate which means left
3789 already in a pointer register, then
3790 if size > 0 && this could be used again
3791 we have to point it back to where it
3793 if (AOP_SIZE(right) > 1 &&
3794 !OP_SYMBOL(result)->remat &&
3795 ( OP_SYMBOL(result)->liveTo > ic->seq ||
3797 int size = AOP_SIZE(right) - 1;
3799 emitcode("dec","%s",rname);
3804 freeAsmop(right,NULL,ic,TRUE);
3809 /*-----------------------------------------------------------------*/
3810 /* genFarPointerSet - set value from far space */
3811 /*-----------------------------------------------------------------*/
3812 static void genFarPointerSet (operand *right,
3813 operand *result, iCode *ic)
3816 link *retype = getSpec(operandType(right));
3818 aopOp(result,ic,FALSE);
3820 /* if the operand is already in dptr
3821 then we do nothing else we move the value to dptr */
3822 if (AOP_TYPE(result) != AOP_STR) {
3823 /* if this is remateriazable */
3824 if (AOP_TYPE(result) == AOP_IMMD)
3825 emitcode("mov","dptr,%s",aopGet(AOP(result),0));
3826 else { /* we need to get it byte by byte */
3827 emitcode("mov","dpl,%s",aopGet(AOP(result),0));
3828 emitcode("mov","dph,%s",aopGet(AOP(result),1));
3829 if (options.model == MODEL_FLAT24)
3831 emitcode("mov", "dpx,%s",aopGet(AOP(result),2));
3835 /* so dptr know contains the address */
3836 freeAsmop(result,NULL,ic,TRUE);
3837 aopOp(right,ic,FALSE);
3839 /* if bit then unpack */
3840 if (IS_BITVAR(retype))
3841 genPackBits(retype,right,"dptr",FPOINTER);
3843 size = AOP_SIZE(right);
3847 char *l = aopGet(AOP(right),offset++);
3849 emitcode("movx","@dptr,a");
3851 emitcode("inc","dptr");
3855 freeAsmop(right,NULL,ic,TRUE);
3858 /*-----------------------------------------------------------------*/
3859 /* genGenPointerSet - set value from generic pointer space */
3860 /*-----------------------------------------------------------------*/
3861 static void genGenPointerSet (operand *right,
3862 operand *result, iCode *ic)
3865 link *retype = getSpec(operandType(right));
3867 aopOp(result,ic,FALSE);
3869 /* if the operand is already in dptr
3870 then we do nothing else we move the value to dptr */
3871 if (AOP_TYPE(result) != AOP_STR) {
3872 /* if this is remateriazable */
3873 if (AOP_TYPE(result) == AOP_IMMD) {
3874 emitcode("mov","dptr,%s",aopGet(AOP(result),0));
3875 emitcode("mov","b,%s + 1",aopGet(AOP(result),0));
3877 else { /* we need to get it byte by byte */
3878 emitcode("mov","dpl,%s",aopGet(AOP(result),0));
3879 emitcode("mov","dph,%s",aopGet(AOP(result),1));
3880 if (options.model == MODEL_FLAT24)
3882 emitcode("mov", "dpx,%s",aopGet(AOP(result),2));
3883 emitcode("mov","b,%s",aopGet(AOP(result),3));
3887 emitcode("mov","b,%s",aopGet(AOP(result),2));
3891 /* so dptr know contains the address */
3892 freeAsmop(result,NULL,ic,TRUE);
3893 aopOp(right,ic,FALSE);
3895 /* if bit then unpack */
3896 if (IS_BITVAR(retype))
3897 genPackBits(retype,right,"dptr",GPOINTER);
3899 size = AOP_SIZE(right);
3903 char *l = aopGet(AOP(right),offset++);
3905 emitcode("lcall","__gptrput");
3907 emitcode("inc","dptr");
3911 freeAsmop(right,NULL,ic,TRUE);
3914 /*-----------------------------------------------------------------*/
3915 /* genPointerSet - stores the value into a pointer location */
3916 /*-----------------------------------------------------------------*/
3917 static void genPointerSet (iCode *ic)
3919 operand *right, *result ;
3923 right = IC_RIGHT(ic);
3924 result = IC_RESULT(ic) ;
3926 /* depending on the type of pointer we need to
3927 move it to the correct pointer register */
3928 type = operandType(result);
3929 etype = getSpec(type);
3930 /* if left is of type of pointer then it is simple */
3931 if (IS_PTR(type) && !IS_FUNC(type->next)) {
3932 p_type = DCL_TYPE(type);
3935 /* we have to go by the storage class */
3936 p_type = PTR_TYPE(SPEC_OCLS(etype));
3938 /* if (SPEC_OCLS(etype)->codesp ) { */
3939 /* p_type = CPOINTER ; */
3942 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
3943 /* p_type = FPOINTER ; */
3945 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
3946 /* p_type = PPOINTER ; */
3948 /* if (SPEC_OCLS(etype) == idata ) */
3949 /* p_type = IPOINTER ; */
3951 /* p_type = POINTER ; */
3954 /* now that we have the pointer type we assign
3955 the pointer values */
3960 genNearPointerSet (right,result,ic);
3964 genPagedPointerSet (right,result,ic);
3968 genFarPointerSet (right,result,ic);
3972 genGenPointerSet (right,result,ic);
3978 /*-----------------------------------------------------------------*/
3979 /* genIfx - generate code for Ifx statement */
3980 /*-----------------------------------------------------------------*/
3981 static void genIfx (iCode *ic, iCode *popIc)
3983 operand *cond = IC_COND(ic);
3986 aopOp(cond,ic,FALSE);
3988 /* get the value into acc */
3989 if (AOP_TYPE(cond) != AOP_CRY)
3990 toBoolean(cond,"",0);
3993 /* the result is now in the accumulator */
3994 freeAsmop(cond,NULL,ic,TRUE);
3996 /* if there was something to be popped then do it */
4000 /* if the condition is a bit variable */
4001 /* if (isbit && IS_ITEMP(cond) && SPIL_LOC(cond)) { */
4002 /* // genIfxJump(ic,SPIL_LOC(cond)->rname); */
4005 /* if (isbit && !IS_ITEMP(cond)) */
4006 /* // genIfxJump(ic,OP_SYMBOL(cond)->rname); */
4008 /* // genIfxJump(ic,"a"); */
4013 /*-----------------------------------------------------------------*/
4014 /* genAddrOf - generates code for address of */
4015 /*-----------------------------------------------------------------*/
4016 static void genAddrOf (iCode *ic)
4018 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
4021 aopOp(IC_RESULT(ic),ic,FALSE);
4023 /* if the operand is on the stack then we
4024 need to get the stack offset of this
4027 /* if it has an offset then we need to compute
4030 emitcode("mov","a,_bp");
4031 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
4032 aopPut(AOP(IC_RESULT(ic)),"a",0);
4034 /* we can just move _bp */
4035 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
4037 /* fill the result with zero */
4038 size = AOP_SIZE(IC_RESULT(ic)) - 1;
4041 if (options.stack10bit && size < (FPTRSIZE - 1))
4044 "*** warning: pointer to stack var truncated.\n");
4051 if (options.stack10bit && offset == 2)
4053 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
4057 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
4064 /* object not on stack then we need the name */
4065 size = AOP_SIZE(IC_RESULT(ic));
4069 char s[SDCC_NAME_MAX];
4071 sprintf(s,"#(%s >> %d)",
4075 sprintf(s,"#%s",sym->rname);
4076 aopPut(AOP(IC_RESULT(ic)),s,offset++);
4080 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
4084 /*-----------------------------------------------------------------*/
4085 /* genFarFarAssign - assignment when both are in far space */
4086 /*-----------------------------------------------------------------*/
4087 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
4089 int size = AOP_SIZE(right);
4092 /* first push the right side on to the stack */
4094 l = aopGet(AOP(right),offset++);
4096 emitcode ("push","acc");
4099 freeAsmop(right,NULL,ic,FALSE);
4100 /* now assign DPTR to result */
4101 aopOp(result,ic,FALSE);
4102 size = AOP_SIZE(result);
4104 emitcode ("pop","acc");
4105 aopPut(AOP(result),"a",--offset);
4107 freeAsmop(result,NULL,ic,FALSE);
4111 /*-----------------------------------------------------------------*/
4112 /* genAssign - generate code for assignment */
4113 /*-----------------------------------------------------------------*/
4114 static void genAssign (iCode *ic)
4116 operand *result, *right;
4118 unsigned long lit = 0L;
4120 result = IC_RESULT(ic);
4121 right = IC_RIGHT(ic) ;
4123 /* if they are the same */
4124 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
4127 aopOp(right,ic,FALSE);
4129 /* special case both in far space */
4130 if (AOP_TYPE(right) == AOP_DPTR &&
4131 IS_TRUE_SYMOP(result) &&
4132 isOperandInFarSpace(result)) {
4134 genFarFarAssign (result,right,ic);
4138 aopOp(result,ic,TRUE);
4140 /* if they are the same registers */
4141 if (sameRegs(AOP(right),AOP(result)))
4144 /* if the result is a bit */
4145 if (AOP_TYPE(result) == AOP_CRY) {
4147 /* if the right size is a literal then
4148 we know what the value is */
4149 if (AOP_TYPE(right) == AOP_LIT) {
4150 if (((int) operandLitValue(right)))
4151 aopPut(AOP(result),one,0);
4153 aopPut(AOP(result),zero,0);
4157 /* the right is also a bit variable */
4158 if (AOP_TYPE(right) == AOP_CRY) {
4159 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4160 aopPut(AOP(result),"c",0);
4165 toBoolean(right,"",0);
4166 aopPut(AOP(result),"a",0);
4170 /* bit variables done */
4172 size = AOP_SIZE(result);
4174 if(AOP_TYPE(right) == AOP_LIT)
4175 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4177 (AOP_TYPE(result) != AOP_REG) &&
4178 (AOP_TYPE(right) == AOP_LIT) &&
4179 !IS_FLOAT(operandType(right)) &&
4181 emitcode("clr","a");
4183 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
4184 aopPut(AOP(result),"a",size);
4187 aopGet(AOP(right),size),
4193 aopGet(AOP(right),offset),
4200 freeAsmop (right,NULL,ic,FALSE);
4201 freeAsmop (result,NULL,ic,TRUE);
4204 /*-----------------------------------------------------------------*/
4205 /* genJumpTab - genrates code for jump table */
4206 /*-----------------------------------------------------------------*/
4207 static void genJumpTab (iCode *ic)
4212 aopOp(IC_JTCOND(ic),ic,FALSE);
4213 /* get the condition into accumulator */
4214 l = aopGet(AOP(IC_JTCOND(ic)),0);
4216 /* multiply by three */
4217 emitcode("add","a,acc");
4218 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0));
4219 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
4221 jtab = newiTempLabel(NULL);
4222 emitcode("mov","dptr,#%05d$",jtab->key+100);
4223 emitcode("jmp","@a+dptr");
4224 emitcode("","%05d$:",jtab->key+100);
4225 /* now generate the jump labels */
4226 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
4227 jtab = setNextItem(IC_JTLABELS(ic)))
4228 emitcode("ljmp","%05d$",jtab->key+100);
4232 /*-----------------------------------------------------------------*/
4233 /* genCast - gen code for casting */
4234 /*-----------------------------------------------------------------*/
4235 static void genCast (iCode *ic)
4237 operand *result = IC_RESULT(ic);
4238 link *ctype = operandType(IC_LEFT(ic));
4239 link *rtype = operandType(IC_RIGHT(ic));
4240 operand *right = IC_RIGHT(ic);
4243 /* if they are equivalent then do nothing */
4244 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
4247 aopOp(right,ic,FALSE) ;
4248 aopOp(result,ic,FALSE);
4250 /* if the result is a bit */
4251 if (AOP_TYPE(result) == AOP_CRY) {
4252 /* if the right size is a literal then
4253 we know what the value is */
4254 if (AOP_TYPE(right) == AOP_LIT) {
4255 if (((int) operandLitValue(right)))
4256 aopPut(AOP(result),one,0);
4258 aopPut(AOP(result),zero,0);
4263 /* the right is also a bit variable */
4264 if (AOP_TYPE(right) == AOP_CRY) {
4265 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4266 aopPut(AOP(result),"c",0);
4271 toBoolean(right,"",0);
4272 aopPut(AOP(result),"a",0);
4276 /* if they are the same size : or less */
4277 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
4279 /* if they are in the same place */
4280 if (sameRegs(AOP(right),AOP(result)))
4283 /* if they in different places then copy */
4284 size = AOP_SIZE(result);
4288 aopGet(AOP(right),offset),
4296 /* if the result is of type pointer */
4297 if (IS_PTR(ctype)) {
4300 link *type = operandType(right);
4301 link *etype = getSpec(type);
4303 /* pointer to generic pointer */
4304 if (IS_GENPTR(ctype)) {
4308 p_type = DCL_TYPE(type);
4310 /* we have to go by the storage class */
4311 p_type = PTR_TYPE(SPEC_OCLS(etype));
4314 /* the first two bytes are known */
4315 size = GPTRSIZE - 1;
4319 aopGet(AOP(right),offset),
4323 /* the last byte depending on type */
4340 /* this should never happen */
4341 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
4342 "got unknown pointer type");
4345 aopPut(AOP(result),l, GPTRSIZE - 1);
4349 /* just copy the pointers */
4350 size = AOP_SIZE(result);
4354 aopGet(AOP(right),offset),
4361 /* so we now know that the size of destination is greater
4362 than the size of the source */
4363 /* we move to result for the size of source */
4364 size = AOP_SIZE(right);
4368 aopGet(AOP(right),offset),
4373 /* now depending on the sign of the source && destination */
4374 size = AOP_SIZE(result) - AOP_SIZE(right);
4375 /* if unsigned or not an integral type */
4376 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
4378 aopPut(AOP(result),zero,offset++);
4380 /* we need to extend the sign :{ */
4381 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1);
4383 emitcode("rlc","a");
4384 emitcode("subb","a,acc");
4386 aopPut(AOP(result),"a",offset++);
4389 /* we are done hurray !!!! */
4392 freeAsmop(right,NULL,ic,TRUE);
4393 freeAsmop(result,NULL,ic,TRUE);
4397 /*-----------------------------------------------------------------*/
4398 /* genDjnz - generate decrement & jump if not zero instrucion */
4399 /*-----------------------------------------------------------------*/
4400 static int genDjnz (iCode *ic, iCode *ifx)
4406 /* if the if condition has a false label
4407 then we cannot save */
4411 /* if the minus is not of the form
4413 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
4414 !IS_OP_LITERAL(IC_RIGHT(ic)))
4417 if (operandLitValue(IC_RIGHT(ic)) != 1)
4420 /* if the size of this greater than one then no
4422 if (getSize(operandType(IC_RESULT(ic))) > 1)
4425 /* otherwise we can save BIG */
4426 lbl = newiTempLabel(NULL);
4427 lbl1= newiTempLabel(NULL);
4429 aopOp(IC_RESULT(ic),ic,FALSE);
4431 if (IS_AOP_PREG(IC_RESULT(ic))) {
4432 emitcode("dec","%s",
4433 aopGet(AOP(IC_RESULT(ic)),0));
4434 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0));
4435 emitcode("jnz","%05d$",lbl->key+100);
4437 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0),
4440 emitcode ("sjmp","%05d$",lbl1->key+100);
4441 emitcode ("","%05d$:",lbl->key+100);
4442 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4443 emitcode ("","%05d$:",lbl1->key+100);
4445 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
4450 static char *recvregs[8] =
4452 "r16","r17","r18","r19","r20","r21","r22","r23"
4456 /*-----------------------------------------------------------------*/
4457 /* genReceive - generate code for a receive iCode */
4458 /*-----------------------------------------------------------------*/
4459 static void genReceive (iCode *ic)
4461 int size , offset =0;
4462 aopOp(IC_RESULT(ic),ic,FALSE);
4463 size = AOP_SIZE(IC_RESULT(ic));
4465 aopPut(AOP(IC_RESULT(ic)),recvregs[recvCnt++],offset);
4468 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
4471 /*-----------------------------------------------------------------*/
4472 /* gen51Code - generate code for 8051 based controllers */
4473 /*-----------------------------------------------------------------*/
4474 void genAVRCode (iCode *lic)
4479 lineHead = lineCurr = NULL;
4481 /* print the allocation information */
4483 printAllocInfo( currFunc, codeOutFile);
4484 /* if debug information required */
4485 /* if (options.debug && currFunc) { */
4487 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
4489 if (IS_STATIC(currFunc->etype))
4490 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
4492 emitcode("","G$%s$0$0 ==.",currFunc->name);
4495 /* stack pointer name */
4496 if (options.useXstack)
4502 for (ic = lic ; ic ; ic = ic->next ) {
4504 if ( cln != ic->lineno ) {
4505 if ( options.debug ) {
4507 emitcode("","C$%s$%d$%d$%d ==.",
4508 ic->filename,ic->lineno,
4509 ic->level,ic->block);
4512 emitcode(";","%s %d",ic->filename,ic->lineno);
4515 /* if the result is marked as
4516 spilt and rematerializable or code for
4517 this has already been generated then
4519 if (resultRemat(ic) || ic->generated )
4522 /* depending on the operation */
4541 /* IPOP happens only when trying to restore a
4542 spilt live range, if there is an ifx statement
4543 following this pop then the if statement might
4544 be using some of the registers being popped which
4545 would destory the contents of the register so
4546 we need to check for this condition and handle it */
4548 ic->next->op == IFX &&
4549 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
4550 genIfx (ic->next,ic);
4568 genEndFunction (ic);
4588 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
4605 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
4609 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
4613 genCmpLe (ic,ifxForOp(IC_RESULT(ic),ic));
4617 genCmpGe (ic,ifxForOp(IC_RESULT(ic),ic));
4621 genCmpNe (ic,ifxForOp(IC_RESULT(ic),ic));
4625 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
4637 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
4641 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
4645 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
4672 case GET_VALUE_AT_ADDRESS:
4677 if (POINTER_SET(ic))
4704 addSet(&_G.sendSet,ic);
4709 /* piCode(ic,stdout); */
4715 /* now we are ready to call the
4716 peep hole optimizer */
4717 if (!options.nopeep)
4718 peepHole (&lineHead);
4720 /* now do the actual printing */
4721 printLine (lineHead,codeOutFile);