1 /*-------------------------------------------------------------------------
2 avrgen.c - source file for code generation for ATMEL AVR
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (2000)
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding!
25 -------------------------------------------------------------------------*/
31 #include "SDCCglobl.h"
33 #ifdef HAVE_SYS_ISA_DEFS_H
34 #include <sys/isa_defs.h>
40 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
41 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
47 #include "SDCCpeeph.h"
51 char *aopLiteral (value *val, int offset);
54 /* this is the down and dirty file with all kinds of
55 kludgy & hacky stuff. This is what it is all about
56 CODE GENERATION for a specific MCU . some of the
57 routines may be reusable, will have to see */
59 static char *zero = "0x00";
60 static char *one = "0x01";
63 char *fReturnAVR[] = {"r16","r17","r18","r19" };
64 unsigned fAVRReturnSize = 4; /* shared with ralloc.c */
65 char **fAVRReturn = fReturnAVR;
67 static short rbank = -1;
68 static char *larray[4] = {"lo8","hi8","hlo8","hhi8"};
80 extern int avr_ptrRegReq ;
82 extern FILE *codeOutFile;
83 static void saverbank (int, iCode *,bool);
84 #define RESULTONSTACK(x) \
85 (IC_RESULT(x) && IC_RESULT(x)->aop && \
86 IC_RESULT(x)->aop->type == AOP_STK )
88 #define MOVR0(x) if (strcmp(x,"r0")) emitcode("mov","r0,%s",x);
89 #define CLRC emitcode("clc","")
90 #define SETC emitcode("stc","")
92 #define IS_REGIDX(a,r) (a->type == AOP_REG && a->aopu.aop_reg[0]->rIdx == r)
94 static lineNode *lineHead = NULL;
95 static lineNode *lineCurr = NULL;
97 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
98 0xE0, 0xC0, 0x80, 0x00};
99 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
100 0x07, 0x03, 0x01, 0x00};
107 /*-----------------------------------------------------------------*/
108 /* emitcode - writes the code into a file : for now it is simple */
109 /*-----------------------------------------------------------------*/
110 static void emitcode (char *inst,char *fmt, ...)
113 char lb[MAX_INLINEASM];
120 sprintf(lb,"%s\t",inst);
122 sprintf(lb,"%s",inst);
123 vsprintf(lb+(strlen(lb)),fmt,ap);
127 while (isspace(*lbp)) lbp++;
130 lineCurr = (lineCurr ?
131 connectLine(lineCurr,newLineNode(lb)) :
132 (lineHead = newLineNode(lb)));
133 lineCurr->isInline = _G.inLine;
134 lineCurr->isDebug = _G.debugLine;
138 /*-----------------------------------------------------------------*/
139 /* getFreePtr - returns X or Z whichever is free or can be pushed */
140 /*-----------------------------------------------------------------*/
141 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result, bool zonly)
143 bool xiu = FALSE , ziu = FALSE;
144 bool xou = FALSE , zou = FALSE;
146 /* the logic: if x & z used in the instruction
147 then we are in trouble otherwise */
149 /* first check if x & z are used by this
150 instruction, in which case we are in trouble */
151 if ((xiu = bitVectBitValue(ic->rUsed,X_IDX)) &&
152 (ziu = bitVectBitValue(ic->rUsed,Z_IDX)))
157 xou = bitVectBitValue(ic->rMask,X_IDX);
158 zou = bitVectBitValue(ic->rMask,Z_IDX);
160 /* if no usage of Z then return it */
162 ic->rUsed = bitVectSetBit(ic->rUsed,Z_IDX);
163 (*aopp)->type = AOP_Z;
165 (*aopp)->aop_ptr2 = avr_regWithIdx(R31_IDX);
166 return (*aopp)->aopu.aop_ptr = avr_regWithIdx(R30_IDX);
169 /* if no usage of X then return it */
170 if (!xiu && !xou && !zonly) {
171 ic->rUsed = bitVectSetBit(ic->rUsed,X_IDX);
172 (*aopp)->type = AOP_X;
174 (*aopp)->aop_ptr2 = avr_regWithIdx(R27_IDX);
175 return (*aopp)->aopu.aop_ptr = avr_regWithIdx(R26_IDX);
178 /* if z not used then */
181 /* push it if not already pushed */
183 emitcode ("push","%s",
184 avr_regWithIdx(R30_IDX)->dname);
185 emitcode ("push","%s",
186 avr_regWithIdx(R31_IDX)->dname);
190 ic->rUsed = bitVectSetBit(ic->rUsed,Z_IDX);
191 (*aopp)->type = AOP_Z;
192 (*aopp)->aop_ptr2 = avr_regWithIdx(R31_IDX);
193 return (*aopp)->aopu.aop_ptr = avr_regWithIdx(R30_IDX);
196 /* now we know they both have usage */
197 /* if x not used in this instruction */
198 if (!xiu && !zonly) {
199 /* push it if not already pushed */
201 emitcode ("push","%s",
202 avr_regWithIdx(R26_IDX)->dname);
203 emitcode ("push","%s",
204 avr_regWithIdx(R27_IDX)->dname);
208 ic->rUsed = bitVectSetBit(ic->rUsed,X_IDX);
209 (*aopp)->type = AOP_X;
211 (*aopp)->aop_ptr2 = avr_regWithIdx(R27_IDX);
212 return (*aopp)->aopu.aop_ptr = avr_regWithIdx(R26_IDX);
217 /* I said end of world but not quite end of world yet */
218 /* if this is a result then we can push it on the stack*/
220 (*aopp)->type = AOP_STK;
225 /* other wise this is true end of the world */
226 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
227 "getFreePtr should never reach here");
231 /*-----------------------------------------------------------------*/
232 /* newAsmop - creates a new asmOp */
233 /*-----------------------------------------------------------------*/
234 static asmop *newAsmop (short type)
238 ALLOC(aop,sizeof(asmop));
243 /*-----------------------------------------------------------------*/
244 /* pointerCode - returns the code for a pointer type */
245 /*-----------------------------------------------------------------*/
246 static int pointerCode (link *etype)
249 return PTR_TYPE(SPEC_OCLS(etype));
253 /*-----------------------------------------------------------------*/
254 /* aopForSym - for a true symbol */
255 /*-----------------------------------------------------------------*/
256 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
259 memmap *space= SPEC_OCLS(sym->etype);
261 /* if already has one */
265 /* assign depending on the storage class */
266 /* if it is on the stack */
268 sym->aop = aop = newAsmop(0);
269 aop->size = getSize(sym->type);
271 /* we can use std / ldd instruction */
272 if (sym->stack > 0 && (sym->stack + getSize(sym->type) - 1) <= 63) {
273 aop->type = AOP_STK_D;
274 aop->aopu.aop_stk = sym->stack;
278 /* otherwise get a free pointer register X/Z */
279 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result,FALSE);
281 /* now assign the address of the variable to
282 the pointer register */
283 if (aop->type != AOP_STK) {
284 emitcode("movw","%s,r28",aop->aopu.aop_ptr->name);
285 if (sym->stack < 0) {
286 if ((sym->stack - _G.nRegsSaved) > -63) {
287 emitcode("sbiw","%s,0x%02x",
288 aop->aopu.aop_ptr->name,
289 (sym->stack - _G.nRegsSaved));
291 emitcode("subi","%s,lo8(%d)", aop->aopu.aop_ptr->name,
292 sym->stack - _G.nRegsSaved);
293 emitcode("sbci","%s,hi8(%d)",aop->aop_ptr2->name,
294 sym->stack - _G.nRegsSaved);
297 if (sym->stack <= 63) {
298 emitcode("adiw","%s,0x%02x",aop->aopu.aop_ptr->name,sym->stack);
300 emitcode("subi","%s,lo8(-%d)",aop->aopu.aop_ptr->name,sym->stack);
301 emitcode("sbci","%s,hi8(-%d)",aop->aop_ptr2->name,sym->stack);
308 /* if in bit space */
309 if (IN_BITSPACE(space)) {
310 sym->aop = aop = newAsmop (AOP_CRY);
311 aop->aopu.aop_dir = sym->rname ;
312 aop->size = getSize(sym->type);
315 /* if it is in direct space */
316 if (IN_DIRSPACE(space)) {
317 sym->aop = aop = newAsmop (AOP_DIR);
318 aop->aopu.aop_dir = sym->rname ;
319 aop->size = getSize(sym->type);
323 /* special case for a function */
324 if (IS_FUNC(sym->type)) {
325 sym->aop = aop = newAsmop(AOP_IMMD);
326 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
327 strcpy(aop->aopu.aop_immd,sym->rname);
328 aop->size = FPTRSIZE;
332 /* only remaining is code / eeprom which will need pointer reg */
333 /* if it is in code space */
334 if (IN_CODESPACE(space))
337 sym->aop = aop = newAsmop(0);
338 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result,aop->code);
339 aop->size = getSize(sym->type);
340 emitcode ("ldi","%s,lo8(%s)",aop->aopu.aop_ptr->name,sym->rname);
341 emitcode ("ldi","%s,hi8(%s)",aop->aop_ptr2);
346 /*-----------------------------------------------------------------*/
347 /* aopForRemat - rematerialzes an object */
348 /*-----------------------------------------------------------------*/
349 static asmop *aopForRemat (symbol *sym)
351 iCode *ic = sym->rematiCode;
352 asmop *aop = newAsmop(AOP_IMMD);
357 val += operandLitValue(IC_RIGHT(ic));
358 else if (ic->op == '-')
359 val -= operandLitValue(IC_RIGHT(ic));
363 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
367 sprintf(buffer,"(%s %c 0x%04x)",
368 OP_SYMBOL(IC_LEFT(ic))->rname,
369 val >= 0 ? '+' : '-',
372 strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
374 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
375 strcpy(aop->aopu.aop_immd,buffer);
379 /*-----------------------------------------------------------------*/
380 /* regsInCommon - two operands have some registers in common */
381 /*-----------------------------------------------------------------*/
382 static bool regsInCommon (operand *op1, operand *op2)
387 /* if they have registers in common */
388 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
391 sym1 = OP_SYMBOL(op1);
392 sym2 = OP_SYMBOL(op2);
394 if (sym1->nRegs == 0 || sym2->nRegs == 0)
397 for (i = 0 ; i < sym1->nRegs ; i++) {
402 for (j = 0 ; j < sym2->nRegs ;j++ ) {
406 if (sym2->regs[j] == sym1->regs[i])
414 /*-----------------------------------------------------------------*/
415 /* operandsEqu - equivalent */
416 /*-----------------------------------------------------------------*/
417 static bool operandsEqu ( operand *op1, operand *op2)
421 /* if they not symbols */
422 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
425 sym1 = OP_SYMBOL(op1);
426 sym2 = OP_SYMBOL(op2);
428 /* if both are itemps & one is spilt
429 and the other is not then false */
430 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
431 sym1->isspilt != sym2->isspilt )
434 /* if they are the same */
438 if (strcmp(sym1->rname,sym2->rname) == 0)
442 /* if left is a tmp & right is not */
446 (sym1->usl.spillLoc == sym2))
453 (sym2->usl.spillLoc == sym1))
459 /*-----------------------------------------------------------------*/
460 /* sameRegs - two asmops have the same registers */
461 /*-----------------------------------------------------------------*/
462 static bool sameRegs (asmop *aop1, asmop *aop2 )
469 if (aop1->type != AOP_REG ||
470 aop2->type != AOP_REG )
473 if (aop1->size != aop2->size )
476 for (i = 0 ; i < aop1->size ; i++ )
477 if (aop1->aopu.aop_reg[i] !=
478 aop2->aopu.aop_reg[i] )
484 /*-----------------------------------------------------------------*/
485 /* isRegPair - for size 2 if this operand has a register pair */
486 /*-----------------------------------------------------------------*/
487 static int isRegPair (asmop *aop)
489 if (!aop || aop->size != 2) return 0;
490 if (aop->type == AOP_X || aop->type == AOP_Z) return 1;
491 if (aop->type != AOP_REG) return 0;
492 if ((aop->aopu.aop_reg[1]->rIdx -
493 aop->aopu.aop_reg[0]->rIdx) == 1) return 1;
497 /*-----------------------------------------------------------------*/
498 /* aopOp - allocates an asmop for an operand : */
499 /*-----------------------------------------------------------------*/
500 static void aopOp (operand *op, iCode *ic, bool result)
509 /* if this a literal */
510 if (IS_OP_LITERAL(op)) {
511 op->aop = aop = newAsmop(AOP_LIT);
512 aop->aopu.aop_lit = op->operand.valOperand;
513 aop->size = getSize(operandType(op));
517 /* if already has a asmop then continue */
521 /* if the underlying symbol has a aop */
522 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
523 op->aop = OP_SYMBOL(op)->aop;
527 /* if this is a true symbol */
528 if (IS_TRUE_SYMOP(op)) {
529 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
533 /* this is a temporary : this has
539 e) can be a return use only */
544 /* if the type is a conditional */
545 if (sym->regType == REG_CND) {
546 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
551 /* if it is spilt then two situations
553 b) has a spill location */
554 if (sym->isspilt || sym->nRegs == 0) {
556 /* rematerialize it NOW */
558 sym->aop = op->aop = aop =
560 aop->size = getSize(sym->type);
565 assert("ACC_USE cannot happen in AVR\n");
570 aop = op->aop = sym->aop = newAsmop(AOP_STR);
571 aop->size = getSize(sym->type);
572 for ( i = 0 ; i < fAVRReturnSize ; i++ )
573 aop->aopu.aop_str[i] = fAVRReturn[i];
577 /* else spill location */
578 sym->aop = op->aop = aop =
579 aopForSym(ic,sym->usl.spillLoc,result);
580 aop->size = getSize(sym->type);
584 /* must be in a register */
585 sym->aop = op->aop = aop = newAsmop(AOP_REG);
586 aop->size = sym->nRegs;
587 for ( i = 0 ; i < sym->nRegs ;i++)
588 aop->aopu.aop_reg[i] = sym->regs[i];
591 /*-----------------------------------------------------------------*/
592 /* freeAsmop - free up the asmop given to an operand */
593 /*----------------------------------------------------------------*/
594 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
611 /* depending on the asmop type only three cases need work AOP_RO
612 , AOP_R1 && AOP_STK */
617 emitcode ("pop","r26");
618 emitcode ("pop","r27");
622 bitVectUnSetBit(ic->rUsed,X_IDX);
628 emitcode ("pop","r30");
629 emitcode ("pop","r31");
633 bitVectUnSetBit(ic->rUsed,Z_IDX);
639 int stk = aop->aopu.aop_stk + aop->size;
640 bitVectUnSetBit(ic->rUsed,X_IDX);
641 bitVectUnSetBit(ic->rUsed,Z_IDX);
643 getFreePtr(ic,&aop,FALSE,0);
645 emitcode ("movw","%s,r28");
647 if (stk <= 63 && stk > 0) {
648 emitcode ("adiw","%s,0x%02x",aop->aopu.aop_ptr->name,stk+1);
650 emitcode ("subi","%s,lo8(%d)",aop->aopu.aop_ptr->name,-(stk+1));
651 emitcode ("sbci","%s,hi8(%d)",aop->aop_ptr2->name,-(stk+1));
656 emitcode("pop","r24");
657 emitcode("st","-%s,r24",aop->type == AOP_X ? "X" : "Z");
661 freeAsmop(op,NULL,ic,TRUE);
663 emitcode("pop","r26");
664 emitcode("pop","r27");
669 emitcode("pop","r30");
670 emitcode("pop","r31");
677 /* all other cases just dealloc */
681 OP_SYMBOL(op)->aop = NULL;
682 /* if the symbol has a spill */
684 SPIL_LOC(op)->aop = NULL;
689 /*-----------------------------------------------------------------*/
690 /* aopGet - for fetching value of the aop */
691 /*-----------------------------------------------------------------*/
692 static char *aopGet (asmop *aop, int offset)
697 /* offset is greater than
699 if (offset > (aop->size - 1) &&
700 aop->type != AOP_LIT)
703 /* depending on type */
707 if (offset > aop->coff) {
708 emitcode ("adiw","%s,%d",aop->aopu.aop_ptr->name,offset - aop->coff);
711 if (offset < aop->coff) {
712 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,aop->coff - offset);
716 emitcode("ld","%s,x",
717 (rs = ((offset & 1) ? "r25" : "r24")));
722 if (offset > aop->coff) {
723 emitcode("adiw","r30,%d",offset - aop->coff);
725 emitcode("sbiw","r30,%d",aop->coff - offset);
727 emitcode("lpm","%s,z",(rs = ((offset & 1) ? "r25" : "r24")));
730 if (offset > aop->coff) {
731 emitcode ("ldd","%s,z+%d",(rs = ((offset & 1) ? "r25" : "r24")),
734 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,aop->coff - offset);
736 emitcode ("ld","%s,z",(rs = ((offset & 1) ? "r25" : "r24")));
743 emitcode ("lds","%s,(%s)+%d",
744 (rs = ((offset & 1) ? "r25" : "r24")),
745 aop->aopu.aop_immd, offset);
749 emitcode ("lds","%s,(%s)+%d",
750 (rs = ((offset & 1) ? "r25" : "r24")),
751 aop->aopu.aop_dir, offset);
755 return aop->aopu.aop_reg[offset]->name;
758 assert("cannot be in bit space AOP_CRY\n");
762 s = aopLiteral(aop->aopu.aop_lit,offset);
763 emitcode("ldi","%s,lo8(%s)",(rs = ((offset & 1)?"r24" : "r25")),s);
768 return aop->aopu.aop_str[offset];
771 emitcode ("ldd","%s,Y+%d",
772 (rs = ((offset & 1) ? "r25" : "r24")),
773 aop->aopu.aop_stk+offset);
777 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
778 "aopget got unsupported aop->type");
781 /*-----------------------------------------------------------------*/
782 /* aopPut - puts a string for a aop */
783 /*-----------------------------------------------------------------*/
784 static void aopPut (asmop *aop, char *s, int offset)
788 if (aop->size && offset > ( aop->size - 1)) {
789 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
790 "aopPut got offset > aop->size");
794 /* will assign value to value */
795 /* depending on where it is ofcourse */
799 sprintf(d,"(%s)+%d", aop->aopu.aop_dir,offset);
802 sprintf(d,"%s",aop->aopu.aop_dir);
805 emitcode("sts","%s,%s",d,s);
809 if (toupper(*s) != 'R') {
811 emitcode("clr","%s",aop->aopu.aop_reg[offset]->name);
813 emitcode("ldi","r25,%s",s);
814 emitcode("mov","%s,r35",aop->aopu.aop_reg[offset]->name);
817 if (strcmp( aop->aopu.aop_reg[offset]->name,s)) {
818 emitcode("mov","%s,%s", aop->aopu.aop_reg[offset]->name,s);
824 if (offset > aop->coff) {
825 emitcode ("adiw","%s,%d",aop->aopu.aop_ptr->name,offset - aop->coff);
828 if (offset < aop->coff) {
829 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,aop->coff - offset);
833 emitcode("st","x,%s", s);
838 if (offset > aop->coff) {
839 emitcode("adiw","r30,%d",offset - aop->coff);
841 emitcode("sbiw","r30,%d",aop->coff - offset);
843 emitcode("lpm","%s,z",s);
846 if (offset > aop->coff) {
847 emitcode ("sdd","z+%d,%s",offset - aop->coff,s);
849 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,aop->coff - offset);
851 emitcode ("ld","%s,z",s);
857 emitcode("push","%s",s);
861 /* if used only for a condition code check */
862 assert(toupper(*s) == 'R');
864 emitcode("xrl","r0,r0");
865 emitcode("cpi","%s,0",s);
868 emitcode("cpc","r0,%s",s);
874 if (strcmp(aop->aopu.aop_str[offset],s))
875 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
879 emitcode ("std","y+%d,%s",offset,s);
883 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
884 "aopPut got unsupported aop->type");
890 /*-----------------------------------------------------------------*/
891 /* reAdjustPreg - points a register back to where it should */
892 /*-----------------------------------------------------------------*/
893 static void reAdjustPreg (asmop *aop)
898 if ((size = aop->size) <= 1)
904 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,size);
910 #define AOP(op) op->aop
911 #define AOP_TYPE(op) AOP(op)->type
912 #define AOP_SIZE(op) AOP(op)->size
913 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_X || \
914 AOP_TYPE(x) == AOP_Z))
915 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
916 (x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) || \
917 x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) )))
919 /*-----------------------------------------------------------------*/
920 /* genNotFloat - generates not for float operations */
921 /*-----------------------------------------------------------------*/
922 static void genNotFloat (operand *op, operand *res)
928 /* we will put 127 in the first byte of
930 aopPut(AOP(res),"127",0);
931 size = AOP_SIZE(op) - 1;
934 l = aopGet(op->aop,offset++);
938 emitcode("or","R0,%s", aopGet(op->aop, offset++));
940 tlbl = newiTempLabel(NULL);
942 tlbl = newiTempLabel(NULL);
943 aopPut(res->aop,zero,1);
944 emitcode("cpi","r0,0");
945 emitcode("breq","L%05d",tlbl->key);
946 aopPut(res->aop,one,1);
947 emitcode("","L%05d:",tlbl->key);
949 size = res->aop->size - 2;
951 /* put zeros in the rest */
953 aopPut(res->aop,zero,offset++);
956 /*-----------------------------------------------------------------*/
957 /* opIsGptr: returns non-zero if the passed operand is */
958 /* a generic pointer type. */
959 /*-----------------------------------------------------------------*/
960 static int opIsGptr(operand *op)
962 link *type = operandType(op);
964 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
971 /*-----------------------------------------------------------------*/
972 /* getDataSize - get the operand data size */
973 /*-----------------------------------------------------------------*/
974 static int getDataSize(operand *op)
978 if (size == GPTRSIZE)
980 link *type = operandType(op);
983 /* generic pointer; arithmetic operations
984 * should ignore the high byte (pointer type).
992 /*-----------------------------------------------------------------*/
993 /* outAcc - output Acc */
994 /*-----------------------------------------------------------------*/
995 static void outAcc(operand *result)
998 size = getDataSize(result);
1000 aopPut(AOP(result),"r0",0);
1003 /* unsigned or positive */
1005 aopPut(AOP(result),zero,offset++);
1010 /*-----------------------------------------------------------------*/
1011 /* outBitC - output a bit C */
1012 /*-----------------------------------------------------------------*/
1013 static void outBitC(operand *result)
1015 emitcode("clr","r0");
1016 emitcode("rol","r0");
1020 /*-----------------------------------------------------------------*/
1021 /* toBoolean - emit code for orl a,operator(sizeop) */
1022 /*-----------------------------------------------------------------*/
1023 static void toBoolean(operand *oper, char *r, bool clr)
1025 int size = AOP_SIZE(oper) ;
1027 if (clr) emitcode ("clr","%s",r);
1029 emitcode("or","%s,%s",r,aopGet(AOP(oper),offset++));
1033 /*-----------------------------------------------------------------*/
1034 /* genNot - generate code for ! operation */
1035 /*-----------------------------------------------------------------*/
1036 static void genNot (iCode *ic)
1039 link *optype = operandType(IC_LEFT(ic));
1040 int size, offset = 1;
1042 /* assign asmOps to operand & result */
1043 aopOp (IC_LEFT(ic),ic,FALSE);
1044 aopOp (IC_RESULT(ic),ic,TRUE);
1046 /* if type float then do float */
1047 if (IS_FLOAT(optype)) {
1048 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1051 emitcode("clr","r0");
1052 tlbl = newiTempLabel(NULL);
1053 size = AOP_SIZE(IC_LEFT(ic));
1056 emitcode("cpse","%s,r0",aopGet(AOP(IC_LEFT(ic)),0));
1060 if (offset) emitcode("cpc","%s,r0",aopGet(AOP(IC_LEFT(ic)),offset));
1061 else emitcode("cpi","%s,0",aopGet(AOP(IC_LEFT(ic)),offset));
1064 emitcode("bne","L%05d",tlbl->key);
1066 emitcode("ldi","r0,1");
1067 emitcode("","L%05d:",tlbl->key);
1068 aopPut(AOP(IC_RESULT(ic)),"r0",0);
1069 size = AOP_SIZE(IC_RESULT(ic)) -1;
1071 while (size--) aopPut(AOP(IC_RESULT(ic)),zero,offset++);
1075 /* release the aops */
1076 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1077 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1081 /*-----------------------------------------------------------------*/
1082 /* genCpl - generate code for complement */
1083 /*-----------------------------------------------------------------*/
1084 static void genCpl (iCode *ic)
1090 /* assign asmOps to operand & result */
1091 aopOp (IC_LEFT(ic),ic,FALSE);
1092 aopOp (IC_RESULT(ic),ic,TRUE);
1093 samer = sameRegs(AOP(IC_LEFT(ic)),AOP(IC_RESULT(ic)));
1094 size = AOP_SIZE(IC_RESULT(ic));
1096 char *l = aopGet(AOP(IC_LEFT(ic)),offset);
1098 emitcode ("com","%s",l);
1100 aopPut(AOP(IC_RESULT(ic)),l,offset);
1101 emitcode ("com","%s",aopGet(AOP(IC_RESULT(ic)),offset));
1106 /* release the aops */
1107 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1108 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1111 /*-----------------------------------------------------------------*/
1112 /* genUminusFloat - unary minus for floating points */
1113 /*-----------------------------------------------------------------*/
1114 static void genUminusFloat(operand *op,operand *result)
1116 int size ,offset =0 ;
1118 /* for this we just need to flip the
1119 first it then copy the rest in place */
1120 size = AOP_SIZE(op) - 1;
1121 l = aopGet(AOP(op),3);
1123 emitcode("ldi","r24,0x80");
1124 if (sameRegs(AOP(op),AOP(result))) {
1125 emitcode("eor","%s,r24",l);
1127 aopPut(AOP(result),l,3);
1128 emitcode("eor","%s,r24",aopGet(AOP(result),3));
1131 aopPut(AOP(result), aopGet(AOP(op),offset), offset);
1136 /*-----------------------------------------------------------------*/
1137 /* genUminus - unary minus code generation */
1138 /*-----------------------------------------------------------------*/
1139 static void genUminus (iCode *ic)
1142 link *optype, *rtype;
1146 aopOp(IC_LEFT(ic),ic,FALSE);
1147 aopOp(IC_RESULT(ic),ic,TRUE);
1149 optype = operandType(IC_LEFT(ic));
1150 rtype = operandType(IC_RESULT(ic));
1152 /* if float then do float stuff */
1153 if (IS_FLOAT(optype)) {
1154 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1158 /* otherwise subtract from zero */
1159 size = AOP_SIZE(IC_LEFT(ic));
1161 samer = sameRegs(AOP(IC_LEFT(ic)),AOP(IC_RESULT(ic)));
1164 emitcode("neg","%s",aopGet(AOP(IC_LEFT(ic)),0));
1166 aopPut(AOP(IC_RESULT(ic)),aopGet(AOP(IC_LEFT(ic)),0),0);
1167 emitcode("neg","%s",aopGet(AOP(IC_RESULT(ic)),0));
1172 char *l = aopGet(AOP(IC_LEFT(ic)),offset);
1174 aopPut(AOP(IC_RESULT(ic)),l,offset);
1175 l = aopGet(AOP(IC_RESULT(ic)),offset);
1177 if (offset) emitcode("com","%s",l);
1178 else emitcode("neg","%s",l);
1181 size = AOP_SIZE(IC_LEFT(ic)) -1;
1184 emitcode("sbci","%s,lo8(-1)",aopGet(AOP(IC_RESULT(ic)),offset++));
1188 /* if any remaining bytes in the result */
1189 /* we just need to propagate the sign */
1190 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1191 symbol *tlbl = newiTempLabel(NULL);
1192 emitcode("clr","r0");
1193 emitcode("brcc","L%05d",tlbl->key);
1194 emitcode("com","r0");
1195 emitcode("","L%05d:",tlbl->key);
1197 aopPut(AOP(IC_RESULT(ic)),"r0",offset++);
1201 /* release the aops */
1202 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1203 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1206 /*-----------------------------------------------------------------*/
1207 /* assignResultValue - */
1208 /*-----------------------------------------------------------------*/
1209 static void assignResultValue(operand * oper)
1212 int size = AOP_SIZE(oper);
1214 aopPut(AOP(oper),fAVRReturn[offset],offset);
1219 /*-----------------------------------------------------------------*/
1220 /* saveZreg - if indirect call then save z-pointer register */
1221 /*-----------------------------------------------------------------*/
1222 static void saveZreg (iCode *ic)
1224 /* only if live accross this call */
1225 if (ic->regsSaved == 0 &&
1226 (bitVectBitValue(ic->rMask,R30_IDX) ||
1227 bitVectBitValue(ic->rMask,R31_IDX))) {
1229 emitcode("push","r30");
1230 emitcode("push","r31");
1234 /*-----------------------------------------------------------------*/
1235 /* popZreg - restore values of zreg */
1236 /*-----------------------------------------------------------------*/
1237 static void popZreg (iCode *ic)
1239 if (ic->regsSaved) {
1240 emitcode ("pop","r31");
1241 emitcode ("pop","r30");
1245 /*-----------------------------------------------------------------*/
1246 /* genIpush - genrate code for pushing this gets a little complex */
1247 /*-----------------------------------------------------------------*/
1248 static void genIpush (iCode *ic)
1250 int size, offset = 0 ;
1254 if (!ic->parmPush) {
1255 /* and the item is spilt then do nothing */
1256 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1260 for (lic = ic->next ; lic ; lic = lic->next)
1261 if (lic->op == PCALL) break;
1262 if (lic) saveZreg(lic);
1265 /* this is a paramter push */
1266 aopOp(IC_LEFT(ic),ic,FALSE);
1267 size = AOP_SIZE(IC_LEFT(ic));
1269 l = aopGet(AOP(IC_LEFT(ic)),offset++);
1270 emitcode("push","%s",l);
1273 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1276 /*-----------------------------------------------------------------*/
1277 /* genIpop - recover the registers: can happen only for spilling */
1278 /*-----------------------------------------------------------------*/
1279 static void genIpop (iCode *ic)
1284 /* if the temp was not pushed then */
1285 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1288 aopOp(IC_LEFT(ic),ic,FALSE);
1289 size = AOP_SIZE(IC_LEFT(ic));
1292 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--));
1294 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1297 /*-----------------------------------------------------------------*/
1298 /* genCall - generates a call statement */
1299 /*-----------------------------------------------------------------*/
1300 static void genCall (iCode *ic)
1303 /* if send set is not empty the assign */
1307 for (sic = setFirstItem(_G.sendSet) ; sic ;
1308 sic = setNextItem(_G.sendSet)) {
1309 int size, offset = 0;
1310 aopOp(IC_LEFT(sic),sic,FALSE);
1311 size = AOP_SIZE(IC_LEFT(sic));
1313 char *l = aopGet(AOP(IC_LEFT(sic)),offset);
1314 if (strcmp(l,fAVRReturn[offset]))
1315 emitcode("mov","%s,%s",
1320 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1325 emitcode("call","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1326 OP_SYMBOL(IC_LEFT(ic))->rname :
1327 OP_SYMBOL(IC_LEFT(ic))->name));
1329 /* if we need assign a result value */
1330 if ((IS_ITEMP(IC_RESULT(ic)) &&
1331 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1332 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1333 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1335 aopOp(IC_RESULT(ic),ic,FALSE);
1336 assignResultValue(IC_RESULT(ic));
1337 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1340 /* adjust the stack for parameters if required */
1341 if (IC_LEFT(ic)->parmBytes) {
1342 if (IC_LEFT(ic)->parmBytes > 63) {
1343 emitcode("sbiw","r28,%d",IC_LEFT(ic)->parmBytes);
1345 emitcode("subi","r28,lo8(%d)",IC_LEFT(ic)->parmBytes);
1346 emitcode("sbci","r29,hi8(%d)",IC_LEFT(ic)->parmBytes);
1352 /*-----------------------------------------------------------------*/
1353 /* genPcall - generates a call by pointer statement */
1354 /*-----------------------------------------------------------------*/
1355 static void genPcall (iCode *ic)
1358 if (!ic->regsSaved) saveZreg(ic);
1360 aopOp(IC_LEFT(ic),ic,FALSE);
1361 emitcode("mov","r30",aopGet(AOP(IC_LEFT(ic)),0));
1362 emitcode("mov","r31",aopGet(AOP(IC_RIGHT(ic)),0));
1363 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1365 /* if send set is not empty the assign */
1369 for (sic = setFirstItem(_G.sendSet) ; sic ;
1370 sic = setNextItem(_G.sendSet)) {
1371 int size, offset = 0;
1372 aopOp(IC_LEFT(sic),sic,FALSE);
1373 size = AOP_SIZE(IC_LEFT(sic));
1375 char *l = aopGet(AOP(IC_LEFT(sic)),offset);
1376 if (strcmp(l,fAVRReturn[offset]))
1377 emitcode("mov","%s,%s",
1382 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1387 emitcode("icall","");
1389 /* if we need assign a result value */
1390 if ((IS_ITEMP(IC_RESULT(ic)) &&
1391 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1392 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
1393 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1395 aopOp(IC_RESULT(ic),ic,FALSE);
1397 assignResultValue(IC_RESULT(ic));
1398 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1401 /* adjust the stack for parameters if
1403 if (IC_LEFT(ic)->parmBytes) {
1405 if (IC_LEFT(ic)->parmBytes > 3) {
1406 emitcode("mov","a,%s",spname);
1407 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1408 emitcode("mov","%s,a",spname);
1410 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1411 emitcode("dec","%s",spname);
1415 /* adjust the stack for parameters if required */
1416 if (IC_LEFT(ic)->parmBytes) {
1417 if (IC_LEFT(ic)->parmBytes > 63) {
1418 emitcode("sbiw","r28,%d",IC_LEFT(ic)->parmBytes);
1420 emitcode("subi","r28,lo8(%d)",IC_LEFT(ic)->parmBytes);
1421 emitcode("sbci","r29,hi8(%d)",IC_LEFT(ic)->parmBytes);
1424 if (ic->regsSaved) popZreg(ic);
1427 /*-----------------------------------------------------------------*/
1428 /* resultRemat - result is rematerializable */
1429 /*-----------------------------------------------------------------*/
1430 static int resultRemat (iCode *ic)
1432 if (SKIP_IC(ic) || ic->op == IFX)
1435 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1436 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1437 if (sym->remat && !POINTER_SET(ic))
1445 #define STRCASECMP stricmp
1447 #define STRCASECMP strcasecmp
1450 /*-----------------------------------------------------------------*/
1451 /* inExcludeList - return 1 if the string is in exclude Reg list */
1452 /*-----------------------------------------------------------------*/
1453 static bool inExcludeList(char *s)
1457 if (options.excludeRegs[i] &&
1458 STRCASECMP(options.excludeRegs[i],"none") == 0)
1461 for ( i = 0 ; options.excludeRegs[i]; i++) {
1462 if (options.excludeRegs[i] &&
1463 STRCASECMP(s,options.excludeRegs[i]) == 0)
1469 /*-----------------------------------------------------------------*/
1470 /* genFunction - generated code for function entry */
1471 /*-----------------------------------------------------------------*/
1472 static void genFunction (iCode *ic)
1479 /* create the function header */
1480 emitcode(";","-----------------------------------------");
1481 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1482 emitcode(";","-----------------------------------------");
1484 emitcode("","%s:",sym->rname);
1485 fetype = getSpec(operandType(IC_LEFT(ic)));
1487 /* if critical function then turn interrupts off */
1488 if (SPEC_CRTCL(fetype))
1491 if (IS_ISR(sym->etype)) {
1494 /* save the preserved registers that are used in this function */
1495 for (i = R2_IDX ; i <= R15_IDX ; i++ ) {
1496 if (bitVectBitValue(sym->regsUsed,i)) {
1498 emitcode("push","%s",avr_regWithIdx(i)->name);
1501 /* now for the pointer registers */
1502 if (bitVectBitValue(sym->regsUsed,R26_IDX)) {
1504 emitcode("push","r26");
1506 if (bitVectBitValue(sym->regsUsed,R27_IDX)) {
1508 emitcode("push","r27");
1510 if (bitVectBitValue(sym->regsUsed,R30_IDX)) {
1512 emitcode("push","r30");
1514 if (bitVectBitValue(sym->regsUsed,R31_IDX)) {
1516 emitcode("push","r31");
1518 /* adjust the stack for the function */
1520 emitcode ("push","r28");
1521 emitcode ("push","r29");
1522 emitcode ("in","r28,__SP_L__");
1523 emitcode ("in","r29,__SP_H__");
1524 if (sym->stack <= 63) {
1525 emitcode("sbiw","r28,%d",sym->stack);
1527 emitcode ("subi","r28,lo8(%d)",sym->stack);
1528 emitcode ("sbci","r29,hi8(%d)",sym->stack);
1530 emitcode("out","__SP_L__,r28");
1531 emitcode("out","__SP_H__,r29");
1535 /*-----------------------------------------------------------------*/
1536 /* genEndFunction - generates epilogue for functions */
1537 /*-----------------------------------------------------------------*/
1538 static void genEndFunction (iCode *ic)
1540 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1543 /* restore stack pointer */
1545 if (sym->stack <= 63) {
1546 emitcode("adiw","r28,%d",sym->stack);
1548 emitcode ("subi","r28,lo8(-%d)",sym->stack);
1549 emitcode ("sbci","r29,hi8(-%d)",sym->stack);
1551 emitcode("out","__SP_L__,r28");
1552 emitcode("out","__SP_H__,r29");
1554 /* pop frame pointer */
1555 emitcode ("pop","r29");
1556 emitcode ("pop","r28");
1558 /* restore preserved registers */
1559 if (bitVectBitValue(sym->regsUsed,R31_IDX)) {
1561 emitcode("pop","r31");
1563 if (bitVectBitValue(sym->regsUsed,R30_IDX)) {
1565 emitcode("pop","r30");
1567 if (bitVectBitValue(sym->regsUsed,R27_IDX)) {
1569 emitcode("push","r27");
1571 if (bitVectBitValue(sym->regsUsed,R26_IDX)) {
1573 emitcode("push","r26");
1575 for (i = R15_IDX ; i >= R2_IDX ; i-- ) {
1576 if (bitVectBitValue(sym->regsUsed,i)) {
1578 emitcode("pop","%s",avr_regWithIdx(i)->name);
1582 if (SPEC_CRTCL(sym->etype))
1585 if (IS_ISR(sym->etype)) {
1593 /*-----------------------------------------------------------------*/
1594 /* genRet - generate code for return statement */
1595 /*-----------------------------------------------------------------*/
1596 static void genRet (iCode *ic)
1598 int size,offset = 0 ;
1600 /* if we have no return value then
1601 just generate the "ret" */
1605 /* we have something to return then
1606 move the return value into place */
1607 aopOp(IC_LEFT(ic),ic,FALSE);
1608 size = AOP_SIZE(IC_LEFT(ic));
1611 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
1612 emitcode("ldi","%s,%s(%d)",fAVRReturn[offset],larray[offset],
1613 (int)floatFromVal (AOP(IC_LEFT(ic))->aopu.aop_lit),offset);
1616 l = aopGet(AOP(IC_LEFT(ic)),offset);
1617 if (strcmp(fAVRReturn[offset],l))
1618 emitcode("mov","%s,%s",fAVRReturn[offset],l);
1623 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
1626 /* generate a jump to the return label
1627 if the next is not the return statement */
1628 if (!(ic->next && ic->next->op == LABEL &&
1629 IC_LABEL(ic->next) == returnLabel))
1631 emitcode("rjmp","L%05d",returnLabel->key);
1635 /*-----------------------------------------------------------------*/
1636 /* genLabel - generates a label */
1637 /*-----------------------------------------------------------------*/
1638 static void genLabel (iCode *ic)
1640 /* special case never generate */
1641 if (IC_LABEL(ic) == entryLabel)
1644 emitcode("","L%05d:",IC_LABEL(ic)->key);
1647 /*-----------------------------------------------------------------*/
1648 /* genGoto - generates a ljmp */
1649 /*-----------------------------------------------------------------*/
1650 static void genGoto (iCode *ic)
1652 emitcode ("rjmp","L%05d:",(IC_LABEL(ic)->key+100));
1655 /*-----------------------------------------------------------------*/
1656 /* findLabelBackwards: walks back through the iCode chain looking */
1657 /* for the given label. Returns number of iCode instructions */
1658 /* between that label and given ic. */
1659 /* Returns zero if label not found. */
1660 /*-----------------------------------------------------------------*/
1661 static int findLabelBackwards(iCode *ic, int key)
1670 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
1672 /* printf("findLabelBackwards = %d\n", count); */
1680 /*-----------------------------------------------------------------*/
1681 /* genPlusIncr :- does addition with increment if possible */
1682 /*-----------------------------------------------------------------*/
1683 static bool genPlusIncr (iCode *ic)
1685 unsigned int icount ;
1687 /* will try to generate an increment */
1688 /* if the right side is not a literal
1690 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1693 icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
1695 /* if the sizes are greater than 2 or they are not the same regs
1697 if (!sameRegs(AOP(IC_LEFT(ic)),AOP(IC_RESULT(ic))))
1700 /* so we know LEFT & RESULT in the same registers and add
1702 /* for short & char types */
1703 if (AOP_SIZE(IC_RESULT(ic)) < 2) {
1705 emitcode("inc","%s",aopGet(AOP(IC_LEFT(ic)),0));
1708 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_LEFT(ic)),0),-icount);
1712 if (AOP_SIZE(IC_RESULT(ic)) <= 3) {
1713 /* if register pair and starts with 26/30 then adiw */
1714 if (isRegPair(AOP(IC_RESULT(ic))) && icount > 0 && icount < 64 &&
1715 ( IS_REGIDX(AOP(IC_RESULT(ic)),R26_IDX) ||
1716 IS_REGIDX(AOP(IC_RESULT(ic)),R30_IDX) )) {
1717 emitcode("adiw","%s,%d",aopGet(AOP(IC_RESULT(ic)),0),icount);
1722 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_RESULT(ic)),0),-icount);
1723 emitcode("sbci","%s,hi8(%d)",aopGet(AOP(IC_RESULT(ic)),1),-icount);
1727 /* for 32 bit longs */
1728 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_RESULT(ic)),0),-icount);
1729 emitcode("sbci","%s,hi8(%d)",aopGet(AOP(IC_RESULT(ic)),1),-icount);
1730 emitcode("sbci","%s,hlo8(%d)",aopGet(AOP(IC_RESULT(ic)),2),-icount);
1731 emitcode("sbci","%s,hhi8(%d)",aopGet(AOP(IC_RESULT(ic)),3),-icount);
1736 /* This is the pure and virtuous version of this code.
1737 * I'm pretty certain it's right, but not enough to toss the old
1740 static void adjustArithmeticResult (iCode *ic)
1742 if (opIsGptr(IC_RESULT(ic)) &&
1743 opIsGptr(IC_LEFT(ic)) &&
1744 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1746 aopPut(AOP(IC_RESULT(ic)),
1747 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1),
1751 if (opIsGptr(IC_RESULT(ic)) &&
1752 opIsGptr(IC_RIGHT(ic)) &&
1753 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
1755 aopPut(AOP(IC_RESULT(ic)),
1756 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1),
1760 if (opIsGptr(IC_RESULT(ic)) &&
1761 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
1762 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
1763 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
1764 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
1766 sprintf(buffer,"%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
1767 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
1771 /*-----------------------------------------------------------------*/
1772 /* genPlus - generates code for addition */
1773 /*-----------------------------------------------------------------*/
1774 static void genPlus (iCode *ic)
1776 int size, offset = 0;
1780 /* special cases :- */
1782 aopOp (IC_LEFT(ic),ic,FALSE);
1783 aopOp (IC_RIGHT(ic),ic,FALSE);
1784 aopOp (IC_RESULT(ic),ic,TRUE);
1786 /* if I can do an increment instead
1787 of add then GOOD for ME */
1788 if (genPlusIncr (ic) == TRUE)
1791 size = getDataSize(IC_RESULT(ic));
1792 samer = sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic)));
1796 aopPut(AOP(IC_RESULT(ic)),aopGet(AOP(IC_LEFT(ic)),offset),offset);
1798 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
1800 if(offset == 0) l = "add";
1803 emitcode(l,"%s,%s",aopGet(AOP(IC_RESULT(ic)),offset),
1804 aopGet(AOP(IC_RIGHT(ic)),offset));
1806 if (offset == 0) l = "subi";
1809 emitcode(l,"%s,%s(-%d)",aopGet(AOP(IC_RESULT(ic)),offset),
1811 (int)floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
1816 adjustArithmeticResult(ic);
1819 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1820 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1821 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1824 /*-----------------------------------------------------------------*/
1825 /* genMinusDec :- does subtraction with deccrement if possible */
1826 /*-----------------------------------------------------------------*/
1827 static bool genMinusDec (iCode *ic)
1829 unsigned int icount ;
1831 /* will try to generate an increment */
1832 /* if the right side is not a literal
1834 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1837 icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
1839 /* if the sizes are greater than 2 or they are not the same regs
1841 if (!sameRegs(AOP(IC_LEFT(ic)),AOP(IC_RIGHT(ic))))
1844 /* so we know LEFT & RESULT in the same registers and add
1846 /* for short & char types */
1847 if (AOP_SIZE(IC_RESULT(ic)) < 2) {
1849 emitcode("dec","%s",aopGet(AOP(IC_LEFT(ic)),0));
1852 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_LEFT(ic)),0),icount);
1856 if (AOP_SIZE(IC_RESULT(ic)) <= 3) {
1857 /* if register pair and starts with 26/30 then adiw */
1858 if (isRegPair(AOP(IC_RESULT(ic))) && icount > 0 && icount < 64 &&
1859 ( IS_REGIDX(AOP(IC_RESULT(ic)),R26_IDX) ||
1860 IS_REGIDX(AOP(IC_RESULT(ic)),R30_IDX) )) {
1861 emitcode("sbiw","%s,%d",aopGet(AOP(IC_RESULT(ic)),0),icount);
1866 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_RESULT(ic)),0),icount);
1867 emitcode("sbci","%s,hi8(%d)",aopGet(AOP(IC_RESULT(ic)),1),icount);
1870 /* for 32 bit longs */
1871 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_RESULT(ic)),0),icount);
1872 emitcode("sbci","%s,hi8(%d)",aopGet(AOP(IC_RESULT(ic)),1),icount);
1873 emitcode("sbci","%s,hlo8(%d)",aopGet(AOP(IC_RESULT(ic)),2),icount);
1874 emitcode("sbci","%s,hhi8(%d)",aopGet(AOP(IC_RESULT(ic)),3),icount);
1879 /*-----------------------------------------------------------------*/
1880 /* addSign - complete with sign */
1881 /*-----------------------------------------------------------------*/
1882 static void addSign(operand *result, int offset, int sign)
1884 int size = (getDataSize(result) - offset);
1887 emitcode("rlc","a");
1888 emitcode("subb","a,acc");
1890 aopPut(AOP(result),"a",offset++);
1893 aopPut(AOP(result),zero,offset++);
1897 /*-----------------------------------------------------------------*/
1898 /* genMinus - generates code for subtraction */
1899 /*-----------------------------------------------------------------*/
1900 static void genMinus (iCode *ic)
1902 int size, offset = 0, samer;
1905 aopOp (IC_LEFT(ic),ic,FALSE);
1906 aopOp (IC_RIGHT(ic),ic,FALSE);
1907 aopOp (IC_RESULT(ic),ic,TRUE);
1909 /* if I can do an decrement instead
1910 of subtract then GOOD for ME */
1911 if (genMinusDec (ic) == TRUE)
1914 size = getDataSize(IC_RESULT(ic));
1915 samer = sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic)));
1918 aopPut(AOP(IC_RESULT(ic)),aopGet(AOP(IC_LEFT(ic)),offset),offset);
1920 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
1922 if(offset == 0) l = "sub";
1925 emitcode(l,"%s,%s",aopGet(AOP(IC_RESULT(ic)),offset),
1926 aopGet(AOP(IC_RIGHT(ic)),offset));
1928 if (offset == 0) l = "subi";
1931 emitcode(l,"%s,%s(%d)",aopGet(AOP(IC_RESULT(ic)),offset),
1933 (int)floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
1938 adjustArithmeticResult(ic);
1941 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1942 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1943 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1946 /*-----------------------------------------------------------------*/
1947 /* genMultOneByte : 8 bit multiplication & division */
1948 /*-----------------------------------------------------------------*/
1949 static void genMultOneByte (operand *left,
1953 link *opetype = operandType(result);
1957 /* (if two literals, the value is computed before) */
1958 /* if one literal, literal on the right */
1959 if (AOP_TYPE(left) == AOP_LIT){
1965 size = AOP_SIZE(result);
1967 if (SPEC_USIGN(opetype)) {
1968 emitcode("mul","%s,%s", aopGet(AOP(left),0),aopGet(AOP(right),0));
1970 emitcode("muls","%s,%s", aopGet(AOP(left),0),
1971 aopGet(AOP(right),0));
1973 aopPut(AOP(result),"r0",0);
1975 aopPut(AOP(result),"r1",1);
1978 if (SPEC_USIGN(opetype)) {
1980 aopPut(AOP(result),zero,offset++);
1984 lbl = newiTempLabel(NULL);
1985 emitcode("ldi","r24,0");
1986 emitcode("brcc","L%05d",lbl->key);
1987 emitcode("ldi","r24,lo8(-1)");
1988 emitcode("","L%05d:",lbl->key);
1989 while (size--) aopPut(AOP(result),"r24",offset++);
1996 /*-----------------------------------------------------------------*/
1997 /* genMult - generates code for multiplication */
1998 /*-----------------------------------------------------------------*/
1999 static void genMult (iCode *ic)
2001 operand *left = IC_LEFT(ic);
2002 operand *right = IC_RIGHT(ic);
2003 operand *result= IC_RESULT(ic);
2005 /* assign the amsops */
2006 aopOp (left,ic,FALSE);
2007 aopOp (right,ic,FALSE);
2008 aopOp (result,ic,TRUE);
2010 /* if both are of size == 1 */
2011 if (AOP_SIZE(left) == 1 &&
2012 AOP_SIZE(right) == 1 ) {
2013 genMultOneByte(left,right,result);
2017 /* should have been converted to function call */
2021 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2022 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2023 freeAsmop(result,NULL,ic,TRUE);
2026 /*-----------------------------------------------------------------*/
2027 /* genDiv - generates code for division */
2028 /*-----------------------------------------------------------------*/
2029 static void genDiv (iCode *ic)
2031 /* should have been converted to function call */
2035 /*-----------------------------------------------------------------*/
2036 /* genMod - generates code for division */
2037 /*-----------------------------------------------------------------*/
2038 static void genMod (iCode *ic)
2040 /* should have been converted to function call */
2052 /*-----------------------------------------------------------------*/
2053 /* revavrcnd - reverse a conditional for avr */
2054 /*-----------------------------------------------------------------*/
2055 static int revavrcnd(int type)
2059 } rar[] = { { AVR_EQ, AVR_NE}, {AVR_LT, AVR_GE}};
2062 for (i = 0 ; i < (sizeof(rar)/sizeof(rar[0]));i++) {
2063 if (rar[i].type == type) return rar[i].rtype;
2064 if (rar[i].rtype== type) return rar[i].type;
2066 assert(1); /* cannot happen */
2069 static char *br_name[4] = {"breq","brne","brlt","brge"};
2070 static char *br_uname[4]= {"breq","brne","brlo","brcc"};
2072 /*-----------------------------------------------------------------*/
2073 /* genBranch - generate the branch instruction */
2074 /*-----------------------------------------------------------------*/
2075 static void genBranch (iCode *ifx, int br_type, int sign)
2077 int tj = (IC_TRUE(ifx) ? 1 : 0) ;
2079 if (tj) { /* if true jump */
2080 char *nm = (sign ? br_name[br_type] : br_uname[br_type]);
2081 emitcode(nm,"L%05d",IC_TRUE(ifx)->key);
2082 } else { /* if false jump */
2083 int rtype = revavrcnd(br_type);
2084 char *nm = (sign ? br_name[rtype] : br_uname[rtype]);
2085 emitcode(nm,"L%05d",IC_FALSE(ifx)->key);
2090 /*-----------------------------------------------------------------*/
2091 /* genCmp - compare & jump */
2092 /*-----------------------------------------------------------------*/
2093 static void genCmp (iCode *ic, iCode *ifx, int br_type)
2095 operand *left, *right, *result;
2096 link *letype , *retype;
2098 int sign, size, offset =0;
2101 right= IC_RIGHT(ic);
2102 result = IC_RESULT(ic);
2104 letype = getSpec(operandType(left));
2105 retype =getSpec(operandType(right));
2106 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2108 /* assign the amsops */
2109 aopOp (left,ic,FALSE);
2110 aopOp (right,ic,FALSE);
2111 aopOp (result,ic,TRUE);
2112 size = AOP_SIZE(left);
2116 if (AOP_TYPE(right) == AOP_LIT) {
2117 emitcode("cpi","%s,lo8(%d)",aopGet(AOP(left),0),
2118 (int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
2119 genBranch(ifx,br_type,sign);
2120 } else { /* right != literal */
2121 emitcode("cp","%s,%s",aopGet(AOP(left),0),aopGet(AOP(right),0));
2122 genBranch(ifx,br_type,sign);
2124 } else { /* size != 1 */
2127 emitcode("cp","%s,%s",aopGet(AOP(left),0),aopGet(AOP(right),0));
2129 emitcode("cpc","%s,%s",aopGet(AOP(left),offset),aopGet(AOP(right),offset));
2132 genBranch(ifx,br_type,sign);
2134 } else { /* no ifx */
2135 emitcode("clr","r0");
2138 emitcode("cp","%s,%s",aopGet(AOP(left),0),aopGet(AOP(right),0));
2140 emitcode("cpc","%s,%s",aopGet(AOP(left),offset),aopGet(AOP(right),offset));
2143 lbl = newiTempLabel(NULL);
2144 br_type = revavrcnd(br_type);
2145 if (sign) emitcode(br_uname[br_type],"L%05d",lbl->key);
2146 else emitcode(br_name[br_type],"L%05d",lbl->key);
2147 emitcode("inc","r0");
2148 emitcode("","L%05d:",lbl->key);
2149 aopPut(AOP(result),"r0",0);
2150 size = AOP_SIZE(result) - 1;
2152 while (size--) aopPut(AOP(result),zero,offset++);
2155 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2156 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2157 freeAsmop(result,NULL,ic,TRUE);
2160 /*-----------------------------------------------------------------*/
2161 /* genCmpGt :- greater than comparison */
2162 /*-----------------------------------------------------------------*/
2163 static void genCmpGt (iCode *ic, iCode *ifx)
2165 /* should have transformed by the parser */
2169 /*-----------------------------------------------------------------*/
2170 /* genCmpLt - less than comparisons */
2171 /*-----------------------------------------------------------------*/
2172 static void genCmpLt (iCode *ic, iCode *ifx)
2174 genCmp(ic,ifx,AVR_LT);
2177 /*-----------------------------------------------------------------*/
2178 /* genCmpEq - generates code for equal to */
2179 /*-----------------------------------------------------------------*/
2180 static void genCmpEq (iCode *ic, iCode *ifx)
2182 genCmp(ic,ifx,AVR_EQ);
2185 /*-----------------------------------------------------------------*/
2186 /* genCmpNe - generates code for not equal to */
2187 /*-----------------------------------------------------------------*/
2188 static void genCmpNe (iCode *ic, iCode *ifx)
2190 genCmp(ic,ifx,AVR_NE);
2193 /*-----------------------------------------------------------------*/
2194 /* genCmpGe - generates code for greater than equal to */
2195 /*-----------------------------------------------------------------*/
2196 static void genCmpGe (iCode *ic, iCode *ifx)
2198 genCmp(ic,ifx,AVR_GE);
2201 /*-----------------------------------------------------------------*/
2202 /* genCmpLe - generates code for less than equal to */
2203 /*-----------------------------------------------------------------*/
2204 static void genCmpLe (iCode *ic, iCode *ifx)
2206 operand *left = IC_LEFT(ic);
2207 operand *right= IC_RIGHT(ic);
2209 IC_RIGHT(ic) = left;
2210 IC_LEFT(ic) = right;
2211 genCmp(ic,ifx,AVR_GE);
2214 /*-----------------------------------------------------------------*/
2215 /* ifxForOp - returns the icode containing the ifx for operand */
2216 /*-----------------------------------------------------------------*/
2217 static iCode *ifxForOp ( operand *op, iCode *ic )
2219 /* if true symbol then needs to be assigned */
2220 if (IS_TRUE_SYMOP(op))
2223 /* if this has register type condition and
2224 the next instruction is ifx with the same operand
2225 and live to of the operand is upto the ifx only then */
2227 ic->next->op == IFX &&
2228 IC_COND(ic->next)->key == op->key &&
2229 OP_SYMBOL(op)->liveTo <= ic->next->seq )
2234 /*-----------------------------------------------------------------*/
2235 /* genAndOp - for && operation */
2236 /*-----------------------------------------------------------------*/
2237 static void genAndOp (iCode *ic)
2239 operand *left,*right, *result;
2243 /* note here that && operations that are in an
2244 if statement are taken away by backPatchLabels
2245 only those used in arthmetic operations remain */
2246 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2247 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2248 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2250 tlbl = newiTempLabel(NULL);
2251 toBoolean(left,"r0",TRUE);
2252 toBoolean(right,"r1",TRUE);
2253 emitcode("and","r0,r1");
2254 emitcode("ldi","r24,1");
2255 emitcode("breq","L%05d",tlbl->key);
2256 emitcode("dec","r24");
2257 emitcode("","L%05d:",tlbl->key);
2258 aopPut(AOP(result),"r24",0);
2259 size = AOP_SIZE(result) -1;
2261 while (size--) aopPut(AOP(result),zero,offset++);
2263 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2264 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2265 freeAsmop(result,NULL,ic,TRUE);
2269 /*-----------------------------------------------------------------*/
2270 /* genOrOp - for || operation */
2271 /*-----------------------------------------------------------------*/
2272 static void genOrOp (iCode *ic)
2274 operand *left,*right, *result;
2278 /* note here that || operations that are in an
2279 if statement are taken away by backPatchLabels
2280 only those used in arthmetic operations remain */
2281 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2282 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2283 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2285 tlbl = newiTempLabel(NULL);
2286 toBoolean(left,"r0",TRUE);
2287 toBoolean(right,"r0",FALSE);
2288 emitcode("ldi","r24,1");
2289 emitcode("breq","L%05d",tlbl->key);
2290 emitcode("dec","r24");
2291 emitcode("","L%05d:",tlbl->key);
2292 aopPut(AOP(result),"r24",0);
2293 size = AOP_SIZE(result) -1;
2295 while (size--) aopPut(AOP(result),zero,offset++);
2297 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2298 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2299 freeAsmop(result,NULL,ic,TRUE);
2302 /*-----------------------------------------------------------------*/
2303 /* isLiteralBit - test if lit == 2^n */
2304 /*-----------------------------------------------------------------*/
2305 static int isLiteralBit(unsigned long lit)
2307 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
2308 0x100L,0x200L,0x400L,0x800L,
2309 0x1000L,0x2000L,0x4000L,0x8000L,
2310 0x10000L,0x20000L,0x40000L,0x80000L,
2311 0x100000L,0x200000L,0x400000L,0x800000L,
2312 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
2313 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
2316 for(idx = 0; idx < 32; idx++)
2323 /*-----------------------------------------------------------------*/
2324 /* genAnd - code for and */
2325 /*-----------------------------------------------------------------*/
2326 static void genAnd (iCode *ic, iCode *ifx)
2328 operand *left, *right, *result;
2332 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2333 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2334 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2336 size = AOP_SIZE(left);
2338 if (ifx) { /* used only for jumps */
2339 if (AOP_TYPE(right) == AOP_LIT) {
2340 int p2 = powof2((int) floatFromVal (AOP(right)->aopu.aop_lit));
2341 if (p2) { /* right side is a power of 2 */
2342 l = aopGet(AOP(left),p2 / 8);
2344 emitcode("sbrc","%s,%d",l,(p2 % 8));
2345 emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2347 emitcode("sbrs","%s,%d",l,(p2 % 8));
2348 emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2350 } else { /* right not power of two */
2354 } else { /* right is not a literal */
2356 } else { /* other jump -> result goes to register*/
2360 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2361 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2362 freeAsmop(result,NULL,ic,TRUE);
2365 /*-----------------------------------------------------------------*/
2366 /* genOr - code for or */
2367 /*-----------------------------------------------------------------*/
2368 static void genOr (iCode *ic, iCode *ifx)
2370 operand *left, *right, *result;
2372 unsigned long lit = 0L;
2374 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2375 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2376 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2380 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2381 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2382 freeAsmop(result,NULL,ic,TRUE);
2385 /*-----------------------------------------------------------------*/
2386 /* genXor - code for xclusive or */
2387 /*-----------------------------------------------------------------*/
2388 static void genXor (iCode *ic, iCode *ifx)
2390 operand *left, *right, *result;
2392 unsigned long lit = 0L;
2394 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2395 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2396 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2401 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2402 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2403 freeAsmop(result,NULL,ic,TRUE);
2406 /*-----------------------------------------------------------------*/
2407 /* genInline - write the inline code out */
2408 /*-----------------------------------------------------------------*/
2409 static void genInline (iCode *ic)
2411 char buffer[MAX_INLINEASM];
2415 _G.inLine += (!options.asmpeep);
2416 strcpy(buffer,IC_INLINE(ic));
2418 /* emit each line as a code */
2437 /* emitcode("",buffer); */
2438 _G.inLine -= (!options.asmpeep);
2441 /*-----------------------------------------------------------------*/
2442 /* genRRC - rotate right with carry */
2443 /*-----------------------------------------------------------------*/
2444 static void genRRC (iCode *ic)
2446 operand *left , *result ;
2447 int size, offset = 0;
2450 /* rotate right with carry */
2452 result=IC_RESULT(ic);
2453 aopOp (left,ic,FALSE);
2454 aopOp (result,ic,FALSE);
2456 /* move it to the result */
2457 size = AOP_SIZE(result);
2461 freeAsmop(left,NULL,ic,TRUE);
2462 freeAsmop(result,NULL,ic,TRUE);
2465 /*-----------------------------------------------------------------*/
2466 /* genRLC - generate code for rotate left with carry */
2467 /*-----------------------------------------------------------------*/
2468 static void genRLC (iCode *ic)
2470 operand *left , *result ;
2471 int size, offset = 0;
2474 /* rotate right with carry */
2476 result=IC_RESULT(ic);
2477 aopOp (left,ic,FALSE);
2478 aopOp (result,ic,FALSE);
2481 freeAsmop(left,NULL,ic,TRUE);
2482 freeAsmop(result,NULL,ic,TRUE);
2485 /*-----------------------------------------------------------------*/
2486 /* genGetHbit - generates code get highest order bit */
2487 /*-----------------------------------------------------------------*/
2488 static void genGetHbit (iCode *ic)
2490 operand *left, *result;
2492 result=IC_RESULT(ic);
2493 aopOp (left,ic,FALSE);
2494 aopOp (result,ic,FALSE);
2497 freeAsmop(left,NULL,ic,TRUE);
2498 freeAsmop(result,NULL,ic,TRUE);
2501 /*-----------------------------------------------------------------*/
2502 /* AccRol - rotate left accumulator by known count */
2503 /*-----------------------------------------------------------------*/
2504 static void AccRol (int shCount)
2506 shCount &= 0x0007; // shCount : 0..7
2518 emitcode("swap","a");
2522 emitcode("swap","a");
2525 emitcode("swap","a");
2538 /*-----------------------------------------------------------------*/
2539 /* AccLsh - left shift accumulator by known count */
2540 /*-----------------------------------------------------------------*/
2541 static void AccLsh (int shCount)
2545 emitcode("add","a,acc");
2548 emitcode("add","a,acc");
2549 emitcode("add","a,acc");
2551 /* rotate left accumulator */
2553 /* and kill the lower order bits */
2554 emitcode("anl","a,#0x%02x", SLMask[shCount]);
2559 /*-----------------------------------------------------------------*/
2560 /* AccRsh - right shift accumulator by known count */
2561 /*-----------------------------------------------------------------*/
2562 static void AccRsh (int shCount)
2567 emitcode("rrc","a");
2569 /* rotate right accumulator */
2570 AccRol(8 - shCount);
2571 /* and kill the higher order bits */
2572 emitcode("anl","a,#0x%02x", SRMask[shCount]);
2577 /*-----------------------------------------------------------------*/
2578 /* AccSRsh - signed right shift accumulator by known count */
2579 /*-----------------------------------------------------------------*/
2580 static void AccSRsh (int shCount)
2585 emitcode("mov","c,acc.7");
2586 emitcode("rrc","a");
2587 } else if(shCount == 2){
2588 emitcode("mov","c,acc.7");
2589 emitcode("rrc","a");
2590 emitcode("mov","c,acc.7");
2591 emitcode("rrc","a");
2593 tlbl = newiTempLabel(NULL);
2594 /* rotate right accumulator */
2595 AccRol(8 - shCount);
2596 /* and kill the higher order bits */
2597 emitcode("anl","a,#0x%02x", SRMask[shCount]);
2598 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
2599 emitcode("orl","a,#0x%02x",
2600 (unsigned char)~SRMask[shCount]);
2601 emitcode("","%05d$:",tlbl->key+100);
2606 /*-----------------------------------------------------------------*/
2607 /* shiftR1Left2Result - shift right one byte from left to result */
2608 /*-----------------------------------------------------------------*/
2609 static void shiftR1Left2Result (operand *left, int offl,
2610 operand *result, int offr,
2611 int shCount, int sign)
2613 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
2614 /* shift right accumulator */
2619 aopPut(AOP(result),"a",offr);
2622 /*-----------------------------------------------------------------*/
2623 /* shiftL1Left2Result - shift left one byte from left to result */
2624 /*-----------------------------------------------------------------*/
2625 static void shiftL1Left2Result (operand *left, int offl,
2626 operand *result, int offr, int shCount)
2629 l = aopGet(AOP(left),offl);
2631 /* shift left accumulator */
2633 aopPut(AOP(result),"a",offr);
2636 /*-----------------------------------------------------------------*/
2637 /* movLeft2Result - move byte from left to result */
2638 /*-----------------------------------------------------------------*/
2639 static void movLeft2Result (operand *left, int offl,
2640 operand *result, int offr, int sign)
2643 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
2644 l = aopGet(AOP(left),offl);
2646 if (*l == '@' && (IS_AOP_PREG(result))) {
2647 emitcode("mov","a,%s",l);
2648 aopPut(AOP(result),"a",offr);
2651 aopPut(AOP(result),l,offr);
2653 /* MSB sign in acc.7 ! */
2654 if(getDataSize(left) == offl+1){
2655 emitcode("mov","a,%s",l);
2656 aopPut(AOP(result),"a",offr);
2663 /*-----------------------------------------------------------------*/
2664 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
2665 /*-----------------------------------------------------------------*/
2666 static void AccAXRrl1 (char *x)
2668 emitcode("rrc","a");
2669 emitcode("xch","a,%s", x);
2670 emitcode("rrc","a");
2671 emitcode("xch","a,%s", x);
2674 /*-----------------------------------------------------------------*/
2675 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
2676 /*-----------------------------------------------------------------*/
2677 static void AccAXLrl1 (char *x)
2679 emitcode("xch","a,%s",x);
2680 emitcode("rlc","a");
2681 emitcode("xch","a,%s",x);
2682 emitcode("rlc","a");
2685 /*-----------------------------------------------------------------*/
2686 /* AccAXLsh1 - left shift a:x<-0 by 1 */
2687 /*-----------------------------------------------------------------*/
2688 static void AccAXLsh1 (char *x)
2690 emitcode("xch","a,%s",x);
2691 emitcode("add","a,acc");
2692 emitcode("xch","a,%s",x);
2693 emitcode("rlc","a");
2696 /*-----------------------------------------------------------------*/
2697 /* AccAXLsh - left shift a:x by known count (0..7) */
2698 /*-----------------------------------------------------------------*/
2699 static void AccAXLsh (char *x, int shCount)
2713 case 5 : // AAAAABBB:CCCCCDDD
2714 AccRol(shCount); // BBBAAAAA:CCCCCDDD
2715 emitcode("anl","a,#0x%02x",
2716 SLMask[shCount]); // BBB00000:CCCCCDDD
2717 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
2718 AccRol(shCount); // DDDCCCCC:BBB00000
2719 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
2720 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
2721 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
2722 emitcode("anl","a,#0x%02x",
2723 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
2724 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
2725 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
2727 case 6 : // AAAAAABB:CCCCCCDD
2728 emitcode("anl","a,#0x%02x",
2729 SRMask[shCount]); // 000000BB:CCCCCCDD
2730 emitcode("mov","c,acc.0"); // c = B
2731 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
2732 AccAXRrl1(x); // BCCCCCCD:D000000B
2733 AccAXRrl1(x); // BBCCCCCC:DD000000
2735 case 7 : // a:x <<= 7
2736 emitcode("anl","a,#0x%02x",
2737 SRMask[shCount]); // 0000000B:CCCCCCCD
2738 emitcode("mov","c,acc.0"); // c = B
2739 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
2740 AccAXRrl1(x); // BCCCCCCC:D0000000
2747 /*-----------------------------------------------------------------*/
2748 /* AccAXRsh - right shift a:x known count (0..7) */
2749 /*-----------------------------------------------------------------*/
2750 static void AccAXRsh (char *x, int shCount)
2757 AccAXRrl1(x); // 0->a:x
2761 AccAXRrl1(x); // 0->a:x
2763 AccAXRrl1(x); // 0->a:x
2767 case 5 : // AAAAABBB:CCCCCDDD = a:x
2768 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
2769 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
2770 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
2771 emitcode("anl","a,#0x%02x",
2772 SRMask[shCount]); // 000CCCCC:BBBAAAAA
2773 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
2774 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
2775 emitcode("anl","a,#0x%02x",
2776 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
2777 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
2778 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
2779 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
2781 case 6 : // AABBBBBB:CCDDDDDD
2782 emitcode("mov","c,acc.7");
2783 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
2784 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
2785 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
2786 emitcode("anl","a,#0x%02x",
2787 SRMask[shCount]); // 000000AA:BBBBBBCC
2789 case 7 : // ABBBBBBB:CDDDDDDD
2790 emitcode("mov","c,acc.7"); // c = A
2791 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
2792 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
2793 emitcode("anl","a,#0x%02x",
2794 SRMask[shCount]); // 0000000A:BBBBBBBC
2801 /*-----------------------------------------------------------------*/
2802 /* AccAXRshS - right shift signed a:x known count (0..7) */
2803 /*-----------------------------------------------------------------*/
2804 static void AccAXRshS (char *x, int shCount)
2811 emitcode("mov","c,acc.7");
2812 AccAXRrl1(x); // s->a:x
2815 emitcode("mov","c,acc.7");
2816 AccAXRrl1(x); // s->a:x
2817 emitcode("mov","c,acc.7");
2818 AccAXRrl1(x); // s->a:x
2822 case 5 : // AAAAABBB:CCCCCDDD = a:x
2823 tlbl = newiTempLabel(NULL);
2824 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
2825 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
2826 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
2827 emitcode("anl","a,#0x%02x",
2828 SRMask[shCount]); // 000CCCCC:BBBAAAAA
2829 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
2830 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
2831 emitcode("anl","a,#0x%02x",
2832 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
2833 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
2834 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
2835 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
2836 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
2837 emitcode("orl","a,#0x%02x",
2838 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
2839 emitcode("","%05d$:",tlbl->key+100);
2840 break; // SSSSAAAA:BBBCCCCC
2841 case 6 : // AABBBBBB:CCDDDDDD
2842 tlbl = newiTempLabel(NULL);
2843 emitcode("mov","c,acc.7");
2844 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
2845 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
2846 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
2847 emitcode("anl","a,#0x%02x",
2848 SRMask[shCount]); // 000000AA:BBBBBBCC
2849 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
2850 emitcode("orl","a,#0x%02x",
2851 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
2852 emitcode("","%05d$:",tlbl->key+100);
2854 case 7 : // ABBBBBBB:CDDDDDDD
2855 tlbl = newiTempLabel(NULL);
2856 emitcode("mov","c,acc.7"); // c = A
2857 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
2858 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
2859 emitcode("anl","a,#0x%02x",
2860 SRMask[shCount]); // 0000000A:BBBBBBBC
2861 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
2862 emitcode("orl","a,#0x%02x",
2863 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
2864 emitcode("","%05d$:",tlbl->key+100);
2871 /*-----------------------------------------------------------------*/
2872 /* shiftL2Left2Result - shift left two bytes from left to result */
2873 /*-----------------------------------------------------------------*/
2874 static void shiftL2Left2Result (operand *left, int offl,
2875 operand *result, int offr, int shCount)
2877 if(sameRegs(AOP(result), AOP(left)) &&
2878 ((offl + MSB16) == offr)){
2879 /* don't crash result[offr] */
2880 // MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
2881 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16));
2883 movLeft2Result(left,offl, result, offr, 0);
2884 MOVA(aopGet(AOP(left),offl+MSB16));
2886 /* ax << shCount (x = lsb(result))*/
2887 AccAXLsh( aopGet(AOP(result),offr) , shCount);
2888 aopPut(AOP(result),"a",offr+MSB16);
2892 /*-----------------------------------------------------------------*/
2893 /* shiftR2Left2Result - shift right two bytes from left to result */
2894 /*-----------------------------------------------------------------*/
2895 static void shiftR2Left2Result (operand *left, int offl,
2896 operand *result, int offr,
2897 int shCount, int sign)
2899 if(sameRegs(AOP(result), AOP(left)) &&
2900 ((offl + MSB16) == offr)){
2901 /* don't crash result[offr] */
2902 // MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
2903 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16));
2905 movLeft2Result(left,offl, result, offr, 0);
2906 // MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
2908 /* a:x >> shCount (x = lsb(result))*/
2910 AccAXRshS( aopGet(AOP(result),offr) , shCount);
2912 AccAXRsh( aopGet(AOP(result),offr) , shCount);
2913 if(getDataSize(result) > 1)
2914 aopPut(AOP(result),"a",offr+MSB16);
2917 /*-----------------------------------------------------------------*/
2918 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
2919 /*-----------------------------------------------------------------*/
2920 static void shiftLLeftOrResult (operand *left, int offl,
2921 operand *result, int offr, int shCount)
2923 // MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
2924 /* shift left accumulator */
2926 /* or with result */
2927 emitcode("orl","a,%s", aopGet(AOP(result),offr));
2928 /* back to result */
2929 aopPut(AOP(result),"a",offr);
2932 /*-----------------------------------------------------------------*/
2933 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
2934 /*-----------------------------------------------------------------*/
2935 static void shiftRLeftOrResult (operand *left, int offl,
2936 operand *result, int offr, int shCount)
2938 // MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
2939 /* shift right accumulator */
2941 /* or with result */
2942 emitcode("orl","a,%s", aopGet(AOP(result),offr));
2943 /* back to result */
2944 aopPut(AOP(result),"a",offr);
2947 /*-----------------------------------------------------------------*/
2948 /* genlshOne - left shift a one byte quantity by known count */
2949 /*-----------------------------------------------------------------*/
2950 static void genlshOne (operand *result, operand *left, int shCount)
2952 shiftL1Left2Result(left, LSB, result, LSB, shCount);
2955 /*-----------------------------------------------------------------*/
2956 /* genlshTwo - left shift two bytes by known amount != 0 */
2957 /*-----------------------------------------------------------------*/
2958 static void genlshTwo (operand *result,operand *left, int shCount)
2962 size = getDataSize(result);
2964 /* if shCount >= 8 */
2970 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
2972 movLeft2Result(left, LSB, result, MSB16, 0);
2974 aopPut(AOP(result),zero,LSB);
2977 /* 1 <= shCount <= 7 */
2980 shiftL1Left2Result(left, LSB, result, LSB, shCount);
2982 shiftL2Left2Result(left, LSB, result, LSB, shCount);
2986 /*-----------------------------------------------------------------*/
2987 /* shiftLLong - shift left one long from left to result */
2988 /* offl = LSB or MSB16 */
2989 /*-----------------------------------------------------------------*/
2990 static void shiftLLong (operand *left, operand *result, int offr )
2993 int size = AOP_SIZE(result);
2995 if(size >= LSB+offr){
2996 l = aopGet(AOP(left),LSB);
2998 emitcode("add","a,acc");
2999 if (sameRegs(AOP(left),AOP(result)) &&
3000 size >= MSB16+offr && offr != LSB )
3001 emitcode("xch","a,%s",
3002 aopGet(AOP(left),LSB+offr));
3004 aopPut(AOP(result),"a",LSB+offr);
3007 if(size >= MSB16+offr){
3008 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
3009 l = aopGet(AOP(left),MSB16);
3012 emitcode("rlc","a");
3013 if (sameRegs(AOP(left),AOP(result)) &&
3014 size >= MSB24+offr && offr != LSB)
3015 emitcode("xch","a,%s",
3016 aopGet(AOP(left),MSB16+offr));
3018 aopPut(AOP(result),"a",MSB16+offr);
3021 if(size >= MSB24+offr){
3022 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
3023 l = aopGet(AOP(left),MSB24);
3026 emitcode("rlc","a");
3027 if (sameRegs(AOP(left),AOP(result)) &&
3028 size >= MSB32+offr && offr != LSB )
3029 emitcode("xch","a,%s",
3030 aopGet(AOP(left),MSB24+offr));
3032 aopPut(AOP(result),"a",MSB24+offr);
3035 if(size > MSB32+offr){
3036 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
3037 l = aopGet(AOP(left),MSB32);
3040 emitcode("rlc","a");
3041 aopPut(AOP(result),"a",MSB32+offr);
3044 aopPut(AOP(result),zero,LSB);
3047 /*-----------------------------------------------------------------*/
3048 /* genlshFour - shift four byte by a known amount != 0 */
3049 /*-----------------------------------------------------------------*/
3050 static void genlshFour (operand *result, operand *left, int shCount)
3054 size = AOP_SIZE(result);
3056 /* if shifting more that 3 bytes */
3057 if (shCount >= 24 ) {
3060 /* lowest order of left goes to the highest
3061 order of the destination */
3062 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
3064 movLeft2Result(left, LSB, result, MSB32, 0);
3065 aopPut(AOP(result),zero,LSB);
3066 aopPut(AOP(result),zero,MSB16);
3067 aopPut(AOP(result),zero,MSB32);
3071 /* more than two bytes */
3072 else if ( shCount >= 16 ) {
3073 /* lower order two bytes goes to higher order two bytes */
3075 /* if some more remaining */
3077 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
3079 movLeft2Result(left, MSB16, result, MSB32, 0);
3080 movLeft2Result(left, LSB, result, MSB24, 0);
3082 aopPut(AOP(result),zero,MSB16);
3083 aopPut(AOP(result),zero,LSB);
3087 /* if more than 1 byte */
3088 else if ( shCount >= 8 ) {
3089 /* lower order three bytes goes to higher order three bytes */
3093 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
3095 movLeft2Result(left, LSB, result, MSB16, 0);
3097 else{ /* size = 4 */
3099 movLeft2Result(left, MSB24, result, MSB32, 0);
3100 movLeft2Result(left, MSB16, result, MSB24, 0);
3101 movLeft2Result(left, LSB, result, MSB16, 0);
3102 aopPut(AOP(result),zero,LSB);
3104 else if(shCount == 1)
3105 shiftLLong(left, result, MSB16);
3107 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
3108 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
3109 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
3110 aopPut(AOP(result),zero,LSB);
3115 /* 1 <= shCount <= 7 */
3116 else if(shCount <= 2){
3117 shiftLLong(left, result, LSB);
3119 shiftLLong(result, result, LSB);
3121 /* 3 <= shCount <= 7, optimize */
3123 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
3124 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
3125 shiftL2Left2Result(left, LSB, result, LSB, shCount);
3129 /*-----------------------------------------------------------------*/
3130 /* genLeftShiftLiteral - left shifting by known count */
3131 /*-----------------------------------------------------------------*/
3132 static void genLeftShiftLiteral (operand *left,
3137 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3140 freeAsmop(right,NULL,ic,TRUE);
3142 aopOp(left,ic,FALSE);
3143 aopOp(result,ic,FALSE);
3145 size = getSize(operandType(result));
3148 emitcode("; shift left ","result %d, left %d",size,
3152 /* I suppose that the left size >= result size */
3155 movLeft2Result(left, size, result, size, 0);
3159 else if(shCount >= (size * 8))
3161 aopPut(AOP(result),zero,size);
3165 genlshOne (result,left,shCount);
3170 genlshTwo (result,left,shCount);
3174 genlshFour (result,left,shCount);
3178 freeAsmop(left,NULL,ic,TRUE);
3179 freeAsmop(result,NULL,ic,TRUE);
3182 /*-----------------------------------------------------------------*/
3183 /* genLeftShift - generates code for left shifting */
3184 /*-----------------------------------------------------------------*/
3185 static void genLeftShift (iCode *ic)
3187 operand *left,*right, *result;
3190 symbol *tlbl , *tlbl1;
3192 right = IC_RIGHT(ic);
3194 result = IC_RESULT(ic);
3196 aopOp(right,ic,FALSE);
3198 /* if the shift count is known then do it
3199 as efficiently as possible */
3200 if (AOP_TYPE(right) == AOP_LIT) {
3201 genLeftShiftLiteral (left,right,result,ic);
3205 /* shift count is unknown then we have to form
3206 a loop get the loop count in B : Note: we take
3207 only the lower order byte since shifting
3208 more that 32 bits make no sense anyway, ( the
3209 largest size of an object can be only 32 bits ) */
3211 emitcode("mov","b,%s",aopGet(AOP(right),0));
3212 emitcode("inc","b");
3213 freeAsmop (right,NULL,ic,TRUE);
3214 aopOp(left,ic,FALSE);
3215 aopOp(result,ic,FALSE);
3217 /* now move the left to the result if they are not the
3219 if (!sameRegs(AOP(left),AOP(result)) &&
3220 AOP_SIZE(result) > 1) {
3222 size = AOP_SIZE(result);
3225 l = aopGet(AOP(left),offset);
3226 if (*l == '@' && (IS_AOP_PREG(result))) {
3228 emitcode("mov","a,%s",l);
3229 aopPut(AOP(result),"a",offset);
3231 aopPut(AOP(result),l,offset);
3236 tlbl = newiTempLabel(NULL);
3237 size = AOP_SIZE(result);
3239 tlbl1 = newiTempLabel(NULL);
3241 /* if it is only one byte then */
3243 symbol *tlbl1 = newiTempLabel(NULL);
3245 l = aopGet(AOP(left),0);
3247 emitcode("sjmp","%05d$",tlbl1->key+100);
3248 emitcode("","%05d$:",tlbl->key+100);
3249 emitcode("add","a,acc");
3250 emitcode("","%05d$:",tlbl1->key+100);
3251 emitcode("djnz","b,%05d$",tlbl->key+100);
3252 aopPut(AOP(result),"a",0);
3256 reAdjustPreg(AOP(result));
3258 emitcode("sjmp","%05d$",tlbl1->key+100);
3259 emitcode("","%05d$:",tlbl->key+100);
3260 l = aopGet(AOP(result),offset);
3262 emitcode("add","a,acc");
3263 aopPut(AOP(result),"a",offset++);
3265 l = aopGet(AOP(result),offset);
3267 emitcode("rlc","a");
3268 aopPut(AOP(result),"a",offset++);
3270 reAdjustPreg(AOP(result));
3272 emitcode("","%05d$:",tlbl1->key+100);
3273 emitcode("djnz","b,%05d$",tlbl->key+100);
3275 freeAsmop(left,NULL,ic,TRUE);
3276 freeAsmop(result,NULL,ic,TRUE);
3279 /*-----------------------------------------------------------------*/
3280 /* genrshOne - right shift a one byte quantity by known count */
3281 /*-----------------------------------------------------------------*/
3282 static void genrshOne (operand *result, operand *left,
3283 int shCount, int sign)
3285 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
3288 /*-----------------------------------------------------------------*/
3289 /* genrshTwo - right shift two bytes by known amount != 0 */
3290 /*-----------------------------------------------------------------*/
3291 static void genrshTwo (operand *result,operand *left,
3292 int shCount, int sign)
3294 /* if shCount >= 8 */
3298 shiftR1Left2Result(left, MSB16, result, LSB,
3301 movLeft2Result(left, MSB16, result, LSB, sign);
3302 addSign(result, MSB16, sign);
3305 /* 1 <= shCount <= 7 */
3307 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
3310 /*-----------------------------------------------------------------*/
3311 /* shiftRLong - shift right one long from left to result */
3312 /* offl = LSB or MSB16 */
3313 /*-----------------------------------------------------------------*/
3314 static void shiftRLong (operand *left, int offl,
3315 operand *result, int sign)
3318 emitcode("clr","c");
3319 MOVA(aopGet(AOP(left),MSB32));
3321 emitcode("mov","c,acc.7");
3322 emitcode("rrc","a");
3323 aopPut(AOP(result),"a",MSB32-offl);
3325 /* add sign of "a" */
3326 addSign(result, MSB32, sign);
3328 MOVA(aopGet(AOP(left),MSB24));
3329 emitcode("rrc","a");
3330 aopPut(AOP(result),"a",MSB24-offl);
3332 MOVA(aopGet(AOP(left),MSB16));
3333 emitcode("rrc","a");
3334 aopPut(AOP(result),"a",MSB16-offl);
3337 MOVA(aopGet(AOP(left),LSB));
3338 emitcode("rrc","a");
3339 aopPut(AOP(result),"a",LSB);
3343 /*-----------------------------------------------------------------*/
3344 /* genrshFour - shift four byte by a known amount != 0 */
3345 /*-----------------------------------------------------------------*/
3346 static void genrshFour (operand *result, operand *left,
3347 int shCount, int sign)
3349 /* if shifting more that 3 bytes */
3350 if(shCount >= 24 ) {
3353 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
3355 movLeft2Result(left, MSB32, result, LSB, sign);
3356 addSign(result, MSB16, sign);
3358 else if(shCount >= 16){
3361 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
3363 movLeft2Result(left, MSB24, result, LSB, 0);
3364 movLeft2Result(left, MSB32, result, MSB16, sign);
3366 addSign(result, MSB24, sign);
3368 else if(shCount >= 8){
3371 shiftRLong(left, MSB16, result, sign);
3372 else if(shCount == 0){
3373 movLeft2Result(left, MSB16, result, LSB, 0);
3374 movLeft2Result(left, MSB24, result, MSB16, 0);
3375 movLeft2Result(left, MSB32, result, MSB24, sign);
3376 addSign(result, MSB32, sign);
3379 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
3380 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
3381 /* the last shift is signed */
3382 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
3383 addSign(result, MSB32, sign);
3386 else{ /* 1 <= shCount <= 7 */
3388 shiftRLong(left, LSB, result, sign);
3390 shiftRLong(result, LSB, result, sign);
3393 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
3394 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
3395 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
3400 /*-----------------------------------------------------------------*/
3401 /* genRightShiftLiteral - right shifting by known count */
3402 /*-----------------------------------------------------------------*/
3403 static void genRightShiftLiteral (operand *left,
3409 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3412 freeAsmop(right,NULL,ic,TRUE);
3414 aopOp(left,ic,FALSE);
3415 aopOp(result,ic,FALSE);
3418 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
3422 size = getDataSize(left);
3423 /* test the LEFT size !!! */
3425 /* I suppose that the left size >= result size */
3427 size = getDataSize(result);
3429 movLeft2Result(left, size, result, size, 0);
3432 else if(shCount >= (size * 8)){
3434 /* get sign in acc.7 */
3435 MOVA(aopGet(AOP(left),size-1));
3436 addSign(result, LSB, sign);
3440 genrshOne (result,left,shCount,sign);
3444 genrshTwo (result,left,shCount,sign);
3448 genrshFour (result,left,shCount,sign);
3454 freeAsmop(left,NULL,ic,TRUE);
3455 freeAsmop(result,NULL,ic,TRUE);
3459 /*-----------------------------------------------------------------*/
3460 /* genSignedRightShift - right shift of signed number */
3461 /*-----------------------------------------------------------------*/
3462 static void genSignedRightShift (iCode *ic)
3464 operand *right, *left, *result;
3467 symbol *tlbl, *tlbl1 ;
3469 /* we do it the hard way put the shift count in b
3470 and loop thru preserving the sign */
3472 right = IC_RIGHT(ic);
3474 result = IC_RESULT(ic);
3476 aopOp(right,ic,FALSE);
3479 if ( AOP_TYPE(right) == AOP_LIT) {
3480 genRightShiftLiteral (left,right,result,ic,1);
3483 /* shift count is unknown then we have to form
3484 a loop get the loop count in B : Note: we take
3485 only the lower order byte since shifting
3486 more that 32 bits make no sense anyway, ( the
3487 largest size of an object can be only 32 bits ) */
3489 emitcode("mov","b,%s",aopGet(AOP(right),0));
3490 emitcode("inc","b");
3491 freeAsmop (right,NULL,ic,TRUE);
3492 aopOp(left,ic,FALSE);
3493 aopOp(result,ic,FALSE);
3495 /* now move the left to the result if they are not the
3497 if (!sameRegs(AOP(left),AOP(result)) &&
3498 AOP_SIZE(result) > 1) {
3500 size = AOP_SIZE(result);
3503 l = aopGet(AOP(left),offset);
3504 if (*l == '@' && IS_AOP_PREG(result)) {
3506 emitcode("mov","a,%s",l);
3507 aopPut(AOP(result),"a",offset);
3509 aopPut(AOP(result),l,offset);
3514 /* mov the highest order bit to OVR */
3515 tlbl = newiTempLabel(NULL);
3516 tlbl1= newiTempLabel(NULL);
3518 size = AOP_SIZE(result);
3520 emitcode("mov","a,%s",aopGet(AOP(left),offset));
3521 emitcode("rlc","a");
3522 emitcode("mov","ov,c");
3523 /* if it is only one byte then */
3525 l = aopGet(AOP(left),0);
3527 emitcode("sjmp","%05d$",tlbl1->key+100);
3528 emitcode("","%05d$:",tlbl->key+100);
3529 emitcode("mov","c,ov");
3530 emitcode("rrc","a");
3531 emitcode("","%05d$:",tlbl1->key+100);
3532 emitcode("djnz","b,%05d$",tlbl->key+100);
3533 aopPut(AOP(result),"a",0);
3537 reAdjustPreg(AOP(result));
3538 emitcode("sjmp","%05d$",tlbl1->key+100);
3539 emitcode("","%05d$:",tlbl->key+100);
3540 emitcode("mov","c,ov");
3542 l = aopGet(AOP(result),offset);
3544 emitcode("rrc","a");
3545 aopPut(AOP(result),"a",offset--);
3547 reAdjustPreg(AOP(result));
3548 emitcode("","%05d$:",tlbl1->key+100);
3549 emitcode("djnz","b,%05d$",tlbl->key+100);
3552 freeAsmop(left,NULL,ic,TRUE);
3553 freeAsmop(result,NULL,ic,TRUE);
3556 /*-----------------------------------------------------------------*/
3557 /* genRightShift - generate code for right shifting */
3558 /*-----------------------------------------------------------------*/
3559 static void genRightShift (iCode *ic)
3561 operand *right, *left, *result;
3565 symbol *tlbl, *tlbl1 ;
3567 /* if signed then we do it the hard way preserve the
3568 sign bit moving it inwards */
3569 retype = getSpec(operandType(IC_RESULT(ic)));
3571 if (!SPEC_USIGN(retype)) {
3572 genSignedRightShift (ic);
3576 /* signed & unsigned types are treated the same : i.e. the
3577 signed is NOT propagated inwards : quoting from the
3578 ANSI - standard : "for E1 >> E2, is equivalent to division
3579 by 2**E2 if unsigned or if it has a non-negative value,
3580 otherwise the result is implementation defined ", MY definition
3581 is that the sign does not get propagated */
3583 right = IC_RIGHT(ic);
3585 result = IC_RESULT(ic);
3587 aopOp(right,ic,FALSE);
3589 /* if the shift count is known then do it
3590 as efficiently as possible */
3591 if (AOP_TYPE(right) == AOP_LIT) {
3592 genRightShiftLiteral (left,right,result,ic, 0);
3596 /* shift count is unknown then we have to form
3597 a loop get the loop count in B : Note: we take
3598 only the lower order byte since shifting
3599 more that 32 bits make no sense anyway, ( the
3600 largest size of an object can be only 32 bits ) */
3602 emitcode("mov","b,%s",aopGet(AOP(right),0));
3603 emitcode("inc","b");
3604 freeAsmop (right,NULL,ic,TRUE);
3605 aopOp(left,ic,FALSE);
3606 aopOp(result,ic,FALSE);
3608 /* now move the left to the result if they are not the
3610 if (!sameRegs(AOP(left),AOP(result)) &&
3611 AOP_SIZE(result) > 1) {
3613 size = AOP_SIZE(result);
3616 l = aopGet(AOP(left),offset);
3617 if (*l == '@' && IS_AOP_PREG(result)) {
3619 emitcode("mov","a,%s",l);
3620 aopPut(AOP(result),"a",offset);
3622 aopPut(AOP(result),l,offset);
3627 tlbl = newiTempLabel(NULL);
3628 tlbl1= newiTempLabel(NULL);
3629 size = AOP_SIZE(result);
3632 /* if it is only one byte then */
3634 l = aopGet(AOP(left),0);
3636 emitcode("sjmp","%05d$",tlbl1->key+100);
3637 emitcode("","%05d$:",tlbl->key+100);
3639 emitcode("rrc","a");
3640 emitcode("","%05d$:",tlbl1->key+100);
3641 emitcode("djnz","b,%05d$",tlbl->key+100);
3642 aopPut(AOP(result),"a",0);
3646 reAdjustPreg(AOP(result));
3647 emitcode("sjmp","%05d$",tlbl1->key+100);
3648 emitcode("","%05d$:",tlbl->key+100);
3651 l = aopGet(AOP(result),offset);
3653 emitcode("rrc","a");
3654 aopPut(AOP(result),"a",offset--);
3656 reAdjustPreg(AOP(result));
3658 emitcode("","%05d$:",tlbl1->key+100);
3659 emitcode("djnz","b,%05d$",tlbl->key+100);
3662 freeAsmop(left,NULL,ic,TRUE);
3663 freeAsmop(result,NULL,ic,TRUE);
3666 /*-----------------------------------------------------------------*/
3667 /* genUnpackBits - generates code for unpacking bits */
3668 /*-----------------------------------------------------------------*/
3669 static void genUnpackBits (operand *result, char *rname, int ptype)
3676 etype = getSpec(operandType(result));
3678 /* read the first byte */
3683 emitcode("mov","a,@%s",rname);
3687 emitcode("movx","a,@%s",rname);
3691 emitcode("movx","a,@dptr");
3695 emitcode("clr","a");
3696 emitcode("movc","a","@a+dptr");
3700 emitcode("lcall","__gptrget");
3704 /* if we have bitdisplacement then it fits */
3705 /* into this byte completely or if length is */
3706 /* less than a byte */
3707 if ((shCnt = SPEC_BSTR(etype)) ||
3708 (SPEC_BLEN(etype) <= 8)) {
3710 /* shift right acc */
3713 emitcode("anl","a,#0x%02x",
3714 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
3715 aopPut(AOP(result),"a",offset);
3719 /* bit field did not fit in a byte */
3720 rlen = SPEC_BLEN(etype) - 8;
3721 aopPut(AOP(result),"a",offset++);
3728 emitcode("inc","%s",rname);
3729 emitcode("mov","a,@%s",rname);
3733 emitcode("inc","%s",rname);
3734 emitcode("movx","a,@%s",rname);
3738 emitcode("inc","dptr");
3739 emitcode("movx","a,@dptr");
3743 emitcode("clr","a");
3744 emitcode("inc","dptr");
3745 emitcode("movc","a","@a+dptr");
3749 emitcode("inc","dptr");
3750 emitcode("lcall","__gptrget");
3755 /* if we are done */
3759 aopPut(AOP(result),"a",offset++);
3764 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
3765 aopPut(AOP(result),"a",offset);
3772 /*-----------------------------------------------------------------*/
3773 /* genDataPointerGet - generates code when ptr offset is known */
3774 /*-----------------------------------------------------------------*/
3775 static void genDataPointerGet (operand *left,
3781 int size , offset = 0;
3782 aopOp(result,ic,TRUE);
3784 /* get the string representation of the name */
3785 l = aopGet(AOP(left),0);
3786 size = AOP_SIZE(result);
3789 sprintf(buffer,"(%s + %d)",l+1,offset);
3791 sprintf(buffer,"%s",l+1);
3792 aopPut(AOP(result),buffer,offset++);
3795 freeAsmop(left,NULL,ic,TRUE);
3796 freeAsmop(result,NULL,ic,TRUE);
3799 /*-----------------------------------------------------------------*/
3800 /* genNearPointerGet - emitcode for near pointer fetch */
3801 /*-----------------------------------------------------------------*/
3802 static void genNearPointerGet (operand *left,
3809 link *rtype, *retype;
3810 link *ltype = operandType(left);
3813 rtype = operandType(result);
3814 retype= getSpec(rtype);
3816 aopOp(left,ic,FALSE);
3818 /* if left is rematerialisable and
3819 result is not bit variable type and
3820 the left is pointer to data space i.e
3821 lower 128 bytes of space */
3822 if (AOP_TYPE(left) == AOP_IMMD &&
3823 !IS_BITVAR(retype) &&
3824 DCL_TYPE(ltype) == POINTER) {
3825 genDataPointerGet (left,result,ic);
3829 /* if the value is already in a pointer register
3830 then don't need anything more */
3831 if (!AOP_INPREG(AOP(left))) {
3832 /* otherwise get a free pointer register */
3834 preg = getFreePtr(ic,&aop,FALSE,0);
3835 emitcode("mov","%s,%s",
3837 aopGet(AOP(left),0));
3838 rname = preg->name ;
3840 rname = aopGet(AOP(left),0);
3842 freeAsmop(left,NULL,ic,TRUE);
3843 aopOp (result,ic,FALSE);
3845 /* if bitfield then unpack the bits */
3846 if (IS_BITVAR(retype))
3847 genUnpackBits (result,rname,POINTER);
3849 /* we have can just get the values */
3850 int size = AOP_SIZE(result);
3854 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
3856 emitcode("mov","a,@%s",rname);
3857 aopPut(AOP(result),"a",offset);
3859 sprintf(buffer,"@%s",rname);
3860 aopPut(AOP(result),buffer,offset);
3864 emitcode("inc","%s",rname);
3868 /* now some housekeeping stuff */
3870 /* we had to allocate for this iCode */
3871 freeAsmop(NULL,aop,ic,TRUE);
3873 /* we did not allocate which means left
3874 already in a pointer register, then
3875 if size > 0 && this could be used again
3876 we have to point it back to where it
3878 if (AOP_SIZE(result) > 1 &&
3879 !OP_SYMBOL(left)->remat &&
3880 ( OP_SYMBOL(left)->liveTo > ic->seq ||
3882 int size = AOP_SIZE(result) - 1;
3884 emitcode("dec","%s",rname);
3889 freeAsmop(result,NULL,ic,TRUE);
3893 /*-----------------------------------------------------------------*/
3894 /* genPagedPointerGet - emitcode for paged pointer fetch */
3895 /*-----------------------------------------------------------------*/
3896 static void genPagedPointerGet (operand *left,
3903 link *rtype, *retype;
3905 rtype = operandType(result);
3906 retype= getSpec(rtype);
3908 aopOp(left,ic,FALSE);
3910 /* if the value is already in a pointer register
3911 then don't need anything more */
3912 if (!AOP_INPREG(AOP(left))) {
3913 /* otherwise get a free pointer register */
3915 preg = getFreePtr(ic,&aop,FALSE,0);
3916 emitcode("mov","%s,%s",
3918 aopGet(AOP(left),0));
3919 rname = preg->name ;
3921 rname = aopGet(AOP(left),0);
3923 freeAsmop(left,NULL,ic,TRUE);
3924 aopOp (result,ic,FALSE);
3926 /* if bitfield then unpack the bits */
3927 if (IS_BITVAR(retype))
3928 genUnpackBits (result,rname,PPOINTER);
3930 /* we have can just get the values */
3931 int size = AOP_SIZE(result);
3936 emitcode("movx","a,@%s",rname);
3937 aopPut(AOP(result),"a",offset);
3942 emitcode("inc","%s",rname);
3946 /* now some housekeeping stuff */
3948 /* we had to allocate for this iCode */
3949 freeAsmop(NULL,aop,ic,TRUE);
3951 /* we did not allocate which means left
3952 already in a pointer register, then
3953 if size > 0 && this could be used again
3954 we have to point it back to where it
3956 if (AOP_SIZE(result) > 1 &&
3957 !OP_SYMBOL(left)->remat &&
3958 ( OP_SYMBOL(left)->liveTo > ic->seq ||
3960 int size = AOP_SIZE(result) - 1;
3962 emitcode("dec","%s",rname);
3967 freeAsmop(result,NULL,ic,TRUE);
3972 /*-----------------------------------------------------------------*/
3973 /* genFarPointerGet - gget value from far space */
3974 /*-----------------------------------------------------------------*/
3975 static void genFarPointerGet (operand *left,
3976 operand *result, iCode *ic)
3979 link *retype = getSpec(operandType(result));
3981 aopOp(left,ic,FALSE);
3983 /* if the operand is already in dptr
3984 then we do nothing else we move the value to dptr */
3985 if (AOP_TYPE(left) != AOP_STR) {
3986 /* if this is remateriazable */
3987 if (AOP_TYPE(left) == AOP_IMMD)
3988 emitcode("mov","dptr,%s",aopGet(AOP(left),0));
3989 else { /* we need to get it byte by byte */
3990 emitcode("mov","dpl,%s",aopGet(AOP(left),0));
3991 emitcode("mov","dph,%s",aopGet(AOP(left),1));
3992 if (options.model == MODEL_FLAT24)
3994 emitcode("mov", "dpx,%s",aopGet(AOP(left),2));
3998 /* so dptr know contains the address */
3999 freeAsmop(left,NULL,ic,TRUE);
4000 aopOp(result,ic,FALSE);
4002 /* if bit then unpack */
4003 if (IS_BITVAR(retype))
4004 genUnpackBits(result,"dptr",FPOINTER);
4006 size = AOP_SIZE(result);
4010 emitcode("movx","a,@dptr");
4011 aopPut(AOP(result),"a",offset++);
4013 emitcode("inc","dptr");
4017 freeAsmop(result,NULL,ic,TRUE);
4020 /*-----------------------------------------------------------------*/
4021 /* emitcodePointerGet - gget value from code space */
4022 /*-----------------------------------------------------------------*/
4023 static void emitcodePointerGet (operand *left,
4024 operand *result, iCode *ic)
4027 link *retype = getSpec(operandType(result));
4029 aopOp(left,ic,FALSE);
4031 /* if the operand is already in dptr
4032 then we do nothing else we move the value to dptr */
4033 if (AOP_TYPE(left) != AOP_STR) {
4034 /* if this is remateriazable */
4035 if (AOP_TYPE(left) == AOP_IMMD)
4036 emitcode("mov","dptr,%s",aopGet(AOP(left),0));
4037 else { /* we need to get it byte by byte */
4038 emitcode("mov","dpl,%s",aopGet(AOP(left),0));
4039 emitcode("mov","dph,%s",aopGet(AOP(left),1));
4040 if (options.model == MODEL_FLAT24)
4042 emitcode("mov", "dpx,%s",aopGet(AOP(left),2));
4046 /* so dptr know contains the address */
4047 freeAsmop(left,NULL,ic,TRUE);
4048 aopOp(result,ic,FALSE);
4050 /* if bit then unpack */
4051 if (IS_BITVAR(retype))
4052 genUnpackBits(result,"dptr",CPOINTER);
4054 size = AOP_SIZE(result);
4058 emitcode("clr","a");
4059 emitcode("movc","a,@a+dptr");
4060 aopPut(AOP(result),"a",offset++);
4062 emitcode("inc","dptr");
4066 freeAsmop(result,NULL,ic,TRUE);
4069 /*-----------------------------------------------------------------*/
4070 /* genGenPointerGet - gget value from generic pointer space */
4071 /*-----------------------------------------------------------------*/
4072 static void genGenPointerGet (operand *left,
4073 operand *result, iCode *ic)
4076 link *retype = getSpec(operandType(result));
4078 aopOp(left,ic,FALSE);
4080 /* if the operand is already in dptr
4081 then we do nothing else we move the value to dptr */
4082 if (AOP_TYPE(left) != AOP_STR) {
4083 /* if this is remateriazable */
4084 if (AOP_TYPE(left) == AOP_IMMD) {
4085 emitcode("mov","dptr,%s",aopGet(AOP(left),0));
4086 emitcode("mov","b,#%d",pointerCode(retype));
4088 else { /* we need to get it byte by byte */
4089 emitcode("mov","dpl,%s",aopGet(AOP(left),0));
4090 emitcode("mov","dph,%s",aopGet(AOP(left),1));
4091 if (options.model == MODEL_FLAT24)
4093 emitcode("mov", "dpx,%s",aopGet(AOP(left),2));
4094 emitcode("mov","b,%s",aopGet(AOP(left),3));
4098 emitcode("mov","b,%s",aopGet(AOP(left),2));
4102 /* so dptr know contains the address */
4103 freeAsmop(left,NULL,ic,TRUE);
4104 aopOp(result,ic,FALSE);
4106 /* if bit then unpack */
4107 if (IS_BITVAR(retype))
4108 genUnpackBits(result,"dptr",GPOINTER);
4110 size = AOP_SIZE(result);
4114 emitcode("lcall","__gptrget");
4115 aopPut(AOP(result),"a",offset++);
4117 emitcode("inc","dptr");
4121 freeAsmop(result,NULL,ic,TRUE);
4124 /*-----------------------------------------------------------------*/
4125 /* genPointerGet - generate code for pointer get */
4126 /*-----------------------------------------------------------------*/
4127 static void genPointerGet (iCode *ic)
4129 operand *left, *result ;
4134 result = IC_RESULT(ic) ;
4136 /* depending on the type of pointer we need to
4137 move it to the correct pointer register */
4138 type = operandType(left);
4139 etype = getSpec(type);
4140 /* if left is of type of pointer then it is simple */
4141 if (IS_PTR(type) && !IS_FUNC(type->next))
4142 p_type = DCL_TYPE(type);
4144 /* we have to go by the storage class */
4145 p_type = PTR_TYPE(SPEC_OCLS(etype));
4147 /* if (SPEC_OCLS(etype)->codesp ) { */
4148 /* p_type = CPOINTER ; */
4151 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
4152 /* p_type = FPOINTER ; */
4154 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
4155 /* p_type = PPOINTER; */
4157 /* if (SPEC_OCLS(etype) == idata ) */
4158 /* p_type = IPOINTER; */
4160 /* p_type = POINTER ; */
4163 /* now that we have the pointer type we assign
4164 the pointer values */
4169 genNearPointerGet (left,result,ic);
4173 genPagedPointerGet(left,result,ic);
4177 genFarPointerGet (left,result,ic);
4181 emitcodePointerGet (left,result,ic);
4185 genGenPointerGet (left,result,ic);
4191 /*-----------------------------------------------------------------*/
4192 /* genPackBits - generates code for packed bit storage */
4193 /*-----------------------------------------------------------------*/
4194 static void genPackBits (link *etype ,
4196 char *rname, int p_type)
4204 blen = SPEC_BLEN(etype);
4205 bstr = SPEC_BSTR(etype);
4207 l = aopGet(AOP(right),offset++);
4210 /* if the bit lenth is less than or */
4211 /* it exactly fits a byte then */
4212 if (SPEC_BLEN(etype) <= 8 ) {
4213 shCount = SPEC_BSTR(etype) ;
4215 /* shift left acc */
4218 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
4223 emitcode ("mov","b,a");
4224 emitcode("mov","a,@%s",rname);
4228 emitcode ("mov","b,a");
4229 emitcode("movx","a,@dptr");
4233 emitcode ("push","b");
4234 emitcode ("push","acc");
4235 emitcode ("lcall","__gptrget");
4236 emitcode ("pop","b");
4240 emitcode ("anl","a,#0x%02x",(unsigned char)
4241 ((unsigned char)(0xFF << (blen+bstr)) |
4242 (unsigned char)(0xFF >> (8-bstr)) ) );
4243 emitcode ("orl","a,b");
4244 if (p_type == GPOINTER)
4245 emitcode("pop","b");
4251 emitcode("mov","@%s,a",rname);
4255 emitcode("movx","@dptr,a");
4259 emitcode("lcall","__gptrput");
4264 if ( SPEC_BLEN(etype) <= 8 )
4267 emitcode("inc","%s",rname);
4268 rLen = SPEC_BLEN(etype) ;
4270 /* now generate for lengths greater than one byte */
4273 l = aopGet(AOP(right),offset++);
4283 emitcode("mov","@%s,a",rname);
4285 emitcode("mov","@%s,%s",rname,l);
4290 emitcode("movx","@dptr,a");
4295 emitcode("lcall","__gptrput");
4298 emitcode ("inc","%s",rname);
4303 /* last last was not complete */
4305 /* save the byte & read byte */
4308 emitcode ("mov","b,a");
4309 emitcode("mov","a,@%s",rname);
4313 emitcode ("mov","b,a");
4314 emitcode("movx","a,@dptr");
4318 emitcode ("push","b");
4319 emitcode ("push","acc");
4320 emitcode ("lcall","__gptrget");
4321 emitcode ("pop","b");
4325 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
4326 emitcode ("orl","a,b");
4329 if (p_type == GPOINTER)
4330 emitcode("pop","b");
4335 emitcode("mov","@%s,a",rname);
4339 emitcode("movx","@dptr,a");
4343 emitcode("lcall","__gptrput");
4347 /*-----------------------------------------------------------------*/
4348 /* genDataPointerSet - remat pointer to data space */
4349 /*-----------------------------------------------------------------*/
4350 static void genDataPointerSet(operand *right,
4354 int size, offset = 0 ;
4355 char *l, buffer[256];
4357 aopOp(right,ic,FALSE);
4359 l = aopGet(AOP(result),0);
4360 size = AOP_SIZE(right);
4363 sprintf(buffer,"(%s + %d)",l+1,offset);
4365 sprintf(buffer,"%s",l+1);
4366 emitcode("mov","%s,%s",buffer,
4367 aopGet(AOP(right),offset++));
4370 freeAsmop(right,NULL,ic,TRUE);
4371 freeAsmop(result,NULL,ic,TRUE);
4374 /*-----------------------------------------------------------------*/
4375 /* genNearPointerSet - emitcode for near pointer put */
4376 /*-----------------------------------------------------------------*/
4377 static void genNearPointerSet (operand *right,
4385 link *ptype = operandType(result);
4387 retype= getSpec(operandType(right));
4389 aopOp(result,ic,FALSE);
4391 /* if the result is rematerializable &
4392 in data space & not a bit variable */
4393 if (AOP_TYPE(result) == AOP_IMMD &&
4394 DCL_TYPE(ptype) == POINTER &&
4395 !IS_BITVAR(retype)) {
4396 genDataPointerSet (right,result,ic);
4400 /* if the value is already in a pointer register
4401 then don't need anything more */
4402 if (!AOP_INPREG(AOP(result))) {
4403 /* otherwise get a free pointer register */
4405 preg = getFreePtr(ic,&aop,FALSE,0);
4406 emitcode("mov","%s,%s",
4408 aopGet(AOP(result),0));
4409 rname = preg->name ;
4411 rname = aopGet(AOP(result),0);
4413 freeAsmop(result,NULL,ic,TRUE);
4414 aopOp (right,ic,FALSE);
4416 /* if bitfield then unpack the bits */
4417 if (IS_BITVAR(retype))
4418 genPackBits (retype,right,rname,POINTER);
4420 /* we have can just get the values */
4421 int size = AOP_SIZE(right);
4425 l = aopGet(AOP(right),offset);
4428 emitcode("mov","@%s,a",rname);
4430 emitcode("mov","@%s,%s",rname,l);
4432 emitcode("inc","%s",rname);
4437 /* now some housekeeping stuff */
4439 /* we had to allocate for this iCode */
4440 freeAsmop(NULL,aop,ic,TRUE);
4442 /* we did not allocate which means left
4443 already in a pointer register, then
4444 if size > 0 && this could be used again
4445 we have to point it back to where it
4447 if (AOP_SIZE(right) > 1 &&
4448 !OP_SYMBOL(result)->remat &&
4449 ( OP_SYMBOL(result)->liveTo > ic->seq ||
4451 int size = AOP_SIZE(right) - 1;
4453 emitcode("dec","%s",rname);
4458 freeAsmop(right,NULL,ic,TRUE);
4463 /*-----------------------------------------------------------------*/
4464 /* genPagedPointerSet - emitcode for Paged pointer put */
4465 /*-----------------------------------------------------------------*/
4466 static void genPagedPointerSet (operand *right,
4475 retype= getSpec(operandType(right));
4477 aopOp(result,ic,FALSE);
4479 /* if the value is already in a pointer register
4480 then don't need anything more */
4481 if (!AOP_INPREG(AOP(result))) {
4482 /* otherwise get a free pointer register */
4484 preg = getFreePtr(ic,&aop,FALSE,0);
4485 emitcode("mov","%s,%s",
4487 aopGet(AOP(result),0));
4488 rname = preg->name ;
4490 rname = aopGet(AOP(result),0);
4492 freeAsmop(result,NULL,ic,TRUE);
4493 aopOp (right,ic,FALSE);
4495 /* if bitfield then unpack the bits */
4496 if (IS_BITVAR(retype))
4497 genPackBits (retype,right,rname,PPOINTER);
4499 /* we have can just get the values */
4500 int size = AOP_SIZE(right);
4504 l = aopGet(AOP(right),offset);
4507 emitcode("movx","@%s,a",rname);
4510 emitcode("inc","%s",rname);
4516 /* now some housekeeping stuff */
4518 /* we had to allocate for this iCode */
4519 freeAsmop(NULL,aop,ic,TRUE);
4521 /* we did not allocate which means left
4522 already in a pointer register, then
4523 if size > 0 && this could be used again
4524 we have to point it back to where it
4526 if (AOP_SIZE(right) > 1 &&
4527 !OP_SYMBOL(result)->remat &&
4528 ( OP_SYMBOL(result)->liveTo > ic->seq ||
4530 int size = AOP_SIZE(right) - 1;
4532 emitcode("dec","%s",rname);
4537 freeAsmop(right,NULL,ic,TRUE);
4542 /*-----------------------------------------------------------------*/
4543 /* genFarPointerSet - set value from far space */
4544 /*-----------------------------------------------------------------*/
4545 static void genFarPointerSet (operand *right,
4546 operand *result, iCode *ic)
4549 link *retype = getSpec(operandType(right));
4551 aopOp(result,ic,FALSE);
4553 /* if the operand is already in dptr
4554 then we do nothing else we move the value to dptr */
4555 if (AOP_TYPE(result) != AOP_STR) {
4556 /* if this is remateriazable */
4557 if (AOP_TYPE(result) == AOP_IMMD)
4558 emitcode("mov","dptr,%s",aopGet(AOP(result),0));
4559 else { /* we need to get it byte by byte */
4560 emitcode("mov","dpl,%s",aopGet(AOP(result),0));
4561 emitcode("mov","dph,%s",aopGet(AOP(result),1));
4562 if (options.model == MODEL_FLAT24)
4564 emitcode("mov", "dpx,%s",aopGet(AOP(result),2));
4568 /* so dptr know contains the address */
4569 freeAsmop(result,NULL,ic,TRUE);
4570 aopOp(right,ic,FALSE);
4572 /* if bit then unpack */
4573 if (IS_BITVAR(retype))
4574 genPackBits(retype,right,"dptr",FPOINTER);
4576 size = AOP_SIZE(right);
4580 char *l = aopGet(AOP(right),offset++);
4582 emitcode("movx","@dptr,a");
4584 emitcode("inc","dptr");
4588 freeAsmop(right,NULL,ic,TRUE);
4591 /*-----------------------------------------------------------------*/
4592 /* genGenPointerSet - set value from generic pointer space */
4593 /*-----------------------------------------------------------------*/
4594 static void genGenPointerSet (operand *right,
4595 operand *result, iCode *ic)
4598 link *retype = getSpec(operandType(right));
4600 aopOp(result,ic,FALSE);
4602 /* if the operand is already in dptr
4603 then we do nothing else we move the value to dptr */
4604 if (AOP_TYPE(result) != AOP_STR) {
4605 /* if this is remateriazable */
4606 if (AOP_TYPE(result) == AOP_IMMD) {
4607 emitcode("mov","dptr,%s",aopGet(AOP(result),0));
4608 emitcode("mov","b,%s + 1",aopGet(AOP(result),0));
4610 else { /* we need to get it byte by byte */
4611 emitcode("mov","dpl,%s",aopGet(AOP(result),0));
4612 emitcode("mov","dph,%s",aopGet(AOP(result),1));
4613 if (options.model == MODEL_FLAT24)
4615 emitcode("mov", "dpx,%s",aopGet(AOP(result),2));
4616 emitcode("mov","b,%s",aopGet(AOP(result),3));
4620 emitcode("mov","b,%s",aopGet(AOP(result),2));
4624 /* so dptr know contains the address */
4625 freeAsmop(result,NULL,ic,TRUE);
4626 aopOp(right,ic,FALSE);
4628 /* if bit then unpack */
4629 if (IS_BITVAR(retype))
4630 genPackBits(retype,right,"dptr",GPOINTER);
4632 size = AOP_SIZE(right);
4636 char *l = aopGet(AOP(right),offset++);
4638 emitcode("lcall","__gptrput");
4640 emitcode("inc","dptr");
4644 freeAsmop(right,NULL,ic,TRUE);
4647 /*-----------------------------------------------------------------*/
4648 /* genPointerSet - stores the value into a pointer location */
4649 /*-----------------------------------------------------------------*/
4650 static void genPointerSet (iCode *ic)
4652 operand *right, *result ;
4656 right = IC_RIGHT(ic);
4657 result = IC_RESULT(ic) ;
4659 /* depending on the type of pointer we need to
4660 move it to the correct pointer register */
4661 type = operandType(result);
4662 etype = getSpec(type);
4663 /* if left is of type of pointer then it is simple */
4664 if (IS_PTR(type) && !IS_FUNC(type->next)) {
4665 p_type = DCL_TYPE(type);
4668 /* we have to go by the storage class */
4669 p_type = PTR_TYPE(SPEC_OCLS(etype));
4671 /* if (SPEC_OCLS(etype)->codesp ) { */
4672 /* p_type = CPOINTER ; */
4675 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
4676 /* p_type = FPOINTER ; */
4678 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
4679 /* p_type = PPOINTER ; */
4681 /* if (SPEC_OCLS(etype) == idata ) */
4682 /* p_type = IPOINTER ; */
4684 /* p_type = POINTER ; */
4687 /* now that we have the pointer type we assign
4688 the pointer values */
4693 genNearPointerSet (right,result,ic);
4697 genPagedPointerSet (right,result,ic);
4701 genFarPointerSet (right,result,ic);
4705 genGenPointerSet (right,result,ic);
4711 /*-----------------------------------------------------------------*/
4712 /* genIfx - generate code for Ifx statement */
4713 /*-----------------------------------------------------------------*/
4714 static void genIfx (iCode *ic, iCode *popIc)
4716 operand *cond = IC_COND(ic);
4719 aopOp(cond,ic,FALSE);
4721 /* get the value into acc */
4722 if (AOP_TYPE(cond) != AOP_CRY)
4723 toBoolean(cond,"",0);
4726 /* the result is now in the accumulator */
4727 freeAsmop(cond,NULL,ic,TRUE);
4729 /* if there was something to be popped then do it */
4733 /* if the condition is a bit variable */
4734 /* if (isbit && IS_ITEMP(cond) && SPIL_LOC(cond)) { */
4735 /* // genIfxJump(ic,SPIL_LOC(cond)->rname); */
4738 /* if (isbit && !IS_ITEMP(cond)) */
4739 /* // genIfxJump(ic,OP_SYMBOL(cond)->rname); */
4741 /* // genIfxJump(ic,"a"); */
4746 /*-----------------------------------------------------------------*/
4747 /* genAddrOf - generates code for address of */
4748 /*-----------------------------------------------------------------*/
4749 static void genAddrOf (iCode *ic)
4751 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
4754 aopOp(IC_RESULT(ic),ic,FALSE);
4756 /* if the operand is on the stack then we
4757 need to get the stack offset of this
4760 /* if it has an offset then we need to compute
4763 emitcode("mov","a,_bp");
4764 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
4765 aopPut(AOP(IC_RESULT(ic)),"a",0);
4767 /* we can just move _bp */
4768 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
4770 /* fill the result with zero */
4771 size = AOP_SIZE(IC_RESULT(ic)) - 1;
4774 if (options.stack10bit && size < (FPTRSIZE - 1))
4777 "*** warning: pointer to stack var truncated.\n");
4784 if (options.stack10bit && offset == 2)
4786 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
4790 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
4797 /* object not on stack then we need the name */
4798 size = AOP_SIZE(IC_RESULT(ic));
4802 char s[SDCC_NAME_MAX];
4804 sprintf(s,"#(%s >> %d)",
4808 sprintf(s,"#%s",sym->rname);
4809 aopPut(AOP(IC_RESULT(ic)),s,offset++);
4813 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
4817 /*-----------------------------------------------------------------*/
4818 /* genFarFarAssign - assignment when both are in far space */
4819 /*-----------------------------------------------------------------*/
4820 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
4822 int size = AOP_SIZE(right);
4825 /* first push the right side on to the stack */
4827 l = aopGet(AOP(right),offset++);
4829 emitcode ("push","acc");
4832 freeAsmop(right,NULL,ic,FALSE);
4833 /* now assign DPTR to result */
4834 aopOp(result,ic,FALSE);
4835 size = AOP_SIZE(result);
4837 emitcode ("pop","acc");
4838 aopPut(AOP(result),"a",--offset);
4840 freeAsmop(result,NULL,ic,FALSE);
4844 /*-----------------------------------------------------------------*/
4845 /* genAssign - generate code for assignment */
4846 /*-----------------------------------------------------------------*/
4847 static void genAssign (iCode *ic)
4849 operand *result, *right;
4851 unsigned long lit = 0L;
4853 result = IC_RESULT(ic);
4854 right = IC_RIGHT(ic) ;
4856 /* if they are the same */
4857 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
4860 aopOp(right,ic,FALSE);
4862 /* special case both in far space */
4863 if (AOP_TYPE(right) == AOP_DPTR &&
4864 IS_TRUE_SYMOP(result) &&
4865 isOperandInFarSpace(result)) {
4867 genFarFarAssign (result,right,ic);
4871 aopOp(result,ic,TRUE);
4873 /* if they are the same registers */
4874 if (sameRegs(AOP(right),AOP(result)))
4877 /* if the result is a bit */
4878 if (AOP_TYPE(result) == AOP_CRY) {
4880 /* if the right size is a literal then
4881 we know what the value is */
4882 if (AOP_TYPE(right) == AOP_LIT) {
4883 if (((int) operandLitValue(right)))
4884 aopPut(AOP(result),one,0);
4886 aopPut(AOP(result),zero,0);
4890 /* the right is also a bit variable */
4891 if (AOP_TYPE(right) == AOP_CRY) {
4892 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4893 aopPut(AOP(result),"c",0);
4898 toBoolean(right,"",0);
4899 aopPut(AOP(result),"a",0);
4903 /* bit variables done */
4905 size = AOP_SIZE(result);
4907 if(AOP_TYPE(right) == AOP_LIT)
4908 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4910 (AOP_TYPE(result) != AOP_REG) &&
4911 (AOP_TYPE(right) == AOP_LIT) &&
4912 !IS_FLOAT(operandType(right)) &&
4914 emitcode("clr","a");
4916 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
4917 aopPut(AOP(result),"a",size);
4920 aopGet(AOP(right),size),
4926 aopGet(AOP(right),offset),
4933 freeAsmop (right,NULL,ic,FALSE);
4934 freeAsmop (result,NULL,ic,TRUE);
4937 /*-----------------------------------------------------------------*/
4938 /* genJumpTab - genrates code for jump table */
4939 /*-----------------------------------------------------------------*/
4940 static void genJumpTab (iCode *ic)
4945 aopOp(IC_JTCOND(ic),ic,FALSE);
4946 /* get the condition into accumulator */
4947 l = aopGet(AOP(IC_JTCOND(ic)),0);
4949 /* multiply by three */
4950 emitcode("add","a,acc");
4951 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0));
4952 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
4954 jtab = newiTempLabel(NULL);
4955 emitcode("mov","dptr,#%05d$",jtab->key+100);
4956 emitcode("jmp","@a+dptr");
4957 emitcode("","%05d$:",jtab->key+100);
4958 /* now generate the jump labels */
4959 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
4960 jtab = setNextItem(IC_JTLABELS(ic)))
4961 emitcode("ljmp","%05d$",jtab->key+100);
4965 /*-----------------------------------------------------------------*/
4966 /* genCast - gen code for casting */
4967 /*-----------------------------------------------------------------*/
4968 static void genCast (iCode *ic)
4970 operand *result = IC_RESULT(ic);
4971 link *ctype = operandType(IC_LEFT(ic));
4972 link *rtype = operandType(IC_RIGHT(ic));
4973 operand *right = IC_RIGHT(ic);
4976 /* if they are equivalent then do nothing */
4977 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
4980 aopOp(right,ic,FALSE) ;
4981 aopOp(result,ic,FALSE);
4983 /* if the result is a bit */
4984 if (AOP_TYPE(result) == AOP_CRY) {
4985 /* if the right size is a literal then
4986 we know what the value is */
4987 if (AOP_TYPE(right) == AOP_LIT) {
4988 if (((int) operandLitValue(right)))
4989 aopPut(AOP(result),one,0);
4991 aopPut(AOP(result),zero,0);
4996 /* the right is also a bit variable */
4997 if (AOP_TYPE(right) == AOP_CRY) {
4998 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4999 aopPut(AOP(result),"c",0);
5004 toBoolean(right,"",0);
5005 aopPut(AOP(result),"a",0);
5009 /* if they are the same size : or less */
5010 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
5012 /* if they are in the same place */
5013 if (sameRegs(AOP(right),AOP(result)))
5016 /* if they in different places then copy */
5017 size = AOP_SIZE(result);
5021 aopGet(AOP(right),offset),
5029 /* if the result is of type pointer */
5030 if (IS_PTR(ctype)) {
5033 link *type = operandType(right);
5034 link *etype = getSpec(type);
5036 /* pointer to generic pointer */
5037 if (IS_GENPTR(ctype)) {
5041 p_type = DCL_TYPE(type);
5043 /* we have to go by the storage class */
5044 p_type = PTR_TYPE(SPEC_OCLS(etype));
5047 /* the first two bytes are known */
5048 size = GPTRSIZE - 1;
5052 aopGet(AOP(right),offset),
5056 /* the last byte depending on type */
5073 /* this should never happen */
5074 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
5075 "got unknown pointer type");
5078 aopPut(AOP(result),l, GPTRSIZE - 1);
5082 /* just copy the pointers */
5083 size = AOP_SIZE(result);
5087 aopGet(AOP(right),offset),
5094 /* so we now know that the size of destination is greater
5095 than the size of the source */
5096 /* we move to result for the size of source */
5097 size = AOP_SIZE(right);
5101 aopGet(AOP(right),offset),
5106 /* now depending on the sign of the source && destination */
5107 size = AOP_SIZE(result) - AOP_SIZE(right);
5108 /* if unsigned or not an integral type */
5109 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
5111 aopPut(AOP(result),zero,offset++);
5113 /* we need to extend the sign :{ */
5114 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1);
5116 emitcode("rlc","a");
5117 emitcode("subb","a,acc");
5119 aopPut(AOP(result),"a",offset++);
5122 /* we are done hurray !!!! */
5125 freeAsmop(right,NULL,ic,TRUE);
5126 freeAsmop(result,NULL,ic,TRUE);
5130 /*-----------------------------------------------------------------*/
5131 /* genDjnz - generate decrement & jump if not zero instrucion */
5132 /*-----------------------------------------------------------------*/
5133 static int genDjnz (iCode *ic, iCode *ifx)
5139 /* if the if condition has a false label
5140 then we cannot save */
5144 /* if the minus is not of the form
5146 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
5147 !IS_OP_LITERAL(IC_RIGHT(ic)))
5150 if (operandLitValue(IC_RIGHT(ic)) != 1)
5153 /* if the size of this greater than one then no
5155 if (getSize(operandType(IC_RESULT(ic))) > 1)
5158 /* otherwise we can save BIG */
5159 lbl = newiTempLabel(NULL);
5160 lbl1= newiTempLabel(NULL);
5162 aopOp(IC_RESULT(ic),ic,FALSE);
5164 if (IS_AOP_PREG(IC_RESULT(ic))) {
5165 emitcode("dec","%s",
5166 aopGet(AOP(IC_RESULT(ic)),0));
5167 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0));
5168 emitcode("jnz","%05d$",lbl->key+100);
5170 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0),
5173 emitcode ("sjmp","%05d$",lbl1->key+100);
5174 emitcode ("","%05d$:",lbl->key+100);
5175 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
5176 emitcode ("","%05d$:",lbl1->key+100);
5178 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
5183 static char *recvregs[8] =
5185 "r16","r17","r18","r19","r20","r21","r22","r23"
5189 /*-----------------------------------------------------------------*/
5190 /* genReceive - generate code for a receive iCode */
5191 /*-----------------------------------------------------------------*/
5192 static void genReceive (iCode *ic)
5194 int size , offset =0;
5195 aopOp(IC_RESULT(ic),ic,FALSE);
5196 size = AOP_SIZE(IC_RESULT(ic));
5198 aopPut(AOP(IC_RESULT(ic)),recvregs[recvCnt++],offset);
5201 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
5204 /*-----------------------------------------------------------------*/
5205 /* gen51Code - generate code for 8051 based controllers */
5206 /*-----------------------------------------------------------------*/
5207 void genAVRCode (iCode *lic)
5212 lineHead = lineCurr = NULL;
5214 /* print the allocation information */
5216 printAllocInfo( currFunc, codeOutFile);
5217 /* if debug information required */
5218 /* if (options.debug && currFunc) { */
5220 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
5222 if (IS_STATIC(currFunc->etype))
5223 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
5225 emitcode("","G$%s$0$0 ==.",currFunc->name);
5228 /* stack pointer name */
5229 if (options.useXstack)
5235 for (ic = lic ; ic ; ic = ic->next ) {
5237 if ( cln != ic->lineno ) {
5238 if ( options.debug ) {
5240 emitcode("","C$%s$%d$%d$%d ==.",
5241 ic->filename,ic->lineno,
5242 ic->level,ic->block);
5245 emitcode(";","%s %d",ic->filename,ic->lineno);
5248 /* if the result is marked as
5249 spilt and rematerializable or code for
5250 this has already been generated then
5252 if (resultRemat(ic) || ic->generated )
5255 /* depending on the operation */
5274 /* IPOP happens only when trying to restore a
5275 spilt live range, if there is an ifx statement
5276 following this pop then the if statement might
5277 be using some of the registers being popped which
5278 would destory the contents of the register so
5279 we need to check for this condition and handle it */
5281 ic->next->op == IFX &&
5282 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
5283 genIfx (ic->next,ic);
5301 genEndFunction (ic);
5321 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
5338 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
5342 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
5346 genCmpLe (ic,ifxForOp(IC_RESULT(ic),ic));
5350 genCmpGe (ic,ifxForOp(IC_RESULT(ic),ic));
5354 genCmpNe (ic,ifxForOp(IC_RESULT(ic),ic));
5358 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
5370 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
5374 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
5378 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
5405 case GET_VALUE_AT_ADDRESS:
5410 if (POINTER_SET(ic))
5437 addSet(&_G.sendSet,ic);
5442 /* piCode(ic,stdout); */
5448 /* now we are ready to call the
5449 peep hole optimizer */
5450 if (!options.nopeep)
5451 peepHole (&lineHead);
5453 /* now do the actual printing */
5454 printLine (lineHead,codeOutFile);