1 /*-------------------------------------------------------------------------
2 avrgen.c - source file for code generation for ATMEL AVR
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (2000)
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding!
25 -------------------------------------------------------------------------*/
31 #include "SDCCglobl.h"
33 #ifdef HAVE_SYS_ISA_DEFS_H
34 #include <sys/isa_defs.h>
40 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
41 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
47 #include "SDCCpeeph.h"
51 char *aopLiteral (value *val, int offset);
54 /* this is the down and dirty file with all kinds of
55 kludgy & hacky stuff. This is what it is all about
56 CODE GENERATION for a specific MCU . some of the
57 routines may be reusable, will have to see */
59 static char *zero = "0x00";
60 static char *one = "0x01";
63 char *fReturnAVR[] = {"r16","r17","r18","r19" };
64 unsigned fAVRReturnSize = 4; /* shared with ralloc.c */
65 char **fAVRReturn = fReturnAVR;
67 static short rbank = -1;
79 extern int avr_ptrRegReq ;
81 extern FILE *codeOutFile;
82 static void saverbank (int, iCode *,bool);
83 #define RESULTONSTACK(x) \
84 (IC_RESULT(x) && IC_RESULT(x)->aop && \
85 IC_RESULT(x)->aop->type == AOP_STK )
87 #define MOVR0(x) if (strcmp(x,"r0")) emitcode("mov","r0,%s",x);
88 #define CLRC emitcode("clc","")
89 #define SETC emitcode("stc","")
91 #define IS_REGIDX(a,r) (a->type == AOP_REG && a->aopu.aop_reg[0]->rIdx == r)
93 static lineNode *lineHead = NULL;
94 static lineNode *lineCurr = NULL;
96 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
97 0xE0, 0xC0, 0x80, 0x00};
98 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
99 0x07, 0x03, 0x01, 0x00};
106 /*-----------------------------------------------------------------*/
107 /* emitcode - writes the code into a file : for now it is simple */
108 /*-----------------------------------------------------------------*/
109 static void emitcode (char *inst,char *fmt, ...)
112 char lb[MAX_INLINEASM];
119 sprintf(lb,"%s\t",inst);
121 sprintf(lb,"%s",inst);
122 vsprintf(lb+(strlen(lb)),fmt,ap);
126 while (isspace(*lbp)) lbp++;
129 lineCurr = (lineCurr ?
130 connectLine(lineCurr,newLineNode(lb)) :
131 (lineHead = newLineNode(lb)));
132 lineCurr->isInline = _G.inLine;
133 lineCurr->isDebug = _G.debugLine;
137 /*-----------------------------------------------------------------*/
138 /* getFreePtr - returns X or Z whichever is free or can be pushed */
139 /*-----------------------------------------------------------------*/
140 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result, bool zonly)
142 bool xiu = FALSE , ziu = FALSE;
143 bool xou = FALSE , zou = FALSE;
145 /* the logic: if x & z used in the instruction
146 then we are in trouble otherwise */
148 /* first check if x & z are used by this
149 instruction, in which case we are in trouble */
150 if ((xiu = bitVectBitValue(ic->rUsed,X_IDX)) &&
151 (ziu = bitVectBitValue(ic->rUsed,Z_IDX)))
156 xou = bitVectBitValue(ic->rMask,X_IDX);
157 zou = bitVectBitValue(ic->rMask,Z_IDX);
159 /* if no usage of Z then return it */
161 ic->rUsed = bitVectSetBit(ic->rUsed,Z_IDX);
162 (*aopp)->type = AOP_Z;
164 (*aopp)->aop_ptr2 = avr_regWithIdx(R31_IDX);
165 return (*aopp)->aopu.aop_ptr = avr_regWithIdx(R30_IDX);
168 /* if no usage of X then return it */
169 if (!xiu && !xou && !zonly) {
170 ic->rUsed = bitVectSetBit(ic->rUsed,X_IDX);
171 (*aopp)->type = AOP_X;
173 (*aopp)->aop_ptr2 = avr_regWithIdx(R27_IDX);
174 return (*aopp)->aopu.aop_ptr = avr_regWithIdx(R26_IDX);
177 /* if z not used then */
180 /* push it if not already pushed */
182 emitcode ("push","%s",
183 avr_regWithIdx(R30_IDX)->dname);
184 emitcode ("push","%s",
185 avr_regWithIdx(R31_IDX)->dname);
189 ic->rUsed = bitVectSetBit(ic->rUsed,Z_IDX);
190 (*aopp)->type = AOP_Z;
191 (*aopp)->aop_ptr2 = avr_regWithIdx(R31_IDX);
192 return (*aopp)->aopu.aop_ptr = avr_regWithIdx(R30_IDX);
195 /* now we know they both have usage */
196 /* if x not used in this instruction */
197 if (!xiu && !zonly) {
198 /* push it if not already pushed */
200 emitcode ("push","%s",
201 avr_regWithIdx(R26_IDX)->dname);
202 emitcode ("push","%s",
203 avr_regWithIdx(R27_IDX)->dname);
207 ic->rUsed = bitVectSetBit(ic->rUsed,X_IDX);
208 (*aopp)->type = AOP_X;
210 (*aopp)->aop_ptr2 = avr_regWithIdx(R27_IDX);
211 return (*aopp)->aopu.aop_ptr = avr_regWithIdx(R26_IDX);
216 /* I said end of world but not quite end of world yet */
217 /* if this is a result then we can push it on the stack*/
219 (*aopp)->type = AOP_STK;
224 /* other wise this is true end of the world */
225 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
226 "getFreePtr should never reach here");
230 /*-----------------------------------------------------------------*/
231 /* newAsmop - creates a new asmOp */
232 /*-----------------------------------------------------------------*/
233 static asmop *newAsmop (short type)
237 ALLOC(aop,sizeof(asmop));
242 /*-----------------------------------------------------------------*/
243 /* pointerCode - returns the code for a pointer type */
244 /*-----------------------------------------------------------------*/
245 static int pointerCode (link *etype)
248 return PTR_TYPE(SPEC_OCLS(etype));
252 /*-----------------------------------------------------------------*/
253 /* aopForSym - for a true symbol */
254 /*-----------------------------------------------------------------*/
255 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
258 memmap *space= SPEC_OCLS(sym->etype);
260 /* if already has one */
264 /* assign depending on the storage class */
265 /* if it is on the stack */
267 sym->aop = aop = newAsmop(0);
268 aop->size = getSize(sym->type);
270 /* we can use std / ldd instruction */
271 if (sym->stack > 0 && (sym->stack + getSize(sym->type) - 1) <= 63) {
272 aop->type = AOP_STK_D;
273 aop->aopu.aop_stk = sym->stack;
277 /* otherwise get a free pointer register X/Z */
278 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result,FALSE);
280 /* now assign the address of the variable to
281 the pointer register */
282 if (aop->type != AOP_STK) {
283 emitcode("movw","%s,r28",aop->aopu.aop_ptr->name);
284 if (sym->stack < 0) {
285 if ((sym->stack - _G.nRegsSaved) > -63) {
286 emitcode("sbiw","%s,0x%02x",
287 aop->aopu.aop_ptr->name,
288 (sym->stack - _G.nRegsSaved));
290 emitcode("subi","%s,lo8(%d)", aop->aopu.aop_ptr->name,
291 sym->stack - _G.nRegsSaved);
292 emitcode("sbci","%s,hi8(%d)",aop->aop_ptr2->name,
293 sym->stack - _G.nRegsSaved);
296 if (sym->stack <= 63) {
297 emitcode("adiw","%s,0x%02x",aop->aopu.aop_ptr->name,sym->stack);
299 emitcode("subi","%s,lo8(-%d)",aop->aopu.aop_ptr->name,sym->stack);
300 emitcode("sbci","%s,hi8(-%d)",aop->aop_ptr2->name,sym->stack);
307 /* if in bit space */
308 if (IN_BITSPACE(space)) {
309 sym->aop = aop = newAsmop (AOP_CRY);
310 aop->aopu.aop_dir = sym->rname ;
311 aop->size = getSize(sym->type);
314 /* if it is in direct space */
315 if (IN_DIRSPACE(space)) {
316 sym->aop = aop = newAsmop (AOP_DIR);
317 aop->aopu.aop_dir = sym->rname ;
318 aop->size = getSize(sym->type);
322 /* special case for a function */
323 if (IS_FUNC(sym->type)) {
324 sym->aop = aop = newAsmop(AOP_IMMD);
325 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
326 strcpy(aop->aopu.aop_immd,sym->rname);
327 aop->size = FPTRSIZE;
331 /* only remaining is code / eeprom which will need pointer reg */
332 /* if it is in code space */
333 if (IN_CODESPACE(space))
336 sym->aop = aop = newAsmop(0);
337 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result,aop->code);
338 aop->size = getSize(sym->type);
339 emitcode ("ldi","%s,lo8(%s)",aop->aopu.aop_ptr->name,sym->rname);
340 emitcode ("ldi","%s,hi8(%s)",aop->aop_ptr2);
345 /*-----------------------------------------------------------------*/
346 /* aopForRemat - rematerialzes an object */
347 /*-----------------------------------------------------------------*/
348 static asmop *aopForRemat (symbol *sym)
350 iCode *ic = sym->rematiCode;
351 asmop *aop = newAsmop(AOP_IMMD);
356 val += operandLitValue(IC_RIGHT(ic));
357 else if (ic->op == '-')
358 val -= operandLitValue(IC_RIGHT(ic));
362 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
366 sprintf(buffer,"(%s %c 0x%04x)",
367 OP_SYMBOL(IC_LEFT(ic))->rname,
368 val >= 0 ? '+' : '-',
371 strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
373 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
374 strcpy(aop->aopu.aop_immd,buffer);
378 /*-----------------------------------------------------------------*/
379 /* regsInCommon - two operands have some registers in common */
380 /*-----------------------------------------------------------------*/
381 static bool regsInCommon (operand *op1, operand *op2)
386 /* if they have registers in common */
387 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
390 sym1 = OP_SYMBOL(op1);
391 sym2 = OP_SYMBOL(op2);
393 if (sym1->nRegs == 0 || sym2->nRegs == 0)
396 for (i = 0 ; i < sym1->nRegs ; i++) {
401 for (j = 0 ; j < sym2->nRegs ;j++ ) {
405 if (sym2->regs[j] == sym1->regs[i])
413 /*-----------------------------------------------------------------*/
414 /* operandsEqu - equivalent */
415 /*-----------------------------------------------------------------*/
416 static bool operandsEqu ( operand *op1, operand *op2)
420 /* if they not symbols */
421 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
424 sym1 = OP_SYMBOL(op1);
425 sym2 = OP_SYMBOL(op2);
427 /* if both are itemps & one is spilt
428 and the other is not then false */
429 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
430 sym1->isspilt != sym2->isspilt )
433 /* if they are the same */
437 if (strcmp(sym1->rname,sym2->rname) == 0)
441 /* if left is a tmp & right is not */
445 (sym1->usl.spillLoc == sym2))
452 (sym2->usl.spillLoc == sym1))
458 /*-----------------------------------------------------------------*/
459 /* sameRegs - two asmops have the same registers */
460 /*-----------------------------------------------------------------*/
461 static bool sameRegs (asmop *aop1, asmop *aop2 )
468 if (aop1->type != AOP_REG ||
469 aop2->type != AOP_REG )
472 if (aop1->size != aop2->size )
475 for (i = 0 ; i < aop1->size ; i++ )
476 if (aop1->aopu.aop_reg[i] !=
477 aop2->aopu.aop_reg[i] )
483 /*-----------------------------------------------------------------*/
484 /* isRegPair - for size 2 if this operand has a register pair */
485 /*-----------------------------------------------------------------*/
486 static int isRegPair (asmop *aop)
488 if (!aop || aop->size != 2) return 0;
489 if (aop->type == AOP_X || aop->type == AOP_Z) return 1;
490 if (aop->type != AOP_REG) return 0;
491 if ((aop->aopu.aop_reg[1]->rIdx -
492 aop->aopu.aop_reg[0]->rIdx) == 1) return 1;
496 /*-----------------------------------------------------------------*/
497 /* aopOp - allocates an asmop for an operand : */
498 /*-----------------------------------------------------------------*/
499 static void aopOp (operand *op, iCode *ic, bool result)
508 /* if this a literal */
509 if (IS_OP_LITERAL(op)) {
510 op->aop = aop = newAsmop(AOP_LIT);
511 aop->aopu.aop_lit = op->operand.valOperand;
512 aop->size = getSize(operandType(op));
516 /* if already has a asmop then continue */
520 /* if the underlying symbol has a aop */
521 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
522 op->aop = OP_SYMBOL(op)->aop;
526 /* if this is a true symbol */
527 if (IS_TRUE_SYMOP(op)) {
528 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
532 /* this is a temporary : this has
538 e) can be a return use only */
543 /* if the type is a conditional */
544 if (sym->regType == REG_CND) {
545 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
550 /* if it is spilt then two situations
552 b) has a spill location */
553 if (sym->isspilt || sym->nRegs == 0) {
555 /* rematerialize it NOW */
557 sym->aop = op->aop = aop =
559 aop->size = getSize(sym->type);
564 assert("ACC_USE cannot happen in AVR\n");
569 aop = op->aop = sym->aop = newAsmop(AOP_STR);
570 aop->size = getSize(sym->type);
571 for ( i = 0 ; i < fAVRReturnSize ; i++ )
572 aop->aopu.aop_str[i] = fAVRReturn[i];
576 /* else spill location */
577 sym->aop = op->aop = aop =
578 aopForSym(ic,sym->usl.spillLoc,result);
579 aop->size = getSize(sym->type);
583 /* must be in a register */
584 sym->aop = op->aop = aop = newAsmop(AOP_REG);
585 aop->size = sym->nRegs;
586 for ( i = 0 ; i < sym->nRegs ;i++)
587 aop->aopu.aop_reg[i] = sym->regs[i];
590 /*-----------------------------------------------------------------*/
591 /* freeAsmop - free up the asmop given to an operand */
592 /*----------------------------------------------------------------*/
593 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
610 /* depending on the asmop type only three cases need work AOP_RO
611 , AOP_R1 && AOP_STK */
616 emitcode ("pop","r26");
617 emitcode ("pop","r27");
621 bitVectUnSetBit(ic->rUsed,X_IDX);
627 emitcode ("pop","r30");
628 emitcode ("pop","r31");
632 bitVectUnSetBit(ic->rUsed,Z_IDX);
638 int stk = aop->aopu.aop_stk + aop->size;
639 bitVectUnSetBit(ic->rUsed,X_IDX);
640 bitVectUnSetBit(ic->rUsed,Z_IDX);
642 getFreePtr(ic,&aop,FALSE,0);
644 emitcode ("movw","%s,r28");
646 if (stk <= 63 && stk > 0) {
647 emitcode ("adiw","%s,0x%02x",aop->aopu.aop_ptr->name,stk+1);
649 emitcode ("subi","%s,lo8(%d)",aop->aopu.aop_ptr->name,-(stk+1));
650 emitcode ("sbci","%s,hi8(%d)",aop->aop_ptr2->name,-(stk+1));
655 emitcode("pop","r24");
656 emitcode("st","-%s,r24",aop->type == AOP_X ? "X" : "Z");
660 freeAsmop(op,NULL,ic,TRUE);
662 emitcode("pop","r26");
663 emitcode("pop","r27");
668 emitcode("pop","r30");
669 emitcode("pop","r31");
676 /* all other cases just dealloc */
680 OP_SYMBOL(op)->aop = NULL;
681 /* if the symbol has a spill */
683 SPIL_LOC(op)->aop = NULL;
688 /*-----------------------------------------------------------------*/
689 /* aopGet - for fetching value of the aop */
690 /*-----------------------------------------------------------------*/
691 static char *aopGet (asmop *aop, int offset)
696 /* offset is greater than
698 if (offset > (aop->size - 1) &&
699 aop->type != AOP_LIT)
702 /* depending on type */
706 if (offset > aop->coff) {
707 emitcode ("adiw","%s,%d",aop->aopu.aop_ptr->name,offset - aop->coff);
710 if (offset < aop->coff) {
711 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,aop->coff - offset);
715 emitcode("ld","%s,x",
716 (rs = ((offset & 1) ? "r25" : "r24")));
721 if (offset > aop->coff) {
722 emitcode("adiw","r30,%d",offset - aop->coff);
724 emitcode("sbiw","r30,%d",aop->coff - offset);
726 emitcode("lpm","%s,z",(rs = ((offset & 1) ? "r25" : "r24")));
729 if (offset > aop->coff) {
730 emitcode ("ldd","%s,z+%d",(rs = ((offset & 1) ? "r25" : "r24")),
733 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,aop->coff - offset);
735 emitcode ("ld","%s,z",(rs = ((offset & 1) ? "r25" : "r24")));
742 emitcode ("lds","%s,(%s)+%d",
743 (rs = ((offset & 1) ? "r25" : "r24")),
744 aop->aopu.aop_immd, offset);
748 emitcode ("lds","%s,(%s)+%d",
749 (rs = ((offset & 1) ? "r25" : "r24")),
750 aop->aopu.aop_dir, offset);
754 return aop->aopu.aop_reg[offset]->name;
757 assert("cannot be in bit space AOP_CRY\n");
761 s = aopLiteral(aop->aopu.aop_lit,offset);
762 emitcode("ldi","%s,lo8(%s)",(rs = ((offset & 1)?"r24" : "r25")),s);
767 return aop->aopu.aop_str[offset];
770 emitcode ("ldd","%s,Y+%d",
771 (rs = ((offset & 1) ? "r25" : "r24")),
772 aop->aopu.aop_stk+offset);
776 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
777 "aopget got unsupported aop->type");
780 /*-----------------------------------------------------------------*/
781 /* aopPut - puts a string for a aop */
782 /*-----------------------------------------------------------------*/
783 static void aopPut (asmop *aop, char *s, int offset)
787 if (aop->size && offset > ( aop->size - 1)) {
788 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
789 "aopPut got offset > aop->size");
793 /* will assign value to value */
794 /* depending on where it is ofcourse */
798 sprintf(d,"(%s)+%d", aop->aopu.aop_dir,offset);
801 sprintf(d,"%s",aop->aopu.aop_dir);
804 emitcode("sts","%s,%s",d,s);
808 if (toupper(*s) != 'R') {
810 emitcode("clr","%s",aop->aopu.aop_reg[offset]->name);
812 emitcode("ldi","r25,%s",s);
813 emitcode("mov","%s,r35",aop->aopu.aop_reg[offset]->name);
816 if (strcmp( aop->aopu.aop_reg[offset]->name,s)) {
817 emitcode("mov","%s,%s", aop->aopu.aop_reg[offset]->name,s);
823 if (offset > aop->coff) {
824 emitcode ("adiw","%s,%d",aop->aopu.aop_ptr->name,offset - aop->coff);
827 if (offset < aop->coff) {
828 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,aop->coff - offset);
832 emitcode("st","x,%s", s);
837 if (offset > aop->coff) {
838 emitcode("adiw","r30,%d",offset - aop->coff);
840 emitcode("sbiw","r30,%d",aop->coff - offset);
842 emitcode("lpm","%s,z",s);
845 if (offset > aop->coff) {
846 emitcode ("sdd","z+%d,%s",offset - aop->coff,s);
848 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,aop->coff - offset);
850 emitcode ("ld","%s,z",s);
856 emitcode("push","%s",s);
860 /* if used only for a condition code check */
861 assert(toupper(*s) == 'R');
863 emitcode("xrl","r0,r0");
864 emitcode("cpi","%s,0",s);
867 emitcode("cpc","r0,%s",s);
873 if (strcmp(aop->aopu.aop_str[offset],s))
874 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
878 emitcode ("std","y+%d,%s",offset,s);
882 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
883 "aopPut got unsupported aop->type");
889 /*-----------------------------------------------------------------*/
890 /* reAdjustPreg - points a register back to where it should */
891 /*-----------------------------------------------------------------*/
892 static void reAdjustPreg (asmop *aop)
897 if ((size = aop->size) <= 1)
903 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,size);
909 #define AOP(op) op->aop
910 #define AOP_TYPE(op) AOP(op)->type
911 #define AOP_SIZE(op) AOP(op)->size
912 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_X || \
913 AOP_TYPE(x) == AOP_Z))
914 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
915 (x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) || \
916 x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) )))
918 /*-----------------------------------------------------------------*/
919 /* genNotFloat - generates not for float operations */
920 /*-----------------------------------------------------------------*/
921 static void genNotFloat (operand *op, operand *res)
927 /* we will put 127 in the first byte of
929 aopPut(AOP(res),"127",0);
930 size = AOP_SIZE(op) - 1;
933 l = aopGet(op->aop,offset++);
937 emitcode("or","R0,%s", aopGet(op->aop, offset++));
939 tlbl = newiTempLabel(NULL);
941 tlbl = newiTempLabel(NULL);
942 aopPut(res->aop,zero,1);
943 emitcode("cpi","r0,0");
944 emitcode("breq","L%05d",tlbl->key);
945 aopPut(res->aop,one,1);
946 emitcode("","L%05d:",tlbl->key);
948 size = res->aop->size - 2;
950 /* put zeros in the rest */
952 aopPut(res->aop,zero,offset++);
955 /*-----------------------------------------------------------------*/
956 /* opIsGptr: returns non-zero if the passed operand is */
957 /* a generic pointer type. */
958 /*-----------------------------------------------------------------*/
959 static int opIsGptr(operand *op)
961 link *type = operandType(op);
963 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
970 /*-----------------------------------------------------------------*/
971 /* getDataSize - get the operand data size */
972 /*-----------------------------------------------------------------*/
973 static int getDataSize(operand *op)
977 if (size == GPTRSIZE)
979 link *type = operandType(op);
982 /* generic pointer; arithmetic operations
983 * should ignore the high byte (pointer type).
991 /*-----------------------------------------------------------------*/
992 /* outAcc - output Acc */
993 /*-----------------------------------------------------------------*/
994 static void outAcc(operand *result)
997 size = getDataSize(result);
999 aopPut(AOP(result),"r0",0);
1002 /* unsigned or positive */
1004 aopPut(AOP(result),zero,offset++);
1009 /*-----------------------------------------------------------------*/
1010 /* outBitC - output a bit C */
1011 /*-----------------------------------------------------------------*/
1012 static void outBitC(operand *result)
1014 emitcode("clr","r0");
1015 emitcode("rol","r0");
1019 /*-----------------------------------------------------------------*/
1020 /* toBoolean - emit code for orl a,operator(sizeop) */
1021 /*-----------------------------------------------------------------*/
1022 static void toBoolean(operand *oper, char *r, bool clr)
1024 int size = AOP_SIZE(oper) ;
1026 if (clr) emitcode ("clr","%s",r);
1028 emitcode("or","%s,%s",r,aopGet(AOP(oper),offset++));
1032 /*-----------------------------------------------------------------*/
1033 /* genNot - generate code for ! operation */
1034 /*-----------------------------------------------------------------*/
1035 static void genNot (iCode *ic)
1038 link *optype = operandType(IC_LEFT(ic));
1039 int size, offset = 1;
1041 /* assign asmOps to operand & result */
1042 aopOp (IC_LEFT(ic),ic,FALSE);
1043 aopOp (IC_RESULT(ic),ic,TRUE);
1045 /* if type float then do float */
1046 if (IS_FLOAT(optype)) {
1047 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1050 emitcode("clr","r0");
1051 tlbl = newiTempLabel(NULL);
1052 size = AOP_SIZE(IC_LEFT(ic));
1055 emitcode("cpse","%s,r0",aopGet(AOP(IC_LEFT(ic)),0));
1059 if (offset) emitcode("cpc","%s,r0",aopGet(AOP(IC_LEFT(ic)),offset));
1060 else emitcode("cpi","%s,0",aopGet(AOP(IC_LEFT(ic)),offset));
1063 emitcode("bne","L%05d",tlbl->key);
1065 emitcode("ldi","r0,1");
1066 emitcode("","L%05d:",tlbl->key);
1067 aopPut(AOP(IC_RESULT(ic)),"r0",0);
1068 size = AOP_SIZE(IC_RESULT(ic)) -1;
1070 while (size--) aopPut(AOP(IC_RESULT(ic)),zero,offset++);
1074 /* release the aops */
1075 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1076 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1080 /*-----------------------------------------------------------------*/
1081 /* genCpl - generate code for complement */
1082 /*-----------------------------------------------------------------*/
1083 static void genCpl (iCode *ic)
1089 /* assign asmOps to operand & result */
1090 aopOp (IC_LEFT(ic),ic,FALSE);
1091 aopOp (IC_RESULT(ic),ic,TRUE);
1092 samer = sameRegs(AOP(IC_LEFT(ic)),AOP(IC_RESULT(ic)));
1093 size = AOP_SIZE(IC_RESULT(ic));
1095 char *l = aopGet(AOP(IC_LEFT(ic)),offset);
1097 emitcode ("com","%s",l);
1099 aopPut(AOP(IC_RESULT(ic)),l,offset);
1100 emitcode ("com","%s",aopGet(AOP(IC_RESULT(ic)),offset++));
1105 /* release the aops */
1106 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1107 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1110 /*-----------------------------------------------------------------*/
1111 /* genUminusFloat - unary minus for floating points */
1112 /*-----------------------------------------------------------------*/
1113 static void genUminusFloat(operand *op,operand *result)
1115 int size ,offset =0 ;
1117 /* for this we just need to flip the
1118 first it then copy the rest in place */
1119 size = AOP_SIZE(op) - 1;
1120 l = aopGet(AOP(op),3);
1122 emitcode("ldi","r24,0x80");
1123 if (sameRegs(AOP(op),AOP(result))) {
1124 emitcode("eor","%s,r24",l);
1126 aopPut(AOP(result),l,3);
1127 emitcode("eor","%s,r24",aopGet(AOP(result),3));
1130 aopPut(AOP(result), aopGet(AOP(op),offset), offset);
1135 /*-----------------------------------------------------------------*/
1136 /* genUminus - unary minus code generation */
1137 /*-----------------------------------------------------------------*/
1138 static void genUminus (iCode *ic)
1141 link *optype, *rtype;
1145 aopOp(IC_LEFT(ic),ic,FALSE);
1146 aopOp(IC_RESULT(ic),ic,TRUE);
1148 optype = operandType(IC_LEFT(ic));
1149 rtype = operandType(IC_RESULT(ic));
1151 /* if float then do float stuff */
1152 if (IS_FLOAT(optype)) {
1153 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1157 /* otherwise subtract from zero */
1158 size = AOP_SIZE(IC_LEFT(ic));
1160 samer = sameRegs(AOP(IC_LEFT(ic)),AOP(IC_RESULT(ic)));
1163 char *l = aopGet(AOP(IC_LEFT(ic)),offset);
1165 emitcode("clr","r0");
1166 emitcode("sbc","r0,%s",l);
1167 aopPut(AOP(IC_RESULT(ic)),"r0",offset++);
1170 emitcode("clr","%s",s=aopGet(AOP(IC_RESULT(ic)),offset++));
1171 emitcode("sbc","%s,%s",s,l);
1175 /* if any remaining bytes in the result */
1176 /* we just need to propagate the sign */
1177 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1178 symbol *tlbl = newiTempLabel(NULL);
1179 emitcode("clr","r0");
1180 emitcode("brcc","L%05d",tlbl->key);
1181 emitcode("com","r0");
1182 emitcode("","L%05d:",tlbl->key);
1184 aopPut(AOP(IC_RESULT(ic)),"r0",offset++);
1188 /* release the aops */
1189 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1190 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1193 /*-----------------------------------------------------------------*/
1194 /* assignResultValue - */
1195 /*-----------------------------------------------------------------*/
1196 static void assignResultValue(operand * oper)
1199 int size = AOP_SIZE(oper);
1201 aopPut(AOP(oper),fAVRReturn[offset],offset);
1206 /*-----------------------------------------------------------------*/
1207 /* saveZreg - if indirect call then save z-pointer register */
1208 /*-----------------------------------------------------------------*/
1209 static void saveZreg (iCode *ic)
1211 /* only if live accross this call */
1212 if (ic->regsSaved == 0 &&
1213 (bitVectBitValue(ic->rMask,R30_IDX) ||
1214 bitVectBitValue(ic->rMask,R31_IDX))) {
1216 emitcode("push","r30");
1217 emitcode("push","r31");
1221 /*-----------------------------------------------------------------*/
1222 /* popZreg - restore values of zreg */
1223 /*-----------------------------------------------------------------*/
1224 static void popZreg (iCode *ic)
1226 if (ic->regsSaved) {
1227 emitcode ("pop","r31");
1228 emitcode ("pop","r30");
1232 /*-----------------------------------------------------------------*/
1233 /* genIpush - genrate code for pushing this gets a little complex */
1234 /*-----------------------------------------------------------------*/
1235 static void genIpush (iCode *ic)
1237 int size, offset = 0 ;
1241 if (!ic->parmPush) {
1242 /* and the item is spilt then do nothing */
1243 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1247 for (lic = ic->next ; lic ; lic = lic->next)
1248 if (lic->op == PCALL) break;
1249 if (lic) saveZreg(lic);
1252 /* this is a paramter push */
1253 aopOp(IC_LEFT(ic),ic,FALSE);
1254 size = AOP_SIZE(IC_LEFT(ic));
1256 l = aopGet(AOP(IC_LEFT(ic)),offset++);
1257 emitcode("push","%s",l);
1260 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1263 /*-----------------------------------------------------------------*/
1264 /* genIpop - recover the registers: can happen only for spilling */
1265 /*-----------------------------------------------------------------*/
1266 static void genIpop (iCode *ic)
1271 /* if the temp was not pushed then */
1272 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1275 aopOp(IC_LEFT(ic),ic,FALSE);
1276 size = AOP_SIZE(IC_LEFT(ic));
1279 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--));
1281 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1284 /*-----------------------------------------------------------------*/
1285 /* genCall - generates a call statement */
1286 /*-----------------------------------------------------------------*/
1287 static void genCall (iCode *ic)
1290 /* if send set is not empty the assign */
1294 for (sic = setFirstItem(_G.sendSet) ; sic ;
1295 sic = setNextItem(_G.sendSet)) {
1296 int size, offset = 0;
1297 aopOp(IC_LEFT(sic),sic,FALSE);
1298 size = AOP_SIZE(IC_LEFT(sic));
1300 char *l = aopGet(AOP(IC_LEFT(sic)),offset);
1301 if (strcmp(l,fAVRReturn[offset]))
1302 emitcode("mov","%s,%s",
1307 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1312 emitcode("call","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1313 OP_SYMBOL(IC_LEFT(ic))->rname :
1314 OP_SYMBOL(IC_LEFT(ic))->name));
1316 /* if we need assign a result value */
1317 if ((IS_ITEMP(IC_RESULT(ic)) &&
1318 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1319 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1320 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1322 aopOp(IC_RESULT(ic),ic,FALSE);
1323 assignResultValue(IC_RESULT(ic));
1324 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1327 /* adjust the stack for parameters if required */
1328 if (IC_LEFT(ic)->parmBytes) {
1329 if (IC_LEFT(ic)->parmBytes > 63) {
1330 emitcode("sbiw","r28,%d",IC_LEFT(ic)->parmBytes);
1332 emitcode("subi","r28,lo8(%d)",IC_LEFT(ic)->parmBytes);
1333 emitcode("sbci","r29,hi8(%d)",IC_LEFT(ic)->parmBytes);
1339 /*-----------------------------------------------------------------*/
1340 /* genPcall - generates a call by pointer statement */
1341 /*-----------------------------------------------------------------*/
1342 static void genPcall (iCode *ic)
1345 if (!ic->regsSaved) saveZreg(ic);
1347 aopOp(IC_LEFT(ic),ic,FALSE);
1348 emitcode("mov","r30",aopGet(AOP(IC_LEFT(ic)),0));
1349 emitcode("mov","r31",aopGet(AOP(IC_RIGHT(ic)),0));
1350 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1352 /* if send set is not empty the assign */
1356 for (sic = setFirstItem(_G.sendSet) ; sic ;
1357 sic = setNextItem(_G.sendSet)) {
1358 int size, offset = 0;
1359 aopOp(IC_LEFT(sic),sic,FALSE);
1360 size = AOP_SIZE(IC_LEFT(sic));
1362 char *l = aopGet(AOP(IC_LEFT(sic)),offset);
1363 if (strcmp(l,fAVRReturn[offset]))
1364 emitcode("mov","%s,%s",
1369 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1374 emitcode("icall","");
1376 /* if we need assign a result value */
1377 if ((IS_ITEMP(IC_RESULT(ic)) &&
1378 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1379 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
1380 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1382 aopOp(IC_RESULT(ic),ic,FALSE);
1384 assignResultValue(IC_RESULT(ic));
1385 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1388 /* adjust the stack for parameters if
1390 if (IC_LEFT(ic)->parmBytes) {
1392 if (IC_LEFT(ic)->parmBytes > 3) {
1393 emitcode("mov","a,%s",spname);
1394 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1395 emitcode("mov","%s,a",spname);
1397 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1398 emitcode("dec","%s",spname);
1402 /* adjust the stack for parameters if required */
1403 if (IC_LEFT(ic)->parmBytes) {
1404 if (IC_LEFT(ic)->parmBytes > 63) {
1405 emitcode("sbiw","r28,%d",IC_LEFT(ic)->parmBytes);
1407 emitcode("subi","r28,lo8(%d)",IC_LEFT(ic)->parmBytes);
1408 emitcode("sbci","r29,hi8(%d)",IC_LEFT(ic)->parmBytes);
1411 if (ic->regsSaved) popZreg(ic);
1414 /*-----------------------------------------------------------------*/
1415 /* resultRemat - result is rematerializable */
1416 /*-----------------------------------------------------------------*/
1417 static int resultRemat (iCode *ic)
1419 if (SKIP_IC(ic) || ic->op == IFX)
1422 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1423 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1424 if (sym->remat && !POINTER_SET(ic))
1432 #define STRCASECMP stricmp
1434 #define STRCASECMP strcasecmp
1437 /*-----------------------------------------------------------------*/
1438 /* inExcludeList - return 1 if the string is in exclude Reg list */
1439 /*-----------------------------------------------------------------*/
1440 static bool inExcludeList(char *s)
1444 if (options.excludeRegs[i] &&
1445 STRCASECMP(options.excludeRegs[i],"none") == 0)
1448 for ( i = 0 ; options.excludeRegs[i]; i++) {
1449 if (options.excludeRegs[i] &&
1450 STRCASECMP(s,options.excludeRegs[i]) == 0)
1456 /*-----------------------------------------------------------------*/
1457 /* genFunction - generated code for function entry */
1458 /*-----------------------------------------------------------------*/
1459 static void genFunction (iCode *ic)
1466 /* create the function header */
1467 emitcode(";","-----------------------------------------");
1468 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1469 emitcode(";","-----------------------------------------");
1471 emitcode("","%s:",sym->rname);
1472 fetype = getSpec(operandType(IC_LEFT(ic)));
1474 /* if critical function then turn interrupts off */
1475 if (SPEC_CRTCL(fetype))
1478 if (IS_ISR(sym->etype)) {
1481 /* save the preserved registers that are used in this function */
1482 for (i = R2_IDX ; i <= R15_IDX ; i++ ) {
1483 if (bitVectBitValue(sym->regsUsed,i)) {
1485 emitcode("push","%s",avr_regWithIdx(i)->name);
1488 /* now for the pointer registers */
1489 if (bitVectBitValue(sym->regsUsed,R26_IDX)) {
1491 emitcode("push","r26");
1493 if (bitVectBitValue(sym->regsUsed,R27_IDX)) {
1495 emitcode("push","r27");
1497 if (bitVectBitValue(sym->regsUsed,R30_IDX)) {
1499 emitcode("push","r30");
1501 if (bitVectBitValue(sym->regsUsed,R31_IDX)) {
1503 emitcode("push","r31");
1505 /* adjust the stack for the function */
1507 emitcode ("push","r28");
1508 emitcode ("push","r29");
1509 emitcode ("in","r28,__SP_L__");
1510 emitcode ("in","r29,__SP_H__");
1511 if (sym->stack <= 63) {
1512 emitcode("sbiw","r28,%d",sym->stack);
1514 emitcode ("subi","r28,lo8(%d)",sym->stack);
1515 emitcode ("sbci","r29,hi8(%d)",sym->stack);
1517 emitcode("out","__SP_L__,r28");
1518 emitcode("out","__SP_H__,r29");
1522 /*-----------------------------------------------------------------*/
1523 /* genEndFunction - generates epilogue for functions */
1524 /*-----------------------------------------------------------------*/
1525 static void genEndFunction (iCode *ic)
1527 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1530 /* restore stack pointer */
1532 if (sym->stack <= 63) {
1533 emitcode("adiw","r28,%d",sym->stack);
1535 emitcode ("subi","r28,lo8(-%d)",sym->stack);
1536 emitcode ("sbci","r29,hi8(-%d)",sym->stack);
1538 emitcode("out","__SP_L__,r28");
1539 emitcode("out","__SP_H__,r29");
1541 /* pop frame pointer */
1542 emitcode ("pop","r29");
1543 emitcode ("pop","r28");
1545 /* restore preserved registers */
1546 if (bitVectBitValue(sym->regsUsed,R31_IDX)) {
1548 emitcode("pop","r31");
1550 if (bitVectBitValue(sym->regsUsed,R30_IDX)) {
1552 emitcode("pop","r30");
1554 if (bitVectBitValue(sym->regsUsed,R27_IDX)) {
1556 emitcode("push","r27");
1558 if (bitVectBitValue(sym->regsUsed,R26_IDX)) {
1560 emitcode("push","r26");
1562 for (i = R15_IDX ; i >= R2_IDX ; i-- ) {
1563 if (bitVectBitValue(sym->regsUsed,i)) {
1565 emitcode("pop","%s",avr_regWithIdx(i)->name);
1569 if (SPEC_CRTCL(sym->etype))
1572 if (IS_ISR(sym->etype)) {
1580 /*-----------------------------------------------------------------*/
1581 /* genRet - generate code for return statement */
1582 /*-----------------------------------------------------------------*/
1583 static void genRet (iCode *ic)
1585 int size,offset = 0 ;
1587 /* if we have no return value then
1588 just generate the "ret" */
1592 /* we have something to return then
1593 move the return value into place */
1594 aopOp(IC_LEFT(ic),ic,FALSE);
1595 size = AOP_SIZE(IC_LEFT(ic));
1599 l = aopGet(AOP(IC_LEFT(ic)),offset);
1600 if (strcmp(fAVRReturn[offset],l))
1601 emitcode("mov","%s,%s",fAVRReturn[offset++],l);
1604 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
1607 /* generate a jump to the return label
1608 if the next is not the return statement */
1609 if (!(ic->next && ic->next->op == LABEL &&
1610 IC_LABEL(ic->next) == returnLabel))
1612 emitcode("rjmp","L%05d",returnLabel->key);
1616 /*-----------------------------------------------------------------*/
1617 /* genLabel - generates a label */
1618 /*-----------------------------------------------------------------*/
1619 static void genLabel (iCode *ic)
1621 /* special case never generate */
1622 if (IC_LABEL(ic) == entryLabel)
1625 emitcode("","L%05d:",IC_LABEL(ic)->key);
1628 /*-----------------------------------------------------------------*/
1629 /* genGoto - generates a ljmp */
1630 /*-----------------------------------------------------------------*/
1631 static void genGoto (iCode *ic)
1633 emitcode ("rjmp","L%05d:",(IC_LABEL(ic)->key+100));
1636 /*-----------------------------------------------------------------*/
1637 /* findLabelBackwards: walks back through the iCode chain looking */
1638 /* for the given label. Returns number of iCode instructions */
1639 /* between that label and given ic. */
1640 /* Returns zero if label not found. */
1641 /*-----------------------------------------------------------------*/
1642 static int findLabelBackwards(iCode *ic, int key)
1651 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
1653 /* printf("findLabelBackwards = %d\n", count); */
1661 /*-----------------------------------------------------------------*/
1662 /* genPlusIncr :- does addition with increment if possible */
1663 /*-----------------------------------------------------------------*/
1664 static bool genPlusIncr (iCode *ic)
1666 unsigned int icount ;
1668 /* will try to generate an increment */
1669 /* if the right side is not a literal
1671 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1674 icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
1676 /* if the sizes are greater than 2 or they are not the same regs
1678 if (AOP_SIZE(IC_RESULT(ic)) > 2 ||
1679 AOP_SIZE(IC_LEFT(ic)) > 2 ||
1680 !sameRegs(AOP(IC_LEFT(ic)),AOP(IC_RESULT(ic))))
1683 /* so we know LEFT & RESULT in the same registers and add
1685 /* for short & char types */
1686 if (AOP_SIZE(IC_RESULT(ic)) < 2) {
1688 emitcode("inc","%s",aopGet(AOP(IC_LEFT(ic)),0));
1691 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_LEFT(ic)),0),-icount);
1695 /* if register pair and starts with 26/30 then adiw */
1696 if (isRegPair(AOP(IC_RESULT(ic))) && icount > 0 && icount < 64 &&
1697 ( IS_REGIDX(AOP(IC_RESULT(ic)),R26_IDX) ||
1698 IS_REGIDX(AOP(IC_RESULT(ic)),R30_IDX) )) {
1699 emitcode("adiw","%s,%d",aopGet(AOP(IC_RESULT(ic)),0),icount);
1704 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_RESULT(ic)),0),-icount);
1705 emitcode("sbci","%s,hi8(%d)",aopGet(AOP(IC_RESULT(ic)),1),-icount);
1709 /* This is the pure and virtuous version of this code.
1710 * I'm pretty certain it's right, but not enough to toss the old
1713 static void adjustArithmeticResult (iCode *ic)
1715 if (opIsGptr(IC_RESULT(ic)) &&
1716 opIsGptr(IC_LEFT(ic)) &&
1717 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1719 aopPut(AOP(IC_RESULT(ic)),
1720 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1),
1724 if (opIsGptr(IC_RESULT(ic)) &&
1725 opIsGptr(IC_RIGHT(ic)) &&
1726 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
1728 aopPut(AOP(IC_RESULT(ic)),
1729 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1),
1733 if (opIsGptr(IC_RESULT(ic)) &&
1734 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
1735 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
1736 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
1737 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
1739 sprintf(buffer,"%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
1740 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
1744 /*-----------------------------------------------------------------*/
1745 /* genPlus - generates code for addition */
1746 /*-----------------------------------------------------------------*/
1747 static void genPlus (iCode *ic)
1749 int size, offset = 0;
1751 /* special cases :- */
1753 aopOp (IC_LEFT(ic),ic,FALSE);
1754 aopOp (IC_RIGHT(ic),ic,FALSE);
1755 aopOp (IC_RESULT(ic),ic,TRUE);
1757 /* if I can do an increment instead
1758 of add then GOOD for ME */
1759 if (genPlusIncr (ic) == TRUE)
1762 size = getDataSize(IC_RESULT(ic));
1765 aopPut(AOP(IC_RESULT(ic)),aopGet(AOP(IC_RIGHT(ic)),offset),offset);
1767 emitcode("add","%s,%s",aopGet(AOP(IC_RESULT(ic)),offset),
1768 aopGet(AOP(IC_LEFT(ic)),offset));
1770 emitcode("adc","%s,%s",aopGet(AOP(IC_RESULT(ic)),offset),
1771 aopGet(AOP(IC_LEFT(ic)),offset));
1774 adjustArithmeticResult(ic);
1777 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1778 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1779 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1782 /*-----------------------------------------------------------------*/
1783 /* genMinusDec :- does subtraction with deccrement if possible */
1784 /*-----------------------------------------------------------------*/
1785 static bool genMinusDec (iCode *ic)
1787 unsigned int icount ;
1789 /* will try to generate an increment */
1790 /* if the right side is not a literal
1792 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1795 icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
1797 /* if the sizes are greater than 2 or they are not the same regs
1799 if (AOP_SIZE(IC_RESULT(ic)) > 2 ||
1800 AOP_SIZE(IC_LEFT(ic)) > 2 ||
1801 !sameRegs(AOP(IC_LEFT(ic)),AOP(IC_RIGHT(ic))))
1804 /* so we know LEFT & RESULT in the same registers and add
1806 /* for short & char types */
1807 if (AOP_SIZE(IC_RESULT(ic)) < 2) {
1809 emitcode("dec","%s",aopGet(AOP(IC_LEFT(ic)),0));
1812 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_LEFT(ic)),0),icount);
1816 /* if register pair and starts with 26/30 then adiw */
1817 if (isRegPair(AOP(IC_RESULT(ic))) && icount > 0 && icount < 64 &&
1818 ( IS_REGIDX(AOP(IC_RESULT(ic)),R26_IDX) ||
1819 IS_REGIDX(AOP(IC_RESULT(ic)),R30_IDX) )) {
1820 emitcode("sbiw","%s,%d",aopGet(AOP(IC_RESULT(ic)),0),icount);
1825 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_RESULT(ic)),0),icount);
1826 emitcode("sbci","%s,hi8(%d)",aopGet(AOP(IC_RESULT(ic)),1),icount);
1830 /*-----------------------------------------------------------------*/
1831 /* addSign - complete with sign */
1832 /*-----------------------------------------------------------------*/
1833 static void addSign(operand *result, int offset, int sign)
1835 int size = (getDataSize(result) - offset);
1838 emitcode("rlc","a");
1839 emitcode("subb","a,acc");
1841 aopPut(AOP(result),"a",offset++);
1844 aopPut(AOP(result),zero,offset++);
1848 /*-----------------------------------------------------------------*/
1849 /* genMinus - generates code for subtraction */
1850 /*-----------------------------------------------------------------*/
1851 static void genMinus (iCode *ic)
1853 int size, offset = 0;
1855 aopOp (IC_LEFT(ic),ic,FALSE);
1856 aopOp (IC_RIGHT(ic),ic,FALSE);
1857 aopOp (IC_RESULT(ic),ic,TRUE);
1859 /* if I can do an decrement instead
1860 of subtract then GOOD for ME */
1861 if (genMinusDec (ic) == TRUE)
1864 size = getDataSize(IC_RESULT(ic));
1867 aopPut(AOP(IC_RESULT(ic)),aopGet(AOP(IC_RIGHT(ic)),offset),offset);
1869 emitcode("sub","%s,%s",aopGet(AOP(IC_RESULT(ic)),offset),
1870 aopGet(AOP(IC_LEFT(ic)),offset));
1872 emitcode("sbc","%s,%s",aopGet(AOP(IC_RESULT(ic)),offset),
1873 aopGet(AOP(IC_LEFT(ic)),offset));
1876 adjustArithmeticResult(ic);
1879 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1880 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1881 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1884 /*-----------------------------------------------------------------*/
1885 /* genMultOneByte : 8 bit multiplication & division */
1886 /*-----------------------------------------------------------------*/
1887 static void genMultOneByte (operand *left,
1891 link *opetype = operandType(result);
1895 /* (if two literals, the value is computed before) */
1896 /* if one literal, literal on the right */
1897 if (AOP_TYPE(left) == AOP_LIT){
1903 size = AOP_SIZE(result);
1905 if (SPEC_USIGN(opetype)) {
1906 emitcode("mul","%s,%s", aopGet(AOP(left),0),aopGet(AOP(right),0));
1908 emitcode("muls","%s,%s", aopGet(AOP(left),0),
1909 aopGet(AOP(right),0));
1911 aopPut(AOP(result),"r0",0);
1913 aopPut(AOP(result),"r1",1);
1916 if (SPEC_USIGN(opetype)) {
1918 aopPut(AOP(result),zero,offset++);
1921 lbl = newiTempLabel(NULL);
1922 emitcode("ldi","r24,0");
1923 emitcode("brcc","L%05d",lbl->key);
1924 emitcode("ldi","r24,lo8(-1)");
1925 emitcode("","L%05d:",lbl->key);
1926 while (size--) aopPut(AOP(result),"r24",offset++);
1932 /*-----------------------------------------------------------------*/
1933 /* genMult - generates code for multiplication */
1934 /*-----------------------------------------------------------------*/
1935 static void genMult (iCode *ic)
1937 operand *left = IC_LEFT(ic);
1938 operand *right = IC_RIGHT(ic);
1939 operand *result= IC_RESULT(ic);
1941 /* assign the amsops */
1942 aopOp (left,ic,FALSE);
1943 aopOp (right,ic,FALSE);
1944 aopOp (result,ic,TRUE);
1946 /* if both are of size == 1 */
1947 if (AOP_SIZE(left) == 1 &&
1948 AOP_SIZE(right) == 1 ) {
1949 genMultOneByte(left,right,result);
1953 /* should have been converted to function call */
1957 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1958 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1959 freeAsmop(result,NULL,ic,TRUE);
1962 /*-----------------------------------------------------------------*/
1963 /* genDiv - generates code for division */
1964 /*-----------------------------------------------------------------*/
1965 static void genDiv (iCode *ic)
1967 /* should have been converted to function call */
1971 /*-----------------------------------------------------------------*/
1972 /* genMod - generates code for division */
1973 /*-----------------------------------------------------------------*/
1974 static void genMod (iCode *ic)
1976 /* should have been converted to function call */
1988 /*-----------------------------------------------------------------*/
1989 /* revavrcnd - reverse a conditional for avr */
1990 /*-----------------------------------------------------------------*/
1991 static int revavrcnd(int type)
1995 } rar[] = { { AVR_EQ, AVR_NE}, {AVR_LT, AVR_GE}};
1998 for (i = 0 ; i < (sizeof(rar)/sizeof(rar[0]));i++) {
1999 if (rar[i].type == type) return rar[i].rtype;
2000 if (rar[i].rtype== type) return rar[i].type;
2002 assert(1); /* cannot happen */
2005 static char *br_name[4] = {"breq","brne","brlt","brge"};
2006 static char *br_uname[4]= {"breq","brne","brlo","brcc"};
2008 /*-----------------------------------------------------------------*/
2009 /* genBranch - generate the branch instruction */
2010 /*-----------------------------------------------------------------*/
2011 static void genBranch (iCode *ifx, int br_type, int sign)
2013 int tj = (IC_TRUE(ifx) ? 1 : 0) ;
2015 if (tj) { /* if true jump */
2016 char *nm = (sign ? br_name[br_type] : br_uname[br_type]);
2017 emitcode(nm,"L%05d",IC_TRUE(ifx)->key);
2018 } else { /* if false jump */
2019 int rtype = revavrcnd(br_type);
2020 char *nm = (sign ? br_name[rtype] : br_uname[rtype]);
2021 emitcode(nm,"L%05d",IC_FALSE(ifx)->key);
2026 /*-----------------------------------------------------------------*/
2027 /* genCmp - compare & jump */
2028 /*-----------------------------------------------------------------*/
2029 static void genCmp (iCode *ic, iCode *ifx, int br_type)
2031 operand *left, *right, *result;
2032 link *letype , *retype;
2034 int sign, size, offset =0;
2037 right= IC_RIGHT(ic);
2038 result = IC_RESULT(ic);
2040 letype = getSpec(operandType(left));
2041 retype =getSpec(operandType(right));
2042 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2044 /* assign the amsops */
2045 aopOp (left,ic,FALSE);
2046 aopOp (right,ic,FALSE);
2047 aopOp (result,ic,TRUE);
2048 size = AOP_SIZE(left);
2052 if (AOP_TYPE(right) == AOP_LIT) {
2053 emitcode("cpi","%s,lo8(%d)",aopGet(AOP(left),0),
2054 (int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
2055 genBranch(ifx,br_type,sign);
2056 } else { /* right != literal */
2057 emitcode("cp","%s,%s",aopGet(AOP(left),0),aopGet(AOP(right),0));
2058 genBranch(ifx,br_type,sign);
2060 } else { /* size != 1 */
2063 emitcode("cp","%s,%s",aopGet(AOP(left),0),aopGet(AOP(right),0));
2065 emitcode("cpc","%s,%s",aopGet(AOP(left),offset),aopGet(AOP(right),offset));
2068 genBranch(ifx,br_type,sign);
2070 } else { /* no ifx */
2071 emitcode("clr","r0");
2074 emitcode("cp","%s,%s",aopGet(AOP(left),0),aopGet(AOP(right),0));
2076 emitcode("cpc","%s,%s",aopGet(AOP(left),offset),aopGet(AOP(right),offset));
2079 lbl = newiTempLabel(NULL);
2080 br_type = revavrcnd(br_type);
2081 if (sign) emitcode(br_uname[br_type],"L%05d",lbl->key);
2082 else emitcode(br_name[br_type],"L%05d",lbl->key);
2083 emitcode("inc","r0");
2084 emitcode("","L%05d:",lbl->key);
2085 aopPut(AOP(result),"r0",0);
2086 size = AOP_SIZE(result) - 1;
2088 while (size--) aopPut(AOP(result),zero,offset++);
2091 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2092 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2093 freeAsmop(result,NULL,ic,TRUE);
2096 /*-----------------------------------------------------------------*/
2097 /* genCmpGt :- greater than comparison */
2098 /*-----------------------------------------------------------------*/
2099 static void genCmpGt (iCode *ic, iCode *ifx)
2101 /* should have transformed by the parser */
2105 /*-----------------------------------------------------------------*/
2106 /* genCmpLt - less than comparisons */
2107 /*-----------------------------------------------------------------*/
2108 static void genCmpLt (iCode *ic, iCode *ifx)
2110 genCmp(ic,ifx,AVR_LT);
2113 /*-----------------------------------------------------------------*/
2114 /* genCmpEq - generates code for equal to */
2115 /*-----------------------------------------------------------------*/
2116 static void genCmpEq (iCode *ic, iCode *ifx)
2118 genCmp(ic,ifx,AVR_EQ);
2121 /*-----------------------------------------------------------------*/
2122 /* genCmpNe - generates code for not equal to */
2123 /*-----------------------------------------------------------------*/
2124 static void genCmpNe (iCode *ic, iCode *ifx)
2126 genCmp(ic,ifx,AVR_NE);
2129 /*-----------------------------------------------------------------*/
2130 /* genCmpGe - generates code for greater than equal to */
2131 /*-----------------------------------------------------------------*/
2132 static void genCmpGe (iCode *ic, iCode *ifx)
2134 genCmp(ic,ifx,AVR_GE);
2137 /*-----------------------------------------------------------------*/
2138 /* genCmpLe - generates code for less than equal to */
2139 /*-----------------------------------------------------------------*/
2140 static void genCmpLe (iCode *ic, iCode *ifx)
2142 operand *left = IC_LEFT(ic);
2143 operand *right= IC_RIGHT(ic);
2145 IC_RIGHT(ic) = left;
2146 IC_LEFT(ic) = right;
2147 genCmp(ic,ifx,AVR_GE);
2150 /*-----------------------------------------------------------------*/
2151 /* ifxForOp - returns the icode containing the ifx for operand */
2152 /*-----------------------------------------------------------------*/
2153 static iCode *ifxForOp ( operand *op, iCode *ic )
2155 /* if true symbol then needs to be assigned */
2156 if (IS_TRUE_SYMOP(op))
2159 /* if this has register type condition and
2160 the next instruction is ifx with the same operand
2161 and live to of the operand is upto the ifx only then */
2163 ic->next->op == IFX &&
2164 IC_COND(ic->next)->key == op->key &&
2165 OP_SYMBOL(op)->liveTo <= ic->next->seq )
2170 /*-----------------------------------------------------------------*/
2171 /* genAndOp - for && operation */
2172 /*-----------------------------------------------------------------*/
2173 static void genAndOp (iCode *ic)
2175 operand *left,*right, *result;
2179 /* note here that && operations that are in an
2180 if statement are taken away by backPatchLabels
2181 only those used in arthmetic operations remain */
2182 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2183 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2184 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2186 tlbl = newiTempLabel(NULL);
2187 toBoolean(left,"r0",TRUE);
2188 toBoolean(right,"r1",TRUE);
2189 emitcode("and","r0,r1");
2190 emitcode("ldi","r24,1");
2191 emitcode("breq","L%05d",tlbl->key);
2192 emitcode("dec","r24");
2193 emitcode("","L%05d:",tlbl->key);
2194 aopPut(AOP(result),"r24",0);
2195 size = AOP_SIZE(result) -1;
2197 while (size--) aopPut(AOP(result),zero,offset++);
2199 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2200 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2201 freeAsmop(result,NULL,ic,TRUE);
2205 /*-----------------------------------------------------------------*/
2206 /* genOrOp - for || operation */
2207 /*-----------------------------------------------------------------*/
2208 static void genOrOp (iCode *ic)
2210 operand *left,*right, *result;
2214 /* note here that || operations that are in an
2215 if statement are taken away by backPatchLabels
2216 only those used in arthmetic operations remain */
2217 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2218 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2219 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2221 tlbl = newiTempLabel(NULL);
2222 toBoolean(left,"r0",TRUE);
2223 toBoolean(right,"r0",FALSE);
2224 emitcode("ldi","r24,1");
2225 emitcode("breq","L%05d",tlbl->key);
2226 emitcode("dec","r24");
2227 emitcode("","L%05d:",tlbl->key);
2228 aopPut(AOP(result),"r24",0);
2229 size = AOP_SIZE(result) -1;
2231 while (size--) aopPut(AOP(result),zero,offset++);
2233 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2234 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2235 freeAsmop(result,NULL,ic,TRUE);
2238 /*-----------------------------------------------------------------*/
2239 /* isLiteralBit - test if lit == 2^n */
2240 /*-----------------------------------------------------------------*/
2241 static int isLiteralBit(unsigned long lit)
2243 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
2244 0x100L,0x200L,0x400L,0x800L,
2245 0x1000L,0x2000L,0x4000L,0x8000L,
2246 0x10000L,0x20000L,0x40000L,0x80000L,
2247 0x100000L,0x200000L,0x400000L,0x800000L,
2248 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
2249 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
2252 for(idx = 0; idx < 32; idx++)
2259 /*-----------------------------------------------------------------*/
2260 /* genAnd - code for and */
2261 /*-----------------------------------------------------------------*/
2262 static void genAnd (iCode *ic, iCode *ifx)
2264 operand *left, *right, *result;
2268 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2269 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2270 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2272 size = AOP_SIZE(left);
2274 if (ifx) { /* used only for jumps */
2275 if (AOP_TYPE(right) == AOP_LIT) {
2276 int p2 = powof2((int) floatFromVal (AOP(right)->aopu.aop_lit));
2277 if (p2) { /* right side is a power of 2 */
2278 l = aopGet(AOP(left),p2 / 8);
2280 emitcode("sbrc","%s,%d",l,p2 % 8);
2281 emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2283 emitcode("sbrs","%s,%d",l,p2 % 8);
2284 emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2286 } else { /* right not power of two */
2290 } else { /* right is not a literal */
2292 } else { /* other jump -> result goes to register*/
2296 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2297 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2298 freeAsmop(result,NULL,ic,TRUE);
2301 /*-----------------------------------------------------------------*/
2302 /* genOr - code for or */
2303 /*-----------------------------------------------------------------*/
2304 static void genOr (iCode *ic, iCode *ifx)
2306 operand *left, *right, *result;
2308 unsigned long lit = 0L;
2310 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2311 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2312 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2316 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2317 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2318 freeAsmop(result,NULL,ic,TRUE);
2321 /*-----------------------------------------------------------------*/
2322 /* genXor - code for xclusive or */
2323 /*-----------------------------------------------------------------*/
2324 static void genXor (iCode *ic, iCode *ifx)
2326 operand *left, *right, *result;
2328 unsigned long lit = 0L;
2330 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2331 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2332 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2337 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2338 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2339 freeAsmop(result,NULL,ic,TRUE);
2342 /*-----------------------------------------------------------------*/
2343 /* genInline - write the inline code out */
2344 /*-----------------------------------------------------------------*/
2345 static void genInline (iCode *ic)
2347 char buffer[MAX_INLINEASM];
2351 _G.inLine += (!options.asmpeep);
2352 strcpy(buffer,IC_INLINE(ic));
2354 /* emit each line as a code */
2373 /* emitcode("",buffer); */
2374 _G.inLine -= (!options.asmpeep);
2377 /*-----------------------------------------------------------------*/
2378 /* genRRC - rotate right with carry */
2379 /*-----------------------------------------------------------------*/
2380 static void genRRC (iCode *ic)
2382 operand *left , *result ;
2383 int size, offset = 0;
2386 /* rotate right with carry */
2388 result=IC_RESULT(ic);
2389 aopOp (left,ic,FALSE);
2390 aopOp (result,ic,FALSE);
2392 /* move it to the result */
2393 size = AOP_SIZE(result);
2397 freeAsmop(left,NULL,ic,TRUE);
2398 freeAsmop(result,NULL,ic,TRUE);
2401 /*-----------------------------------------------------------------*/
2402 /* genRLC - generate code for rotate left with carry */
2403 /*-----------------------------------------------------------------*/
2404 static void genRLC (iCode *ic)
2406 operand *left , *result ;
2407 int size, offset = 0;
2410 /* rotate right with carry */
2412 result=IC_RESULT(ic);
2413 aopOp (left,ic,FALSE);
2414 aopOp (result,ic,FALSE);
2417 freeAsmop(left,NULL,ic,TRUE);
2418 freeAsmop(result,NULL,ic,TRUE);
2421 /*-----------------------------------------------------------------*/
2422 /* genGetHbit - generates code get highest order bit */
2423 /*-----------------------------------------------------------------*/
2424 static void genGetHbit (iCode *ic)
2426 operand *left, *result;
2428 result=IC_RESULT(ic);
2429 aopOp (left,ic,FALSE);
2430 aopOp (result,ic,FALSE);
2433 freeAsmop(left,NULL,ic,TRUE);
2434 freeAsmop(result,NULL,ic,TRUE);
2437 /*-----------------------------------------------------------------*/
2438 /* AccRol - rotate left accumulator by known count */
2439 /*-----------------------------------------------------------------*/
2440 static void AccRol (int shCount)
2442 shCount &= 0x0007; // shCount : 0..7
2454 emitcode("swap","a");
2458 emitcode("swap","a");
2461 emitcode("swap","a");
2474 /*-----------------------------------------------------------------*/
2475 /* AccLsh - left shift accumulator by known count */
2476 /*-----------------------------------------------------------------*/
2477 static void AccLsh (int shCount)
2481 emitcode("add","a,acc");
2484 emitcode("add","a,acc");
2485 emitcode("add","a,acc");
2487 /* rotate left accumulator */
2489 /* and kill the lower order bits */
2490 emitcode("anl","a,#0x%02x", SLMask[shCount]);
2495 /*-----------------------------------------------------------------*/
2496 /* AccRsh - right shift accumulator by known count */
2497 /*-----------------------------------------------------------------*/
2498 static void AccRsh (int shCount)
2503 emitcode("rrc","a");
2505 /* rotate right accumulator */
2506 AccRol(8 - shCount);
2507 /* and kill the higher order bits */
2508 emitcode("anl","a,#0x%02x", SRMask[shCount]);
2513 /*-----------------------------------------------------------------*/
2514 /* AccSRsh - signed right shift accumulator by known count */
2515 /*-----------------------------------------------------------------*/
2516 static void AccSRsh (int shCount)
2521 emitcode("mov","c,acc.7");
2522 emitcode("rrc","a");
2523 } else if(shCount == 2){
2524 emitcode("mov","c,acc.7");
2525 emitcode("rrc","a");
2526 emitcode("mov","c,acc.7");
2527 emitcode("rrc","a");
2529 tlbl = newiTempLabel(NULL);
2530 /* rotate right accumulator */
2531 AccRol(8 - shCount);
2532 /* and kill the higher order bits */
2533 emitcode("anl","a,#0x%02x", SRMask[shCount]);
2534 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
2535 emitcode("orl","a,#0x%02x",
2536 (unsigned char)~SRMask[shCount]);
2537 emitcode("","%05d$:",tlbl->key+100);
2542 /*-----------------------------------------------------------------*/
2543 /* shiftR1Left2Result - shift right one byte from left to result */
2544 /*-----------------------------------------------------------------*/
2545 static void shiftR1Left2Result (operand *left, int offl,
2546 operand *result, int offr,
2547 int shCount, int sign)
2549 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
2550 /* shift right accumulator */
2555 aopPut(AOP(result),"a",offr);
2558 /*-----------------------------------------------------------------*/
2559 /* shiftL1Left2Result - shift left one byte from left to result */
2560 /*-----------------------------------------------------------------*/
2561 static void shiftL1Left2Result (operand *left, int offl,
2562 operand *result, int offr, int shCount)
2565 l = aopGet(AOP(left),offl);
2567 /* shift left accumulator */
2569 aopPut(AOP(result),"a",offr);
2572 /*-----------------------------------------------------------------*/
2573 /* movLeft2Result - move byte from left to result */
2574 /*-----------------------------------------------------------------*/
2575 static void movLeft2Result (operand *left, int offl,
2576 operand *result, int offr, int sign)
2579 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
2580 l = aopGet(AOP(left),offl);
2582 if (*l == '@' && (IS_AOP_PREG(result))) {
2583 emitcode("mov","a,%s",l);
2584 aopPut(AOP(result),"a",offr);
2587 aopPut(AOP(result),l,offr);
2589 /* MSB sign in acc.7 ! */
2590 if(getDataSize(left) == offl+1){
2591 emitcode("mov","a,%s",l);
2592 aopPut(AOP(result),"a",offr);
2599 /*-----------------------------------------------------------------*/
2600 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
2601 /*-----------------------------------------------------------------*/
2602 static void AccAXRrl1 (char *x)
2604 emitcode("rrc","a");
2605 emitcode("xch","a,%s", x);
2606 emitcode("rrc","a");
2607 emitcode("xch","a,%s", x);
2610 /*-----------------------------------------------------------------*/
2611 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
2612 /*-----------------------------------------------------------------*/
2613 static void AccAXLrl1 (char *x)
2615 emitcode("xch","a,%s",x);
2616 emitcode("rlc","a");
2617 emitcode("xch","a,%s",x);
2618 emitcode("rlc","a");
2621 /*-----------------------------------------------------------------*/
2622 /* AccAXLsh1 - left shift a:x<-0 by 1 */
2623 /*-----------------------------------------------------------------*/
2624 static void AccAXLsh1 (char *x)
2626 emitcode("xch","a,%s",x);
2627 emitcode("add","a,acc");
2628 emitcode("xch","a,%s",x);
2629 emitcode("rlc","a");
2632 /*-----------------------------------------------------------------*/
2633 /* AccAXLsh - left shift a:x by known count (0..7) */
2634 /*-----------------------------------------------------------------*/
2635 static void AccAXLsh (char *x, int shCount)
2649 case 5 : // AAAAABBB:CCCCCDDD
2650 AccRol(shCount); // BBBAAAAA:CCCCCDDD
2651 emitcode("anl","a,#0x%02x",
2652 SLMask[shCount]); // BBB00000:CCCCCDDD
2653 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
2654 AccRol(shCount); // DDDCCCCC:BBB00000
2655 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
2656 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
2657 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
2658 emitcode("anl","a,#0x%02x",
2659 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
2660 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
2661 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
2663 case 6 : // AAAAAABB:CCCCCCDD
2664 emitcode("anl","a,#0x%02x",
2665 SRMask[shCount]); // 000000BB:CCCCCCDD
2666 emitcode("mov","c,acc.0"); // c = B
2667 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
2668 AccAXRrl1(x); // BCCCCCCD:D000000B
2669 AccAXRrl1(x); // BBCCCCCC:DD000000
2671 case 7 : // a:x <<= 7
2672 emitcode("anl","a,#0x%02x",
2673 SRMask[shCount]); // 0000000B:CCCCCCCD
2674 emitcode("mov","c,acc.0"); // c = B
2675 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
2676 AccAXRrl1(x); // BCCCCCCC:D0000000
2683 /*-----------------------------------------------------------------*/
2684 /* AccAXRsh - right shift a:x known count (0..7) */
2685 /*-----------------------------------------------------------------*/
2686 static void AccAXRsh (char *x, int shCount)
2693 AccAXRrl1(x); // 0->a:x
2697 AccAXRrl1(x); // 0->a:x
2699 AccAXRrl1(x); // 0->a:x
2703 case 5 : // AAAAABBB:CCCCCDDD = a:x
2704 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
2705 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
2706 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
2707 emitcode("anl","a,#0x%02x",
2708 SRMask[shCount]); // 000CCCCC:BBBAAAAA
2709 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
2710 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
2711 emitcode("anl","a,#0x%02x",
2712 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
2713 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
2714 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
2715 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
2717 case 6 : // AABBBBBB:CCDDDDDD
2718 emitcode("mov","c,acc.7");
2719 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
2720 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
2721 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
2722 emitcode("anl","a,#0x%02x",
2723 SRMask[shCount]); // 000000AA:BBBBBBCC
2725 case 7 : // ABBBBBBB:CDDDDDDD
2726 emitcode("mov","c,acc.7"); // c = A
2727 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
2728 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
2729 emitcode("anl","a,#0x%02x",
2730 SRMask[shCount]); // 0000000A:BBBBBBBC
2737 /*-----------------------------------------------------------------*/
2738 /* AccAXRshS - right shift signed a:x known count (0..7) */
2739 /*-----------------------------------------------------------------*/
2740 static void AccAXRshS (char *x, int shCount)
2747 emitcode("mov","c,acc.7");
2748 AccAXRrl1(x); // s->a:x
2751 emitcode("mov","c,acc.7");
2752 AccAXRrl1(x); // s->a:x
2753 emitcode("mov","c,acc.7");
2754 AccAXRrl1(x); // s->a:x
2758 case 5 : // AAAAABBB:CCCCCDDD = a:x
2759 tlbl = newiTempLabel(NULL);
2760 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
2761 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
2762 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
2763 emitcode("anl","a,#0x%02x",
2764 SRMask[shCount]); // 000CCCCC:BBBAAAAA
2765 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
2766 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
2767 emitcode("anl","a,#0x%02x",
2768 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
2769 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
2770 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
2771 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
2772 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
2773 emitcode("orl","a,#0x%02x",
2774 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
2775 emitcode("","%05d$:",tlbl->key+100);
2776 break; // SSSSAAAA:BBBCCCCC
2777 case 6 : // AABBBBBB:CCDDDDDD
2778 tlbl = newiTempLabel(NULL);
2779 emitcode("mov","c,acc.7");
2780 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
2781 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
2782 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
2783 emitcode("anl","a,#0x%02x",
2784 SRMask[shCount]); // 000000AA:BBBBBBCC
2785 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
2786 emitcode("orl","a,#0x%02x",
2787 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
2788 emitcode("","%05d$:",tlbl->key+100);
2790 case 7 : // ABBBBBBB:CDDDDDDD
2791 tlbl = newiTempLabel(NULL);
2792 emitcode("mov","c,acc.7"); // c = A
2793 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
2794 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
2795 emitcode("anl","a,#0x%02x",
2796 SRMask[shCount]); // 0000000A:BBBBBBBC
2797 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
2798 emitcode("orl","a,#0x%02x",
2799 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
2800 emitcode("","%05d$:",tlbl->key+100);
2807 /*-----------------------------------------------------------------*/
2808 /* shiftL2Left2Result - shift left two bytes from left to result */
2809 /*-----------------------------------------------------------------*/
2810 static void shiftL2Left2Result (operand *left, int offl,
2811 operand *result, int offr, int shCount)
2813 if(sameRegs(AOP(result), AOP(left)) &&
2814 ((offl + MSB16) == offr)){
2815 /* don't crash result[offr] */
2816 // MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
2817 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16));
2819 movLeft2Result(left,offl, result, offr, 0);
2820 MOVA(aopGet(AOP(left),offl+MSB16));
2822 /* ax << shCount (x = lsb(result))*/
2823 AccAXLsh( aopGet(AOP(result),offr) , shCount);
2824 aopPut(AOP(result),"a",offr+MSB16);
2828 /*-----------------------------------------------------------------*/
2829 /* shiftR2Left2Result - shift right two bytes from left to result */
2830 /*-----------------------------------------------------------------*/
2831 static void shiftR2Left2Result (operand *left, int offl,
2832 operand *result, int offr,
2833 int shCount, int sign)
2835 if(sameRegs(AOP(result), AOP(left)) &&
2836 ((offl + MSB16) == offr)){
2837 /* don't crash result[offr] */
2838 // MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
2839 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16));
2841 movLeft2Result(left,offl, result, offr, 0);
2842 // MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
2844 /* a:x >> shCount (x = lsb(result))*/
2846 AccAXRshS( aopGet(AOP(result),offr) , shCount);
2848 AccAXRsh( aopGet(AOP(result),offr) , shCount);
2849 if(getDataSize(result) > 1)
2850 aopPut(AOP(result),"a",offr+MSB16);
2853 /*-----------------------------------------------------------------*/
2854 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
2855 /*-----------------------------------------------------------------*/
2856 static void shiftLLeftOrResult (operand *left, int offl,
2857 operand *result, int offr, int shCount)
2859 // MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
2860 /* shift left accumulator */
2862 /* or with result */
2863 emitcode("orl","a,%s", aopGet(AOP(result),offr));
2864 /* back to result */
2865 aopPut(AOP(result),"a",offr);
2868 /*-----------------------------------------------------------------*/
2869 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
2870 /*-----------------------------------------------------------------*/
2871 static void shiftRLeftOrResult (operand *left, int offl,
2872 operand *result, int offr, int shCount)
2874 // MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
2875 /* shift right accumulator */
2877 /* or with result */
2878 emitcode("orl","a,%s", aopGet(AOP(result),offr));
2879 /* back to result */
2880 aopPut(AOP(result),"a",offr);
2883 /*-----------------------------------------------------------------*/
2884 /* genlshOne - left shift a one byte quantity by known count */
2885 /*-----------------------------------------------------------------*/
2886 static void genlshOne (operand *result, operand *left, int shCount)
2888 shiftL1Left2Result(left, LSB, result, LSB, shCount);
2891 /*-----------------------------------------------------------------*/
2892 /* genlshTwo - left shift two bytes by known amount != 0 */
2893 /*-----------------------------------------------------------------*/
2894 static void genlshTwo (operand *result,operand *left, int shCount)
2898 size = getDataSize(result);
2900 /* if shCount >= 8 */
2906 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
2908 movLeft2Result(left, LSB, result, MSB16, 0);
2910 aopPut(AOP(result),zero,LSB);
2913 /* 1 <= shCount <= 7 */
2916 shiftL1Left2Result(left, LSB, result, LSB, shCount);
2918 shiftL2Left2Result(left, LSB, result, LSB, shCount);
2922 /*-----------------------------------------------------------------*/
2923 /* shiftLLong - shift left one long from left to result */
2924 /* offl = LSB or MSB16 */
2925 /*-----------------------------------------------------------------*/
2926 static void shiftLLong (operand *left, operand *result, int offr )
2929 int size = AOP_SIZE(result);
2931 if(size >= LSB+offr){
2932 l = aopGet(AOP(left),LSB);
2934 emitcode("add","a,acc");
2935 if (sameRegs(AOP(left),AOP(result)) &&
2936 size >= MSB16+offr && offr != LSB )
2937 emitcode("xch","a,%s",
2938 aopGet(AOP(left),LSB+offr));
2940 aopPut(AOP(result),"a",LSB+offr);
2943 if(size >= MSB16+offr){
2944 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
2945 l = aopGet(AOP(left),MSB16);
2948 emitcode("rlc","a");
2949 if (sameRegs(AOP(left),AOP(result)) &&
2950 size >= MSB24+offr && offr != LSB)
2951 emitcode("xch","a,%s",
2952 aopGet(AOP(left),MSB16+offr));
2954 aopPut(AOP(result),"a",MSB16+offr);
2957 if(size >= MSB24+offr){
2958 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
2959 l = aopGet(AOP(left),MSB24);
2962 emitcode("rlc","a");
2963 if (sameRegs(AOP(left),AOP(result)) &&
2964 size >= MSB32+offr && offr != LSB )
2965 emitcode("xch","a,%s",
2966 aopGet(AOP(left),MSB24+offr));
2968 aopPut(AOP(result),"a",MSB24+offr);
2971 if(size > MSB32+offr){
2972 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
2973 l = aopGet(AOP(left),MSB32);
2976 emitcode("rlc","a");
2977 aopPut(AOP(result),"a",MSB32+offr);
2980 aopPut(AOP(result),zero,LSB);
2983 /*-----------------------------------------------------------------*/
2984 /* genlshFour - shift four byte by a known amount != 0 */
2985 /*-----------------------------------------------------------------*/
2986 static void genlshFour (operand *result, operand *left, int shCount)
2990 size = AOP_SIZE(result);
2992 /* if shifting more that 3 bytes */
2993 if (shCount >= 24 ) {
2996 /* lowest order of left goes to the highest
2997 order of the destination */
2998 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
3000 movLeft2Result(left, LSB, result, MSB32, 0);
3001 aopPut(AOP(result),zero,LSB);
3002 aopPut(AOP(result),zero,MSB16);
3003 aopPut(AOP(result),zero,MSB32);
3007 /* more than two bytes */
3008 else if ( shCount >= 16 ) {
3009 /* lower order two bytes goes to higher order two bytes */
3011 /* if some more remaining */
3013 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
3015 movLeft2Result(left, MSB16, result, MSB32, 0);
3016 movLeft2Result(left, LSB, result, MSB24, 0);
3018 aopPut(AOP(result),zero,MSB16);
3019 aopPut(AOP(result),zero,LSB);
3023 /* if more than 1 byte */
3024 else if ( shCount >= 8 ) {
3025 /* lower order three bytes goes to higher order three bytes */
3029 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
3031 movLeft2Result(left, LSB, result, MSB16, 0);
3033 else{ /* size = 4 */
3035 movLeft2Result(left, MSB24, result, MSB32, 0);
3036 movLeft2Result(left, MSB16, result, MSB24, 0);
3037 movLeft2Result(left, LSB, result, MSB16, 0);
3038 aopPut(AOP(result),zero,LSB);
3040 else if(shCount == 1)
3041 shiftLLong(left, result, MSB16);
3043 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
3044 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
3045 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
3046 aopPut(AOP(result),zero,LSB);
3051 /* 1 <= shCount <= 7 */
3052 else if(shCount <= 2){
3053 shiftLLong(left, result, LSB);
3055 shiftLLong(result, result, LSB);
3057 /* 3 <= shCount <= 7, optimize */
3059 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
3060 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
3061 shiftL2Left2Result(left, LSB, result, LSB, shCount);
3065 /*-----------------------------------------------------------------*/
3066 /* genLeftShiftLiteral - left shifting by known count */
3067 /*-----------------------------------------------------------------*/
3068 static void genLeftShiftLiteral (operand *left,
3073 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3076 freeAsmop(right,NULL,ic,TRUE);
3078 aopOp(left,ic,FALSE);
3079 aopOp(result,ic,FALSE);
3081 size = getSize(operandType(result));
3084 emitcode("; shift left ","result %d, left %d",size,
3088 /* I suppose that the left size >= result size */
3091 movLeft2Result(left, size, result, size, 0);
3095 else if(shCount >= (size * 8))
3097 aopPut(AOP(result),zero,size);
3101 genlshOne (result,left,shCount);
3106 genlshTwo (result,left,shCount);
3110 genlshFour (result,left,shCount);
3114 freeAsmop(left,NULL,ic,TRUE);
3115 freeAsmop(result,NULL,ic,TRUE);
3118 /*-----------------------------------------------------------------*/
3119 /* genLeftShift - generates code for left shifting */
3120 /*-----------------------------------------------------------------*/
3121 static void genLeftShift (iCode *ic)
3123 operand *left,*right, *result;
3126 symbol *tlbl , *tlbl1;
3128 right = IC_RIGHT(ic);
3130 result = IC_RESULT(ic);
3132 aopOp(right,ic,FALSE);
3134 /* if the shift count is known then do it
3135 as efficiently as possible */
3136 if (AOP_TYPE(right) == AOP_LIT) {
3137 genLeftShiftLiteral (left,right,result,ic);
3141 /* shift count is unknown then we have to form
3142 a loop get the loop count in B : Note: we take
3143 only the lower order byte since shifting
3144 more that 32 bits make no sense anyway, ( the
3145 largest size of an object can be only 32 bits ) */
3147 emitcode("mov","b,%s",aopGet(AOP(right),0));
3148 emitcode("inc","b");
3149 freeAsmop (right,NULL,ic,TRUE);
3150 aopOp(left,ic,FALSE);
3151 aopOp(result,ic,FALSE);
3153 /* now move the left to the result if they are not the
3155 if (!sameRegs(AOP(left),AOP(result)) &&
3156 AOP_SIZE(result) > 1) {
3158 size = AOP_SIZE(result);
3161 l = aopGet(AOP(left),offset);
3162 if (*l == '@' && (IS_AOP_PREG(result))) {
3164 emitcode("mov","a,%s",l);
3165 aopPut(AOP(result),"a",offset);
3167 aopPut(AOP(result),l,offset);
3172 tlbl = newiTempLabel(NULL);
3173 size = AOP_SIZE(result);
3175 tlbl1 = newiTempLabel(NULL);
3177 /* if it is only one byte then */
3179 symbol *tlbl1 = newiTempLabel(NULL);
3181 l = aopGet(AOP(left),0);
3183 emitcode("sjmp","%05d$",tlbl1->key+100);
3184 emitcode("","%05d$:",tlbl->key+100);
3185 emitcode("add","a,acc");
3186 emitcode("","%05d$:",tlbl1->key+100);
3187 emitcode("djnz","b,%05d$",tlbl->key+100);
3188 aopPut(AOP(result),"a",0);
3192 reAdjustPreg(AOP(result));
3194 emitcode("sjmp","%05d$",tlbl1->key+100);
3195 emitcode("","%05d$:",tlbl->key+100);
3196 l = aopGet(AOP(result),offset);
3198 emitcode("add","a,acc");
3199 aopPut(AOP(result),"a",offset++);
3201 l = aopGet(AOP(result),offset);
3203 emitcode("rlc","a");
3204 aopPut(AOP(result),"a",offset++);
3206 reAdjustPreg(AOP(result));
3208 emitcode("","%05d$:",tlbl1->key+100);
3209 emitcode("djnz","b,%05d$",tlbl->key+100);
3211 freeAsmop(left,NULL,ic,TRUE);
3212 freeAsmop(result,NULL,ic,TRUE);
3215 /*-----------------------------------------------------------------*/
3216 /* genrshOne - right shift a one byte quantity by known count */
3217 /*-----------------------------------------------------------------*/
3218 static void genrshOne (operand *result, operand *left,
3219 int shCount, int sign)
3221 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
3224 /*-----------------------------------------------------------------*/
3225 /* genrshTwo - right shift two bytes by known amount != 0 */
3226 /*-----------------------------------------------------------------*/
3227 static void genrshTwo (operand *result,operand *left,
3228 int shCount, int sign)
3230 /* if shCount >= 8 */
3234 shiftR1Left2Result(left, MSB16, result, LSB,
3237 movLeft2Result(left, MSB16, result, LSB, sign);
3238 addSign(result, MSB16, sign);
3241 /* 1 <= shCount <= 7 */
3243 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
3246 /*-----------------------------------------------------------------*/
3247 /* shiftRLong - shift right one long from left to result */
3248 /* offl = LSB or MSB16 */
3249 /*-----------------------------------------------------------------*/
3250 static void shiftRLong (operand *left, int offl,
3251 operand *result, int sign)
3254 emitcode("clr","c");
3255 MOVA(aopGet(AOP(left),MSB32));
3257 emitcode("mov","c,acc.7");
3258 emitcode("rrc","a");
3259 aopPut(AOP(result),"a",MSB32-offl);
3261 /* add sign of "a" */
3262 addSign(result, MSB32, sign);
3264 MOVA(aopGet(AOP(left),MSB24));
3265 emitcode("rrc","a");
3266 aopPut(AOP(result),"a",MSB24-offl);
3268 MOVA(aopGet(AOP(left),MSB16));
3269 emitcode("rrc","a");
3270 aopPut(AOP(result),"a",MSB16-offl);
3273 MOVA(aopGet(AOP(left),LSB));
3274 emitcode("rrc","a");
3275 aopPut(AOP(result),"a",LSB);
3279 /*-----------------------------------------------------------------*/
3280 /* genrshFour - shift four byte by a known amount != 0 */
3281 /*-----------------------------------------------------------------*/
3282 static void genrshFour (operand *result, operand *left,
3283 int shCount, int sign)
3285 /* if shifting more that 3 bytes */
3286 if(shCount >= 24 ) {
3289 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
3291 movLeft2Result(left, MSB32, result, LSB, sign);
3292 addSign(result, MSB16, sign);
3294 else if(shCount >= 16){
3297 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
3299 movLeft2Result(left, MSB24, result, LSB, 0);
3300 movLeft2Result(left, MSB32, result, MSB16, sign);
3302 addSign(result, MSB24, sign);
3304 else if(shCount >= 8){
3307 shiftRLong(left, MSB16, result, sign);
3308 else if(shCount == 0){
3309 movLeft2Result(left, MSB16, result, LSB, 0);
3310 movLeft2Result(left, MSB24, result, MSB16, 0);
3311 movLeft2Result(left, MSB32, result, MSB24, sign);
3312 addSign(result, MSB32, sign);
3315 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
3316 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
3317 /* the last shift is signed */
3318 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
3319 addSign(result, MSB32, sign);
3322 else{ /* 1 <= shCount <= 7 */
3324 shiftRLong(left, LSB, result, sign);
3326 shiftRLong(result, LSB, result, sign);
3329 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
3330 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
3331 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
3336 /*-----------------------------------------------------------------*/
3337 /* genRightShiftLiteral - right shifting by known count */
3338 /*-----------------------------------------------------------------*/
3339 static void genRightShiftLiteral (operand *left,
3345 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3348 freeAsmop(right,NULL,ic,TRUE);
3350 aopOp(left,ic,FALSE);
3351 aopOp(result,ic,FALSE);
3354 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
3358 size = getDataSize(left);
3359 /* test the LEFT size !!! */
3361 /* I suppose that the left size >= result size */
3363 size = getDataSize(result);
3365 movLeft2Result(left, size, result, size, 0);
3368 else if(shCount >= (size * 8)){
3370 /* get sign in acc.7 */
3371 MOVA(aopGet(AOP(left),size-1));
3372 addSign(result, LSB, sign);
3376 genrshOne (result,left,shCount,sign);
3380 genrshTwo (result,left,shCount,sign);
3384 genrshFour (result,left,shCount,sign);
3390 freeAsmop(left,NULL,ic,TRUE);
3391 freeAsmop(result,NULL,ic,TRUE);
3395 /*-----------------------------------------------------------------*/
3396 /* genSignedRightShift - right shift of signed number */
3397 /*-----------------------------------------------------------------*/
3398 static void genSignedRightShift (iCode *ic)
3400 operand *right, *left, *result;
3403 symbol *tlbl, *tlbl1 ;
3405 /* we do it the hard way put the shift count in b
3406 and loop thru preserving the sign */
3408 right = IC_RIGHT(ic);
3410 result = IC_RESULT(ic);
3412 aopOp(right,ic,FALSE);
3415 if ( AOP_TYPE(right) == AOP_LIT) {
3416 genRightShiftLiteral (left,right,result,ic,1);
3419 /* shift count is unknown then we have to form
3420 a loop get the loop count in B : Note: we take
3421 only the lower order byte since shifting
3422 more that 32 bits make no sense anyway, ( the
3423 largest size of an object can be only 32 bits ) */
3425 emitcode("mov","b,%s",aopGet(AOP(right),0));
3426 emitcode("inc","b");
3427 freeAsmop (right,NULL,ic,TRUE);
3428 aopOp(left,ic,FALSE);
3429 aopOp(result,ic,FALSE);
3431 /* now move the left to the result if they are not the
3433 if (!sameRegs(AOP(left),AOP(result)) &&
3434 AOP_SIZE(result) > 1) {
3436 size = AOP_SIZE(result);
3439 l = aopGet(AOP(left),offset);
3440 if (*l == '@' && IS_AOP_PREG(result)) {
3442 emitcode("mov","a,%s",l);
3443 aopPut(AOP(result),"a",offset);
3445 aopPut(AOP(result),l,offset);
3450 /* mov the highest order bit to OVR */
3451 tlbl = newiTempLabel(NULL);
3452 tlbl1= newiTempLabel(NULL);
3454 size = AOP_SIZE(result);
3456 emitcode("mov","a,%s",aopGet(AOP(left),offset));
3457 emitcode("rlc","a");
3458 emitcode("mov","ov,c");
3459 /* if it is only one byte then */
3461 l = aopGet(AOP(left),0);
3463 emitcode("sjmp","%05d$",tlbl1->key+100);
3464 emitcode("","%05d$:",tlbl->key+100);
3465 emitcode("mov","c,ov");
3466 emitcode("rrc","a");
3467 emitcode("","%05d$:",tlbl1->key+100);
3468 emitcode("djnz","b,%05d$",tlbl->key+100);
3469 aopPut(AOP(result),"a",0);
3473 reAdjustPreg(AOP(result));
3474 emitcode("sjmp","%05d$",tlbl1->key+100);
3475 emitcode("","%05d$:",tlbl->key+100);
3476 emitcode("mov","c,ov");
3478 l = aopGet(AOP(result),offset);
3480 emitcode("rrc","a");
3481 aopPut(AOP(result),"a",offset--);
3483 reAdjustPreg(AOP(result));
3484 emitcode("","%05d$:",tlbl1->key+100);
3485 emitcode("djnz","b,%05d$",tlbl->key+100);
3488 freeAsmop(left,NULL,ic,TRUE);
3489 freeAsmop(result,NULL,ic,TRUE);
3492 /*-----------------------------------------------------------------*/
3493 /* genRightShift - generate code for right shifting */
3494 /*-----------------------------------------------------------------*/
3495 static void genRightShift (iCode *ic)
3497 operand *right, *left, *result;
3501 symbol *tlbl, *tlbl1 ;
3503 /* if signed then we do it the hard way preserve the
3504 sign bit moving it inwards */
3505 retype = getSpec(operandType(IC_RESULT(ic)));
3507 if (!SPEC_USIGN(retype)) {
3508 genSignedRightShift (ic);
3512 /* signed & unsigned types are treated the same : i.e. the
3513 signed is NOT propagated inwards : quoting from the
3514 ANSI - standard : "for E1 >> E2, is equivalent to division
3515 by 2**E2 if unsigned or if it has a non-negative value,
3516 otherwise the result is implementation defined ", MY definition
3517 is that the sign does not get propagated */
3519 right = IC_RIGHT(ic);
3521 result = IC_RESULT(ic);
3523 aopOp(right,ic,FALSE);
3525 /* if the shift count is known then do it
3526 as efficiently as possible */
3527 if (AOP_TYPE(right) == AOP_LIT) {
3528 genRightShiftLiteral (left,right,result,ic, 0);
3532 /* shift count is unknown then we have to form
3533 a loop get the loop count in B : Note: we take
3534 only the lower order byte since shifting
3535 more that 32 bits make no sense anyway, ( the
3536 largest size of an object can be only 32 bits ) */
3538 emitcode("mov","b,%s",aopGet(AOP(right),0));
3539 emitcode("inc","b");
3540 freeAsmop (right,NULL,ic,TRUE);
3541 aopOp(left,ic,FALSE);
3542 aopOp(result,ic,FALSE);
3544 /* now move the left to the result if they are not the
3546 if (!sameRegs(AOP(left),AOP(result)) &&
3547 AOP_SIZE(result) > 1) {
3549 size = AOP_SIZE(result);
3552 l = aopGet(AOP(left),offset);
3553 if (*l == '@' && IS_AOP_PREG(result)) {
3555 emitcode("mov","a,%s",l);
3556 aopPut(AOP(result),"a",offset);
3558 aopPut(AOP(result),l,offset);
3563 tlbl = newiTempLabel(NULL);
3564 tlbl1= newiTempLabel(NULL);
3565 size = AOP_SIZE(result);
3568 /* if it is only one byte then */
3570 l = aopGet(AOP(left),0);
3572 emitcode("sjmp","%05d$",tlbl1->key+100);
3573 emitcode("","%05d$:",tlbl->key+100);
3575 emitcode("rrc","a");
3576 emitcode("","%05d$:",tlbl1->key+100);
3577 emitcode("djnz","b,%05d$",tlbl->key+100);
3578 aopPut(AOP(result),"a",0);
3582 reAdjustPreg(AOP(result));
3583 emitcode("sjmp","%05d$",tlbl1->key+100);
3584 emitcode("","%05d$:",tlbl->key+100);
3587 l = aopGet(AOP(result),offset);
3589 emitcode("rrc","a");
3590 aopPut(AOP(result),"a",offset--);
3592 reAdjustPreg(AOP(result));
3594 emitcode("","%05d$:",tlbl1->key+100);
3595 emitcode("djnz","b,%05d$",tlbl->key+100);
3598 freeAsmop(left,NULL,ic,TRUE);
3599 freeAsmop(result,NULL,ic,TRUE);
3602 /*-----------------------------------------------------------------*/
3603 /* genUnpackBits - generates code for unpacking bits */
3604 /*-----------------------------------------------------------------*/
3605 static void genUnpackBits (operand *result, char *rname, int ptype)
3612 etype = getSpec(operandType(result));
3614 /* read the first byte */
3619 emitcode("mov","a,@%s",rname);
3623 emitcode("movx","a,@%s",rname);
3627 emitcode("movx","a,@dptr");
3631 emitcode("clr","a");
3632 emitcode("movc","a","@a+dptr");
3636 emitcode("lcall","__gptrget");
3640 /* if we have bitdisplacement then it fits */
3641 /* into this byte completely or if length is */
3642 /* less than a byte */
3643 if ((shCnt = SPEC_BSTR(etype)) ||
3644 (SPEC_BLEN(etype) <= 8)) {
3646 /* shift right acc */
3649 emitcode("anl","a,#0x%02x",
3650 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
3651 aopPut(AOP(result),"a",offset);
3655 /* bit field did not fit in a byte */
3656 rlen = SPEC_BLEN(etype) - 8;
3657 aopPut(AOP(result),"a",offset++);
3664 emitcode("inc","%s",rname);
3665 emitcode("mov","a,@%s",rname);
3669 emitcode("inc","%s",rname);
3670 emitcode("movx","a,@%s",rname);
3674 emitcode("inc","dptr");
3675 emitcode("movx","a,@dptr");
3679 emitcode("clr","a");
3680 emitcode("inc","dptr");
3681 emitcode("movc","a","@a+dptr");
3685 emitcode("inc","dptr");
3686 emitcode("lcall","__gptrget");
3691 /* if we are done */
3695 aopPut(AOP(result),"a",offset++);
3700 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
3701 aopPut(AOP(result),"a",offset);
3708 /*-----------------------------------------------------------------*/
3709 /* genDataPointerGet - generates code when ptr offset is known */
3710 /*-----------------------------------------------------------------*/
3711 static void genDataPointerGet (operand *left,
3717 int size , offset = 0;
3718 aopOp(result,ic,TRUE);
3720 /* get the string representation of the name */
3721 l = aopGet(AOP(left),0);
3722 size = AOP_SIZE(result);
3725 sprintf(buffer,"(%s + %d)",l+1,offset);
3727 sprintf(buffer,"%s",l+1);
3728 aopPut(AOP(result),buffer,offset++);
3731 freeAsmop(left,NULL,ic,TRUE);
3732 freeAsmop(result,NULL,ic,TRUE);
3735 /*-----------------------------------------------------------------*/
3736 /* genNearPointerGet - emitcode for near pointer fetch */
3737 /*-----------------------------------------------------------------*/
3738 static void genNearPointerGet (operand *left,
3745 link *rtype, *retype;
3746 link *ltype = operandType(left);
3749 rtype = operandType(result);
3750 retype= getSpec(rtype);
3752 aopOp(left,ic,FALSE);
3754 /* if left is rematerialisable and
3755 result is not bit variable type and
3756 the left is pointer to data space i.e
3757 lower 128 bytes of space */
3758 if (AOP_TYPE(left) == AOP_IMMD &&
3759 !IS_BITVAR(retype) &&
3760 DCL_TYPE(ltype) == POINTER) {
3761 genDataPointerGet (left,result,ic);
3765 /* if the value is already in a pointer register
3766 then don't need anything more */
3767 if (!AOP_INPREG(AOP(left))) {
3768 /* otherwise get a free pointer register */
3770 preg = getFreePtr(ic,&aop,FALSE,0);
3771 emitcode("mov","%s,%s",
3773 aopGet(AOP(left),0));
3774 rname = preg->name ;
3776 rname = aopGet(AOP(left),0);
3778 freeAsmop(left,NULL,ic,TRUE);
3779 aopOp (result,ic,FALSE);
3781 /* if bitfield then unpack the bits */
3782 if (IS_BITVAR(retype))
3783 genUnpackBits (result,rname,POINTER);
3785 /* we have can just get the values */
3786 int size = AOP_SIZE(result);
3790 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
3792 emitcode("mov","a,@%s",rname);
3793 aopPut(AOP(result),"a",offset);
3795 sprintf(buffer,"@%s",rname);
3796 aopPut(AOP(result),buffer,offset);
3800 emitcode("inc","%s",rname);
3804 /* now some housekeeping stuff */
3806 /* we had to allocate for this iCode */
3807 freeAsmop(NULL,aop,ic,TRUE);
3809 /* we did not allocate which means left
3810 already in a pointer register, then
3811 if size > 0 && this could be used again
3812 we have to point it back to where it
3814 if (AOP_SIZE(result) > 1 &&
3815 !OP_SYMBOL(left)->remat &&
3816 ( OP_SYMBOL(left)->liveTo > ic->seq ||
3818 int size = AOP_SIZE(result) - 1;
3820 emitcode("dec","%s",rname);
3825 freeAsmop(result,NULL,ic,TRUE);
3829 /*-----------------------------------------------------------------*/
3830 /* genPagedPointerGet - emitcode for paged pointer fetch */
3831 /*-----------------------------------------------------------------*/
3832 static void genPagedPointerGet (operand *left,
3839 link *rtype, *retype;
3841 rtype = operandType(result);
3842 retype= getSpec(rtype);
3844 aopOp(left,ic,FALSE);
3846 /* if the value is already in a pointer register
3847 then don't need anything more */
3848 if (!AOP_INPREG(AOP(left))) {
3849 /* otherwise get a free pointer register */
3851 preg = getFreePtr(ic,&aop,FALSE,0);
3852 emitcode("mov","%s,%s",
3854 aopGet(AOP(left),0));
3855 rname = preg->name ;
3857 rname = aopGet(AOP(left),0);
3859 freeAsmop(left,NULL,ic,TRUE);
3860 aopOp (result,ic,FALSE);
3862 /* if bitfield then unpack the bits */
3863 if (IS_BITVAR(retype))
3864 genUnpackBits (result,rname,PPOINTER);
3866 /* we have can just get the values */
3867 int size = AOP_SIZE(result);
3872 emitcode("movx","a,@%s",rname);
3873 aopPut(AOP(result),"a",offset);
3878 emitcode("inc","%s",rname);
3882 /* now some housekeeping stuff */
3884 /* we had to allocate for this iCode */
3885 freeAsmop(NULL,aop,ic,TRUE);
3887 /* we did not allocate which means left
3888 already in a pointer register, then
3889 if size > 0 && this could be used again
3890 we have to point it back to where it
3892 if (AOP_SIZE(result) > 1 &&
3893 !OP_SYMBOL(left)->remat &&
3894 ( OP_SYMBOL(left)->liveTo > ic->seq ||
3896 int size = AOP_SIZE(result) - 1;
3898 emitcode("dec","%s",rname);
3903 freeAsmop(result,NULL,ic,TRUE);
3908 /*-----------------------------------------------------------------*/
3909 /* genFarPointerGet - gget value from far space */
3910 /*-----------------------------------------------------------------*/
3911 static void genFarPointerGet (operand *left,
3912 operand *result, iCode *ic)
3915 link *retype = getSpec(operandType(result));
3917 aopOp(left,ic,FALSE);
3919 /* if the operand is already in dptr
3920 then we do nothing else we move the value to dptr */
3921 if (AOP_TYPE(left) != AOP_STR) {
3922 /* if this is remateriazable */
3923 if (AOP_TYPE(left) == AOP_IMMD)
3924 emitcode("mov","dptr,%s",aopGet(AOP(left),0));
3925 else { /* we need to get it byte by byte */
3926 emitcode("mov","dpl,%s",aopGet(AOP(left),0));
3927 emitcode("mov","dph,%s",aopGet(AOP(left),1));
3928 if (options.model == MODEL_FLAT24)
3930 emitcode("mov", "dpx,%s",aopGet(AOP(left),2));
3934 /* so dptr know contains the address */
3935 freeAsmop(left,NULL,ic,TRUE);
3936 aopOp(result,ic,FALSE);
3938 /* if bit then unpack */
3939 if (IS_BITVAR(retype))
3940 genUnpackBits(result,"dptr",FPOINTER);
3942 size = AOP_SIZE(result);
3946 emitcode("movx","a,@dptr");
3947 aopPut(AOP(result),"a",offset++);
3949 emitcode("inc","dptr");
3953 freeAsmop(result,NULL,ic,TRUE);
3956 /*-----------------------------------------------------------------*/
3957 /* emitcodePointerGet - gget value from code space */
3958 /*-----------------------------------------------------------------*/
3959 static void emitcodePointerGet (operand *left,
3960 operand *result, iCode *ic)
3963 link *retype = getSpec(operandType(result));
3965 aopOp(left,ic,FALSE);
3967 /* if the operand is already in dptr
3968 then we do nothing else we move the value to dptr */
3969 if (AOP_TYPE(left) != AOP_STR) {
3970 /* if this is remateriazable */
3971 if (AOP_TYPE(left) == AOP_IMMD)
3972 emitcode("mov","dptr,%s",aopGet(AOP(left),0));
3973 else { /* we need to get it byte by byte */
3974 emitcode("mov","dpl,%s",aopGet(AOP(left),0));
3975 emitcode("mov","dph,%s",aopGet(AOP(left),1));
3976 if (options.model == MODEL_FLAT24)
3978 emitcode("mov", "dpx,%s",aopGet(AOP(left),2));
3982 /* so dptr know contains the address */
3983 freeAsmop(left,NULL,ic,TRUE);
3984 aopOp(result,ic,FALSE);
3986 /* if bit then unpack */
3987 if (IS_BITVAR(retype))
3988 genUnpackBits(result,"dptr",CPOINTER);
3990 size = AOP_SIZE(result);
3994 emitcode("clr","a");
3995 emitcode("movc","a,@a+dptr");
3996 aopPut(AOP(result),"a",offset++);
3998 emitcode("inc","dptr");
4002 freeAsmop(result,NULL,ic,TRUE);
4005 /*-----------------------------------------------------------------*/
4006 /* genGenPointerGet - gget value from generic pointer space */
4007 /*-----------------------------------------------------------------*/
4008 static void genGenPointerGet (operand *left,
4009 operand *result, iCode *ic)
4012 link *retype = getSpec(operandType(result));
4014 aopOp(left,ic,FALSE);
4016 /* if the operand is already in dptr
4017 then we do nothing else we move the value to dptr */
4018 if (AOP_TYPE(left) != AOP_STR) {
4019 /* if this is remateriazable */
4020 if (AOP_TYPE(left) == AOP_IMMD) {
4021 emitcode("mov","dptr,%s",aopGet(AOP(left),0));
4022 emitcode("mov","b,#%d",pointerCode(retype));
4024 else { /* we need to get it byte by byte */
4025 emitcode("mov","dpl,%s",aopGet(AOP(left),0));
4026 emitcode("mov","dph,%s",aopGet(AOP(left),1));
4027 if (options.model == MODEL_FLAT24)
4029 emitcode("mov", "dpx,%s",aopGet(AOP(left),2));
4030 emitcode("mov","b,%s",aopGet(AOP(left),3));
4034 emitcode("mov","b,%s",aopGet(AOP(left),2));
4038 /* so dptr know contains the address */
4039 freeAsmop(left,NULL,ic,TRUE);
4040 aopOp(result,ic,FALSE);
4042 /* if bit then unpack */
4043 if (IS_BITVAR(retype))
4044 genUnpackBits(result,"dptr",GPOINTER);
4046 size = AOP_SIZE(result);
4050 emitcode("lcall","__gptrget");
4051 aopPut(AOP(result),"a",offset++);
4053 emitcode("inc","dptr");
4057 freeAsmop(result,NULL,ic,TRUE);
4060 /*-----------------------------------------------------------------*/
4061 /* genPointerGet - generate code for pointer get */
4062 /*-----------------------------------------------------------------*/
4063 static void genPointerGet (iCode *ic)
4065 operand *left, *result ;
4070 result = IC_RESULT(ic) ;
4072 /* depending on the type of pointer we need to
4073 move it to the correct pointer register */
4074 type = operandType(left);
4075 etype = getSpec(type);
4076 /* if left is of type of pointer then it is simple */
4077 if (IS_PTR(type) && !IS_FUNC(type->next))
4078 p_type = DCL_TYPE(type);
4080 /* we have to go by the storage class */
4081 p_type = PTR_TYPE(SPEC_OCLS(etype));
4083 /* if (SPEC_OCLS(etype)->codesp ) { */
4084 /* p_type = CPOINTER ; */
4087 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
4088 /* p_type = FPOINTER ; */
4090 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
4091 /* p_type = PPOINTER; */
4093 /* if (SPEC_OCLS(etype) == idata ) */
4094 /* p_type = IPOINTER; */
4096 /* p_type = POINTER ; */
4099 /* now that we have the pointer type we assign
4100 the pointer values */
4105 genNearPointerGet (left,result,ic);
4109 genPagedPointerGet(left,result,ic);
4113 genFarPointerGet (left,result,ic);
4117 emitcodePointerGet (left,result,ic);
4121 genGenPointerGet (left,result,ic);
4127 /*-----------------------------------------------------------------*/
4128 /* genPackBits - generates code for packed bit storage */
4129 /*-----------------------------------------------------------------*/
4130 static void genPackBits (link *etype ,
4132 char *rname, int p_type)
4140 blen = SPEC_BLEN(etype);
4141 bstr = SPEC_BSTR(etype);
4143 l = aopGet(AOP(right),offset++);
4146 /* if the bit lenth is less than or */
4147 /* it exactly fits a byte then */
4148 if (SPEC_BLEN(etype) <= 8 ) {
4149 shCount = SPEC_BSTR(etype) ;
4151 /* shift left acc */
4154 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
4159 emitcode ("mov","b,a");
4160 emitcode("mov","a,@%s",rname);
4164 emitcode ("mov","b,a");
4165 emitcode("movx","a,@dptr");
4169 emitcode ("push","b");
4170 emitcode ("push","acc");
4171 emitcode ("lcall","__gptrget");
4172 emitcode ("pop","b");
4176 emitcode ("anl","a,#0x%02x",(unsigned char)
4177 ((unsigned char)(0xFF << (blen+bstr)) |
4178 (unsigned char)(0xFF >> (8-bstr)) ) );
4179 emitcode ("orl","a,b");
4180 if (p_type == GPOINTER)
4181 emitcode("pop","b");
4187 emitcode("mov","@%s,a",rname);
4191 emitcode("movx","@dptr,a");
4195 emitcode("lcall","__gptrput");
4200 if ( SPEC_BLEN(etype) <= 8 )
4203 emitcode("inc","%s",rname);
4204 rLen = SPEC_BLEN(etype) ;
4206 /* now generate for lengths greater than one byte */
4209 l = aopGet(AOP(right),offset++);
4219 emitcode("mov","@%s,a",rname);
4221 emitcode("mov","@%s,%s",rname,l);
4226 emitcode("movx","@dptr,a");
4231 emitcode("lcall","__gptrput");
4234 emitcode ("inc","%s",rname);
4239 /* last last was not complete */
4241 /* save the byte & read byte */
4244 emitcode ("mov","b,a");
4245 emitcode("mov","a,@%s",rname);
4249 emitcode ("mov","b,a");
4250 emitcode("movx","a,@dptr");
4254 emitcode ("push","b");
4255 emitcode ("push","acc");
4256 emitcode ("lcall","__gptrget");
4257 emitcode ("pop","b");
4261 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
4262 emitcode ("orl","a,b");
4265 if (p_type == GPOINTER)
4266 emitcode("pop","b");
4271 emitcode("mov","@%s,a",rname);
4275 emitcode("movx","@dptr,a");
4279 emitcode("lcall","__gptrput");
4283 /*-----------------------------------------------------------------*/
4284 /* genDataPointerSet - remat pointer to data space */
4285 /*-----------------------------------------------------------------*/
4286 static void genDataPointerSet(operand *right,
4290 int size, offset = 0 ;
4291 char *l, buffer[256];
4293 aopOp(right,ic,FALSE);
4295 l = aopGet(AOP(result),0);
4296 size = AOP_SIZE(right);
4299 sprintf(buffer,"(%s + %d)",l+1,offset);
4301 sprintf(buffer,"%s",l+1);
4302 emitcode("mov","%s,%s",buffer,
4303 aopGet(AOP(right),offset++));
4306 freeAsmop(right,NULL,ic,TRUE);
4307 freeAsmop(result,NULL,ic,TRUE);
4310 /*-----------------------------------------------------------------*/
4311 /* genNearPointerSet - emitcode for near pointer put */
4312 /*-----------------------------------------------------------------*/
4313 static void genNearPointerSet (operand *right,
4321 link *ptype = operandType(result);
4323 retype= getSpec(operandType(right));
4325 aopOp(result,ic,FALSE);
4327 /* if the result is rematerializable &
4328 in data space & not a bit variable */
4329 if (AOP_TYPE(result) == AOP_IMMD &&
4330 DCL_TYPE(ptype) == POINTER &&
4331 !IS_BITVAR(retype)) {
4332 genDataPointerSet (right,result,ic);
4336 /* if the value is already in a pointer register
4337 then don't need anything more */
4338 if (!AOP_INPREG(AOP(result))) {
4339 /* otherwise get a free pointer register */
4341 preg = getFreePtr(ic,&aop,FALSE,0);
4342 emitcode("mov","%s,%s",
4344 aopGet(AOP(result),0));
4345 rname = preg->name ;
4347 rname = aopGet(AOP(result),0);
4349 freeAsmop(result,NULL,ic,TRUE);
4350 aopOp (right,ic,FALSE);
4352 /* if bitfield then unpack the bits */
4353 if (IS_BITVAR(retype))
4354 genPackBits (retype,right,rname,POINTER);
4356 /* we have can just get the values */
4357 int size = AOP_SIZE(right);
4361 l = aopGet(AOP(right),offset);
4364 emitcode("mov","@%s,a",rname);
4366 emitcode("mov","@%s,%s",rname,l);
4368 emitcode("inc","%s",rname);
4373 /* now some housekeeping stuff */
4375 /* we had to allocate for this iCode */
4376 freeAsmop(NULL,aop,ic,TRUE);
4378 /* we did not allocate which means left
4379 already in a pointer register, then
4380 if size > 0 && this could be used again
4381 we have to point it back to where it
4383 if (AOP_SIZE(right) > 1 &&
4384 !OP_SYMBOL(result)->remat &&
4385 ( OP_SYMBOL(result)->liveTo > ic->seq ||
4387 int size = AOP_SIZE(right) - 1;
4389 emitcode("dec","%s",rname);
4394 freeAsmop(right,NULL,ic,TRUE);
4399 /*-----------------------------------------------------------------*/
4400 /* genPagedPointerSet - emitcode for Paged pointer put */
4401 /*-----------------------------------------------------------------*/
4402 static void genPagedPointerSet (operand *right,
4411 retype= getSpec(operandType(right));
4413 aopOp(result,ic,FALSE);
4415 /* if the value is already in a pointer register
4416 then don't need anything more */
4417 if (!AOP_INPREG(AOP(result))) {
4418 /* otherwise get a free pointer register */
4420 preg = getFreePtr(ic,&aop,FALSE,0);
4421 emitcode("mov","%s,%s",
4423 aopGet(AOP(result),0));
4424 rname = preg->name ;
4426 rname = aopGet(AOP(result),0);
4428 freeAsmop(result,NULL,ic,TRUE);
4429 aopOp (right,ic,FALSE);
4431 /* if bitfield then unpack the bits */
4432 if (IS_BITVAR(retype))
4433 genPackBits (retype,right,rname,PPOINTER);
4435 /* we have can just get the values */
4436 int size = AOP_SIZE(right);
4440 l = aopGet(AOP(right),offset);
4443 emitcode("movx","@%s,a",rname);
4446 emitcode("inc","%s",rname);
4452 /* now some housekeeping stuff */
4454 /* we had to allocate for this iCode */
4455 freeAsmop(NULL,aop,ic,TRUE);
4457 /* we did not allocate which means left
4458 already in a pointer register, then
4459 if size > 0 && this could be used again
4460 we have to point it back to where it
4462 if (AOP_SIZE(right) > 1 &&
4463 !OP_SYMBOL(result)->remat &&
4464 ( OP_SYMBOL(result)->liveTo > ic->seq ||
4466 int size = AOP_SIZE(right) - 1;
4468 emitcode("dec","%s",rname);
4473 freeAsmop(right,NULL,ic,TRUE);
4478 /*-----------------------------------------------------------------*/
4479 /* genFarPointerSet - set value from far space */
4480 /*-----------------------------------------------------------------*/
4481 static void genFarPointerSet (operand *right,
4482 operand *result, iCode *ic)
4485 link *retype = getSpec(operandType(right));
4487 aopOp(result,ic,FALSE);
4489 /* if the operand is already in dptr
4490 then we do nothing else we move the value to dptr */
4491 if (AOP_TYPE(result) != AOP_STR) {
4492 /* if this is remateriazable */
4493 if (AOP_TYPE(result) == AOP_IMMD)
4494 emitcode("mov","dptr,%s",aopGet(AOP(result),0));
4495 else { /* we need to get it byte by byte */
4496 emitcode("mov","dpl,%s",aopGet(AOP(result),0));
4497 emitcode("mov","dph,%s",aopGet(AOP(result),1));
4498 if (options.model == MODEL_FLAT24)
4500 emitcode("mov", "dpx,%s",aopGet(AOP(result),2));
4504 /* so dptr know contains the address */
4505 freeAsmop(result,NULL,ic,TRUE);
4506 aopOp(right,ic,FALSE);
4508 /* if bit then unpack */
4509 if (IS_BITVAR(retype))
4510 genPackBits(retype,right,"dptr",FPOINTER);
4512 size = AOP_SIZE(right);
4516 char *l = aopGet(AOP(right),offset++);
4518 emitcode("movx","@dptr,a");
4520 emitcode("inc","dptr");
4524 freeAsmop(right,NULL,ic,TRUE);
4527 /*-----------------------------------------------------------------*/
4528 /* genGenPointerSet - set value from generic pointer space */
4529 /*-----------------------------------------------------------------*/
4530 static void genGenPointerSet (operand *right,
4531 operand *result, iCode *ic)
4534 link *retype = getSpec(operandType(right));
4536 aopOp(result,ic,FALSE);
4538 /* if the operand is already in dptr
4539 then we do nothing else we move the value to dptr */
4540 if (AOP_TYPE(result) != AOP_STR) {
4541 /* if this is remateriazable */
4542 if (AOP_TYPE(result) == AOP_IMMD) {
4543 emitcode("mov","dptr,%s",aopGet(AOP(result),0));
4544 emitcode("mov","b,%s + 1",aopGet(AOP(result),0));
4546 else { /* we need to get it byte by byte */
4547 emitcode("mov","dpl,%s",aopGet(AOP(result),0));
4548 emitcode("mov","dph,%s",aopGet(AOP(result),1));
4549 if (options.model == MODEL_FLAT24)
4551 emitcode("mov", "dpx,%s",aopGet(AOP(result),2));
4552 emitcode("mov","b,%s",aopGet(AOP(result),3));
4556 emitcode("mov","b,%s",aopGet(AOP(result),2));
4560 /* so dptr know contains the address */
4561 freeAsmop(result,NULL,ic,TRUE);
4562 aopOp(right,ic,FALSE);
4564 /* if bit then unpack */
4565 if (IS_BITVAR(retype))
4566 genPackBits(retype,right,"dptr",GPOINTER);
4568 size = AOP_SIZE(right);
4572 char *l = aopGet(AOP(right),offset++);
4574 emitcode("lcall","__gptrput");
4576 emitcode("inc","dptr");
4580 freeAsmop(right,NULL,ic,TRUE);
4583 /*-----------------------------------------------------------------*/
4584 /* genPointerSet - stores the value into a pointer location */
4585 /*-----------------------------------------------------------------*/
4586 static void genPointerSet (iCode *ic)
4588 operand *right, *result ;
4592 right = IC_RIGHT(ic);
4593 result = IC_RESULT(ic) ;
4595 /* depending on the type of pointer we need to
4596 move it to the correct pointer register */
4597 type = operandType(result);
4598 etype = getSpec(type);
4599 /* if left is of type of pointer then it is simple */
4600 if (IS_PTR(type) && !IS_FUNC(type->next)) {
4601 p_type = DCL_TYPE(type);
4604 /* we have to go by the storage class */
4605 p_type = PTR_TYPE(SPEC_OCLS(etype));
4607 /* if (SPEC_OCLS(etype)->codesp ) { */
4608 /* p_type = CPOINTER ; */
4611 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
4612 /* p_type = FPOINTER ; */
4614 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
4615 /* p_type = PPOINTER ; */
4617 /* if (SPEC_OCLS(etype) == idata ) */
4618 /* p_type = IPOINTER ; */
4620 /* p_type = POINTER ; */
4623 /* now that we have the pointer type we assign
4624 the pointer values */
4629 genNearPointerSet (right,result,ic);
4633 genPagedPointerSet (right,result,ic);
4637 genFarPointerSet (right,result,ic);
4641 genGenPointerSet (right,result,ic);
4647 /*-----------------------------------------------------------------*/
4648 /* genIfx - generate code for Ifx statement */
4649 /*-----------------------------------------------------------------*/
4650 static void genIfx (iCode *ic, iCode *popIc)
4652 operand *cond = IC_COND(ic);
4655 aopOp(cond,ic,FALSE);
4657 /* get the value into acc */
4658 if (AOP_TYPE(cond) != AOP_CRY)
4659 toBoolean(cond,"",0);
4662 /* the result is now in the accumulator */
4663 freeAsmop(cond,NULL,ic,TRUE);
4665 /* if there was something to be popped then do it */
4669 /* if the condition is a bit variable */
4670 /* if (isbit && IS_ITEMP(cond) && SPIL_LOC(cond)) { */
4671 /* // genIfxJump(ic,SPIL_LOC(cond)->rname); */
4674 /* if (isbit && !IS_ITEMP(cond)) */
4675 /* // genIfxJump(ic,OP_SYMBOL(cond)->rname); */
4677 /* // genIfxJump(ic,"a"); */
4682 /*-----------------------------------------------------------------*/
4683 /* genAddrOf - generates code for address of */
4684 /*-----------------------------------------------------------------*/
4685 static void genAddrOf (iCode *ic)
4687 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
4690 aopOp(IC_RESULT(ic),ic,FALSE);
4692 /* if the operand is on the stack then we
4693 need to get the stack offset of this
4696 /* if it has an offset then we need to compute
4699 emitcode("mov","a,_bp");
4700 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
4701 aopPut(AOP(IC_RESULT(ic)),"a",0);
4703 /* we can just move _bp */
4704 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
4706 /* fill the result with zero */
4707 size = AOP_SIZE(IC_RESULT(ic)) - 1;
4710 if (options.stack10bit && size < (FPTRSIZE - 1))
4713 "*** warning: pointer to stack var truncated.\n");
4720 if (options.stack10bit && offset == 2)
4722 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
4726 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
4733 /* object not on stack then we need the name */
4734 size = AOP_SIZE(IC_RESULT(ic));
4738 char s[SDCC_NAME_MAX];
4740 sprintf(s,"#(%s >> %d)",
4744 sprintf(s,"#%s",sym->rname);
4745 aopPut(AOP(IC_RESULT(ic)),s,offset++);
4749 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
4753 /*-----------------------------------------------------------------*/
4754 /* genFarFarAssign - assignment when both are in far space */
4755 /*-----------------------------------------------------------------*/
4756 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
4758 int size = AOP_SIZE(right);
4761 /* first push the right side on to the stack */
4763 l = aopGet(AOP(right),offset++);
4765 emitcode ("push","acc");
4768 freeAsmop(right,NULL,ic,FALSE);
4769 /* now assign DPTR to result */
4770 aopOp(result,ic,FALSE);
4771 size = AOP_SIZE(result);
4773 emitcode ("pop","acc");
4774 aopPut(AOP(result),"a",--offset);
4776 freeAsmop(result,NULL,ic,FALSE);
4780 /*-----------------------------------------------------------------*/
4781 /* genAssign - generate code for assignment */
4782 /*-----------------------------------------------------------------*/
4783 static void genAssign (iCode *ic)
4785 operand *result, *right;
4787 unsigned long lit = 0L;
4789 result = IC_RESULT(ic);
4790 right = IC_RIGHT(ic) ;
4792 /* if they are the same */
4793 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
4796 aopOp(right,ic,FALSE);
4798 /* special case both in far space */
4799 if (AOP_TYPE(right) == AOP_DPTR &&
4800 IS_TRUE_SYMOP(result) &&
4801 isOperandInFarSpace(result)) {
4803 genFarFarAssign (result,right,ic);
4807 aopOp(result,ic,TRUE);
4809 /* if they are the same registers */
4810 if (sameRegs(AOP(right),AOP(result)))
4813 /* if the result is a bit */
4814 if (AOP_TYPE(result) == AOP_CRY) {
4816 /* if the right size is a literal then
4817 we know what the value is */
4818 if (AOP_TYPE(right) == AOP_LIT) {
4819 if (((int) operandLitValue(right)))
4820 aopPut(AOP(result),one,0);
4822 aopPut(AOP(result),zero,0);
4826 /* the right is also a bit variable */
4827 if (AOP_TYPE(right) == AOP_CRY) {
4828 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4829 aopPut(AOP(result),"c",0);
4834 toBoolean(right,"",0);
4835 aopPut(AOP(result),"a",0);
4839 /* bit variables done */
4841 size = AOP_SIZE(result);
4843 if(AOP_TYPE(right) == AOP_LIT)
4844 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4846 (AOP_TYPE(result) != AOP_REG) &&
4847 (AOP_TYPE(right) == AOP_LIT) &&
4848 !IS_FLOAT(operandType(right)) &&
4850 emitcode("clr","a");
4852 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
4853 aopPut(AOP(result),"a",size);
4856 aopGet(AOP(right),size),
4862 aopGet(AOP(right),offset),
4869 freeAsmop (right,NULL,ic,FALSE);
4870 freeAsmop (result,NULL,ic,TRUE);
4873 /*-----------------------------------------------------------------*/
4874 /* genJumpTab - genrates code for jump table */
4875 /*-----------------------------------------------------------------*/
4876 static void genJumpTab (iCode *ic)
4881 aopOp(IC_JTCOND(ic),ic,FALSE);
4882 /* get the condition into accumulator */
4883 l = aopGet(AOP(IC_JTCOND(ic)),0);
4885 /* multiply by three */
4886 emitcode("add","a,acc");
4887 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0));
4888 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
4890 jtab = newiTempLabel(NULL);
4891 emitcode("mov","dptr,#%05d$",jtab->key+100);
4892 emitcode("jmp","@a+dptr");
4893 emitcode("","%05d$:",jtab->key+100);
4894 /* now generate the jump labels */
4895 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
4896 jtab = setNextItem(IC_JTLABELS(ic)))
4897 emitcode("ljmp","%05d$",jtab->key+100);
4901 /*-----------------------------------------------------------------*/
4902 /* genCast - gen code for casting */
4903 /*-----------------------------------------------------------------*/
4904 static void genCast (iCode *ic)
4906 operand *result = IC_RESULT(ic);
4907 link *ctype = operandType(IC_LEFT(ic));
4908 link *rtype = operandType(IC_RIGHT(ic));
4909 operand *right = IC_RIGHT(ic);
4912 /* if they are equivalent then do nothing */
4913 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
4916 aopOp(right,ic,FALSE) ;
4917 aopOp(result,ic,FALSE);
4919 /* if the result is a bit */
4920 if (AOP_TYPE(result) == AOP_CRY) {
4921 /* if the right size is a literal then
4922 we know what the value is */
4923 if (AOP_TYPE(right) == AOP_LIT) {
4924 if (((int) operandLitValue(right)))
4925 aopPut(AOP(result),one,0);
4927 aopPut(AOP(result),zero,0);
4932 /* the right is also a bit variable */
4933 if (AOP_TYPE(right) == AOP_CRY) {
4934 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4935 aopPut(AOP(result),"c",0);
4940 toBoolean(right,"",0);
4941 aopPut(AOP(result),"a",0);
4945 /* if they are the same size : or less */
4946 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
4948 /* if they are in the same place */
4949 if (sameRegs(AOP(right),AOP(result)))
4952 /* if they in different places then copy */
4953 size = AOP_SIZE(result);
4957 aopGet(AOP(right),offset),
4965 /* if the result is of type pointer */
4966 if (IS_PTR(ctype)) {
4969 link *type = operandType(right);
4970 link *etype = getSpec(type);
4972 /* pointer to generic pointer */
4973 if (IS_GENPTR(ctype)) {
4977 p_type = DCL_TYPE(type);
4979 /* we have to go by the storage class */
4980 p_type = PTR_TYPE(SPEC_OCLS(etype));
4983 /* the first two bytes are known */
4984 size = GPTRSIZE - 1;
4988 aopGet(AOP(right),offset),
4992 /* the last byte depending on type */
5009 /* this should never happen */
5010 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
5011 "got unknown pointer type");
5014 aopPut(AOP(result),l, GPTRSIZE - 1);
5018 /* just copy the pointers */
5019 size = AOP_SIZE(result);
5023 aopGet(AOP(right),offset),
5030 /* so we now know that the size of destination is greater
5031 than the size of the source */
5032 /* we move to result for the size of source */
5033 size = AOP_SIZE(right);
5037 aopGet(AOP(right),offset),
5042 /* now depending on the sign of the source && destination */
5043 size = AOP_SIZE(result) - AOP_SIZE(right);
5044 /* if unsigned or not an integral type */
5045 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
5047 aopPut(AOP(result),zero,offset++);
5049 /* we need to extend the sign :{ */
5050 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1);
5052 emitcode("rlc","a");
5053 emitcode("subb","a,acc");
5055 aopPut(AOP(result),"a",offset++);
5058 /* we are done hurray !!!! */
5061 freeAsmop(right,NULL,ic,TRUE);
5062 freeAsmop(result,NULL,ic,TRUE);
5066 /*-----------------------------------------------------------------*/
5067 /* genDjnz - generate decrement & jump if not zero instrucion */
5068 /*-----------------------------------------------------------------*/
5069 static int genDjnz (iCode *ic, iCode *ifx)
5075 /* if the if condition has a false label
5076 then we cannot save */
5080 /* if the minus is not of the form
5082 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
5083 !IS_OP_LITERAL(IC_RIGHT(ic)))
5086 if (operandLitValue(IC_RIGHT(ic)) != 1)
5089 /* if the size of this greater than one then no
5091 if (getSize(operandType(IC_RESULT(ic))) > 1)
5094 /* otherwise we can save BIG */
5095 lbl = newiTempLabel(NULL);
5096 lbl1= newiTempLabel(NULL);
5098 aopOp(IC_RESULT(ic),ic,FALSE);
5100 if (IS_AOP_PREG(IC_RESULT(ic))) {
5101 emitcode("dec","%s",
5102 aopGet(AOP(IC_RESULT(ic)),0));
5103 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0));
5104 emitcode("jnz","%05d$",lbl->key+100);
5106 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0),
5109 emitcode ("sjmp","%05d$",lbl1->key+100);
5110 emitcode ("","%05d$:",lbl->key+100);
5111 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
5112 emitcode ("","%05d$:",lbl1->key+100);
5114 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
5119 /*-----------------------------------------------------------------*/
5120 /* genReceive - generate code for a receive iCode */
5121 /*-----------------------------------------------------------------*/
5122 static void genReceive (iCode *ic)
5124 if (isOperandInFarSpace(IC_RESULT(ic)) &&
5125 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
5126 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
5128 int size = getSize(operandType(IC_RESULT(ic)));
5129 int offset = fAVRReturnSize - size;
5131 emitcode ("push","%s", (strcmp(fAVRReturn[fAVRReturnSize - offset - 1],"a") ?
5132 fAVRReturn[fAVRReturnSize - offset - 1] : "acc"));
5135 aopOp(IC_RESULT(ic),ic,FALSE);
5136 size = AOP_SIZE(IC_RESULT(ic));
5139 emitcode ("pop","acc");
5140 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
5145 aopOp(IC_RESULT(ic),ic,FALSE);
5147 assignResultValue(IC_RESULT(ic));
5150 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
5153 /*-----------------------------------------------------------------*/
5154 /* gen51Code - generate code for 8051 based controllers */
5155 /*-----------------------------------------------------------------*/
5156 void genAVRCode (iCode *lic)
5161 lineHead = lineCurr = NULL;
5163 /* print the allocation information */
5165 printAllocInfo( currFunc, codeOutFile);
5166 /* if debug information required */
5167 /* if (options.debug && currFunc) { */
5169 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
5171 if (IS_STATIC(currFunc->etype))
5172 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
5174 emitcode("","G$%s$0$0 ==.",currFunc->name);
5177 /* stack pointer name */
5178 if (options.useXstack)
5184 for (ic = lic ; ic ; ic = ic->next ) {
5186 if ( cln != ic->lineno ) {
5187 if ( options.debug ) {
5189 emitcode("","C$%s$%d$%d$%d ==.",
5190 ic->filename,ic->lineno,
5191 ic->level,ic->block);
5194 emitcode(";","%s %d",ic->filename,ic->lineno);
5197 /* if the result is marked as
5198 spilt and rematerializable or code for
5199 this has already been generated then
5201 if (resultRemat(ic) || ic->generated )
5204 /* depending on the operation */
5223 /* IPOP happens only when trying to restore a
5224 spilt live range, if there is an ifx statement
5225 following this pop then the if statement might
5226 be using some of the registers being popped which
5227 would destory the contents of the register so
5228 we need to check for this condition and handle it */
5230 ic->next->op == IFX &&
5231 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
5232 genIfx (ic->next,ic);
5250 genEndFunction (ic);
5270 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
5287 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
5291 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
5295 genCmpLe (ic,ifxForOp(IC_RESULT(ic),ic));
5299 genCmpGe (ic,ifxForOp(IC_RESULT(ic),ic));
5303 genCmpNe (ic,ifxForOp(IC_RESULT(ic),ic));
5307 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
5319 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
5323 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
5327 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
5354 case GET_VALUE_AT_ADDRESS:
5359 if (POINTER_SET(ic))
5386 addSet(&_G.sendSet,ic);
5391 /* piCode(ic,stdout); */
5397 /* now we are ready to call the
5398 peep hole optimizer */
5399 if (!options.nopeep)
5400 peepHole (&lineHead);
5402 /* now do the actual printing */
5403 printLine (lineHead,codeOutFile);