1 /*-------------------------------------------------------------------------
2 avrgen.c - source file for code generation for ATMEL AVR
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (2000)
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding!
25 -------------------------------------------------------------------------*/
31 #include "SDCCglobl.h"
34 #ifdef HAVE_SYS_ISA_DEFS_H
35 #include <sys/isa_defs.h>
40 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
41 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
42 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
48 #include "SDCCpeeph.h"
52 char *aopLiteral (value *val, int offset);
55 /* this is the down and dirty file with all kinds of
56 kludgy & hacky stuff. This is what it is all about
57 CODE GENERATION for a specific MCU . some of the
58 routines may be reusable, will have to see */
60 static char *zero = "0x00";
61 static char *one = "0x01";
64 char *fReturnAVR[] = {"r16","r17","r18","r19" };
65 unsigned fAVRReturnSize = 4; /* shared with ralloc.c */
66 char **fAVRReturn = fReturnAVR;
67 static 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 aop = Safe_calloc(1,sizeof(asmop));
243 /*-----------------------------------------------------------------*/
244 /* pointerCode - returns the code for a pointer type */
245 /*-----------------------------------------------------------------*/
246 static int pointerCode (sym_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 aop->aopu.aop_immd = Safe_calloc(1,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 */
335 sym->aop = aop = newAsmop(0);
337 if (IN_CODESPACE(space))
340 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result,aop->code);
341 aop->size = getSize(sym->type);
342 emitcode ("ldi","%s,lo8(%s)",aop->aopu.aop_ptr->name,sym->rname);
343 emitcode ("ldi","%s,hi8(%s)",aop->aop_ptr2);
348 /*-----------------------------------------------------------------*/
349 /* aopForRemat - rematerialzes an object */
350 /*-----------------------------------------------------------------*/
351 static asmop *aopForRemat (symbol *sym)
353 iCode *ic = sym->rematiCode;
354 asmop *aop = newAsmop(AOP_IMMD);
359 val += (int) operandLitValue(IC_RIGHT(ic));
360 else if (ic->op == '-')
361 val -= (int) operandLitValue(IC_RIGHT(ic));
365 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
369 sprintf(buffer,"(%s %c 0x%04x)",
370 OP_SYMBOL(IC_LEFT(ic))->rname,
371 val >= 0 ? '+' : '-',
374 strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
376 aop->aopu.aop_immd = Safe_calloc(1,strlen(buffer)+1);
377 strcpy(aop->aopu.aop_immd,buffer);
381 /*-----------------------------------------------------------------*/
382 /* regsInCommon - two operands have some registers in common */
383 /*-----------------------------------------------------------------*/
384 static bool regsInCommon (operand *op1, operand *op2)
389 /* if they have registers in common */
390 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
393 sym1 = OP_SYMBOL(op1);
394 sym2 = OP_SYMBOL(op2);
396 if (sym1->nRegs == 0 || sym2->nRegs == 0)
399 for (i = 0 ; i < sym1->nRegs ; i++) {
404 for (j = 0 ; j < sym2->nRegs ;j++ ) {
408 if (sym2->regs[j] == sym1->regs[i])
416 /*-----------------------------------------------------------------*/
417 /* operandsEqu - equivalent */
418 /*-----------------------------------------------------------------*/
419 static bool operandsEqu ( operand *op1, operand *op2)
423 /* if they not symbols */
424 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
427 sym1 = OP_SYMBOL(op1);
428 sym2 = OP_SYMBOL(op2);
430 /* if both are itemps & one is spilt
431 and the other is not then false */
432 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
433 sym1->isspilt != sym2->isspilt )
436 /* if they are the same */
440 if (strcmp(sym1->rname,sym2->rname) == 0)
444 /* if left is a tmp & right is not */
448 (sym1->usl.spillLoc == sym2))
455 (sym2->usl.spillLoc == sym1))
461 /*-----------------------------------------------------------------*/
462 /* sameRegs - two asmops have the same registers */
463 /*-----------------------------------------------------------------*/
464 static bool sameRegs (asmop *aop1, asmop *aop2 )
471 if (aop1->type != AOP_REG ||
472 aop2->type != AOP_REG )
475 if (aop1->size != aop2->size )
478 for (i = 0 ; i < aop1->size ; i++ )
479 if (aop1->aopu.aop_reg[i] !=
480 aop2->aopu.aop_reg[i] )
486 /*-----------------------------------------------------------------*/
487 /* isRegPair - for size 2 if this operand has a register pair */
488 /*-----------------------------------------------------------------*/
489 static int isRegPair (asmop *aop)
491 if (!aop || aop->size != 2) return 0;
492 if (aop->type == AOP_X || aop->type == AOP_Z) return 1;
493 if (aop->type != AOP_REG) return 0;
494 if ((aop->aopu.aop_reg[1]->rIdx -
495 aop->aopu.aop_reg[0]->rIdx) == 1) return 1;
499 /*-----------------------------------------------------------------*/
500 /* aopOp - allocates an asmop for an operand : */
501 /*-----------------------------------------------------------------*/
502 static void aopOp (operand *op, iCode *ic, bool result)
511 /* if this a literal */
512 if (IS_OP_LITERAL(op)) {
513 op->aop = aop = newAsmop(AOP_LIT);
514 aop->aopu.aop_lit = op->operand.valOperand;
515 aop->size = getSize(operandType(op));
519 /* if already has a asmop then continue */
523 /* if the underlying symbol has a aop */
524 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
525 op->aop = OP_SYMBOL(op)->aop;
529 /* if this is a true symbol */
530 if (IS_TRUE_SYMOP(op)) {
531 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
535 /* this is a temporary : this has
541 e) can be a return use only */
546 /* if the type is a conditional */
547 if (sym->regType == REG_CND) {
548 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
553 /* if it is spilt then two situations
555 b) has a spill location */
556 if (sym->isspilt || sym->nRegs == 0) {
558 /* rematerialize it NOW */
560 sym->aop = op->aop = aop =
562 aop->size = getSize(sym->type);
567 assert("ACC_USE cannot happen in AVR\n");
572 aop = op->aop = sym->aop = newAsmop(AOP_STR);
573 aop->size = getSize(sym->type);
574 for ( i = 0 ; i < (int) fAVRReturnSize ; i++ )
575 aop->aopu.aop_str[i] = fAVRReturn[i];
579 /* else spill location */
580 sym->aop = op->aop = aop =
581 aopForSym(ic,sym->usl.spillLoc,result);
582 aop->size = getSize(sym->type);
586 /* must be in a register */
587 sym->aop = op->aop = aop = newAsmop(AOP_REG);
588 aop->size = sym->nRegs;
589 for ( i = 0 ; i < sym->nRegs ;i++)
590 aop->aopu.aop_reg[i] = sym->regs[i];
593 /*-----------------------------------------------------------------*/
594 /* freeAsmop - free up the asmop given to an operand */
595 /*----------------------------------------------------------------*/
596 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
613 /* depending on the asmop type only three cases need work AOP_RO
614 , AOP_R1 && AOP_STK */
619 emitcode ("pop","r26");
620 emitcode ("pop","r27");
624 bitVectUnSetBit(ic->rUsed,X_IDX);
630 emitcode ("pop","r30");
631 emitcode ("pop","r31");
635 bitVectUnSetBit(ic->rUsed,Z_IDX);
641 int stk = aop->aopu.aop_stk + aop->size;
642 bitVectUnSetBit(ic->rUsed,X_IDX);
643 bitVectUnSetBit(ic->rUsed,Z_IDX);
645 getFreePtr(ic,&aop,FALSE,0);
647 emitcode ("movw","%s,r28");
649 if (stk <= 63 && stk > 0) {
650 emitcode ("adiw","%s,0x%02x",aop->aopu.aop_ptr->name,stk+1);
652 emitcode ("subi","%s,lo8(%d)",aop->aopu.aop_ptr->name,-(stk+1));
653 emitcode ("sbci","%s,hi8(%d)",aop->aop_ptr2->name,-(stk+1));
658 emitcode("pop","r24");
659 emitcode("st","-%s,r24",aop->type == AOP_X ? "X" : "Z");
663 freeAsmop(op,NULL,ic,TRUE);
665 emitcode("pop","r26");
666 emitcode("pop","r27");
671 emitcode("pop","r30");
672 emitcode("pop","r31");
679 /* all other cases just dealloc */
683 OP_SYMBOL(op)->aop = NULL;
684 /* if the symbol has a spill */
686 SPIL_LOC(op)->aop = NULL;
691 /*-----------------------------------------------------------------*/
692 /* aopGet - for fetching value of the aop */
693 /*-----------------------------------------------------------------*/
694 static char *aopGet (asmop *aop, int offset)
699 /* offset is greater than
701 if (offset > (aop->size - 1) &&
702 aop->type != AOP_LIT)
705 /* depending on type */
709 if (offset > aop->coff) {
710 emitcode ("adiw","%s,%d",aop->aopu.aop_ptr->name,offset - aop->coff);
713 if (offset < aop->coff) {
714 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,aop->coff - offset);
718 emitcode("ld","%s,x",
719 (rs = ((offset & 1) ? "r25" : "r24")));
724 if (offset > aop->coff) {
725 emitcode("adiw","r30,%d",offset - aop->coff);
727 emitcode("sbiw","r30,%d",aop->coff - offset);
729 emitcode("lpm","%s,z",(rs = ((offset & 1) ? "r25" : "r24")));
732 if (offset > aop->coff) {
733 emitcode ("ldd","%s,z+%d",(rs = ((offset & 1) ? "r25" : "r24")),
736 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,aop->coff - offset);
738 emitcode ("ld","%s,z",(rs = ((offset & 1) ? "r25" : "r24")));
745 emitcode ("lds","%s,(%s)+%d",
746 (rs = ((offset & 1) ? "r25" : "r24")),
747 aop->aopu.aop_immd, offset);
751 emitcode ("lds","%s,(%s)+%d",
752 (rs = ((offset & 1) ? "r25" : "r24")),
753 aop->aopu.aop_dir, offset);
757 return aop->aopu.aop_reg[offset]->name;
760 assert("cannot be in bit space AOP_CRY\n");
764 s = aopLiteral(aop->aopu.aop_lit,offset);
765 emitcode("ldi","%s,lo8(%s)",(rs = ((offset & 1)?"r24" : "r25")),s);
770 return aop->aopu.aop_str[offset];
773 emitcode ("ldd","%s,Y+%d",
774 (rs = ((offset & 1) ? "r25" : "r24")),
775 aop->aopu.aop_stk+offset);
779 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
780 "aopget got unsupported aop->type");
783 /*-----------------------------------------------------------------*/
784 /* aopPut - puts a string for a aop */
785 /*-----------------------------------------------------------------*/
786 static void aopPut (asmop *aop, char *s, int offset)
790 if (aop->size && offset > ( aop->size - 1)) {
791 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
792 "aopPut got offset > aop->size");
796 /* will assign value to value */
797 /* depending on where it is ofcourse */
801 sprintf(d,"(%s)+%d", aop->aopu.aop_dir,offset);
804 sprintf(d,"%s",aop->aopu.aop_dir);
807 emitcode("sts","%s,%s",d,s);
811 if (toupper(*s) != 'R') {
813 emitcode("clr","%s",aop->aopu.aop_reg[offset]->name);
815 emitcode("ldi","r25,%s",s);
816 emitcode("mov","%s,r35",aop->aopu.aop_reg[offset]->name);
819 if (strcmp( aop->aopu.aop_reg[offset]->name,s)) {
820 emitcode("mov","%s,%s", aop->aopu.aop_reg[offset]->name,s);
826 if (offset > aop->coff) {
827 emitcode ("adiw","%s,%d",aop->aopu.aop_ptr->name,offset - aop->coff);
830 if (offset < aop->coff) {
831 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,aop->coff - offset);
835 emitcode("st","x,%s", s);
840 if (offset > aop->coff) {
841 emitcode("adiw","r30,%d",offset - aop->coff);
843 emitcode("sbiw","r30,%d",aop->coff - offset);
845 emitcode("lpm","%s,z",s);
848 if (offset > aop->coff) {
849 emitcode ("sdd","z+%d,%s",offset - aop->coff,s);
851 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,aop->coff - offset);
853 emitcode ("ld","%s,z",s);
859 emitcode("push","%s",s);
863 /* if used only for a condition code check */
864 assert(toupper(*s) == 'R');
866 emitcode("xrl","r0,r0");
867 emitcode("cpi","%s,0",s);
870 emitcode("cpc","r0,%s",s);
876 if (strcmp(aop->aopu.aop_str[offset],s))
877 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
881 emitcode ("std","y+%d,%s",offset,s);
885 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
886 "aopPut got unsupported aop->type");
892 /*-----------------------------------------------------------------*/
893 /* reAdjustPreg - points a register back to where it should */
894 /*-----------------------------------------------------------------*/
895 static void reAdjustPreg (asmop *aop)
900 if ((size = aop->size) <= 1)
906 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,size);
912 #define AOP(op) op->aop
913 #define AOP_TYPE(op) AOP(op)->type
914 #define AOP_SIZE(op) AOP(op)->size
915 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_X || \
916 AOP_TYPE(x) == AOP_Z))
917 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
918 (x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) || \
919 x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) )))
921 /*-----------------------------------------------------------------*/
922 /* genNotFloat - generates not for float operations */
923 /*-----------------------------------------------------------------*/
924 static void genNotFloat (operand *op, operand *res)
930 /* we will put 127 in the first byte of
932 aopPut(AOP(res),"127",0);
933 size = AOP_SIZE(op) - 1;
936 l = aopGet(op->aop,offset++);
940 emitcode("or","R0,%s", aopGet(op->aop, offset++));
942 tlbl = newiTempLabel(NULL);
944 tlbl = newiTempLabel(NULL);
945 aopPut(res->aop,zero,1);
946 emitcode("cpi","r0,0");
947 emitcode("breq","L%05d",tlbl->key);
948 aopPut(res->aop,one,1);
949 emitcode("","L%05d:",tlbl->key);
951 size = res->aop->size - 2;
953 /* put zeros in the rest */
955 aopPut(res->aop,zero,offset++);
958 /*-----------------------------------------------------------------*/
959 /* opIsGptr: returns non-zero if the passed operand is */
960 /* a generic pointer type. */
961 /*-----------------------------------------------------------------*/
962 static int opIsGptr(operand *op)
964 sym_link *type = operandType(op);
966 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
973 /*-----------------------------------------------------------------*/
974 /* getDataSize - get the operand data size */
975 /*-----------------------------------------------------------------*/
976 static int getDataSize(operand *op)
980 if (size == GPTRSIZE)
982 sym_link *type = operandType(op);
985 /* generic pointer; arithmetic operations
986 * should ignore the high byte (pointer type).
994 /*-----------------------------------------------------------------*/
995 /* outAcc - output Acc */
996 /*-----------------------------------------------------------------*/
997 static void outAcc(operand *result)
1000 size = getDataSize(result);
1002 aopPut(AOP(result),"r0",0);
1005 /* unsigned or positive */
1007 aopPut(AOP(result),zero,offset++);
1012 /*-----------------------------------------------------------------*/
1013 /* outBitC - output a bit C */
1014 /*-----------------------------------------------------------------*/
1015 static void outBitC(operand *result)
1017 emitcode("clr","r0");
1018 emitcode("rol","r0");
1022 /*-----------------------------------------------------------------*/
1023 /* toBoolean - emit code for orl a,operator(sizeop) */
1024 /*-----------------------------------------------------------------*/
1025 static void toBoolean(operand *oper, char *r, bool clr)
1027 int size = AOP_SIZE(oper) ;
1029 if (clr) emitcode ("clr","%s",r);
1031 emitcode("or","%s,%s",r,aopGet(AOP(oper),offset++));
1035 /*-----------------------------------------------------------------*/
1036 /* genNot - generate code for ! operation */
1037 /*-----------------------------------------------------------------*/
1038 static void genNot (iCode *ic)
1041 sym_link *optype = operandType(IC_LEFT(ic));
1042 int size, offset = 1;
1044 /* assign asmOps to operand & result */
1045 aopOp (IC_LEFT(ic),ic,FALSE);
1046 aopOp (IC_RESULT(ic),ic,TRUE);
1048 /* if type float then do float */
1049 if (IS_FLOAT(optype)) {
1050 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1053 emitcode("clr","r0");
1054 tlbl = newiTempLabel(NULL);
1055 size = AOP_SIZE(IC_LEFT(ic));
1058 emitcode("cpse","%s,r0",aopGet(AOP(IC_LEFT(ic)),0));
1062 if (offset) emitcode("cpc","%s,r0",aopGet(AOP(IC_LEFT(ic)),offset));
1063 else emitcode("cpi","%s,0",aopGet(AOP(IC_LEFT(ic)),offset));
1066 emitcode("bne","L%05d",tlbl->key);
1068 emitcode("ldi","r0,1");
1069 emitcode("","L%05d:",tlbl->key);
1070 aopPut(AOP(IC_RESULT(ic)),"r0",0);
1071 size = AOP_SIZE(IC_RESULT(ic)) -1;
1073 while (size--) aopPut(AOP(IC_RESULT(ic)),zero,offset++);
1077 /* release the aops */
1078 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1079 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1083 /*-----------------------------------------------------------------*/
1084 /* genCpl - generate code for complement */
1085 /*-----------------------------------------------------------------*/
1086 static void genCpl (iCode *ic)
1092 /* assign asmOps to operand & result */
1093 aopOp (IC_LEFT(ic),ic,FALSE);
1094 aopOp (IC_RESULT(ic),ic,TRUE);
1095 samer = sameRegs(AOP(IC_LEFT(ic)),AOP(IC_RESULT(ic)));
1096 size = AOP_SIZE(IC_RESULT(ic));
1098 char *l = aopGet(AOP(IC_LEFT(ic)),offset);
1100 emitcode ("com","%s",l);
1102 aopPut(AOP(IC_RESULT(ic)),l,offset);
1103 emitcode ("com","%s",aopGet(AOP(IC_RESULT(ic)),offset));
1108 /* release the aops */
1109 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1110 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1113 /*-----------------------------------------------------------------*/
1114 /* genUminusFloat - unary minus for floating points */
1115 /*-----------------------------------------------------------------*/
1116 static void genUminusFloat(operand *op,operand *result)
1118 int size ,offset =0 ;
1120 /* for this we just need to flip the
1121 first it then copy the rest in place */
1122 size = AOP_SIZE(op) - 1;
1123 l = aopGet(AOP(op),3);
1125 emitcode("ldi","r24,0x80");
1126 if (sameRegs(AOP(op),AOP(result))) {
1127 emitcode("eor","%s,r24",l);
1129 aopPut(AOP(result),l,3);
1130 emitcode("eor","%s,r24",aopGet(AOP(result),3));
1133 aopPut(AOP(result), aopGet(AOP(op),offset), offset);
1138 /*-----------------------------------------------------------------*/
1139 /* genUminus - unary minus code generation */
1140 /*-----------------------------------------------------------------*/
1141 static void genUminus (iCode *ic)
1144 sym_link *optype, *rtype;
1148 aopOp(IC_LEFT(ic),ic,FALSE);
1149 aopOp(IC_RESULT(ic),ic,TRUE);
1151 optype = operandType(IC_LEFT(ic));
1152 rtype = operandType(IC_RESULT(ic));
1154 /* if float then do float stuff */
1155 if (IS_FLOAT(optype)) {
1156 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1160 /* otherwise subtract from zero */
1161 size = AOP_SIZE(IC_LEFT(ic));
1163 samer = sameRegs(AOP(IC_LEFT(ic)),AOP(IC_RESULT(ic)));
1166 emitcode("neg","%s",aopGet(AOP(IC_LEFT(ic)),0));
1168 aopPut(AOP(IC_RESULT(ic)),aopGet(AOP(IC_LEFT(ic)),0),0);
1169 emitcode("neg","%s",aopGet(AOP(IC_RESULT(ic)),0));
1174 char *l = aopGet(AOP(IC_LEFT(ic)),offset);
1176 aopPut(AOP(IC_RESULT(ic)),l,offset);
1177 l = aopGet(AOP(IC_RESULT(ic)),offset);
1179 if (offset) emitcode("com","%s",l);
1180 else emitcode("neg","%s",l);
1183 size = AOP_SIZE(IC_LEFT(ic)) -1;
1186 emitcode("sbci","%s,lo8(-1)",aopGet(AOP(IC_RESULT(ic)),offset++));
1190 /* if any remaining bytes in the result */
1191 /* we just need to propagate the sign */
1192 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1193 symbol *tlbl = newiTempLabel(NULL);
1194 emitcode("clr","r0");
1195 emitcode("brcc","L%05d",tlbl->key);
1196 emitcode("com","r0");
1197 emitcode("","L%05d:",tlbl->key);
1199 aopPut(AOP(IC_RESULT(ic)),"r0",offset++);
1203 /* release the aops */
1204 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1205 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1208 /*-----------------------------------------------------------------*/
1209 /* assignResultValue - */
1210 /*-----------------------------------------------------------------*/
1211 static void assignResultValue(operand * oper)
1214 int size = AOP_SIZE(oper);
1216 aopPut(AOP(oper),fAVRReturn[offset],offset);
1221 /*-----------------------------------------------------------------*/
1222 /* saveZreg - if indirect call then save z-pointer register */
1223 /*-----------------------------------------------------------------*/
1224 static void saveZreg (iCode *ic)
1226 /* only if live accross this call */
1227 if (ic->regsSaved == 0 &&
1228 (bitVectBitValue(ic->rMask,R30_IDX) ||
1229 bitVectBitValue(ic->rMask,R31_IDX))) {
1231 emitcode("push","r30");
1232 emitcode("push","r31");
1236 /*-----------------------------------------------------------------*/
1237 /* popZreg - restore values of zreg */
1238 /*-----------------------------------------------------------------*/
1239 static void popZreg (iCode *ic)
1241 if (ic->regsSaved) {
1242 emitcode ("pop","r31");
1243 emitcode ("pop","r30");
1247 /*-----------------------------------------------------------------*/
1248 /* genIpush - genrate code for pushing this gets a little complex */
1249 /*-----------------------------------------------------------------*/
1250 static void genIpush (iCode *ic)
1252 int size, offset = 0 ;
1256 if (!ic->parmPush) {
1257 /* and the item is spilt then do nothing */
1258 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1262 for (lic = ic->next ; lic ; lic = lic->next)
1263 if (lic->op == PCALL) break;
1264 if (lic) saveZreg(lic);
1267 /* this is a paramter push */
1268 aopOp(IC_LEFT(ic),ic,FALSE);
1269 size = AOP_SIZE(IC_LEFT(ic));
1271 l = aopGet(AOP(IC_LEFT(ic)),offset++);
1272 emitcode("push","%s",l);
1275 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1278 /*-----------------------------------------------------------------*/
1279 /* genIpop - recover the registers: can happen only for spilling */
1280 /*-----------------------------------------------------------------*/
1281 static void genIpop (iCode *ic)
1286 /* if the temp was not pushed then */
1287 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1290 aopOp(IC_LEFT(ic),ic,FALSE);
1291 size = AOP_SIZE(IC_LEFT(ic));
1294 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--));
1296 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1299 /*-----------------------------------------------------------------*/
1300 /* genCall - generates a call statement */
1301 /*-----------------------------------------------------------------*/
1302 static void genCall (iCode *ic)
1305 /* if send set is not empty the assign */
1309 for (sic = setFirstItem(_G.sendSet) ; sic ;
1310 sic = setNextItem(_G.sendSet)) {
1311 int size, offset = 0;
1312 aopOp(IC_LEFT(sic),sic,FALSE);
1313 size = AOP_SIZE(IC_LEFT(sic));
1315 char *l = aopGet(AOP(IC_LEFT(sic)),offset);
1317 sprintf(buffer,"r%d",rnum++);
1319 emitcode("mov","%s,%s",b,l);
1322 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1327 emitcode("call","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1328 OP_SYMBOL(IC_LEFT(ic))->rname :
1329 OP_SYMBOL(IC_LEFT(ic))->name));
1331 /* if we need assign a result value */
1332 if ((IS_ITEMP(IC_RESULT(ic)) &&
1333 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1334 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1335 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1337 aopOp(IC_RESULT(ic),ic,FALSE);
1338 assignResultValue(IC_RESULT(ic));
1339 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1342 /* adjust the stack for parameters if required */
1343 if (IC_LEFT(ic)->parmBytes) {
1344 if (IC_LEFT(ic)->parmBytes > 63) {
1345 emitcode("sbiw","r28,%d",IC_LEFT(ic)->parmBytes);
1347 emitcode("subi","r28,lo8(%d)",IC_LEFT(ic)->parmBytes);
1348 emitcode("sbci","r29,hi8(%d)",IC_LEFT(ic)->parmBytes);
1354 /*-----------------------------------------------------------------*/
1355 /* genPcall - generates a call by pointer statement */
1356 /*-----------------------------------------------------------------*/
1357 static void genPcall (iCode *ic)
1360 if (!ic->regsSaved) saveZreg(ic);
1362 aopOp(IC_LEFT(ic),ic,FALSE);
1363 emitcode("mov","r30",aopGet(AOP(IC_LEFT(ic)),0));
1364 emitcode("mov","r31",aopGet(AOP(IC_RIGHT(ic)),0));
1365 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1367 /* if send set is not empty the assign */
1371 for (sic = setFirstItem(_G.sendSet) ; sic ;
1372 sic = setNextItem(_G.sendSet)) {
1373 int size, offset = 0;
1374 aopOp(IC_LEFT(sic),sic,FALSE);
1375 size = AOP_SIZE(IC_LEFT(sic));
1377 char *l = aopGet(AOP(IC_LEFT(sic)),offset);
1379 sprintf(b,"r%d",rnum++);
1381 emitcode("mov","%s,%s",b,l);
1384 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1389 emitcode("icall","");
1391 /* if we need assign a result value */
1392 if ((IS_ITEMP(IC_RESULT(ic)) &&
1393 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1394 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
1395 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1397 aopOp(IC_RESULT(ic),ic,FALSE);
1399 assignResultValue(IC_RESULT(ic));
1400 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1403 /* adjust the stack for parameters if
1405 if (IC_LEFT(ic)->parmBytes) {
1407 if (IC_LEFT(ic)->parmBytes > 3) {
1408 emitcode("mov","a,%s",spname);
1409 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1410 emitcode("mov","%s,a",spname);
1412 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1413 emitcode("dec","%s",spname);
1417 /* adjust the stack for parameters if required */
1418 if (IC_LEFT(ic)->parmBytes) {
1419 if (IC_LEFT(ic)->parmBytes > 63) {
1420 emitcode("sbiw","r28,%d",IC_LEFT(ic)->parmBytes);
1422 emitcode("subi","r28,lo8(%d)",IC_LEFT(ic)->parmBytes);
1423 emitcode("sbci","r29,hi8(%d)",IC_LEFT(ic)->parmBytes);
1426 if (ic->regsSaved) popZreg(ic);
1429 /*-----------------------------------------------------------------*/
1430 /* resultRemat - result is rematerializable */
1431 /*-----------------------------------------------------------------*/
1432 static int resultRemat (iCode *ic)
1434 if (SKIP_IC(ic) || ic->op == IFX)
1437 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1438 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1439 if (sym->remat && !POINTER_SET(ic))
1446 #if defined(__BORLANDC__) || defined(_MSC_VER)
1447 #define STRCASECMP stricmp
1449 #define STRCASECMP strcasecmp
1452 /*-----------------------------------------------------------------*/
1453 /* inExcludeList - return 1 if the string is in exclude Reg list */
1454 /*-----------------------------------------------------------------*/
1455 static bool inExcludeList(char *s)
1459 if (options.excludeRegs[i] &&
1460 STRCASECMP(options.excludeRegs[i],"none") == 0)
1463 for ( i = 0 ; options.excludeRegs[i]; i++) {
1464 if (options.excludeRegs[i] &&
1465 STRCASECMP(s,options.excludeRegs[i]) == 0)
1471 /*-----------------------------------------------------------------*/
1472 /* genFunction - generated code for function entry */
1473 /*-----------------------------------------------------------------*/
1474 static void genFunction (iCode *ic)
1481 /* create the function header */
1482 emitcode(";","-----------------------------------------");
1483 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1484 emitcode(";","-----------------------------------------");
1486 emitcode("","%s:",sym->rname);
1487 fetype = getSpec(operandType(IC_LEFT(ic)));
1489 /* if critical function then turn interrupts off */
1490 if (SPEC_CRTCL(fetype))
1493 if (IS_ISR(sym->etype)) {
1496 /* save the preserved registers that are used in this function */
1497 for (i = R2_IDX ; i <= R15_IDX ; i++ ) {
1498 if (bitVectBitValue(sym->regsUsed,i)) {
1500 emitcode("push","%s",avr_regWithIdx(i)->name);
1503 /* now for the pointer registers */
1504 if (bitVectBitValue(sym->regsUsed,R26_IDX)) {
1506 emitcode("push","r26");
1508 if (bitVectBitValue(sym->regsUsed,R27_IDX)) {
1510 emitcode("push","r27");
1512 if (bitVectBitValue(sym->regsUsed,R30_IDX)) {
1514 emitcode("push","r30");
1516 if (bitVectBitValue(sym->regsUsed,R31_IDX)) {
1518 emitcode("push","r31");
1520 /* adjust the stack for the function */
1522 emitcode ("push","r28");
1523 emitcode ("push","r29");
1524 emitcode ("in","r28,__SP_L__");
1525 emitcode ("in","r29,__SP_H__");
1526 if (sym->stack <= 63) {
1527 emitcode("sbiw","r28,%d",sym->stack);
1529 emitcode ("subi","r28,lo8(%d)",sym->stack);
1530 emitcode ("sbci","r29,hi8(%d)",sym->stack);
1532 emitcode("out","__SP_L__,r28");
1533 emitcode("out","__SP_H__,r29");
1537 /*-----------------------------------------------------------------*/
1538 /* genEndFunction - generates epilogue for functions */
1539 /*-----------------------------------------------------------------*/
1540 static void genEndFunction (iCode *ic)
1542 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1545 /* restore stack pointer */
1547 if (sym->stack <= 63) {
1548 emitcode("adiw","r28,%d",sym->stack);
1550 emitcode ("subi","r28,lo8(-%d)",sym->stack);
1551 emitcode ("sbci","r29,hi8(-%d)",sym->stack);
1553 emitcode("out","__SP_L__,r28");
1554 emitcode("out","__SP_H__,r29");
1556 /* pop frame pointer */
1557 emitcode ("pop","r29");
1558 emitcode ("pop","r28");
1560 /* restore preserved registers */
1561 if (bitVectBitValue(sym->regsUsed,R31_IDX)) {
1563 emitcode("pop","r31");
1565 if (bitVectBitValue(sym->regsUsed,R30_IDX)) {
1567 emitcode("pop","r30");
1569 if (bitVectBitValue(sym->regsUsed,R27_IDX)) {
1571 emitcode("push","r27");
1573 if (bitVectBitValue(sym->regsUsed,R26_IDX)) {
1575 emitcode("push","r26");
1577 for (i = R15_IDX ; i >= R2_IDX ; i-- ) {
1578 if (bitVectBitValue(sym->regsUsed,i)) {
1580 emitcode("pop","%s",avr_regWithIdx(i)->name);
1584 if (SPEC_CRTCL(sym->etype))
1587 if (IS_ISR(sym->etype)) {
1595 /*-----------------------------------------------------------------*/
1596 /* genRet - generate code for return statement */
1597 /*-----------------------------------------------------------------*/
1598 static void genRet (iCode *ic)
1600 int size,offset = 0 ;
1602 /* if we have no return value then
1603 just generate the "ret" */
1607 /* we have something to return then
1608 move the return value into place */
1609 aopOp(IC_LEFT(ic),ic,FALSE);
1610 size = AOP_SIZE(IC_LEFT(ic));
1613 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
1614 emitcode("ldi","%s,%s(%d)",fAVRReturn[offset],larray[offset],
1615 (int)floatFromVal (AOP(IC_LEFT(ic))->aopu.aop_lit),offset);
1618 l = aopGet(AOP(IC_LEFT(ic)),offset);
1619 if (strcmp(fAVRReturn[offset],l))
1620 emitcode("mov","%s,%s",fAVRReturn[offset],l);
1625 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
1628 /* generate a jump to the return label
1629 if the next is not the return statement */
1630 if (!(ic->next && ic->next->op == LABEL &&
1631 IC_LABEL(ic->next) == returnLabel))
1633 emitcode("rjmp","L%05d",returnLabel->key);
1637 /*-----------------------------------------------------------------*/
1638 /* genLabel - generates a label */
1639 /*-----------------------------------------------------------------*/
1640 static void genLabel (iCode *ic)
1642 /* special case never generate */
1643 if (IC_LABEL(ic) == entryLabel)
1646 emitcode("","L%05d:",IC_LABEL(ic)->key);
1649 /*-----------------------------------------------------------------*/
1650 /* genGoto - generates a ljmp */
1651 /*-----------------------------------------------------------------*/
1652 static void genGoto (iCode *ic)
1654 emitcode ("rjmp","L%05d:",(IC_LABEL(ic)->key+100));
1657 /*-----------------------------------------------------------------*/
1658 /* findLabelBackwards: walks back through the iCode chain looking */
1659 /* for the given label. Returns number of iCode instructions */
1660 /* between that label and given ic. */
1661 /* Returns zero if label not found. */
1662 /*-----------------------------------------------------------------*/
1663 static int findLabelBackwards(iCode *ic, int key)
1672 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
1674 /* printf("findLabelBackwards = %d\n", count); */
1682 /*-----------------------------------------------------------------*/
1683 /* genPlusIncr :- does addition with increment if possible */
1684 /*-----------------------------------------------------------------*/
1685 static bool genPlusIncr (iCode *ic)
1687 unsigned int icount ;
1689 /* will try to generate an increment */
1690 /* if the right side is not a literal
1692 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1695 icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
1697 /* if the sizes are greater than 2 or they are not the same regs
1699 if (!sameRegs(AOP(IC_LEFT(ic)),AOP(IC_RESULT(ic))))
1702 /* so we know LEFT & RESULT in the same registers and add
1704 /* for short & char types */
1705 if (AOP_SIZE(IC_RESULT(ic)) < 2) {
1707 emitcode("inc","%s",aopGet(AOP(IC_LEFT(ic)),0));
1710 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_LEFT(ic)),0),-icount);
1714 if (AOP_SIZE(IC_RESULT(ic)) <= 3) {
1715 /* if register pair and starts with 26/30 then adiw */
1716 if (isRegPair(AOP(IC_RESULT(ic))) && icount > 0 && icount < 64 &&
1717 ( IS_REGIDX(AOP(IC_RESULT(ic)),R26_IDX) ||
1718 IS_REGIDX(AOP(IC_RESULT(ic)),R30_IDX) )) {
1719 emitcode("adiw","%s,%d",aopGet(AOP(IC_RESULT(ic)),0),icount);
1724 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_RESULT(ic)),0),-icount);
1725 emitcode("sbci","%s,hi8(%d)",aopGet(AOP(IC_RESULT(ic)),1),-icount);
1729 /* for 32 bit longs */
1730 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_RESULT(ic)),0),-icount);
1731 emitcode("sbci","%s,hi8(%d)",aopGet(AOP(IC_RESULT(ic)),1),-icount);
1732 emitcode("sbci","%s,hlo8(%d)",aopGet(AOP(IC_RESULT(ic)),2),-icount);
1733 emitcode("sbci","%s,hhi8(%d)",aopGet(AOP(IC_RESULT(ic)),3),-icount);
1738 /* This is the pure and virtuous version of this code.
1739 * I'm pretty certain it's right, but not enough to toss the old
1742 static void adjustArithmeticResult (iCode *ic)
1744 if (opIsGptr(IC_RESULT(ic)) &&
1745 opIsGptr(IC_LEFT(ic)) &&
1746 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1748 aopPut(AOP(IC_RESULT(ic)),
1749 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1),
1753 if (opIsGptr(IC_RESULT(ic)) &&
1754 opIsGptr(IC_RIGHT(ic)) &&
1755 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
1757 aopPut(AOP(IC_RESULT(ic)),
1758 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1),
1762 if (opIsGptr(IC_RESULT(ic)) &&
1763 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
1764 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
1765 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
1766 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
1768 sprintf(buffer,"%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
1769 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
1773 /*-----------------------------------------------------------------*/
1774 /* genPlus - generates code for addition */
1775 /*-----------------------------------------------------------------*/
1776 static void genPlus (iCode *ic)
1778 int size, offset = 0;
1782 /* special cases :- */
1784 aopOp (IC_LEFT(ic),ic,FALSE);
1785 aopOp (IC_RIGHT(ic),ic,FALSE);
1786 aopOp (IC_RESULT(ic),ic,TRUE);
1788 /* if I can do an increment instead
1789 of add then GOOD for ME */
1790 if (genPlusIncr (ic) == TRUE)
1793 size = getDataSize(IC_RESULT(ic));
1794 samer = sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic)));
1798 aopPut(AOP(IC_RESULT(ic)),aopGet(AOP(IC_LEFT(ic)),offset),offset);
1800 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
1802 if(offset == 0) l = "add";
1805 emitcode(l,"%s,%s",aopGet(AOP(IC_RESULT(ic)),offset),
1806 aopGet(AOP(IC_RIGHT(ic)),offset));
1808 if (offset == 0) l = "subi";
1811 emitcode(l,"%s,%s(-%d)",aopGet(AOP(IC_RESULT(ic)),offset),
1813 (int)floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
1818 adjustArithmeticResult(ic);
1821 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1822 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1823 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1826 /*-----------------------------------------------------------------*/
1827 /* genMinusDec :- does subtraction with deccrement if possible */
1828 /*-----------------------------------------------------------------*/
1829 static bool genMinusDec (iCode *ic)
1831 unsigned int icount ;
1833 /* will try to generate an increment */
1834 /* if the right side is not a literal
1836 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1839 icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
1841 /* if the sizes are greater than 2 or they are not the same regs
1843 if (!sameRegs(AOP(IC_LEFT(ic)),AOP(IC_RIGHT(ic))))
1846 /* so we know LEFT & RESULT in the same registers and add
1848 /* for short & char types */
1849 if (AOP_SIZE(IC_RESULT(ic)) < 2) {
1851 emitcode("dec","%s",aopGet(AOP(IC_LEFT(ic)),0));
1854 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_LEFT(ic)),0),icount);
1858 if (AOP_SIZE(IC_RESULT(ic)) <= 3) {
1859 /* if register pair and starts with 26/30 then adiw */
1860 if (isRegPair(AOP(IC_RESULT(ic))) && icount > 0 && icount < 64 &&
1861 ( IS_REGIDX(AOP(IC_RESULT(ic)),R26_IDX) ||
1862 IS_REGIDX(AOP(IC_RESULT(ic)),R30_IDX) )) {
1863 emitcode("sbiw","%s,%d",aopGet(AOP(IC_RESULT(ic)),0),icount);
1868 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_RESULT(ic)),0),icount);
1869 emitcode("sbci","%s,hi8(%d)",aopGet(AOP(IC_RESULT(ic)),1),icount);
1872 /* for 32 bit longs */
1873 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_RESULT(ic)),0),icount);
1874 emitcode("sbci","%s,hi8(%d)",aopGet(AOP(IC_RESULT(ic)),1),icount);
1875 emitcode("sbci","%s,hlo8(%d)",aopGet(AOP(IC_RESULT(ic)),2),icount);
1876 emitcode("sbci","%s,hhi8(%d)",aopGet(AOP(IC_RESULT(ic)),3),icount);
1881 /*-----------------------------------------------------------------*/
1882 /* addSign - complete with sign */
1883 /*-----------------------------------------------------------------*/
1884 static void addSign(operand *result, int offset, int sign)
1886 int size = (getDataSize(result) - offset);
1889 emitcode("rlc","a");
1890 emitcode("subb","a,acc");
1892 aopPut(AOP(result),"a",offset++);
1895 aopPut(AOP(result),zero,offset++);
1899 /*-----------------------------------------------------------------*/
1900 /* genMinus - generates code for subtraction */
1901 /*-----------------------------------------------------------------*/
1902 static void genMinus (iCode *ic)
1904 int size, offset = 0, samer;
1907 aopOp (IC_LEFT(ic),ic,FALSE);
1908 aopOp (IC_RIGHT(ic),ic,FALSE);
1909 aopOp (IC_RESULT(ic),ic,TRUE);
1911 /* if I can do an decrement instead
1912 of subtract then GOOD for ME */
1913 if (genMinusDec (ic) == TRUE)
1916 size = getDataSize(IC_RESULT(ic));
1917 samer = sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic)));
1920 aopPut(AOP(IC_RESULT(ic)),aopGet(AOP(IC_LEFT(ic)),offset),offset);
1922 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
1924 if(offset == 0) l = "sub";
1927 emitcode(l,"%s,%s",aopGet(AOP(IC_RESULT(ic)),offset),
1928 aopGet(AOP(IC_RIGHT(ic)),offset));
1930 if (offset == 0) l = "subi";
1933 emitcode(l,"%s,%s(%d)",aopGet(AOP(IC_RESULT(ic)),offset),
1935 (int)floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
1940 adjustArithmeticResult(ic);
1943 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1944 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1945 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1948 /*-----------------------------------------------------------------*/
1949 /* genMultOneByte : 8 bit multiplication & division */
1950 /*-----------------------------------------------------------------*/
1951 static void genMultOneByte (operand *left,
1955 sym_link *opetype = operandType(result);
1959 /* (if two literals, the value is computed before) */
1960 /* if one literal, literal on the right */
1961 if (AOP_TYPE(left) == AOP_LIT){
1967 size = AOP_SIZE(result);
1969 if (SPEC_USIGN(opetype)) {
1970 emitcode("mul","%s,%s", aopGet(AOP(left),0),aopGet(AOP(right),0));
1972 emitcode("muls","%s,%s", aopGet(AOP(left),0),
1973 aopGet(AOP(right),0));
1975 aopPut(AOP(result),"r0",0);
1977 aopPut(AOP(result),"r1",1);
1980 if (SPEC_USIGN(opetype)) {
1982 aopPut(AOP(result),zero,offset++);
1986 lbl = newiTempLabel(NULL);
1987 emitcode("ldi","r24,0");
1988 emitcode("brcc","L%05d",lbl->key);
1989 emitcode("ldi","r24,lo8(-1)");
1990 emitcode("","L%05d:",lbl->key);
1991 while (size--) aopPut(AOP(result),"r24",offset++);
1998 /*-----------------------------------------------------------------*/
1999 /* genMult - generates code for multiplication */
2000 /*-----------------------------------------------------------------*/
2001 static void genMult (iCode *ic)
2003 operand *left = IC_LEFT(ic);
2004 operand *right = IC_RIGHT(ic);
2005 operand *result= IC_RESULT(ic);
2007 /* assign the amsops */
2008 aopOp (left,ic,FALSE);
2009 aopOp (right,ic,FALSE);
2010 aopOp (result,ic,TRUE);
2012 /* if both are of size == 1 */
2013 if (AOP_SIZE(left) == 1 &&
2014 AOP_SIZE(right) == 1 ) {
2015 genMultOneByte(left,right,result);
2019 /* should have been converted to function call */
2023 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2024 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2025 freeAsmop(result,NULL,ic,TRUE);
2028 /*-----------------------------------------------------------------*/
2029 /* genDiv - generates code for division */
2030 /*-----------------------------------------------------------------*/
2031 static void genDiv (iCode *ic)
2033 /* should have been converted to function call */
2037 /*-----------------------------------------------------------------*/
2038 /* genMod - generates code for division */
2039 /*-----------------------------------------------------------------*/
2040 static void genMod (iCode *ic)
2042 /* should have been converted to function call */
2054 /*-----------------------------------------------------------------*/
2055 /* revavrcnd - reverse a conditional for avr */
2056 /*-----------------------------------------------------------------*/
2057 static int revavrcnd(int type)
2061 } rar[] = { { AVR_EQ, AVR_NE}, {AVR_LT, AVR_GE}};
2064 for (i = 0 ; i < (sizeof(rar)/sizeof(rar[0]));i++) {
2065 if (rar[i].type == type) return rar[i].rtype;
2066 if (rar[i].rtype== type) return rar[i].type;
2068 assert(1); /* cannot happen */
2069 return 0; /* makes the compiler happy */
2072 static char *br_name[4] = {"breq","brne","brlt","brge"};
2073 static char *br_uname[4]= {"breq","brne","brlo","brcc"};
2075 /*-----------------------------------------------------------------*/
2076 /* genBranch - generate the branch instruction */
2077 /*-----------------------------------------------------------------*/
2078 static void genBranch (iCode *ifx, int br_type, int sign)
2080 int tj = (IC_TRUE(ifx) ? 1 : 0) ;
2082 if (tj) { /* if true jump */
2083 char *nm = (sign ? br_name[br_type] : br_uname[br_type]);
2084 emitcode(nm,"L%05d",IC_TRUE(ifx)->key);
2085 } else { /* if false jump */
2086 int rtype = revavrcnd(br_type);
2087 char *nm = (sign ? br_name[rtype] : br_uname[rtype]);
2088 emitcode(nm,"L%05d",IC_FALSE(ifx)->key);
2093 /*-----------------------------------------------------------------*/
2094 /* genCmp - compare & jump */
2095 /*-----------------------------------------------------------------*/
2096 static void genCmp (iCode *ic, iCode *ifx, int br_type)
2098 operand *left, *right, *result;
2099 sym_link *letype , *retype;
2101 int sign, size, offset =0;
2104 right= IC_RIGHT(ic);
2105 result = IC_RESULT(ic);
2107 letype = getSpec(operandType(left));
2108 retype =getSpec(operandType(right));
2109 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2111 /* assign the amsops */
2112 aopOp (left,ic,FALSE);
2113 aopOp (right,ic,FALSE);
2114 aopOp (result,ic,TRUE);
2115 size = AOP_SIZE(left);
2119 if (AOP_TYPE(right) == AOP_LIT) {
2120 emitcode("cpi","%s,lo8(%d)",aopGet(AOP(left),0),
2121 (int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
2122 genBranch(ifx,br_type,sign);
2123 } else { /* right != literal */
2124 emitcode("cp","%s,%s",aopGet(AOP(left),0),aopGet(AOP(right),0));
2125 genBranch(ifx,br_type,sign);
2127 } else { /* size != 1 */
2130 emitcode("cp","%s,%s",aopGet(AOP(left),0),aopGet(AOP(right),0));
2132 emitcode("cpc","%s,%s",aopGet(AOP(left),offset),aopGet(AOP(right),offset));
2135 genBranch(ifx,br_type,sign);
2137 } else { /* no ifx */
2138 emitcode("clr","r0");
2141 emitcode("cp","%s,%s",aopGet(AOP(left),0),aopGet(AOP(right),0));
2143 emitcode("cpc","%s,%s",aopGet(AOP(left),offset),aopGet(AOP(right),offset));
2146 lbl = newiTempLabel(NULL);
2147 br_type = revavrcnd(br_type);
2148 if (sign) emitcode(br_uname[br_type],"L%05d",lbl->key);
2149 else emitcode(br_name[br_type],"L%05d",lbl->key);
2150 emitcode("inc","r0");
2151 emitcode("","L%05d:",lbl->key);
2152 aopPut(AOP(result),"r0",0);
2153 size = AOP_SIZE(result) - 1;
2155 while (size--) aopPut(AOP(result),zero,offset++);
2158 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2159 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2160 freeAsmop(result,NULL,ic,TRUE);
2163 /*-----------------------------------------------------------------*/
2164 /* genCmpGt :- greater than comparison */
2165 /*-----------------------------------------------------------------*/
2166 static void genCmpGt (iCode *ic, iCode *ifx)
2168 /* should have transformed by the parser */
2172 /*-----------------------------------------------------------------*/
2173 /* genCmpLt - less than comparisons */
2174 /*-----------------------------------------------------------------*/
2175 static void genCmpLt (iCode *ic, iCode *ifx)
2177 genCmp(ic,ifx,AVR_LT);
2180 /*-----------------------------------------------------------------*/
2181 /* genCmpEq - generates code for equal to */
2182 /*-----------------------------------------------------------------*/
2183 static void genCmpEq (iCode *ic, iCode *ifx)
2185 genCmp(ic,ifx,AVR_EQ);
2188 /*-----------------------------------------------------------------*/
2189 /* genCmpNe - generates code for not equal to */
2190 /*-----------------------------------------------------------------*/
2191 static void genCmpNe (iCode *ic, iCode *ifx)
2193 genCmp(ic,ifx,AVR_NE);
2196 /*-----------------------------------------------------------------*/
2197 /* genCmpGe - generates code for greater than equal to */
2198 /*-----------------------------------------------------------------*/
2199 static void genCmpGe (iCode *ic, iCode *ifx)
2201 genCmp(ic,ifx,AVR_GE);
2204 /*-----------------------------------------------------------------*/
2205 /* genCmpLe - generates code for less than equal to */
2206 /*-----------------------------------------------------------------*/
2207 static void genCmpLe (iCode *ic, iCode *ifx)
2209 operand *left = IC_LEFT(ic);
2210 operand *right= IC_RIGHT(ic);
2212 IC_RIGHT(ic) = left;
2213 IC_LEFT(ic) = right;
2214 genCmp(ic,ifx,AVR_GE);
2217 /*-----------------------------------------------------------------*/
2218 /* ifxForOp - returns the icode containing the ifx for operand */
2219 /*-----------------------------------------------------------------*/
2220 static iCode *ifxForOp ( operand *op, iCode *ic )
2222 /* if true symbol then needs to be assigned */
2223 if (IS_TRUE_SYMOP(op))
2226 /* if this has register type condition and
2227 the next instruction is ifx with the same operand
2228 and live to of the operand is upto the ifx only then */
2230 ic->next->op == IFX &&
2231 IC_COND(ic->next)->key == op->key &&
2232 OP_SYMBOL(op)->liveTo <= ic->next->seq )
2237 /*-----------------------------------------------------------------*/
2238 /* genAndOp - for && operation */
2239 /*-----------------------------------------------------------------*/
2240 static void genAndOp (iCode *ic)
2242 operand *left,*right, *result;
2246 /* note here that && operations that are in an
2247 if statement are taken away by backPatchLabels
2248 only those used in arthmetic operations remain */
2249 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2250 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2251 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2253 tlbl = newiTempLabel(NULL);
2254 toBoolean(left,"r0",TRUE);
2255 toBoolean(right,"r1",TRUE);
2256 emitcode("and","r0,r1");
2257 emitcode("ldi","r24,1");
2258 emitcode("breq","L%05d",tlbl->key);
2259 emitcode("dec","r24");
2260 emitcode("","L%05d:",tlbl->key);
2261 aopPut(AOP(result),"r24",0);
2262 size = AOP_SIZE(result) -1;
2264 while (size--) aopPut(AOP(result),zero,offset++);
2266 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2267 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2268 freeAsmop(result,NULL,ic,TRUE);
2272 /*-----------------------------------------------------------------*/
2273 /* genOrOp - for || operation */
2274 /*-----------------------------------------------------------------*/
2275 static void genOrOp (iCode *ic)
2277 operand *left,*right, *result;
2281 /* note here that || operations that are in an
2282 if statement are taken away by backPatchLabels
2283 only those used in arthmetic operations remain */
2284 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2285 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2286 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2288 tlbl = newiTempLabel(NULL);
2289 toBoolean(left,"r0",TRUE);
2290 toBoolean(right,"r0",FALSE);
2291 emitcode("ldi","r24,1");
2292 emitcode("breq","L%05d",tlbl->key);
2293 emitcode("dec","r24");
2294 emitcode("","L%05d:",tlbl->key);
2295 aopPut(AOP(result),"r24",0);
2296 size = AOP_SIZE(result) -1;
2298 while (size--) aopPut(AOP(result),zero,offset++);
2300 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2301 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2302 freeAsmop(result,NULL,ic,TRUE);
2305 /*-----------------------------------------------------------------*/
2306 /* isLiteralBit - test if lit == 2^n */
2307 /*-----------------------------------------------------------------*/
2308 static int isLiteralBit(unsigned long lit)
2310 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
2311 0x100L,0x200L,0x400L,0x800L,
2312 0x1000L,0x2000L,0x4000L,0x8000L,
2313 0x10000L,0x20000L,0x40000L,0x80000L,
2314 0x100000L,0x200000L,0x400000L,0x800000L,
2315 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
2316 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
2319 for(idx = 0; idx < 32; idx++)
2325 enum { AVR_AND = 0, AVR_OR, AVR_XOR };
2326 static char *bopnames_lit[] = {"andi","ori"};
2327 static char *bopnames[] = {"and","or","eor"};
2328 /*-----------------------------------------------------------------*/
2329 /* genBitWise - generate bitwise operations */
2330 /*-----------------------------------------------------------------*/
2331 static void genBitWise(iCode *ic, iCode *ifx, int bitop)
2333 operand *left, *right, *result;
2337 int samerl, samerr ;
2339 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2340 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2341 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2343 size = AOP_SIZE(left);
2345 if (ifx) { /* used only for jumps */
2346 if (AOP_TYPE(right) == AOP_LIT &&
2347 (bitop == AVR_AND || bitop == AVR_OR)) {
2348 int lit = (int) floatFromVal (AOP(right)->aopu.aop_lit);
2349 int p2 = powof2(lit);
2350 if (bitop == AVR_AND && p2) { /* right side is a power of 2 */
2351 l = aopGet(AOP(left),p2 / 8);
2353 emitcode("sbrc","%s,%d",l,(p2 % 8));
2354 emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2356 emitcode("sbrs","%s,%d",l,(p2 % 8));
2357 emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2359 } else { /* right not power of two */
2360 int eh = OP_SYMBOL(left)->liveTo <= ic->seq;
2363 emitcode(bopnames_lit[bitop],"%s,lo8(%d)",
2364 aopGet(AOP(IC_LEFT(ic)),0), lit);
2366 MOVR0(aopGet(AOP(IC_LEFT(ic)),0));
2367 emitcode(bopnames_lit[bitop],"r0,lo8(%d)",lit);
2369 lbl = newiTempLabel(NULL);
2371 emitcode("breq","L%05d",lbl->key);
2372 emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2374 emitcode("brne","L%05d",lbl->key);
2375 emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2377 emitcode("","L%05d:",lbl->key);
2378 } else if (size == 2) {
2379 emitcode("mov","r24,%s",aopGet(AOP(IC_LEFT(ic)),0));
2380 emitcode("mov","r25,%s",aopGet(AOP(IC_LEFT(ic)),1));
2381 emitcode(bopnames_lit[bitop],"r24,lo8(%d)",lit);
2382 emitcode(bopnames_lit[bitop],"r25,hi8(%d)",lit);
2383 emitcode("sbiw","r24,0");
2384 lbl = newiTempLabel(NULL);
2386 emitcode("breq","L%05d",lbl->key);
2387 emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2389 emitcode("brne","L%05d",lbl->key);
2390 emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2392 emitcode("","L%05d:",lbl->key);
2394 lbl = newiTempLabel(NULL);
2395 lbl1 = newiTempLabel(NULL);
2398 emitcode(bopnames_lit[bitop],"%s,lo8(%d)",
2399 aopGet(AOP(IC_LEFT(ic)),offset), lit);
2401 MOVR0(aopGet(AOP(IC_LEFT(ic)),offset));
2402 emitcode("andi","r0,lo8(%d)",lit);
2404 emitcode("brne","L%05d",lbl->key);
2408 if (IC_FALSE(ifx)) emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2409 else emitcode("rjmp","L%05d",lbl1->key);
2410 emitcode("","L%05d:",lbl->key);
2412 if (IC_TRUE(ifx)) emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2413 emitcode("","L%05d:",lbl1->key);
2417 } else { /* right is not a literal */
2418 int eh = OP_SYMBOL(left)->liveTo <= ic->seq;
2419 int reh = OP_SYMBOL(right)->liveTo <= ic->seq;
2422 emitcode(bopnames[bitop],"%s,%s",
2423 aopGet(AOP(IC_LEFT(ic)),0),
2424 aopGet(AOP(IC_RIGHT(ic)),0));
2426 emitcode(bopnames[bitop],"%s,%s",
2427 aopGet(AOP(IC_RIGHT(ic)),0),
2428 aopGet(AOP(IC_LEFT(ic)),0));
2430 MOVR0(aopGet(AOP(IC_LEFT(ic)),0));
2431 emitcode(bopnames[bitop],"r0,%s",aopGet(AOP(IC_RIGHT(ic)),0));
2433 lbl = newiTempLabel(NULL);
2435 emitcode("breq","L%05d",lbl->key);
2436 emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2438 emitcode("brne","L%05d",lbl->key);
2439 emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2441 emitcode("","L%05d:",lbl->key);
2442 } else if (size == 2) {
2443 emitcode("mov","r24,%s",aopGet(AOP(IC_LEFT(ic)),0));
2444 emitcode("mov","r25,%s",aopGet(AOP(IC_LEFT(ic)),1));
2445 emitcode(bopnames[bitop],"r24,%s",aopGet(AOP(IC_RIGHT(ic)),0));
2446 emitcode(bopnames[bitop],"r25,%s",aopGet(AOP(IC_RIGHT(ic)),1));
2447 emitcode("sbiw","r24,0");
2448 lbl = newiTempLabel(NULL);
2450 emitcode("breq","L%05d",lbl->key);
2451 emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2453 emitcode("brne","L%05d",lbl->key);
2454 emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2456 emitcode("","L%05d:",lbl->key);
2458 lbl = newiTempLabel(NULL);
2459 lbl1 = newiTempLabel(NULL);
2462 emitcode(bopnames[bitop],"%s,%s",
2463 aopGet(AOP(IC_LEFT(ic)),offset),
2464 aopGet(AOP(IC_RIGHT(ic)),offset));
2466 emitcode(bopnames[bitop],"%s,%s",
2467 aopGet(AOP(IC_RIGHT(ic)),offset),
2468 aopGet(AOP(IC_LEFT(ic)),offset));
2470 MOVR0(aopGet(AOP(IC_LEFT(ic)),offset));
2471 emitcode(bopnames[bitop],"r0,%s",aopGet(AOP(IC_RIGHT(ic)),offset));
2473 emitcode("brne","L%05d",lbl->key);
2477 if (IC_FALSE(ifx)) emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2478 else emitcode("rjmp","L%05d",lbl1->key);
2479 emitcode("","L%05d:",lbl->key);
2481 if (IC_TRUE(ifx)) emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2482 emitcode("","L%05d:",lbl1->key);
2489 /* result needs to go a register */
2490 samerl = sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic)));
2491 samerr = sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)));
2493 if (AOP_TYPE(right) == AOP_LIT) {
2494 unsigned int lit = (int) floatFromVal (AOP(right)->aopu.aop_lit);
2495 if (((lit >> (8*offset)) & 0xff) == 0) {
2496 if (bitop == AVR_AND) {
2497 aopPut(AOP(result),zero,offset++);
2499 } else if (bitop == AVR_OR) {
2501 aopPut(AOP(result),aopGet(AOP(left),offset),offset);
2508 if (AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT && (bitop == AVR_AND || bitop == AVR_OR)) {
2509 emitcode(bopnames_lit[bitop],"%s,%s(%d)",aopGet(AOP(IC_LEFT(ic)),offset),
2510 larray[offset],(int) floatFromVal (AOP(right)->aopu.aop_lit));
2512 emitcode(bopnames[bitop],"%s,%s",aopGet(AOP(IC_LEFT(ic)),offset),
2513 aopGet(AOP(IC_RIGHT(ic)),offset));
2515 } else if (samerr) {
2516 emitcode(bopnames[bitop],"%s,%s",aopGet(AOP(IC_RIGHT(ic)),offset),
2517 aopGet(AOP(IC_LEFT(ic)),offset));
2519 aopPut(AOP(IC_RESULT(ic)),aopGet(AOP(IC_LEFT(ic)),offset),offset);
2520 emitcode(bopnames[bitop],aopGet(AOP(IC_RESULT(ic)),offset),
2521 aopGet(AOP(IC_RIGHT(ic)),offset));
2526 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2527 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2528 freeAsmop(result,NULL,ic,TRUE);
2531 /*-----------------------------------------------------------------*/
2532 /* genAnd - code for and */
2533 /*-----------------------------------------------------------------*/
2534 static void genAnd (iCode *ic, iCode *ifx)
2536 genBitWise(ic,ifx,AVR_AND);
2539 /*-----------------------------------------------------------------*/
2540 /* genOr - code for or */
2541 /*-----------------------------------------------------------------*/
2542 static void genOr (iCode *ic, iCode *ifx)
2544 genBitWise(ic,ifx,AVR_OR);
2547 /*-----------------------------------------------------------------*/
2548 /* genXor - code for xclusive or */
2549 /*-----------------------------------------------------------------*/
2550 static void genXor (iCode *ic, iCode *ifx)
2552 genBitWise(ic,ifx,AVR_XOR);
2555 /*-----------------------------------------------------------------*/
2556 /* genInline - write the inline code out */
2557 /*-----------------------------------------------------------------*/
2558 static void genInline (iCode *ic)
2560 char buffer[MAX_INLINEASM];
2564 _G.inLine += (!options.asmpeep);
2565 strcpy(buffer,IC_INLINE(ic));
2567 /* emit each line as a code */
2586 /* emitcode("",buffer); */
2587 _G.inLine -= (!options.asmpeep);
2590 /*-----------------------------------------------------------------*/
2591 /* genRotC - rotate right/left with carry , lr = 1 rotate right */
2592 /*-----------------------------------------------------------------*/
2593 static void genRotC (iCode *ic, int lr)
2595 operand *left , *result ;
2596 int size, offset = 0;
2598 /* rotate right with carry */
2600 result=IC_RESULT(ic);
2601 aopOp (left,ic,FALSE);
2602 aopOp (result,ic,FALSE);
2604 /* move it to the result */
2605 size = AOP_SIZE(result);
2606 if (!sameRegs(AOP(left),AOP(result))) {
2610 aopGet(AOP(left),offset),
2614 size = AOP_SIZE(result);
2616 if (lr) offset = size - 1;
2620 emitcode ("sbrc","%s,%d",aopGet(AOP(result),offset),
2625 emitcode((lr ? "ror" : "rol"),"%s",aopGet(AOP(result),offset));
2629 freeAsmop(left,NULL,ic,TRUE);
2630 freeAsmop(result,NULL,ic,TRUE);
2633 /*-----------------------------------------------------------------*/
2634 /* genRRC - rotate right with carry */
2635 /*-----------------------------------------------------------------*/
2636 static void genRRC (iCode *ic)
2641 /*-----------------------------------------------------------------*/
2642 /* genRLC - generate code for rotate left with carry */
2643 /*-----------------------------------------------------------------*/
2644 static void genRLC (iCode *ic)
2649 /*-----------------------------------------------------------------*/
2650 /* genGetHbit - generates code get highest order bit */
2651 /*-----------------------------------------------------------------*/
2652 static void genGetHbit (iCode *ic)
2654 operand *left, *result;
2658 result=IC_RESULT(ic);
2659 aopOp (left,ic,FALSE);
2660 aopOp (result,ic,FALSE);
2662 size = AOP_SIZE(result);
2663 if (!sameRegs(AOP(left),AOP(result))) {
2664 emitcode("clr","%s",aopGet(AOP(result),size -1));
2665 emitcode("sbrc","%s,7",aopGet(AOP(left),size -1));
2666 emitcode("subi","%s,lo8(-1)",aopGet(AOP(result),size-1));
2668 emitcode("clr","r0");
2669 emitcode("sbrc","%s,7",aopGet(AOP(left),size-1));
2670 emitcode("subi","r0,lo8(-1)");
2671 aopPut(AOP(result),"r0",0);
2676 emitcode("clr",aopGet(AOP(result),offset++));
2678 freeAsmop(left,NULL,ic,TRUE);
2679 freeAsmop(result,NULL,ic,TRUE);
2682 /*-----------------------------------------------------------------*/
2683 /* genShiftLeftLit - shift left by a known amount */
2684 /*-----------------------------------------------------------------*/
2685 static void genShiftLeftLit (iCode *ic)
2687 operand *left,*right, *result;
2688 int size , shCount, offset =0;
2691 right = IC_RIGHT(ic);
2693 result = IC_RESULT(ic);
2695 aopOp(left,ic,FALSE);
2696 aopOp(result,ic,FALSE);
2697 size = AOP_SIZE(result);
2698 shCount = (int)floatFromVal (AOP(right)->aopu.aop_lit);
2700 if (shCount > (size*8 -1)) {
2701 while (size--) aopPut(AOP(result),zero,offset++);
2706 if (!sameRegs(AOP(left),AOP(result)))
2707 aopPut(AOP(result),aopGet(AOP(left),0),0);
2709 emitcode("swap","%s",aopGet(AOP(result),0));
2710 emitcode("andi","%s,0xf0");
2714 emitcode("add","%s,%s",aopGet(AOP(result),0),aopGet(AOP(result),0));
2718 emitcode("lsl","%s",aopGet(AOP(result),0));
2721 if (shCount >= 12) {
2722 aopPut(AOP(result),aopGet(AOP(left),0),1);
2723 aopPut(AOP(result),zero,0);
2724 emitcode("swap","%s",aopGet(AOP(result),1));
2725 emitcode("andi","%s,0xf0",aopGet(AOP(result),1));
2730 aopPut(AOP(result),aopGet(AOP(left),0),1);
2731 aopPut(AOP(result),zero,0);
2737 if (!sameRegs(AOP(left),AOP(result))) {
2738 aopPut(AOP(result),aopGet(AOP(left),0),0);
2739 aopPut(AOP(result),aopGet(AOP(left),1),1);
2741 emitcode("mov","r1,%s",aopGet(AOP(result),0));
2742 emitcode("swap","%s",aopGet(AOP(result),0));
2743 emitcode("andi","%s,0xf0",aopGet(AOP(result),0));
2744 emitcode("andi","r1,0x0f");
2745 emitcode("swap","%s",aopGet(AOP(result),1));
2746 emitcode("andi","%s,0xf0",aopGet(AOP(result),1));
2747 emitcode("or","%s,r1",aopGet(AOP(result),1));
2749 emitcode("lsl","%s",aopGet(AOP(result),0));
2750 emitcode("rol","%s",aopGet(AOP(result),1));
2753 if (!lByteZ && !sameRegs(AOP(result),AOP(left)) && shCount) {
2756 aopPut(AOP(result),aopGet(AOP(left),offset),offset);
2762 emitcode("lsl","%s",aopGet(AOP(result),1));
2764 emitcode("lsl","%s",aopGet(AOP(result),0));
2765 emitcode("rol","%s",aopGet(AOP(result),1));
2770 assert("shifting generic pointer ?\n");
2773 /* 32 bits we do only byte boundaries */
2774 if (shCount >= 24) {
2775 aopPut(AOP(result),aopGet(AOP(left),0),3);
2776 aopPut(AOP(result),zero,2);
2777 aopPut(AOP(result),zero,1);
2778 aopPut(AOP(result),zero,0);
2782 if (shCount >= 16) {
2783 aopPut(AOP(result),aopGet(AOP(left),0),3);
2784 aopPut(AOP(result),aopGet(AOP(left),1),2);
2785 aopPut(AOP(result),zero,1);
2786 aopPut(AOP(result),zero,0);
2791 aopPut(AOP(result),aopGet(AOP(left),0),3);
2792 aopPut(AOP(result),aopGet(AOP(left),1),2);
2793 aopPut(AOP(result),aopGet(AOP(left),2),1);
2794 aopPut(AOP(result),zero,0);
2798 if (!lByteZ && !sameRegs(AOP(left),AOP(right))) {
2801 aopPut(AOP(result),aopGet(AOP(left),offset),offset);
2805 size = AOP_SIZE(result);
2811 emitcode("lsl","%s",aopGet(AOP(result),0));
2812 emitcode("rol","%s",aopGet(AOP(result),1));
2813 emitcode("rol","%s",aopGet(AOP(result),2));
2814 emitcode("rol","%s",aopGet(AOP(result),3));
2819 emitcode("lsl","%s",aopGet(AOP(result),1));
2820 emitcode("rol","%s",aopGet(AOP(result),2));
2821 emitcode("rol","%s",aopGet(AOP(result),3));
2826 emitcode("lsl","%s",aopGet(AOP(result),2));
2827 emitcode("rol","%s",aopGet(AOP(result),3));
2832 emitcode("lsl","%s",aopGet(AOP(result),3));
2840 freeAsmop(left,NULL,ic,TRUE);
2841 freeAsmop(right,NULL,ic,TRUE);
2842 freeAsmop(result,NULL,ic,TRUE);
2845 /*-----------------------------------------------------------------*/
2846 /* genLeftShift - generates code for left shifting */
2847 /*-----------------------------------------------------------------*/
2848 static void genLeftShift (iCode *ic)
2850 operand *left,*right, *result;
2854 right = IC_RIGHT(ic);
2856 result = IC_RESULT(ic);
2858 aopOp(right,ic,FALSE);
2860 if (AOP_TYPE(right) == AOP_LIT) {
2861 genShiftLeftLit(ic);
2866 aopOp(left,ic,FALSE);
2867 aopOp(result,ic,FALSE);
2868 size = AOP_SIZE(result);
2870 if (AOP_SIZE(right) > 1) {
2871 if (isRegPair(AOP(right))) {
2872 emitcode("movw","r24,%s",aopGet(AOP(right),0));
2874 emitcode("mov","r24,%s",aopGet(AOP(right),0));
2875 emitcode("mov","r25,%s",aopGet(AOP(right),1));
2878 emitcode("mov","r24,%s",aopGet(AOP(right),0));
2880 if (!sameRegs(AOP(left),AOP(result))) {
2882 aopPut(AOP(result),aopGet(AOP(left),offset),offset);
2885 size = AOP_SIZE(result);
2887 tlbl = newiTempLabel(NULL);
2888 emitcode("","L%05d:",tlbl->key);
2891 if (offset) emitcode("rol","%s",aopGet(AOP(result),offset));
2892 else emitcode("lsl","%s",aopGet(AOP(result),0));
2895 if (AOP_SIZE(right) > 1) emitcode("sbiw","r24,1");
2896 else emitcode("dec","r24");
2897 emitcode("brne","L%05d",tlbl->key);
2899 freeAsmop(left,NULL,ic,TRUE);
2900 freeAsmop(right,NULL,ic,TRUE);
2901 freeAsmop(result,NULL,ic,TRUE);
2904 /*-----------------------------------------------------------------*/
2905 /* genShiftRightLit - generate for right shift with known count */
2906 /*-----------------------------------------------------------------*/
2907 static void genShiftRightLit (iCode *ic)
2909 operand *left = IC_LEFT(ic)
2910 ,*right= IC_RIGHT(ic)
2911 ,*result=IC_RESULT(ic);
2912 int size , shCount, offset =0;
2914 sym_link *letype = getSpec(operandType(left));
2915 int sign = !SPEC_USIGN(letype);
2917 right = IC_RIGHT(ic);
2919 result = IC_RESULT(ic);
2921 aopOp(left,ic,FALSE);
2922 aopOp(result,ic,FALSE);
2923 size = AOP_SIZE(result);
2924 shCount = (int)floatFromVal (AOP(right)->aopu.aop_lit);
2926 /* if signed then give up and use a loop to shift */
2929 if (!sameRegs(AOP(left),AOP(result))) {
2931 aopPut(AOP(result),aopGet(AOP(left),offset),offset);
2934 size = size = AOP_SIZE(result);
2937 /* be as economical as possible */
2942 size = AOP_SIZE(result);
2944 if (offset == (size-1))
2945 emitcode("asr","%s",aopGet(AOP(result),offset));
2947 emitcode("lsr","%s",aopGet(AOP(result),offset));
2952 emitcode("ldi","r24,lo8(%d)",shCount);
2953 tlbl = newiTempLabel(NULL);
2954 emitcode("","L%05d:",tlbl->key);
2957 if (offset == (size-1)) emitcode("asr","%s",aopGet(AOP(result),offset));
2958 else emitcode("lsr","%s",aopGet(AOP(result),offset));
2961 emitcode("dec","r24");
2962 emitcode("brne","L%05d",tlbl->key);
2966 if (shCount > (size*8 -1)) {
2967 while (size--) aopPut(AOP(result),zero,offset++);
2970 /* for unsigned we can much more efficient */
2973 if (!sameRegs(AOP(left),AOP(result)))
2974 aopPut(AOP(result),aopGet(AOP(left),0),0);
2976 emitcode("swap","%s",aopGet(AOP(result),0));
2977 emitcode("andi","%s,0x0f");
2981 emitcode("lsr","%s",aopGet(AOP(result),0));
2984 if (shCount >= 12) {
2985 aopPut(AOP(result),aopGet(AOP(left),1),0);
2986 aopPut(AOP(result),zero,1);
2987 emitcode("swap","%s",aopGet(AOP(result),0));
2988 emitcode("andi","%s,0x0f",aopGet(AOP(result),0));
2993 aopPut(AOP(result),aopGet(AOP(left),1),0);
2994 aopPut(AOP(result),zero,1);
3000 if (!sameRegs(AOP(left),AOP(result))) {
3001 aopPut(AOP(result),aopGet(AOP(left),0),0);
3002 aopPut(AOP(result),aopGet(AOP(left),1),1);
3004 emitcode("mov","r1,%s",aopGet(AOP(result),1));
3005 emitcode("swap","%s",aopGet(AOP(result),0));
3006 emitcode("andi","%s,0x0f",aopGet(AOP(result),0));
3007 emitcode("andi","r1,0xf0");
3008 emitcode("or","%s,r1",aopGet(AOP(result),0));
3009 emitcode("swap","%s",aopGet(AOP(result),1));
3010 emitcode("andi","%s,0x0f",aopGet(AOP(result),1));
3012 emitcode("lsr","%s",aopGet(AOP(result),1));
3013 emitcode("ror","%s",aopGet(AOP(result),0));
3017 if (!hByteZ && !sameRegs(AOP(result),AOP(left)) && shCount) {
3020 aopPut(AOP(result),aopGet(AOP(left),offset),offset);
3026 emitcode("lsr","%s",aopGet(AOP(result),0));
3028 emitcode("lsr","%s",aopGet(AOP(result),1));
3029 emitcode("ror","%s",aopGet(AOP(result),0));
3035 assert("shifting generic pointer ?\n");
3038 /* 32 bits we do only byte boundaries */
3039 if (shCount >= 24) {
3040 aopPut(AOP(result),aopGet(AOP(left),3),0);
3041 aopPut(AOP(result),zero,1);
3042 aopPut(AOP(result),zero,2);
3043 aopPut(AOP(result),zero,3);
3047 if (shCount >= 16) {
3048 aopPut(AOP(result),aopGet(AOP(left),3),1);
3049 aopPut(AOP(result),aopGet(AOP(left),2),0);
3050 aopPut(AOP(result),zero,2);
3051 aopPut(AOP(result),zero,3);
3056 aopPut(AOP(result),aopGet(AOP(left),1),0);
3057 aopPut(AOP(result),aopGet(AOP(left),2),1);
3058 aopPut(AOP(result),aopGet(AOP(left),3),2);
3059 aopPut(AOP(result),zero,3);
3063 if (!hByteZ && !sameRegs(AOP(left),AOP(right))) {
3066 aopPut(AOP(result),aopGet(AOP(left),offset),offset);
3070 size = AOP_SIZE(result);
3076 emitcode("lsr","%s",aopGet(AOP(result),3));
3077 emitcode("ror","%s",aopGet(AOP(result),2));
3078 emitcode("ror","%s",aopGet(AOP(result),1));
3079 emitcode("ror","%s",aopGet(AOP(result),0));
3084 emitcode("lsr","%s",aopGet(AOP(result),2));
3085 emitcode("ror","%s",aopGet(AOP(result),1));
3086 emitcode("ror","%s",aopGet(AOP(result),0));
3091 emitcode("lsr","%s",aopGet(AOP(result),1));
3092 emitcode("ror","%s",aopGet(AOP(result),0));
3097 emitcode("lsr","%s",aopGet(AOP(result),0));
3104 freeAsmop(left,NULL,ic,TRUE);
3105 freeAsmop(right,NULL,ic,TRUE);
3106 freeAsmop(result,NULL,ic,TRUE);
3109 /*-----------------------------------------------------------------*/
3110 /* genRightShift - generate code for right shifting */
3111 /*-----------------------------------------------------------------*/
3112 static void genRightShift (iCode *ic)
3114 operand *right, *left, *result;
3117 int sign = 0, first =1;
3120 aopOp(right=IC_RIGHT(ic),ic,FALSE);
3121 if (AOP_TYPE(right) == AOP_LIT) {
3122 genShiftRightLit(ic);
3126 if (AOP_SIZE(right) > 1) {
3127 if (isRegPair(AOP(right))) {
3128 emitcode("movw","r24,%s",aopGet(AOP(right),0));
3130 emitcode("mov","r24,%s",aopGet(AOP(right),0));
3131 emitcode("mov","r25,%s",aopGet(AOP(right),1));
3134 emitcode("mov","r24,%s",aopGet(AOP(right),0));
3136 aopOp(left=IC_LEFT(ic),ic,FALSE);
3137 aopOp(result=IC_RESULT(ic),ic,FALSE);
3138 size = AOP_SIZE(result);
3139 tlbl = newiTempLabel(NULL);
3140 emitcode("","L%05d:",tlbl->key);
3142 letype = getSpec(operandType(left));
3143 sign = !SPEC_USIGN(letype);
3144 if (!sameRegs(AOP(left),AOP(result))) {
3146 aopPut(AOP(result),aopGet(AOP(left),offset),offset);
3149 size = AOP_SIZE(result);
3151 size = AOP_SIZE(result);
3154 if (sign) emitcode("asr","%s",aopGet(AOP(result),offset));
3155 else emitcode("lsr","%s",aopGet(AOP(result),offset));
3158 else emitcode("ror","%s",aopGet(AOP(result),offset));
3161 if (AOP_SIZE(right) > 1) emitcode("sbiw","r24,1");
3162 else emitcode("dec","r24");
3163 emitcode("brne","L%05d",tlbl->key);
3165 freeAsmop(left,NULL,ic,TRUE);
3166 freeAsmop(result,NULL,ic,TRUE);
3169 /*-----------------------------------------------------------------*/
3170 /* R0Rsh - shift right r0 by known count */
3171 /*-----------------------------------------------------------------*/
3172 static void R0Rsh (int shCount)
3174 shCount &= 0x0007; // shCount : 0..7
3179 emitcode("lsr","r0");
3182 emitcode("lsr","r0");
3183 emitcode("lsr","r0");
3186 emitcode("swap","r0");
3187 emitcode("lsl","r0");
3190 emitcode("swap","r0");
3193 emitcode("swap","r0");
3194 emitcode("lsr","r0");
3197 emitcode("swap","r0");
3198 emitcode("lsr","r0");
3199 emitcode("lsr","r0");
3202 emitcode("swap","r0");
3203 emitcode("lsr","r0");
3204 emitcode("lsr","r0");
3205 emitcode("lsr","r0");
3210 /*-----------------------------------------------------------------*/
3211 /* genUnpackBits - generates code for unpacking bits */
3212 /*-----------------------------------------------------------------*/
3213 static void genUnpackBits (operand *result, char *rname, int ptype)
3220 etype = getSpec(operandType(result));
3222 /* read the first byte */
3229 emitcode("ld","r0,%s+",rname);
3233 emitcode("ldm","r0,%s+",rname);
3237 emitcode("call","__gptrget_pi");
3241 /* if we have bitdisplacement then it fits */
3242 /* into this byte completely or if length is */
3243 /* less than a byte */
3244 if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8)) {
3246 /* shift right r0 */
3248 emitcode("andi","r0,0x%02x",
3249 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
3251 aopPut(AOP(result),"r0",offset);
3255 /* bit field did not fit in a byte */
3256 rlen = SPEC_BLEN(etype) - 8;
3257 aopPut(AOP(result),"a",offset++);
3266 emitcode("ld","r0,%s+",rname);
3270 emitcode("ldm","r0,%s+",rname);
3274 emitcode("lcall","__gptrget_pi");
3279 /* if we are done */
3283 aopPut(AOP(result),"r0",offset++);
3288 emitcode("andi","r0,#0x%02x",((unsigned char)-1)>>(-rlen));
3289 aopPut(AOP(result),"r0",offset);
3296 /*-----------------------------------------------------------------*/
3297 /* genDataPointerGet - generates code when ptr offset is known */
3298 /*-----------------------------------------------------------------*/
3299 static void genDataPointerGet (operand *left,
3305 int size , offset = 0;
3306 aopOp(result,ic,TRUE);
3308 /* get the string representation of the name */
3309 l = aopGet(AOP(left),0);
3310 size = AOP_SIZE(result);
3313 sprintf(buffer,"(%s + %d)",l+1,offset);
3315 sprintf(buffer,"%s",l+1);
3316 emitcode("lds","%s,%s",aopGet(AOP(result),offset++),buffer);
3319 freeAsmop(left,NULL,ic,TRUE);
3320 freeAsmop(result,NULL,ic,TRUE);
3323 /*-----------------------------------------------------------------*/
3324 /* genNearPointerGet - emitcode for near pointer fetch */
3325 /*-----------------------------------------------------------------*/
3326 static void genNearPointerGet (operand *left,
3333 sym_link *rtype, *retype;
3334 sym_link *ltype = operandType(left);
3337 rtype = operandType(result);
3338 retype= getSpec(rtype);
3340 aopOp(left,ic,FALSE);
3342 /* if left is rematerialisable and
3343 result is not bit variable type and
3344 the left is pointer to data space i.e
3345 lower 128 bytes of space */
3346 if (AOP_TYPE(left) == AOP_IMMD &&
3347 !IS_BITVAR(retype) &&
3348 DCL_TYPE(ltype) == POINTER) {
3349 genDataPointerGet (left,result,ic);
3353 /* if the value is already in a pointer register
3354 then don't need anything more */
3355 if (!AOP_INPREG(AOP(left))) {
3356 /* otherwise get a free pointer register */
3358 preg = getFreePtr(ic,&aop,FALSE,0);
3359 emitcode("mov","%s,%s",
3361 aopGet(AOP(left),0));
3362 rname = preg->name ;
3364 rname = aopGet(AOP(left),0);
3366 freeAsmop(left,NULL,ic,TRUE);
3367 aopOp (result,ic,FALSE);
3369 /* if bitfield then unpack the bits */
3370 if (IS_BITVAR(retype))
3371 genUnpackBits (result,rname,POINTER);
3373 /* we have can just get the values */
3374 int size = AOP_SIZE(result);
3378 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
3380 emitcode("mov","a,@%s",rname);
3381 aopPut(AOP(result),"a",offset);
3383 sprintf(buffer,"@%s",rname);
3384 aopPut(AOP(result),buffer,offset);
3388 emitcode("inc","%s",rname);
3392 /* now some housekeeping stuff */
3394 /* we had to allocate for this iCode */
3395 freeAsmop(NULL,aop,ic,TRUE);
3397 /* we did not allocate which means left
3398 already in a pointer register, then
3399 if size > 0 && this could be used again
3400 we have to point it back to where it
3402 if (AOP_SIZE(result) > 1 &&
3403 !OP_SYMBOL(left)->remat &&
3404 ( OP_SYMBOL(left)->liveTo > ic->seq ||
3406 int size = AOP_SIZE(result) - 1;
3408 emitcode("dec","%s",rname);
3413 freeAsmop(result,NULL,ic,TRUE);
3417 /*-----------------------------------------------------------------*/
3418 /* genPagedPointerGet - emitcode for paged pointer fetch */
3419 /*-----------------------------------------------------------------*/
3420 static void genPagedPointerGet (operand *left,
3427 sym_link *rtype, *retype;
3429 rtype = operandType(result);
3430 retype= getSpec(rtype);
3432 aopOp(left,ic,FALSE);
3434 /* if the value is already in a pointer register
3435 then don't need anything more */
3436 if (!AOP_INPREG(AOP(left))) {
3437 /* otherwise get a free pointer register */
3439 preg = getFreePtr(ic,&aop,FALSE,0);
3440 emitcode("mov","%s,%s",
3442 aopGet(AOP(left),0));
3443 rname = preg->name ;
3445 rname = aopGet(AOP(left),0);
3447 freeAsmop(left,NULL,ic,TRUE);
3448 aopOp (result,ic,FALSE);
3450 /* if bitfield then unpack the bits */
3451 if (IS_BITVAR(retype))
3452 genUnpackBits (result,rname,PPOINTER);
3454 /* we have can just get the values */
3455 int size = AOP_SIZE(result);
3460 emitcode("movx","a,@%s",rname);
3461 aopPut(AOP(result),"a",offset);
3466 emitcode("inc","%s",rname);
3470 /* now some housekeeping stuff */
3472 /* we had to allocate for this iCode */
3473 freeAsmop(NULL,aop,ic,TRUE);
3475 /* we did not allocate which means left
3476 already in a pointer register, then
3477 if size > 0 && this could be used again
3478 we have to point it back to where it
3480 if (AOP_SIZE(result) > 1 &&
3481 !OP_SYMBOL(left)->remat &&
3482 ( OP_SYMBOL(left)->liveTo > ic->seq ||
3484 int size = AOP_SIZE(result) - 1;
3486 emitcode("dec","%s",rname);
3491 freeAsmop(result,NULL,ic,TRUE);
3496 /*-----------------------------------------------------------------*/
3497 /* genFarPointerGet - gget value from far space */
3498 /*-----------------------------------------------------------------*/
3499 static void genFarPointerGet (operand *left,
3500 operand *result, iCode *ic)
3503 sym_link *retype = getSpec(operandType(result));
3505 aopOp(left,ic,FALSE);
3507 /* if the operand is already in dptr
3508 then we do nothing else we move the value to dptr */
3509 if (AOP_TYPE(left) != AOP_STR) {
3510 /* if this is remateriazable */
3511 if (AOP_TYPE(left) == AOP_IMMD)
3512 emitcode("mov","dptr,%s",aopGet(AOP(left),0));
3513 else { /* we need to get it byte by byte */
3514 emitcode("mov","dpl,%s",aopGet(AOP(left),0));
3515 emitcode("mov","dph,%s",aopGet(AOP(left),1));
3516 if (options.model == MODEL_FLAT24)
3518 emitcode("mov", "dpx,%s",aopGet(AOP(left),2));
3522 /* so dptr know contains the address */
3523 freeAsmop(left,NULL,ic,TRUE);
3524 aopOp(result,ic,FALSE);
3526 /* if bit then unpack */
3527 if (IS_BITVAR(retype))
3528 genUnpackBits(result,"dptr",FPOINTER);
3530 size = AOP_SIZE(result);
3534 emitcode("movx","a,@dptr");
3535 aopPut(AOP(result),"a",offset++);
3537 emitcode("inc","dptr");
3541 freeAsmop(result,NULL,ic,TRUE);
3544 /*-----------------------------------------------------------------*/
3545 /* emitcodePointerGet - gget value from code space */
3546 /*-----------------------------------------------------------------*/
3547 static void emitcodePointerGet (operand *left,
3548 operand *result, iCode *ic)
3551 sym_link *retype = getSpec(operandType(result));
3553 aopOp(left,ic,FALSE);
3555 /* if the operand is already in dptr
3556 then we do nothing else we move the value to dptr */
3557 if (AOP_TYPE(left) != AOP_STR) {
3558 /* if this is remateriazable */
3559 if (AOP_TYPE(left) == AOP_IMMD)
3560 emitcode("mov","dptr,%s",aopGet(AOP(left),0));
3561 else { /* we need to get it byte by byte */
3562 emitcode("mov","dpl,%s",aopGet(AOP(left),0));
3563 emitcode("mov","dph,%s",aopGet(AOP(left),1));
3564 if (options.model == MODEL_FLAT24)
3566 emitcode("mov", "dpx,%s",aopGet(AOP(left),2));
3570 /* so dptr know contains the address */
3571 freeAsmop(left,NULL,ic,TRUE);
3572 aopOp(result,ic,FALSE);
3574 /* if bit then unpack */
3575 if (IS_BITVAR(retype))
3576 genUnpackBits(result,"dptr",CPOINTER);
3578 size = AOP_SIZE(result);
3582 emitcode("clr","a");
3583 emitcode("movc","a,@a+dptr");
3584 aopPut(AOP(result),"a",offset++);
3586 emitcode("inc","dptr");
3590 freeAsmop(result,NULL,ic,TRUE);
3593 /*-----------------------------------------------------------------*/
3594 /* genGenPointerGet - gget value from generic pointer space */
3595 /*-----------------------------------------------------------------*/
3596 static void genGenPointerGet (operand *left,
3597 operand *result, iCode *ic)
3600 sym_link *retype = getSpec(operandType(result));
3602 aopOp(left,ic,FALSE);
3604 /* if the operand is already in dptr
3605 then we do nothing else we move the value to dptr */
3606 if (AOP_TYPE(left) != AOP_STR) {
3607 /* if this is remateriazable */
3608 if (AOP_TYPE(left) == AOP_IMMD) {
3609 emitcode("mov","dptr,%s",aopGet(AOP(left),0));
3610 emitcode("mov","b,#%d",pointerCode(retype));
3612 else { /* we need to get it byte by byte */
3613 emitcode("mov","dpl,%s",aopGet(AOP(left),0));
3614 emitcode("mov","dph,%s",aopGet(AOP(left),1));
3615 if (options.model == MODEL_FLAT24)
3617 emitcode("mov", "dpx,%s",aopGet(AOP(left),2));
3618 emitcode("mov","b,%s",aopGet(AOP(left),3));
3622 emitcode("mov","b,%s",aopGet(AOP(left),2));
3626 /* so dptr know contains the address */
3627 freeAsmop(left,NULL,ic,TRUE);
3628 aopOp(result,ic,FALSE);
3630 /* if bit then unpack */
3631 if (IS_BITVAR(retype))
3632 genUnpackBits(result,"dptr",GPOINTER);
3634 size = AOP_SIZE(result);
3638 emitcode("lcall","__gptrget");
3639 aopPut(AOP(result),"a",offset++);
3641 emitcode("inc","dptr");
3645 freeAsmop(result,NULL,ic,TRUE);
3648 /*-----------------------------------------------------------------*/
3649 /* genPointerGet - generate code for pointer get */
3650 /*-----------------------------------------------------------------*/
3651 static void genPointerGet (iCode *ic)
3653 operand *left, *result ;
3654 sym_link *type, *etype;
3658 result = IC_RESULT(ic) ;
3660 /* depending on the type of pointer we need to
3661 move it to the correct pointer register */
3662 type = operandType(left);
3663 etype = getSpec(type);
3664 /* if left is of type of pointer then it is simple */
3665 if (IS_PTR(type) && !IS_FUNC(type->next))
3666 p_type = DCL_TYPE(type);
3668 /* we have to go by the storage class */
3669 p_type = PTR_TYPE(SPEC_OCLS(etype));
3671 /* if (SPEC_OCLS(etype)->codesp ) { */
3672 /* p_type = CPOINTER ; */
3675 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
3676 /* p_type = FPOINTER ; */
3678 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
3679 /* p_type = PPOINTER; */
3681 /* if (SPEC_OCLS(etype) == idata ) */
3682 /* p_type = IPOINTER; */
3684 /* p_type = POINTER ; */
3687 /* now that we have the pointer type we assign
3688 the pointer values */
3693 genNearPointerGet (left,result,ic);
3697 genPagedPointerGet(left,result,ic);
3701 genFarPointerGet (left,result,ic);
3705 emitcodePointerGet (left,result,ic);
3709 genGenPointerGet (left,result,ic);
3715 /*-----------------------------------------------------------------*/
3716 /* genPackBits - generates code for packed bit storage */
3717 /*-----------------------------------------------------------------*/
3718 static void genPackBits (sym_link *etype ,
3720 char *rname, int p_type)
3728 blen = SPEC_BLEN(etype);
3729 bstr = SPEC_BSTR(etype);
3731 l = aopGet(AOP(right),offset++);
3734 /* if the bit lenth is less than or */
3735 /* it exactly fits a byte then */
3736 if (SPEC_BLEN(etype) <= 8 ) {
3737 shCount = SPEC_BSTR(etype) ;
3739 /* shift left acc */
3742 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
3747 emitcode ("mov","b,a");
3748 emitcode("mov","a,@%s",rname);
3752 emitcode ("mov","b,a");
3753 emitcode("movx","a,@dptr");
3757 emitcode ("push","b");
3758 emitcode ("push","acc");
3759 emitcode ("lcall","__gptrget");
3760 emitcode ("pop","b");
3764 emitcode ("anl","a,#0x%02x",(unsigned char)
3765 ((unsigned char)(0xFF << (blen+bstr)) |
3766 (unsigned char)(0xFF >> (8-bstr)) ) );
3767 emitcode ("orl","a,b");
3768 if (p_type == GPOINTER)
3769 emitcode("pop","b");
3775 emitcode("mov","@%s,a",rname);
3779 emitcode("movx","@dptr,a");
3783 emitcode("lcall","__gptrput");
3788 if ( SPEC_BLEN(etype) <= 8 )
3791 emitcode("inc","%s",rname);
3792 rLen = SPEC_BLEN(etype) ;
3794 /* now generate for lengths greater than one byte */
3797 l = aopGet(AOP(right),offset++);
3807 emitcode("mov","@%s,a",rname);
3809 emitcode("mov","@%s,%s",rname,l);
3814 emitcode("movx","@dptr,a");
3819 emitcode("lcall","__gptrput");
3822 emitcode ("inc","%s",rname);
3827 /* last last was not complete */
3829 /* save the byte & read byte */
3832 emitcode ("mov","b,a");
3833 emitcode("mov","a,@%s",rname);
3837 emitcode ("mov","b,a");
3838 emitcode("movx","a,@dptr");
3842 emitcode ("push","b");
3843 emitcode ("push","acc");
3844 emitcode ("lcall","__gptrget");
3845 emitcode ("pop","b");
3849 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
3850 emitcode ("orl","a,b");
3853 if (p_type == GPOINTER)
3854 emitcode("pop","b");
3859 emitcode("mov","@%s,a",rname);
3863 emitcode("movx","@dptr,a");
3867 emitcode("lcall","__gptrput");
3871 /*-----------------------------------------------------------------*/
3872 /* genDataPointerSet - remat pointer to data space */
3873 /*-----------------------------------------------------------------*/
3874 static void genDataPointerSet(operand *right,
3878 int size, offset = 0 ;
3879 char *l, buffer[256];
3881 aopOp(right,ic,FALSE);
3883 l = aopGet(AOP(result),0);
3884 size = AOP_SIZE(right);
3887 sprintf(buffer,"(%s + %d)",l+1,offset);
3889 sprintf(buffer,"%s",l+1);
3890 emitcode("mov","%s,%s",buffer,
3891 aopGet(AOP(right),offset++));
3894 freeAsmop(right,NULL,ic,TRUE);
3895 freeAsmop(result,NULL,ic,TRUE);
3898 /*-----------------------------------------------------------------*/
3899 /* genNearPointerSet - emitcode for near pointer put */
3900 /*-----------------------------------------------------------------*/
3901 static void genNearPointerSet (operand *right,
3909 sym_link *ptype = operandType(result);
3911 retype= getSpec(operandType(right));
3913 aopOp(result,ic,FALSE);
3915 /* if the result is rematerializable &
3916 in data space & not a bit variable */
3917 if (AOP_TYPE(result) == AOP_IMMD &&
3918 DCL_TYPE(ptype) == POINTER &&
3919 !IS_BITVAR(retype)) {
3920 genDataPointerSet (right,result,ic);
3924 /* if the value is already in a pointer register
3925 then don't need anything more */
3926 if (!AOP_INPREG(AOP(result))) {
3927 /* otherwise get a free pointer register */
3929 preg = getFreePtr(ic,&aop,FALSE,0);
3930 emitcode("mov","%s,%s",
3932 aopGet(AOP(result),0));
3933 rname = preg->name ;
3935 rname = aopGet(AOP(result),0);
3937 freeAsmop(result,NULL,ic,TRUE);
3938 aopOp (right,ic,FALSE);
3940 /* if bitfield then unpack the bits */
3941 if (IS_BITVAR(retype))
3942 genPackBits (retype,right,rname,POINTER);
3944 /* we have can just get the values */
3945 int size = AOP_SIZE(right);
3949 l = aopGet(AOP(right),offset);
3952 emitcode("mov","@%s,a",rname);
3954 emitcode("mov","@%s,%s",rname,l);
3956 emitcode("inc","%s",rname);
3961 /* now some housekeeping stuff */
3963 /* we had to allocate for this iCode */
3964 freeAsmop(NULL,aop,ic,TRUE);
3966 /* we did not allocate which means left
3967 already in a pointer register, then
3968 if size > 0 && this could be used again
3969 we have to point it back to where it
3971 if (AOP_SIZE(right) > 1 &&
3972 !OP_SYMBOL(result)->remat &&
3973 ( OP_SYMBOL(result)->liveTo > ic->seq ||
3975 int size = AOP_SIZE(right) - 1;
3977 emitcode("dec","%s",rname);
3982 freeAsmop(right,NULL,ic,TRUE);
3987 /*-----------------------------------------------------------------*/
3988 /* genPagedPointerSet - emitcode for Paged pointer put */
3989 /*-----------------------------------------------------------------*/
3990 static void genPagedPointerSet (operand *right,
3999 retype= getSpec(operandType(right));
4001 aopOp(result,ic,FALSE);
4003 /* if the value is already in a pointer register
4004 then don't need anything more */
4005 if (!AOP_INPREG(AOP(result))) {
4006 /* otherwise get a free pointer register */
4008 preg = getFreePtr(ic,&aop,FALSE,0);
4009 emitcode("mov","%s,%s",
4011 aopGet(AOP(result),0));
4012 rname = preg->name ;
4014 rname = aopGet(AOP(result),0);
4016 freeAsmop(result,NULL,ic,TRUE);
4017 aopOp (right,ic,FALSE);
4019 /* if bitfield then unpack the bits */
4020 if (IS_BITVAR(retype))
4021 genPackBits (retype,right,rname,PPOINTER);
4023 /* we have can just get the values */
4024 int size = AOP_SIZE(right);
4028 l = aopGet(AOP(right),offset);
4031 emitcode("movx","@%s,a",rname);
4034 emitcode("inc","%s",rname);
4040 /* now some housekeeping stuff */
4042 /* we had to allocate for this iCode */
4043 freeAsmop(NULL,aop,ic,TRUE);
4045 /* we did not allocate which means left
4046 already in a pointer register, then
4047 if size > 0 && this could be used again
4048 we have to point it back to where it
4050 if (AOP_SIZE(right) > 1 &&
4051 !OP_SYMBOL(result)->remat &&
4052 ( OP_SYMBOL(result)->liveTo > ic->seq ||
4054 int size = AOP_SIZE(right) - 1;
4056 emitcode("dec","%s",rname);
4061 freeAsmop(right,NULL,ic,TRUE);
4066 /*-----------------------------------------------------------------*/
4067 /* genFarPointerSet - set value from far space */
4068 /*-----------------------------------------------------------------*/
4069 static void genFarPointerSet (operand *right,
4070 operand *result, iCode *ic)
4073 sym_link *retype = getSpec(operandType(right));
4075 aopOp(result,ic,FALSE);
4077 /* if the operand is already in dptr
4078 then we do nothing else we move the value to dptr */
4079 if (AOP_TYPE(result) != AOP_STR) {
4080 /* if this is remateriazable */
4081 if (AOP_TYPE(result) == AOP_IMMD)
4082 emitcode("mov","dptr,%s",aopGet(AOP(result),0));
4083 else { /* we need to get it byte by byte */
4084 emitcode("mov","dpl,%s",aopGet(AOP(result),0));
4085 emitcode("mov","dph,%s",aopGet(AOP(result),1));
4086 if (options.model == MODEL_FLAT24)
4088 emitcode("mov", "dpx,%s",aopGet(AOP(result),2));
4092 /* so dptr know contains the address */
4093 freeAsmop(result,NULL,ic,TRUE);
4094 aopOp(right,ic,FALSE);
4096 /* if bit then unpack */
4097 if (IS_BITVAR(retype))
4098 genPackBits(retype,right,"dptr",FPOINTER);
4100 size = AOP_SIZE(right);
4104 char *l = aopGet(AOP(right),offset++);
4106 emitcode("movx","@dptr,a");
4108 emitcode("inc","dptr");
4112 freeAsmop(right,NULL,ic,TRUE);
4115 /*-----------------------------------------------------------------*/
4116 /* genGenPointerSet - set value from generic pointer space */
4117 /*-----------------------------------------------------------------*/
4118 static void genGenPointerSet (operand *right,
4119 operand *result, iCode *ic)
4122 sym_link *retype = getSpec(operandType(right));
4124 aopOp(result,ic,FALSE);
4126 /* if the operand is already in dptr
4127 then we do nothing else we move the value to dptr */
4128 if (AOP_TYPE(result) != AOP_STR) {
4129 /* if this is remateriazable */
4130 if (AOP_TYPE(result) == AOP_IMMD) {
4131 emitcode("mov","dptr,%s",aopGet(AOP(result),0));
4132 emitcode("mov","b,%s + 1",aopGet(AOP(result),0));
4134 else { /* we need to get it byte by byte */
4135 emitcode("mov","dpl,%s",aopGet(AOP(result),0));
4136 emitcode("mov","dph,%s",aopGet(AOP(result),1));
4137 if (options.model == MODEL_FLAT24)
4139 emitcode("mov", "dpx,%s",aopGet(AOP(result),2));
4140 emitcode("mov","b,%s",aopGet(AOP(result),3));
4144 emitcode("mov","b,%s",aopGet(AOP(result),2));
4148 /* so dptr know contains the address */
4149 freeAsmop(result,NULL,ic,TRUE);
4150 aopOp(right,ic,FALSE);
4152 /* if bit then unpack */
4153 if (IS_BITVAR(retype))
4154 genPackBits(retype,right,"dptr",GPOINTER);
4156 size = AOP_SIZE(right);
4160 char *l = aopGet(AOP(right),offset++);
4162 emitcode("lcall","__gptrput");
4164 emitcode("inc","dptr");
4168 freeAsmop(right,NULL,ic,TRUE);
4171 /*-----------------------------------------------------------------*/
4172 /* genPointerSet - stores the value into a pointer location */
4173 /*-----------------------------------------------------------------*/
4174 static void genPointerSet (iCode *ic)
4176 operand *right, *result ;
4177 sym_link *type, *etype;
4180 right = IC_RIGHT(ic);
4181 result = IC_RESULT(ic) ;
4183 /* depending on the type of pointer we need to
4184 move it to the correct pointer register */
4185 type = operandType(result);
4186 etype = getSpec(type);
4187 /* if left is of type of pointer then it is simple */
4188 if (IS_PTR(type) && !IS_FUNC(type->next)) {
4189 p_type = DCL_TYPE(type);
4192 /* we have to go by the storage class */
4193 p_type = PTR_TYPE(SPEC_OCLS(etype));
4195 /* if (SPEC_OCLS(etype)->codesp ) { */
4196 /* p_type = CPOINTER ; */
4199 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
4200 /* p_type = FPOINTER ; */
4202 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
4203 /* p_type = PPOINTER ; */
4205 /* if (SPEC_OCLS(etype) == idata ) */
4206 /* p_type = IPOINTER ; */
4208 /* p_type = POINTER ; */
4211 /* now that we have the pointer type we assign
4212 the pointer values */
4217 genNearPointerSet (right,result,ic);
4221 genPagedPointerSet (right,result,ic);
4225 genFarPointerSet (right,result,ic);
4229 genGenPointerSet (right,result,ic);
4235 /*-----------------------------------------------------------------*/
4236 /* genIfx - generate code for Ifx statement */
4237 /*-----------------------------------------------------------------*/
4238 static void genIfx (iCode *ic, iCode *popIc)
4240 operand *cond = IC_COND(ic);
4243 aopOp(cond,ic,FALSE);
4245 /* get the value into acc */
4246 if (AOP_TYPE(cond) != AOP_CRY)
4247 toBoolean(cond,"",0);
4250 /* the result is now in the accumulator */
4251 freeAsmop(cond,NULL,ic,TRUE);
4253 /* if there was something to be popped then do it */
4257 /* if the condition is a bit variable */
4258 /* if (isbit && IS_ITEMP(cond) && SPIL_LOC(cond)) { */
4259 /* // genIfxJump(ic,SPIL_LOC(cond)->rname); */
4262 /* if (isbit && !IS_ITEMP(cond)) */
4263 /* // genIfxJump(ic,OP_SYMBOL(cond)->rname); */
4265 /* // genIfxJump(ic,"a"); */
4270 /*-----------------------------------------------------------------*/
4271 /* genAddrOf - generates code for address of */
4272 /*-----------------------------------------------------------------*/
4273 static void genAddrOf (iCode *ic)
4275 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
4278 aopOp(IC_RESULT(ic),ic,FALSE);
4280 /* if the operand is on the stack then we
4281 need to get the stack offset of this
4284 /* if it has an offset then we need to compute
4287 emitcode("mov","a,_bp");
4288 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
4289 aopPut(AOP(IC_RESULT(ic)),"a",0);
4291 /* we can just move _bp */
4292 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
4294 /* fill the result with zero */
4295 size = AOP_SIZE(IC_RESULT(ic)) - 1;
4298 if (options.stack10bit && size < (FPTRSIZE - 1))
4301 "*** warning: pointer to stack var truncated.\n");
4308 if (options.stack10bit && offset == 2)
4310 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
4314 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
4321 /* object not on stack then we need the name */
4322 size = AOP_SIZE(IC_RESULT(ic));
4326 char s[SDCC_NAME_MAX];
4328 sprintf(s,"#(%s >> %d)",
4332 sprintf(s,"#%s",sym->rname);
4333 aopPut(AOP(IC_RESULT(ic)),s,offset++);
4337 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
4341 /*-----------------------------------------------------------------*/
4342 /* genFarFarAssign - assignment when both are in far space */
4343 /*-----------------------------------------------------------------*/
4344 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
4346 int size = AOP_SIZE(right);
4349 /* first push the right side on to the stack */
4351 l = aopGet(AOP(right),offset++);
4353 emitcode ("push","acc");
4356 freeAsmop(right,NULL,ic,FALSE);
4357 /* now assign DPTR to result */
4358 aopOp(result,ic,FALSE);
4359 size = AOP_SIZE(result);
4361 emitcode ("pop","acc");
4362 aopPut(AOP(result),"a",--offset);
4364 freeAsmop(result,NULL,ic,FALSE);
4368 /*-----------------------------------------------------------------*/
4369 /* genAssign - generate code for assignment */
4370 /*-----------------------------------------------------------------*/
4371 static void genAssign (iCode *ic)
4373 operand *result, *right;
4375 unsigned long lit = 0L;
4377 result = IC_RESULT(ic);
4378 right = IC_RIGHT(ic) ;
4380 /* if they are the same */
4381 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
4384 aopOp(right,ic,FALSE);
4386 /* special case both in far space */
4387 if (AOP_TYPE(right) == AOP_DPTR &&
4388 IS_TRUE_SYMOP(result) &&
4389 isOperandInFarSpace(result)) {
4391 genFarFarAssign (result,right,ic);
4395 aopOp(result,ic,TRUE);
4397 /* if they are the same registers */
4398 if (sameRegs(AOP(right),AOP(result)))
4401 /* if the result is a bit */
4402 if (AOP_TYPE(result) == AOP_CRY) {
4404 /* if the right size is a literal then
4405 we know what the value is */
4406 if (AOP_TYPE(right) == AOP_LIT) {
4407 if (((int) operandLitValue(right)))
4408 aopPut(AOP(result),one,0);
4410 aopPut(AOP(result),zero,0);
4414 /* the right is also a bit variable */
4415 if (AOP_TYPE(right) == AOP_CRY) {
4416 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4417 aopPut(AOP(result),"c",0);
4422 toBoolean(right,"",0);
4423 aopPut(AOP(result),"a",0);
4427 /* bit variables done */
4429 size = AOP_SIZE(result);
4431 if(AOP_TYPE(right) == AOP_LIT)
4432 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4434 (AOP_TYPE(result) != AOP_REG) &&
4435 (AOP_TYPE(right) == AOP_LIT) &&
4436 !IS_FLOAT(operandType(right)) &&
4438 emitcode("clr","a");
4440 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
4441 aopPut(AOP(result),"a",size);
4444 aopGet(AOP(right),size),
4450 aopGet(AOP(right),offset),
4457 freeAsmop (right,NULL,ic,FALSE);
4458 freeAsmop (result,NULL,ic,TRUE);
4461 /*-----------------------------------------------------------------*/
4462 /* genJumpTab - genrates code for jump table */
4463 /*-----------------------------------------------------------------*/
4464 static void genJumpTab (iCode *ic)
4469 aopOp(IC_JTCOND(ic),ic,FALSE);
4470 /* get the condition into accumulator */
4471 l = aopGet(AOP(IC_JTCOND(ic)),0);
4473 /* multiply by three */
4474 emitcode("add","a,acc");
4475 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0));
4476 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
4478 jtab = newiTempLabel(NULL);
4479 emitcode("mov","dptr,#%05d$",jtab->key+100);
4480 emitcode("jmp","@a+dptr");
4481 emitcode("","%05d$:",jtab->key+100);
4482 /* now generate the jump labels */
4483 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
4484 jtab = setNextItem(IC_JTLABELS(ic)))
4485 emitcode("ljmp","%05d$",jtab->key+100);
4489 /*-----------------------------------------------------------------*/
4490 /* genCast - gen code for casting */
4491 /*-----------------------------------------------------------------*/
4492 static void genCast (iCode *ic)
4494 operand *result = IC_RESULT(ic);
4495 sym_link *ctype = operandType(IC_LEFT(ic));
4496 sym_link *rtype = operandType(IC_RIGHT(ic));
4497 operand *right = IC_RIGHT(ic);
4500 /* if they are equivalent then do nothing */
4501 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
4504 aopOp(right,ic,FALSE) ;
4505 aopOp(result,ic,FALSE);
4507 /* if the result is a bit */
4508 if (AOP_TYPE(result) == AOP_CRY) {
4509 /* if the right size is a literal then
4510 we know what the value is */
4511 if (AOP_TYPE(right) == AOP_LIT) {
4512 if (((int) operandLitValue(right)))
4513 aopPut(AOP(result),one,0);
4515 aopPut(AOP(result),zero,0);
4520 /* the right is also a bit variable */
4521 if (AOP_TYPE(right) == AOP_CRY) {
4522 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4523 aopPut(AOP(result),"c",0);
4528 toBoolean(right,"",0);
4529 aopPut(AOP(result),"a",0);
4533 /* if they are the same size : or less */
4534 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
4536 /* if they are in the same place */
4537 if (sameRegs(AOP(right),AOP(result)))
4540 /* if they in different places then copy */
4541 size = AOP_SIZE(result);
4545 aopGet(AOP(right),offset),
4553 /* if the result is of type pointer */
4554 if (IS_PTR(ctype)) {
4557 sym_link *type = operandType(right);
4558 sym_link *etype = getSpec(type);
4560 /* pointer to generic pointer */
4561 if (IS_GENPTR(ctype)) {
4565 p_type = DCL_TYPE(type);
4567 /* we have to go by the storage class */
4568 p_type = PTR_TYPE(SPEC_OCLS(etype));
4571 /* the first two bytes are known */
4572 size = GPTRSIZE - 1;
4576 aopGet(AOP(right),offset),
4580 /* the last byte depending on type */
4597 /* this should never happen */
4598 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
4599 "got unknown pointer type");
4602 aopPut(AOP(result),l, GPTRSIZE - 1);
4606 /* just copy the pointers */
4607 size = AOP_SIZE(result);
4611 aopGet(AOP(right),offset),
4618 /* so we now know that the size of destination is greater
4619 than the size of the source */
4620 /* we move to result for the size of source */
4621 size = AOP_SIZE(right);
4625 aopGet(AOP(right),offset),
4630 /* now depending on the sign of the source && destination */
4631 size = AOP_SIZE(result) - AOP_SIZE(right);
4632 /* if unsigned or not an integral type */
4633 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
4635 aopPut(AOP(result),zero,offset++);
4637 /* we need to extend the sign :{ */
4638 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1);
4640 emitcode("rlc","a");
4641 emitcode("subb","a,acc");
4643 aopPut(AOP(result),"a",offset++);
4646 /* we are done hurray !!!! */
4649 freeAsmop(right,NULL,ic,TRUE);
4650 freeAsmop(result,NULL,ic,TRUE);
4654 /*-----------------------------------------------------------------*/
4655 /* genDjnz - generate decrement & jump if not zero instrucion */
4656 /*-----------------------------------------------------------------*/
4657 static int genDjnz (iCode *ic, iCode *ifx)
4663 /* if the if condition has a false label
4664 then we cannot save */
4668 /* if the minus is not of the form
4670 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
4671 !IS_OP_LITERAL(IC_RIGHT(ic)))
4674 if (operandLitValue(IC_RIGHT(ic)) != 1)
4677 /* if the size of this greater than one then no
4679 if (getSize(operandType(IC_RESULT(ic))) > 1)
4682 /* otherwise we can save BIG */
4683 lbl = newiTempLabel(NULL);
4684 lbl1= newiTempLabel(NULL);
4686 aopOp(IC_RESULT(ic),ic,FALSE);
4688 if (IS_AOP_PREG(IC_RESULT(ic))) {
4689 emitcode("dec","%s",
4690 aopGet(AOP(IC_RESULT(ic)),0));
4691 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0));
4692 emitcode("jnz","%05d$",lbl->key+100);
4694 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0),
4697 emitcode ("sjmp","%05d$",lbl1->key+100);
4698 emitcode ("","%05d$:",lbl->key+100);
4699 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4700 emitcode ("","%05d$:",lbl1->key+100);
4702 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
4707 static char *recvregs[8] =
4709 "r16","r17","r18","r19","r20","r21","r22","r23"
4713 /*-----------------------------------------------------------------*/
4714 /* genReceive - generate code for a receive iCode */
4715 /*-----------------------------------------------------------------*/
4716 static void genReceive (iCode *ic)
4718 int size , offset =0;
4719 aopOp(IC_RESULT(ic),ic,FALSE);
4720 size = AOP_SIZE(IC_RESULT(ic));
4722 aopPut(AOP(IC_RESULT(ic)),recvregs[recvCnt++],offset);
4725 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
4728 /*-----------------------------------------------------------------*/
4729 /* gen51Code - generate code for 8051 based controllers */
4730 /*-----------------------------------------------------------------*/
4731 void genAVRCode (iCode *lic)
4736 lineHead = lineCurr = NULL;
4738 /* print the allocation information */
4740 printAllocInfo( currFunc, codeOutFile);
4741 /* if debug information required */
4742 /* if (options.debug && currFunc) { */
4744 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
4746 if (IS_STATIC(currFunc->etype))
4747 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
4749 emitcode("","G$%s$0$0 ==.",currFunc->name);
4752 /* stack pointer name */
4753 if (options.useXstack)
4759 for (ic = lic ; ic ; ic = ic->next ) {
4761 if ( cln != ic->lineno ) {
4762 if ( options.debug ) {
4764 emitcode("","C$%s$%d$%d$%d ==.",
4765 FileBaseName(ic->filename),ic->lineno,
4766 ic->level,ic->block);
4769 emitcode(";","%s %d",ic->filename,ic->lineno);
4772 /* if the result is marked as
4773 spilt and rematerializable or code for
4774 this has already been generated then
4776 if (resultRemat(ic) || ic->generated )
4779 /* depending on the operation */
4798 /* IPOP happens only when trying to restore a
4799 spilt live range, if there is an ifx statement
4800 following this pop then the if statement might
4801 be using some of the registers being popped which
4802 would destory the contents of the register so
4803 we need to check for this condition and handle it */
4805 ic->next->op == IFX &&
4806 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
4807 genIfx (ic->next,ic);
4825 genEndFunction (ic);
4845 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
4862 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
4866 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
4870 genCmpLe (ic,ifxForOp(IC_RESULT(ic),ic));
4874 genCmpGe (ic,ifxForOp(IC_RESULT(ic),ic));
4878 genCmpNe (ic,ifxForOp(IC_RESULT(ic),ic));
4882 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
4894 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
4898 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
4902 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
4929 case GET_VALUE_AT_ADDRESS:
4934 if (POINTER_SET(ic))
4961 addSet(&_G.sendSet,ic);
4966 /* piCode(ic,stdout); */
4972 /* now we are ready to call the
4973 peep hole optimizer */
4974 if (!options.nopeep)
4975 peepHole (&lineHead);
4977 /* now do the actual printing */
4978 printLine (lineHead,codeOutFile);