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 fReturnSize = 4; /* shared with ralloc.c */
65 char **fReturn = fReturnAVR;
67 static short rbank = -1;
79 extern int avr_ptrRegReq ;
81 extern FILE *codeOutFile;
82 static void saverbank (int, iCode *,bool);
83 #define RESULTONSTACK(x) \
84 (IC_RESULT(x) && IC_RESULT(x)->aop && \
85 IC_RESULT(x)->aop->type == AOP_STK )
87 #define MOVR0(x) if (strcmp(x,"r0")) emitcode("mov","r0,%s",x);
88 #define CLRC emitcode("clc")
89 #define SETC emitcode("stc")
90 #define IS_REGIDX(a,r) (a->type == AOP_REG && aop->aopu.aop_reg[0]->rIdx == r)
92 static lineNode *lineHead = NULL;
93 static lineNode *lineCurr = NULL;
95 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
96 0xE0, 0xC0, 0x80, 0x00};
97 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
98 0x07, 0x03, 0x01, 0x00};
105 /*-----------------------------------------------------------------*/
106 /* emitcode - writes the code into a file : for now it is simple */
107 /*-----------------------------------------------------------------*/
108 static void emitcode (char *inst,char *fmt, ...)
111 char lb[MAX_INLINEASM];
118 sprintf(lb,"%s\t",inst);
120 sprintf(lb,"%s",inst);
121 vsprintf(lb+(strlen(lb)),fmt,ap);
125 while (isspace(*lbp)) lbp++;
128 lineCurr = (lineCurr ?
129 connectLine(lineCurr,newLineNode(lb)) :
130 (lineHead = newLineNode(lb)));
131 lineCurr->isInline = _G.inLine;
132 lineCurr->isDebug = _G.debugLine;
136 /*-----------------------------------------------------------------*/
137 /* getFreePtr - returns X or Z whichever is free or can be pushed */
138 /*-----------------------------------------------------------------*/
139 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result, bool zonly)
141 bool xiu = FALSE , ziu = FALSE;
142 bool xou = FALSE , zou = FALSE;
144 /* the logic: if x & z used in the instruction
145 then we are in trouble otherwise */
147 /* first check if x & z are used by this
148 instruction, in which case we are in trouble */
149 if ((xiu = bitVectBitValue(ic->rUsed,X_IDX)) &&
150 (ziu = bitVectBitValue(ic->rUsed,Z_IDX)))
155 xou = bitVectBitValue(ic->rMask,X_IDX);
156 zou = bitVectBitValue(ic->rMask,Z_IDX);
158 /* if no usage of Z then return it */
160 ic->rUsed = bitVectSetBit(ic->rUsed,Z_IDX);
161 (*aopp)->type = AOP_Z;
163 (*aopp)->aop_ptr2 = avr_regWithIdx(R31_IDX);
164 return (*aopp)->aopu.aop_ptr = avr_regWithIdx(R30_IDX);
167 /* if no usage of X then return it */
168 if (!xiu && !xou && !zonly) {
169 ic->rUsed = bitVectSetBit(ic->rUsed,X_IDX);
170 (*aopp)->type = AOP_X;
172 (*aopp)->aop_ptr2 = avr_regWithIdx(R27_IDX);
173 return (*aopp)->aopu.aop_ptr = avr_regWithIdx(R26_IDX);
176 /* if z not used then */
179 /* push it if not already pushed */
181 emitcode ("push","%s",
182 avr_regWithIdx(R30_IDX)->dname);
183 emitcode ("push","%s",
184 avr_regWithIdx(R31_IDX)->dname);
188 ic->rUsed = bitVectSetBit(ic->rUsed,Z_IDX);
189 (*aopp)->type = AOP_Z;
190 (*aopp)->aop_ptr2 = avr_regWithIdx(R31_IDX);
191 return (*aopp)->aopu.aop_ptr = avr_regWithIdx(R30_IDX);
194 /* now we know they both have usage */
195 /* if x not used in this instruction */
196 if (!xiu && !zonly) {
197 /* push it if not already pushed */
199 emitcode ("push","%s",
200 avr_regWithIdx(R26_IDX)->dname);
201 emitcode ("push","%s",
202 avr_regWithIdx(R27_IDX)->dname);
206 ic->rUsed = bitVectSetBit(ic->rUsed,X_IDX);
207 (*aopp)->type = AOP_X;
209 (*aopp)->aop_ptr2 = avr_regWithIdx(R27_IDX);
210 return (*aopp)->aopu.aop_ptr = avr_regWithIdx(R26_IDX);
215 /* I said end of world but not quite end of world yet */
216 /* if this is a result then we can push it on the stack*/
218 (*aopp)->type = AOP_STK;
223 /* other wise this is true end of the world */
224 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
225 "getFreePtr should never reach here");
229 /*-----------------------------------------------------------------*/
230 /* newAsmop - creates a new asmOp */
231 /*-----------------------------------------------------------------*/
232 static asmop *newAsmop (short type)
236 ALLOC(aop,sizeof(asmop));
241 /*-----------------------------------------------------------------*/
242 /* pointerCode - returns the code for a pointer type */
243 /*-----------------------------------------------------------------*/
244 static int pointerCode (link *etype)
247 return PTR_TYPE(SPEC_OCLS(etype));
251 /*-----------------------------------------------------------------*/
252 /* aopForSym - for a true symbol */
253 /*-----------------------------------------------------------------*/
254 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
257 memmap *space= SPEC_OCLS(sym->etype);
259 /* if already has one */
263 /* assign depending on the storage class */
264 /* if it is on the stack */
266 sym->aop = aop = newAsmop(0);
267 aop->size = getSize(sym->type);
269 /* we can use std / ldd instruction */
270 if (sym->stack > 0 && (sym->stack + getSize(sym->type) - 1) <= 63) {
271 aop->type = AOP_STK_D;
272 aop->aopu.aop_stk = sym->stack;
276 /* otherwise get a free pointer register X/Z */
277 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result,FALSE);
279 /* now assign the address of the variable to
280 the pointer register */
281 if (aop->type != AOP_STK) {
282 emitcode("movw","%s,r28",aop->aopu.aop_ptr->name);
283 if (sym->stack < 0) {
284 if ((sym->stack - _G.nRegsSaved) > -63) {
285 emitcode("sbiw","%s,0x%02x",
286 aop->aopu.aop_ptr->name,
287 (sym->stack - _G.nRegsSaved));
289 emitcode("subi","%s,lo8(%d)", aop->aopu.aop_ptr->name,
290 sym->stack - _G.nRegsSaved);
291 emitcode("sbci","%s,hi8(%d)",aop->aop_ptr2->name,
292 sym->stack - _G.nRegsSaved);
295 if (sym->stack <= 63) {
296 emitcode("adiw","%s,0x%02x",aop->aopu.aop_ptr->name,sym->stack);
298 emitcode("subi","%s,lo8(-%d)",aop->aopu.aop_ptr->name,sym->stack);
299 emitcode("sbci","%s,hi8(-%d)",aop->aop_ptr2->name,sym->stack);
306 /* if in bit space */
307 if (IN_BITSPACE(space)) {
308 sym->aop = aop = newAsmop (AOP_CRY);
309 aop->aopu.aop_dir = sym->rname ;
310 aop->size = getSize(sym->type);
313 /* if it is in direct space */
314 if (IN_DIRSPACE(space)) {
315 sym->aop = aop = newAsmop (AOP_DIR);
316 aop->aopu.aop_dir = sym->rname ;
317 aop->size = getSize(sym->type);
321 /* special case for a function */
322 if (IS_FUNC(sym->type)) {
323 sym->aop = aop = newAsmop(AOP_IMMD);
324 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
325 strcpy(aop->aopu.aop_immd,sym->rname);
326 aop->size = FPTRSIZE;
330 /* only remaining is code / eeprom which will need pointer reg */
331 /* if it is in code space */
332 if (IN_CODESPACE(space))
335 sym->aop = aop = newAsmop(0);
336 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result,aop->code);
337 aop->size = getSize(sym->type);
338 emitcode ("ldi","%s,lo8(%s)",aop->aopu.aop_ptr->name,sym->rname);
339 emircode ("ldi","%s,hi8(%s)",aop->aop_ptr2);
344 /*-----------------------------------------------------------------*/
345 /* aopForRemat - rematerialzes an object */
346 /*-----------------------------------------------------------------*/
347 static asmop *aopForRemat (symbol *sym)
349 iCode *ic = sym->rematiCode;
350 asmop *aop = newAsmop(AOP_IMMD);
355 val += operandLitValue(IC_RIGHT(ic));
356 else if (ic->op == '-')
357 val -= operandLitValue(IC_RIGHT(ic));
361 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
365 sprintf(buffer,"(%s %c 0x%04x)",
366 OP_SYMBOL(IC_LEFT(ic))->rname,
367 val >= 0 ? '+' : '-',
370 strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
372 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
373 strcpy(aop->aopu.aop_immd,buffer);
377 /*-----------------------------------------------------------------*/
378 /* regsInCommon - two operands have some registers in common */
379 /*-----------------------------------------------------------------*/
380 static bool regsInCommon (operand *op1, operand *op2)
385 /* if they have registers in common */
386 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
389 sym1 = OP_SYMBOL(op1);
390 sym2 = OP_SYMBOL(op2);
392 if (sym1->nRegs == 0 || sym2->nRegs == 0)
395 for (i = 0 ; i < sym1->nRegs ; i++) {
400 for (j = 0 ; j < sym2->nRegs ;j++ ) {
404 if (sym2->regs[j] == sym1->regs[i])
412 /*-----------------------------------------------------------------*/
413 /* operandsEqu - equivalent */
414 /*-----------------------------------------------------------------*/
415 static bool operandsEqu ( operand *op1, operand *op2)
419 /* if they not symbols */
420 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
423 sym1 = OP_SYMBOL(op1);
424 sym2 = OP_SYMBOL(op2);
426 /* if both are itemps & one is spilt
427 and the other is not then false */
428 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
429 sym1->isspilt != sym2->isspilt )
432 /* if they are the same */
436 if (strcmp(sym1->rname,sym2->rname) == 0)
440 /* if left is a tmp & right is not */
444 (sym1->usl.spillLoc == sym2))
451 (sym2->usl.spillLoc == sym1))
457 /*-----------------------------------------------------------------*/
458 /* sameRegs - two asmops have the same registers */
459 /*-----------------------------------------------------------------*/
460 static bool sameRegs (asmop *aop1, asmop *aop2 )
467 if (aop1->type != AOP_REG ||
468 aop2->type != AOP_REG )
471 if (aop1->size != aop2->size )
474 for (i = 0 ; i < aop1->size ; i++ )
475 if (aop1->aopu.aop_reg[i] !=
476 aop2->aopu.aop_reg[i] )
482 /*-----------------------------------------------------------------*/
483 /* isRegPair - for size 2 if this operand has a register pair */
484 /*-----------------------------------------------------------------*/
485 static int isRegPair (aop *aopp)
487 if (!aop || aop->size != 2) return 0;
488 if (aop->type == AOP_X || aop->type == AOP_Y) return 1;
489 if (aop->type != AOP_REG) return 0;
490 if ((aop->aopu.aop_reg[1]->rIdx -
491 aop->aopu.aop_reg[0]->rIdx) == 1) return 1;
495 /*-----------------------------------------------------------------*/
496 /* aopOp - allocates an asmop for an operand : */
497 /*-----------------------------------------------------------------*/
498 static void aopOp (operand *op, iCode *ic, bool result)
507 /* if this a literal */
508 if (IS_OP_LITERAL(op)) {
509 op->aop = aop = newAsmop(AOP_LIT);
510 aop->aopu.aop_lit = op->operand.valOperand;
511 aop->size = getSize(operandType(op));
515 /* if already has a asmop then continue */
519 /* if the underlying symbol has a aop */
520 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
521 op->aop = OP_SYMBOL(op)->aop;
525 /* if this is a true symbol */
526 if (IS_TRUE_SYMOP(op)) {
527 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
531 /* this is a temporary : this has
537 e) can be a return use only */
542 /* if the type is a conditional */
543 if (sym->regType == REG_CND) {
544 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
549 /* if it is spilt then two situations
551 b) has a spill location */
552 if (sym->isspilt || sym->nRegs == 0) {
554 /* rematerialize it NOW */
556 sym->aop = op->aop = aop =
558 aop->size = getSize(sym->type);
563 assert("ACC_USE cannot happen in AVR\n");
568 aop = op->aop = sym->aop = newAsmop(AOP_STR);
569 aop->size = getSize(sym->type);
570 for ( i = 0 ; i < fReturnSize ; i++ )
571 aop->aopu.aop_str[i] = fReturn[i];
575 /* else spill location */
576 sym->aop = op->aop = aop =
577 aopForSym(ic,sym->usl.spillLoc,result);
578 aop->size = getSize(sym->type);
582 /* must be in a register */
583 sym->aop = op->aop = aop = newAsmop(AOP_REG);
584 aop->size = sym->nRegs;
585 for ( i = 0 ; i < sym->nRegs ;i++)
586 aop->aopu.aop_reg[i] = sym->regs[i];
589 /*-----------------------------------------------------------------*/
590 /* freeAsmop - free up the asmop given to an operand */
591 /*----------------------------------------------------------------*/
592 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
609 /* depending on the asmop type only three cases need work AOP_RO
610 , AOP_R1 && AOP_STK */
615 emitcode ("pop","r26");
616 emitcode ("pop","r27");
620 bitVectUnSetBit(ic->rUsed,X_IDX);
626 emitcode ("pop","r30");
627 emitcode ("pop","r31");
631 bitVectUnSetBit(ic->rUsed,Z_IDX);
637 int stk = aop->aopu.aop_stk + aop->size;
638 bitVectUnSetBit(ic->rUsed,X_IDX);
639 bitVectUnSetBit(ic->rUsed,Z_IDX);
641 getFreePtr(ic,&aop,FALSE,0);
643 emitcode ("movw","%s,r28");
645 if (stk <= 63 && stk > 0) {
646 emitcode ("adiw","%s,0x%02x",aop->aopu.aop_ptr->name,stk+1);
648 emitcode ("subi","%s,lo8(%d)",aop->aopu.aop_ptr->name,-(stk+1));
649 emitcode ("sbci","%s,hi8(%d)",aop->aop_ptr2->name,-(stk+1));
654 emitcode("pop","r24");
655 emitcode("st","-%s,r24",aop->type == AOP_X ? "X" : "Z");
659 freeAsmop(op,NULL,ic,TRUE);
661 emitcode("pop","r26");
662 emitcode("pop","r27");
667 emitcode("pop","r30");
668 emitcode("pop","r31");
675 /* all other cases just dealloc */
679 OP_SYMBOL(op)->aop = NULL;
680 /* if the symbol has a spill */
682 SPIL_LOC(op)->aop = NULL;
687 /*-----------------------------------------------------------------*/
688 /* aopGet - for fetching value of the aop */
689 /*-----------------------------------------------------------------*/
690 static char *aopGet (asmop *aop, int offset)
695 /* offset is greater than
697 if (offset > (aop->size - 1) &&
698 aop->type != AOP_LIT)
701 /* depending on type */
705 if (offset > aop->coff) {
706 emitcode ("adiw","%s,%d",aop->aopu.aop_ptr->name,offset - aop->coff);
709 if (offset < aop->coff) {
710 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,aop->coff - offset);
714 emitcode("ld","%s,x",
715 (rs = ((offset & 1) ? "r25" : "r24")));
720 if (offset > aop->coff) {
721 emitcode("adiw","r30,%d",offset - aop->coff);
723 emitcode("sbiw","r30,%d",aop->coff - offset);
725 emitcode("lpm","%s,z",(rs = ((offset & 1) ? "r25" : "r24")));
728 if (offset > aop->coff) {
729 emitcode ("ldd","%s,z+%d",(rs = ((offset & 1) ? "r25" : "r24")),
732 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,aop->coff - offset);
734 emitcode ("ld","%s,z",(rs = ((offset & 1) ? "r25" : "r24")));
741 emitcode ("lds","%s,(%s)+%d",
742 (rs = ((offset & 1) ? "r25" : "r24")),
743 aop->aopu.aop_immd, offset);
747 emitcode ("lds","%s,(%s)+%d",
748 (rs = ((offset & 1) ? "r25" : "r24")),
749 aop->aopu.aop_dir, offset);
753 return aop->aopu.aop_reg[offset]->name;
756 assert("cannot be in bit space AOP_CRY\n");
760 s = aopLiteral(aop->aopu.aop_lit,offset);
761 emitcode("ldi","%s,lo8(%s)",(rs = ((offset & 1)?"r24" : "r25")),s);
766 return aop->aopu.aop_str[offset];
769 emitcode ("ldd","%s,Y+%d",
770 (rs = ((offset & 1) ? "r25" : "r24")),
771 aop->aopu.aop_stk+offset);
775 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
776 "aopget got unsupported aop->type");
779 /*-----------------------------------------------------------------*/
780 /* aopPut - puts a string for a aop */
781 /*-----------------------------------------------------------------*/
782 static void aopPut (asmop *aop, char *s, int offset)
787 if (aop->size && offset > ( aop->size - 1)) {
788 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
789 "aopPut got offset > aop->size");
793 /* will assign value to value */
794 /* depending on where it is ofcourse */
798 sprintf(d,"(%s)+%d", aop->aopu.aop_dir,offset);
801 sprintf(d,"%s",aop->aopu.aop_dir);
804 emitcode("sts","%s,%s",d,s);
808 if (toupper(*s) != 'R') {
810 emitcode("clr","%s",aop->aopu.aop_reg[offset]->name);
812 emitcode("ldi","r25,%s",s);
813 emitcode("mov","%s,r35",aop->aopu.aop_reg[offset]->name);
816 if (strcmp( aop->aopu.aop_reg[offset]->name,s)) {
817 emitcode("mov","%s,%s", aop->aopu.aop_reg[offset]->name,s);
823 if (offset > aop->coff) {
824 emitcode ("adiw","%s,%d",aop->aopu.aop_ptr->name,offset - aop->coff);
827 if (offset < aop->coff) {
828 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,aop->coff - offset);
832 emitcode("st","x,%s", s);
837 if (offset > aop->coff) {
838 emitcode("adiw","r30,%d",offset - aop->coff);
840 emitcode("sbiw","r30,%d",aop->coff - offset);
842 emitcode("lpm","%s,z",s);
845 if (offset > aop->coff) {
846 emitcode ("sdd","z+%d,%s",offset - aop->coff,s);
848 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,aop->coff - offset);
850 emitcode ("ld","%s,z",s);
856 emitcode("push","%s",s);
860 /* if used only for a condition code check */
861 assert(toupper(*s) == 'R');
863 emitcode("xrl","r0,r0");
864 emitcode("cpi","%s,0",s);
867 emitcode("cpc","r0,%s",s);
873 if (strcmp(aop->aopu.aop_str[offset],s))
874 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
878 emitcode ("std","y+%d,%s",offset,s);
882 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
883 "aopPut got unsupported aop->type");
889 /*-----------------------------------------------------------------*/
890 /* reAdjustPreg - points a register back to where it should */
891 /*-----------------------------------------------------------------*/
892 static void reAdjustPreg (asmop *aop)
897 if ((size = aop->size) <= 1)
903 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,size);
909 #define AOP(op) op->aop
910 #define AOP_TYPE(op) AOP(op)->type
911 #define AOP_SIZE(op) AOP(op)->size
912 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_X || \
913 AOP_TYPE(x) == AOP_Z))
914 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
915 (x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) || \
916 x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) )))
918 /*-----------------------------------------------------------------*/
919 /* genNotFloat - generates not for float operations */
920 /*-----------------------------------------------------------------*/
921 static void genNotFloat (operand *op, operand *res)
927 /* we will put 127 in the first byte of
929 aopPut(AOP(res),"127",0);
930 size = AOP_SIZE(op) - 1;
933 l = aopGet(op->aop,offset++);
937 emitcode("or","R0,%s", aopGet(op->aop, offset++);
939 tlbl = newiTempLabel(NULL);
941 tlbl = newiTempLabel(NULL);
942 aopPut(res->aop,zero,1);
943 emitcode("cpi","r0,0");
944 emitcode("breq","L%05d",tlbl->key);
945 aopPut(res->aop,one,1);
946 emitcode("","L%05d:",tlbl->key);
948 size = res->aop->size - 2;
950 /* put zeros in the rest */
952 aopPut(res->aop,zero,offset++);
955 /*-----------------------------------------------------------------*/
956 /* opIsGptr: returns non-zero if the passed operand is */
957 /* a generic pointer type. */
958 /*-----------------------------------------------------------------*/
959 static int opIsGptr(operand *op)
961 link *type = operandType(op);
963 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
970 /*-----------------------------------------------------------------*/
971 /* getDataSize - get the operand data size */
972 /*-----------------------------------------------------------------*/
973 static int getDataSize(operand *op)
977 if (size == GPTRSIZE)
979 link *type = operandType(op);
982 /* generic pointer; arithmetic operations
983 * should ignore the high byte (pointer type).
991 /*-----------------------------------------------------------------*/
992 /* outAcc - output Acc */
993 /*-----------------------------------------------------------------*/
994 static void outAcc(operand *result)
997 size = getDataSize(result);
999 aopPut(AOP(result),"r0",0);
1002 /* unsigned or positive */
1004 aopPut(AOP(result),zero,offset++);
1009 /*-----------------------------------------------------------------*/
1010 /* outBitC - output a bit C */
1011 /*-----------------------------------------------------------------*/
1012 static void outBitC(operand *result)
1014 emitcode("clr","r0");
1015 emitcode("rol","r0");
1019 /*-----------------------------------------------------------------*/
1020 /* toBoolean - emit code for orl a,operator(sizeop) */
1021 /*-----------------------------------------------------------------*/
1022 static void toBoolean(operand *oper, char *r, bool clr)
1024 int size = AOP_SIZE(oper) ;
1026 if (clr) emitcode ("clr","%s",r);
1028 emitcode("or","%s,%s",r,aopGet(AOP(oper),offset++));
1032 /*-----------------------------------------------------------------*/
1033 /* genNot - generate code for ! operation */
1034 /*-----------------------------------------------------------------*/
1035 static void genNot (iCode *ic)
1038 link *optype = operandType(IC_LEFT(ic));
1039 int size, offset = 1;
1041 /* assign asmOps to operand & result */
1042 aopOp (IC_LEFT(ic),ic,FALSE);
1043 aopOp (IC_RESULT(ic),ic,TRUE);
1045 /* if type float then do float */
1046 if (IS_FLOAT(optype)) {
1047 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1050 emitcode("clr","r24");
1051 tlbl = newiTempLabel(NULL);
1052 toBoolean(IC_LEFT(ic),"r0",TRUE);
1053 emitcode("bne","L%05d",tlbl->key);
1054 emitcode("ldi","r24,1");
1055 emitcode("","L%05d:",tlbl->key);
1056 aopPut(AOP(IC_RESULT(ic)),"r24",0);
1057 size = AOP_SIZE(IC_RESULT(ic)) -1;
1058 while (size--) aopPut(AOP(IC_RESULT(ic)),zero,offset++);
1062 /* release the aops */
1063 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1064 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1068 /*-----------------------------------------------------------------*/
1069 /* genCpl - generate code for complement */
1070 /*-----------------------------------------------------------------*/
1071 static void genCpl (iCode *ic)
1077 /* assign asmOps to operand & result */
1078 aopOp (IC_LEFT(ic),ic,FALSE);
1079 aopOp (IC_RESULT(ic),ic,TRUE);
1080 samer = sameRegs(AOP(IC_LEFT(ic),AOP(IC_RESULT(ic))));
1081 size = AOP_SIZE(IC_RESULT(ic));
1083 char *l = aopGet(AOP(IC_LEFT(ic)),offset);
1085 emitcode ("com","%s",l);
1087 aopPut(AOP(IC_RESULT(ic)),l,offset);
1088 emitcode ("com","%s",aopGet(AOP(IC_RESULT(ic)),offset++));
1094 /* release the aops */
1095 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1096 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1099 /*-----------------------------------------------------------------*/
1100 /* genUminusFloat - unary minus for floating points */
1101 /*-----------------------------------------------------------------*/
1102 static void genUminusFloat(operand *op,operand *result)
1104 int size ,offset =0 ;
1106 /* for this we just need to flip the
1107 first it then copy the rest in place */
1108 size = AOP_SIZE(op) - 1;
1109 l = aopGet(AOP(op),3);
1111 emitcode("ldi","r24,0x80");
1112 if (sameRegs(AOP(op),AOP(result))) {
1113 emitcode("eor","%s,r24",l);
1115 aopPut(AOP(result),l,3);
1116 emitcode("eor","%s,r24",aopGet(AOP(result),3));
1119 aopPut(AOP(result), aopGet(AOP(op),offset), offset);
1124 /*-----------------------------------------------------------------*/
1125 /* genUminus - unary minus code generation */
1126 /*-----------------------------------------------------------------*/
1127 static void genUminus (iCode *ic)
1130 link *optype, *rtype;
1134 aopOp(IC_LEFT(ic),ic,FALSE);
1135 aopOp(IC_RESULT(ic),ic,TRUE);
1137 optype = operandType(IC_LEFT(ic));
1138 rtype = operandType(IC_RESULT(ic));
1140 /* if float then do float stuff */
1141 if (IS_FLOAT(optype)) {
1142 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1146 /* otherwise subtract from zero */
1147 size = AOP_SIZE(IC_LEFT(ic));
1149 samer = sameRegs(AOP(IC_LEFT(ic)),AOP(IC_RESULT(ic)));
1152 char *l = aopGet(AOP(IC_LEFT(ic)),offset);
1154 emitcode("clr","r0");
1155 emitcode("sbc","r0,%s",l);
1156 aopPut(AOP(IC_RESULT(ic)),"r0",offset++);
1159 emitcode("clr","%s",s=aopGet(IC_RESULT(ic),offset++));
1160 emitcode("sbc","%s,%s",s,l);
1164 /* if any remaining bytes in the result */
1165 /* we just need to propagate the sign */
1166 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1167 symbol *tlbl = newiTempLabel(NULL);
1168 emitcode("clr","r0");
1169 emitcode("brcc","L%05d",tlbl->key);
1170 emitcode("com","r0");
1171 emitcode("","L%05d:",tlbl->key);
1173 aopPut(AOP(IC_RESULT(ic)),"r0",offset++);
1177 /* release the aops */
1178 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1179 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1182 /*-----------------------------------------------------------------*/
1183 /* assignResultValue - */
1184 /*-----------------------------------------------------------------*/
1185 static void assignResultValue(operand * oper)
1188 int size = AOP_SIZE(oper);
1190 aopPut(AOP(oper),fReturn[offset],offset);
1195 /*-----------------------------------------------------------------*/
1196 /* saveZreg - if indirect call then save z-pointer register */
1197 /*-----------------------------------------------------------------*/
1198 static void saveZreg (iCode *ic)
1200 /* only if live accross this call */
1201 if (ic->regSaved == 0 &&
1202 (bitVectBitValue(ic->rMask,R30_IDX) ||
1203 bitVectBitValue(ic->rMask,R31_IDX))) {
1205 emitcode("push","r30");
1206 emitcode("push","r31");
1210 /*-----------------------------------------------------------------*/
1211 /* popZreg - restore values of zreg */
1212 /*-----------------------------------------------------------------*/
1213 static void popZreg (iCode *ic)
1215 if (ic->regsSaved) {
1216 emitcode ("pop","r31");
1217 emitcode ("pop","r30");
1221 /*-----------------------------------------------------------------*/
1222 /* genIpush - genrate code for pushing this gets a little complex */
1223 /*-----------------------------------------------------------------*/
1224 static void genIpush (iCode *ic)
1226 int size, offset = 0 ;
1230 if (!ic->parmPush) {
1231 /* and the item is spilt then do nothing */
1232 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1236 for (lic = ic->next ; lic ; lic = lic->next)
1237 if (lic->op == PCALL) break;
1238 if (lic) saveZreg(lic);
1241 /* this is a paramter push */
1242 aopOp(IC_LEFT(ic),ic,FALSE);
1243 size = AOP_SIZE(IC_LEFT(ic));
1245 l = aopGet(AOP(IC_LEFT(ic)),offset++);
1246 emitcode("push","%s",l);
1249 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1252 /*-----------------------------------------------------------------*/
1253 /* genIpop - recover the registers: can happen only for spilling */
1254 /*-----------------------------------------------------------------*/
1255 static void genIpop (iCode *ic)
1260 /* if the temp was not pushed then */
1261 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1264 aopOp(IC_LEFT(ic),ic,FALSE);
1265 size = AOP_SIZE(IC_LEFT(ic));
1268 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--));
1270 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1273 /*-----------------------------------------------------------------*/
1274 /* genCall - generates a call statement */
1275 /*-----------------------------------------------------------------*/
1276 static void genCall (iCode *ic)
1280 /* if send set is not empty the assign */
1284 for (sic = setFirstItem(_G.sendSet) ; sic ;
1285 sic = setNextItem(_G.sendSet)) {
1286 int size, offset = 0;
1287 aopOp(IC_LEFT(sic),sic,FALSE);
1288 size = AOP_SIZE(IC_LEFT(sic));
1290 char *l = aopGet(AOP(IC_LEFT(sic)),offset);
1291 if (strcmp(l,fReturn[offset]))
1292 emitcode("mov","%s,%s",
1297 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1302 emitcode("call","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1303 OP_SYMBOL(IC_LEFT(ic))->rname :
1304 OP_SYMBOL(IC_LEFT(ic))->name));
1306 /* if we need assign a result value */
1307 if ((IS_ITEMP(IC_RESULT(ic)) &&
1308 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1309 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1310 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1312 aopOp(IC_RESULT(ic),ic,FALSE);
1313 assignResultValue(IC_RESULT(ic));
1314 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1317 /* adjust the stack for parameters if required */
1318 if (IC_LEFT(ic)->parmBytes) {
1319 if (IC_LEFT(ic)->parmBytes > 63) {
1320 emitcode("sbiw","r28,%d",IC_LEFT(ic)->parmBytes);
1322 emitcode("subi","r28,lo8(%d)",IC_LEFT(ic)->parmBytes);
1323 emitcode("sbci","r29,hi8(%d)",IC_LEFT(ic)->parmBytes);
1329 /*-----------------------------------------------------------------*/
1330 /* genPcall - generates a call by pointer statement */
1331 /*-----------------------------------------------------------------*/
1332 static void genPcall (iCode *ic)
1336 if (!ic->regsSaved) saveZreg(ic);
1338 aopOp(IC_LEFT(ic),ic,FALSE);
1339 emitcode("mov","r30",aopGet(AOP(IC_LEFT(ic)),0));
1340 emitcode("mov","r31",aopGet(AOP(IC_RIGHT(ic)),0));
1341 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1343 /* if send set is not empty the assign */
1347 for (sic = setFirstItem(_G.sendSet) ; sic ;
1348 sic = setNextItem(_G.sendSet)) {
1349 int size, offset = 0;
1350 aopOp(IC_LEFT(sic),sic,FALSE);
1351 size = AOP_SIZE(IC_LEFT(sic));
1353 char *l = aopGet(AOP(IC_LEFT(sic)),offset);
1354 if (strcmp(l,fReturn[offset]))
1355 emitcode("mov","%s,%s",
1360 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1365 emitcode("icall","");
1367 /* if we need assign a result value */
1368 if ((IS_ITEMP(IC_RESULT(ic)) &&
1369 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1370 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
1371 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1373 aopOp(IC_RESULT(ic),ic,FALSE);
1375 assignResultValue(IC_RESULT(ic));
1376 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1379 /* adjust the stack for parameters if
1381 if (IC_LEFT(ic)->parmBytes) {
1383 if (IC_LEFT(ic)->parmBytes > 3) {
1384 emitcode("mov","a,%s",spname);
1385 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1386 emitcode("mov","%s,a",spname);
1388 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1389 emitcode("dec","%s",spname);
1393 /* adjust the stack for parameters if required */
1394 if (IC_LEFT(ic)->parmBytes) {
1395 if (IC_LEFT(ic)->parmBytes > 63) {
1396 emitcode("sbiw","r28,%d",IC_LEFT(ic)->parmBytes);
1398 emitcode("subi","r28,lo8(%d)",IC_LEFT(ic)->parmBytes);
1399 emitcode("sbci","r29,hi8(%d)",IC_LEFT(ic)->parmBytes);
1402 if (ic->regsSaved) popZregs(ic);
1405 /*-----------------------------------------------------------------*/
1406 /* resultRemat - result is rematerializable */
1407 /*-----------------------------------------------------------------*/
1408 static int resultRemat (iCode *ic)
1410 if (SKIP_IC(ic) || ic->op == IFX)
1413 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1414 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1415 if (sym->remat && !POINTER_SET(ic))
1423 #define STRCASECMP stricmp
1425 #define STRCASECMP strcasecmp
1428 /*-----------------------------------------------------------------*/
1429 /* inExcludeList - return 1 if the string is in exclude Reg list */
1430 /*-----------------------------------------------------------------*/
1431 static bool inExcludeList(char *s)
1435 if (options.excludeRegs[i] &&
1436 STRCASECMP(options.excludeRegs[i],"none") == 0)
1439 for ( i = 0 ; options.excludeRegs[i]; i++) {
1440 if (options.excludeRegs[i] &&
1441 STRCASECMP(s,options.excludeRegs[i]) == 0)
1447 /*-----------------------------------------------------------------*/
1448 /* genFunction - generated code for function entry */
1449 /*-----------------------------------------------------------------*/
1450 static void genFunction (iCode *ic)
1457 /* create the function header */
1458 emitcode(";","-----------------------------------------");
1459 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1460 emitcode(";","-----------------------------------------");
1462 emitcode("","%s:",sym->rname);
1463 fetype = getSpec(operandType(IC_LEFT(ic)));
1465 /* if critical function then turn interrupts off */
1466 if (SPEC_CRTCL(fetype))
1469 if (IS_ISR(sym->etype)) {
1472 /* save the preserved registers that are used in this function */
1473 for (i = R2_IDX ; i <= R15_IDX ; i++ ) {
1474 if (bitVectBitValue(sym->regsUsed,i)) {
1476 emitcode("push","%s",avr_regWithIdx(i)->name);
1479 /* now for the pointer registers */
1480 if (bitVectBitValue(sym->regsUsed,R26_IDX)) {
1482 emitcode("push","r26");
1484 if (bitVectBitValue(sym->regsUsed,R27_IDX)) {
1486 emitcode("push","r27");
1488 if (bitVectBitValue(sym->regsUsed,R30_IDX)) {
1490 emitcode("push","r30");
1492 if (bitVectBitValue(sym->regsUsed,R31_IDX)) {
1494 emitcode("push","r31");
1496 /* adjust the stack for the function */
1498 emitcode ("push","r28");
1499 emitcode ("push","r29");
1500 emitcode ("in","r28,__SP_L__");
1501 emitcode ("in","r29,__SP_H__");
1502 if (sym->stack <= 63) {
1503 emitcode("sbiw","r28,%d",sym->stack);
1505 emitcode ("subi","r28,lo8(%d)",sym->stack);
1506 emitcode ("sbci","r29,hi8(%d)",sym->stack);
1508 emitcode("out","__SP_L__,r28");
1509 emitcode("out","__SP_H__,r29");
1513 /*-----------------------------------------------------------------*/
1514 /* genEndFunction - generates epilogue for functions */
1515 /*-----------------------------------------------------------------*/
1516 static void genEndFunction (iCode *ic)
1518 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1520 /* restore stack pointer */
1521 if (sym->stack <= 63) {
1522 emitcode("adiw","r28,%d",sym->stack);
1524 emitcode ("subi","r28,lo8(-%d)",sym->stack);
1525 emitcode ("sbci","r29,hi8(-%d)",sym->stack);
1527 emitcode("out","__SP_L__,r28");
1528 emitcode("out","__SP_H__,r29");
1530 /* pop frame pointer */
1531 emitcode ("pop","r29");
1532 emitcode ("pop","r28");
1534 /* restore preserved registers */
1535 if (bitVectBitValue(sym->regsUsed,R31_IDX)) {
1537 emitcode("pop","r31");
1539 if (bitVectBitValue(sym->regsUsed,R30_IDX)) {
1541 emitcode("pop","r30");
1543 if (bitVectBitValue(sym->regsUsed,R27_IDX)) {
1545 emitcode("push","r27");
1547 if (bitVectBitValue(sym->regsUsed,R26_IDX)) {
1549 emitcode("push","r26");
1551 for (i = R15_IDX ; i >= R2_IDX ; i-- ) {
1552 if (bitVectBitValue(sym->regsUsed,i)) {
1554 emitcode("pop","%s",avr_regWithIdx(i)->name);
1558 if (IS_ISR(sym->etype)) {
1561 if (SPEC_CRTCL(fetype))
1565 /*-----------------------------------------------------------------*/
1566 /* genRet - generate code for return statement */
1567 /*-----------------------------------------------------------------*/
1568 static void genRet (iCode *ic)
1570 int size,offset = 0 , pushed = 0;
1572 /* if we have no return value then
1573 just generate the "ret" */
1577 /* we have something to return then
1578 move the return value into place */
1579 aopOp(IC_LEFT(ic),ic,FALSE);
1580 size = AOP_SIZE(IC_LEFT(ic));
1584 l = aopGet(AOP(IC_LEFT(ic)),offset);
1585 if (strcmp(fReturn[offset],l))
1586 emitcode("mov","%s,%s",fReturn[offset++],l);
1589 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
1592 /* generate a jump to the return label
1593 if the next is not the return statement */
1594 if (!(ic->next && ic->next->op == LABEL &&
1595 IC_LABEL(ic->next) == returnLabel))
1597 emitcode("rjmp","L%05d",returnLabel->key);
1601 /*-----------------------------------------------------------------*/
1602 /* genLabel - generates a label */
1603 /*-----------------------------------------------------------------*/
1604 static void genLabel (iCode *ic)
1606 /* special case never generate */
1607 if (IC_LABEL(ic) == entryLabel)
1610 emitcode("","L%05d:",IC_LABEL(ic)->key);
1613 /*-----------------------------------------------------------------*/
1614 /* genGoto - generates a ljmp */
1615 /*-----------------------------------------------------------------*/
1616 static void genGoto (iCode *ic)
1618 emitcode ("rjmp","L%05d:",(IC_LABEL(ic)->key+100));
1621 /*-----------------------------------------------------------------*/
1622 /* findLabelBackwards: walks back through the iCode chain looking */
1623 /* for the given label. Returns number of iCode instructions */
1624 /* between that label and given ic. */
1625 /* Returns zero if label not found. */
1626 /*-----------------------------------------------------------------*/
1627 static int findLabelBackwards(iCode *ic, int key)
1636 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
1638 /* printf("findLabelBackwards = %d\n", count); */
1646 /*-----------------------------------------------------------------*/
1647 /* genPlusIncr :- does addition with increment if possible */
1648 /*-----------------------------------------------------------------*/
1649 static bool genPlusIncr (iCode *ic)
1651 unsigned int icount ;
1653 /* will try to generate an increment */
1654 /* if the right side is not a literal
1656 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1659 icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
1661 /* if the sizes are greater than 2 or they are not the same regs
1663 if (AOP_SIZE(IC_RESULT(ic)) > 2 ||
1664 AOP_SIZE(IC_LEFT(ic)) > 2 ||
1665 !sameRegs(AOP(IC_LEFT(ic)),AOP(IC_RIGHT(ic))))
1668 /* so we know LEFT & RESULT in the same registers and add
1670 /* for short & char types */
1671 if (AOP_SIZE(IC_RESULT(ic)) < 2) {
1673 emitcode("inc","%s",aopGet(AOP(IC_LEFT(ic)),0));
1676 emicode("subi","%s,lo8(%d)",aopGet(AOP(IC_LEFT(ic)),0),-icount);
1680 /* if register pair and starts with 26/30 then adiw */
1681 if (isRegPair(AOP(IC_RESULT(ic))) && icount > 0 && icount < 64 &&
1682 ( IS_REGIDX(AOP(IC_RESULT(ic)),R26_IDX) ||
1683 IS_REGIDX(AOP(IC_RESULT(ic)),R30_IDX) )) {
1684 emitcode("adiw","%s,%d",aopGet(AOP(IC_RESULT(ic)),0),icount);
1689 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_RESULT(ic)),0),-icount);
1690 emitcode("sbci","%s,hi8(%d)",aopGet(AOP(IC_RESULT(ic)),1),-icount);
1694 /* This is the pure and virtuous version of this code.
1695 * I'm pretty certain it's right, but not enough to toss the old
1698 static void adjustArithmeticResult(iCode *ic)
1700 if (opIsGptr(IC_RESULT(ic)) &&
1701 opIsGptr(IC_LEFT(ic)) &&
1702 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1704 aopPut(AOP(IC_RESULT(ic)),
1705 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1),
1709 if (opIsGptr(IC_RESULT(ic)) &&
1710 opIsGptr(IC_RIGHT(ic)) &&
1711 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
1713 aopPut(AOP(IC_RESULT(ic)),
1714 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1),
1718 if (opIsGptr(IC_RESULT(ic)) &&
1719 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
1720 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
1721 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
1722 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
1724 sprintf(buffer,"%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
1725 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
1729 /*-----------------------------------------------------------------*/
1730 /* genPlus - generates code for addition */
1731 /*-----------------------------------------------------------------*/
1732 static void genPlus (iCode *ic)
1734 int size, offset = 0;
1736 /* special cases :- */
1738 aopOp (IC_LEFT(ic),ic,FALSE);
1739 aopOp (IC_RIGHT(ic),ic,FALSE);
1740 aopOp (IC_RESULT(ic),ic,TRUE);
1742 /* if I can do an increment instead
1743 of add then GOOD for ME */
1744 if (genPlusIncr (ic) == TRUE)
1747 size = getDataSize(IC_RESULT(ic));
1750 aopPut(AOP(IC_RESULT(ic)),aopGet(AOP(IC_RIGHT(ic)),offset),offset);
1752 emitcode("add","%s,%s",aopGet(AOP(IC_RESULT(ic)),offset),
1753 aopGet(AOP(IC_LEFT(ic)),offset));
1755 emitcode("adc","%s,%s",aopGet(AOP(IC_RESULT(ic)),offset),
1756 aopGet(AOP(IC_LEFT(ic)),offset));
1760 adjustArithmeticResult(ic);
1763 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1764 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1765 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1768 /*-----------------------------------------------------------------*/
1769 /* genMinusDec :- does subtraction with deccrement if possible */
1770 /*-----------------------------------------------------------------*/
1771 static bool genMinusDec (iCode *ic)
1773 unsigned int icount ;
1775 /* will try to generate an increment */
1776 /* if the right side is not a literal
1778 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1781 icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
1783 /* if the sizes are greater than 2 or they are not the same regs
1785 if (AOP_SIZE(IC_RESULT(ic)) > 2 ||
1786 AOP_SIZE(IC_LEFT(ic)) > 2 ||
1787 !sameRegs(AOP(IC_LEFT(ic)),AOP(IC_RIGHT(ic))))
1790 /* so we know LEFT & RESULT in the same registers and add
1792 /* for short & char types */
1793 if (AOP_SIZE(IC_RESULT(ic)) < 2) {
1795 emitcode("dec","%s",aopGet(AOP(IC_LEFT(ic)),0));
1798 emicode("subi","%s,lo8(%d)",aopGet(AOP(IC_LEFT(ic)),0),icount);
1802 /* if register pair and starts with 26/30 then adiw */
1803 if (isRegPair(AOP(IC_RESULT(ic))) && icount > 0 && icount < 64 &&
1804 ( IS_REGIDX(AOP(IC_RESULT(ic)),R26_IDX) ||
1805 IS_REGIDX(AOP(IC_RESULT(ic)),R30_IDX) )) {
1806 emitcode("sbiw","%s,%d",aopGet(AOP(IC_RESULT(ic)),0),icount);
1811 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_RESULT(ic)),0),icount);
1812 emitcode("sbci","%s,hi8(%d)",aopGet(AOP(IC_RESULT(ic)),1),icount);
1816 /*-----------------------------------------------------------------*/
1817 /* addSign - complete with sign */
1818 /*-----------------------------------------------------------------*/
1819 static void addSign(operand *result, int offset, int sign)
1821 int size = (getDataSize(result) - offset);
1824 emitcode("rlc","a");
1825 emitcode("subb","a,acc");
1827 aopPut(AOP(result),"a",offset++);
1830 aopPut(AOP(result),zero,offset++);
1834 /*-----------------------------------------------------------------*/
1835 /* genMinus - generates code for subtraction */
1836 /*-----------------------------------------------------------------*/
1837 static void genMinus (iCode *ic)
1839 int size, offset = 0;
1840 unsigned long lit = 0L;
1842 aopOp (IC_LEFT(ic),ic,FALSE);
1843 aopOp (IC_RIGHT(ic),ic,FALSE);
1844 aopOp (IC_RESULT(ic),ic,TRUE);
1846 /* if I can do an decrement instead
1847 of subtract then GOOD for ME */
1848 if (genMinusDec (ic) == TRUE)
1851 size = getDataSize(IC_RESULT(ic));
1854 aopPut(AOP(IC_RESULT(ic)),aopGet(AOP(IC_RIGHT(ic)),offset),offset);
1856 emitcode("sub","%s,%s",aopGet(AOP(IC_RESULT(ic)),offset),
1857 aopGet(AOP(IC_LEFT(ic)),offset));
1859 emitcode("sbc","%s,%s",aopGet(AOP(IC_RESULT(ic)),offset),
1860 aopGet(AOP(IC_LEFT(ic)),offset));
1863 adjustArithmeticResult(ic);
1866 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1867 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1868 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1871 /*-----------------------------------------------------------------*/
1872 /* genMultOneByte : 8 bit multiplication & division */
1873 /*-----------------------------------------------------------------*/
1874 static void genMultOneByte (operand *left,
1878 link *opetype = operandType(result);
1883 /* (if two literals, the value is computed before) */
1884 /* if one literal, literal on the right */
1885 if (AOP_TYPE(left) == AOP_LIT){
1891 size = AOP_SIZE(result);
1893 if (SPEC_USIGN(opetype)) {
1894 emitcode("mul","%s,%s",
1895 aopGet(IC_LEFT(ic),0),
1896 aopGet(IC_RIGHT(ic),0));
1898 emitcode("muls","%s,%s",
1899 aopGet(IC_LEFT(ic),0),
1900 aopGet(IC_RIGHT(ic),0));
1902 aopPut(AOP(IC_RESULT(ic)),"r0",0);
1904 aopPut(AOP(IC_RESULT(ic)),"r1",1);
1907 if (SPEC_USIGN(opetype)) {
1909 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
1912 lbl = newiTempLabel(NULL);
1913 emitcode("ldi","r24,0");
1914 emitcode("brcc","L%05d",lbl->key);
1915 emitcode("ldi","r24,lo8(-1)");
1916 emitcode("","L%05d:",lbl->key);
1917 while (size--) aopPut(AOP(IC_RESULT(ic)),"r24",offset++);
1923 /*-----------------------------------------------------------------*/
1924 /* genMult - generates code for multiplication */
1925 /*-----------------------------------------------------------------*/
1926 static void genMult (iCode *ic)
1928 operand *left = IC_LEFT(ic);
1929 operand *right = IC_RIGHT(ic);
1930 operand *result= IC_RESULT(ic);
1932 /* assign the amsops */
1933 aopOp (left,ic,FALSE);
1934 aopOp (right,ic,FALSE);
1935 aopOp (result,ic,TRUE);
1937 /* if both are of size == 1 */
1938 if (AOP_SIZE(left) == 1 &&
1939 AOP_SIZE(right) == 1 ) {
1940 genMultOneByte(left,right,result);
1944 /* should have been converted to function call */
1948 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1949 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1950 freeAsmop(result,NULL,ic,TRUE);
1953 /*-----------------------------------------------------------------*/
1954 /* genDiv - generates code for division */
1955 /*-----------------------------------------------------------------*/
1956 static void genDiv (iCode *ic)
1958 /* should have been converted to function call */
1962 /*-----------------------------------------------------------------*/
1963 /* genMod - generates code for division */
1964 /*-----------------------------------------------------------------*/
1965 static void genMod (iCode *ic)
1967 /* should have been converted to function call */
1979 /*-----------------------------------------------------------------*/
1980 /* revavrcnd - reverse a conditional for avr */
1981 /*-----------------------------------------------------------------*/
1982 static int revavrcnd(int type)
1986 } rar[] = { { AVR_EQ, AVR_NE}, {AVR_LT, AVR_GE}};
1989 for (i = 0 ; i < (sizeof(rar)/sizeof(rar[0]));i++) {
1990 if (rar[i].type == type) return rar[i].rtype;
1991 if (rar[i].rtype== type) return rar[i].type;
1993 assert(1); /* cannot happen */
1996 static char *br_name[4] = {"breq","brne","brlt","brge"};
1997 static char *br_uname[4]= {"breq","brne","brlo","brcc"};
1999 /*-----------------------------------------------------------------*/
2000 /* genBranch - generate the branch instruction */
2001 /*-----------------------------------------------------------------*/
2002 static void genBranch (iCode *ifx, int br_type, int sign)
2004 int tj = (IC_TRUE(ifx) ? 1 : 0) ;
2006 if (tj) { /* if true jump */
2007 char *nm = (sign ? br_name[br_type] : br_uname[br_type]);
2008 emitcode(nm,"L%05d",IC_TRUE(ifx)->key);
2009 } else { /* if false jump */
2010 int rtype = revavrcnd(br_type);
2011 char *nm = (sign ? br_name[rtype] : br_uname[rtype]);
2012 emitcode(nm,"L%05d",IC_FALSE(ifx)->key);
2017 /*-----------------------------------------------------------------*/
2018 /* genCmp - compare & jump */
2019 /*-----------------------------------------------------------------*/
2020 static void genCmp (iCode *ic, iCode *ifx, int br_type)
2022 operand *left, *right, *result;
2023 link *letype , *retype;
2025 int sign, size, offset =0;
2028 right= IC_RIGHT(ic);
2029 result = IC_RESULT(ic);
2031 letype = getSpec(operandType(left));
2032 retype =getSpec(operandType(right));
2033 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2035 /* assign the amsops */
2036 aopOp (left,ic,FALSE);
2037 aopOp (right,ic,FALSE);
2038 aopOp (result,ic,TRUE);
2039 size = AOP_SIZE(AOP(left));
2043 if (AOP_TYPE(AOP(right)) == AOP_LIT) {
2044 emitcode("cpi","%s,lo8(%d)",aopGet(AOP(left),0),
2045 (int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
2046 genBranch(ifx,br_type);
2047 } else { /* right != literal */
2048 emitcode("cp","%s,%s",aopGet(AOP(left),0),aopGet(AOP(right),0));
2049 genBranch(ifx,br_type);
2050 } else { /* size != 1 */
2053 emitcode("cp","%s,%s",aopGet(AOP(left),0),aopGet(AOP(right),0));
2055 emitcode("cpc","%s,%s",aopGet(AOP(left),offset),aopGet(AOP(right),offset));
2058 genBranch(ifx,br_type);
2060 } else { /* no ifx */
2061 emitCode("clr","r0");
2064 emitcode("cp","%s,%s",aopGet(AOP(left),0),aopGet(AOP(right),0));
2066 emitcode("cpc","%s,%s",aopGet(AOP(left),offset),aopGet(AOP(right),offset));
2069 lbl = newiTempLabel(NULL);
2070 br_type = revavrcnd(br_type);
2071 if (sign) emitcode(br_uname[br_type],"L%05d",lbl->key);
2072 else emitcode(br_name[br_type],"L%05d",lbl->key);
2073 emitcode("inc","r0");
2074 emitcode("","L%05d:",lbl->key);
2075 aopPut(AOP(result),"r0",0);
2076 size = AOP_SIZE(AOP(result)) - 1;
2078 while (size--) aopPut(AOP(result),zero,offset++);
2081 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2082 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2083 freeAsmop(result,NULL,ic,TRUE);
2086 /*-----------------------------------------------------------------*/
2087 /* genCmpGt :- greater than comparison */
2088 /*-----------------------------------------------------------------*/
2089 static void genCmpGt (iCode *ic, iCode *ifx)
2091 /* should have transformed by the parser */
2095 /*-----------------------------------------------------------------*/
2096 /* genCmpLt - less than comparisons */
2097 /*-----------------------------------------------------------------*/
2098 static void genCmpLt (iCode *ic, iCode *ifx)
2100 genCmp(ic,ifx,AVR_LT);
2103 /*-----------------------------------------------------------------*/
2104 /* genCmpEq - generates code for equal to */
2105 /*-----------------------------------------------------------------*/
2106 static void genCmpEq (iCode *ic, iCode *ifx)
2108 genCmp(ic,ifx,AVR_EQ);
2111 /*-----------------------------------------------------------------*/
2112 /* genCmpNe - generates code for not equal to */
2113 /*-----------------------------------------------------------------*/
2114 static void genCmpNe (iCode *ic, iCode *ifx)
2116 genCmp(ic,ifx,AVR_NE);
2119 /*-----------------------------------------------------------------*/
2120 /* genCmpGe - generates code for greater than equal to */
2121 /*-----------------------------------------------------------------*/
2122 static void genCmpGe (iCode *ic, iCode *ifx)
2124 genCmp(ic,ifx,AVR_GE);
2127 /*-----------------------------------------------------------------*/
2128 /* genCmpLe - generates code for less than equal to */
2129 /*-----------------------------------------------------------------*/
2130 static void genCmpLe (iCode *ic, iCode *ifx)
2132 operand *left = IC_LEFT(ic);
2133 operand *right= IC_RIGHT(ic);
2135 IC_RIGHT(ic) = left;
2136 IC_LEFT(ic) = right;
2137 gemCmp(ic,ifx,AVR_GE);
2140 /*-----------------------------------------------------------------*/
2141 /* ifxForOp - returns the icode containing the ifx for operand */
2142 /*-----------------------------------------------------------------*/
2143 static iCode *ifxForOp ( operand *op, iCode *ic )
2145 /* if true symbol then needs to be assigned */
2146 if (IS_TRUE_SYMOP(op))
2149 /* if this has register type condition and
2150 the next instruction is ifx with the same operand
2151 and live to of the operand is upto the ifx only then */
2153 ic->next->op == IFX &&
2154 IC_COND(ic->next)->key == op->key &&
2155 OP_SYMBOL(op)->liveTo <= ic->next->seq )
2160 /*-----------------------------------------------------------------*/
2161 /* genAndOp - for && operation */
2162 /*-----------------------------------------------------------------*/
2163 static void genAndOp (iCode *ic)
2165 operand *left,*right, *result;
2169 /* note here that && operations that are in an
2170 if statement are taken away by backPatchLabels
2171 only those used in arthmetic operations remain */
2172 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2173 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2174 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2176 tlbl = newitempLabel(NULL);
2177 toBoolean(left,"r0",TRUE);
2178 toBoolean(right,"r1",TRUE);
2179 emitcode("and","r0,r1");
2180 emitcode("ldi","r24,1");
2181 emitcode("breq","L%05d",tlbl->key);
2182 emitcode("dec","r24");
2183 emicode("","L%05d:",tlbl->key);
2184 aopPut(AOP(result),"r24",0);
2185 size = AOP_SIZE(AOP(result)) -1;
2187 while (size--) aopPut(AOP(result),zero,offset++);
2189 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2190 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2191 freeAsmop(result,NULL,ic,TRUE);
2195 /*-----------------------------------------------------------------*/
2196 /* genOrOp - for || operation */
2197 /*-----------------------------------------------------------------*/
2198 static void genOrOp (iCode *ic)
2200 operand *left,*right, *result;
2204 /* note here that || operations that are in an
2205 if statement are taken away by backPatchLabels
2206 only those used in arthmetic operations remain */
2207 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2208 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2209 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2211 tlbl = newitempLabel(NULL);
2212 toBoolean(left,"r0",TRUE);
2213 toBoolean(right,"r0",FALSE);
2214 emitcode("ldi","r24,1");
2215 emitcode("breq","L%05d",tlbl->key);
2216 emitcode("dec","r24");
2217 emicode("","L%05d:",tlbl->key);
2218 aopPut(AOP(result),"r24",0);
2219 size = AOP_SIZE(AOP(result)) -1;
2221 while (size--) aopPut(AOP(result),zero,offset++);
2223 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2224 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2225 freeAsmop(result,NULL,ic,TRUE);
2228 /*-----------------------------------------------------------------*/
2229 /* isLiteralBit - test if lit == 2^n */
2230 /*-----------------------------------------------------------------*/
2231 static int isLiteralBit(unsigned long lit)
2233 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
2234 0x100L,0x200L,0x400L,0x800L,
2235 0x1000L,0x2000L,0x4000L,0x8000L,
2236 0x10000L,0x20000L,0x40000L,0x80000L,
2237 0x100000L,0x200000L,0x400000L,0x800000L,
2238 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
2239 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
2242 for(idx = 0; idx < 32; idx++)
2249 /*-----------------------------------------------------------------*/
2250 /* genAnd - code for and */
2251 /*-----------------------------------------------------------------*/
2252 static void genAnd (iCode *ic, iCode *ifx)
2254 operand *left, *right, *result;
2257 unsigned long lit = 0L;
2259 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2260 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2261 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2263 if (ifx) { /* used only for jumps */
2264 if (AOP_TYPE(AOP(right)) == AOP_LIT) {
2265 int p2 = powof2((int) floatFromVal (AOP(right)->aopu.aop_lit));
2266 if (p2) { /* right side is a power of 2 */
2267 l = aopGet(AOP(left),p2 / 8);
2269 emitcode("sbrc","%s,%d",l,p2 % 8);
2270 emitcode("rjmp","L%05d",IC_TRUE(ifx)->key);
2272 emitcode("sbrs","%s,%d",l,p2 % 8);
2273 emitcode("rjmp","L%05d",IC_FALSE(ifx)->key);
2275 } else { /* right not power of two */
2278 } else { /* right is not a literal */
2280 } else { /* other jump -> result goes to register*/
2284 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2285 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2286 freeAsmop(result,NULL,ic,TRUE);
2289 /*-----------------------------------------------------------------*/
2290 /* genOr - code for or */
2291 /*-----------------------------------------------------------------*/
2292 static void genOr (iCode *ic, iCode *ifx)
2294 operand *left, *right, *result;
2296 unsigned long lit = 0L;
2298 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2299 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2300 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2303 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2305 AOP_TYPE(left), AOP_TYPE(right));
2306 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2308 AOP_SIZE(left), AOP_SIZE(right));
2311 /* if left is a literal & right is not then exchange them */
2312 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2313 AOP_NEEDSACC(left)) {
2314 operand *tmp = right ;
2319 /* if result = right then exchange them */
2320 if(sameRegs(AOP(result),AOP(right))){
2321 operand *tmp = right ;
2326 /* if right is bit then exchange them */
2327 if (AOP_TYPE(right) == AOP_CRY &&
2328 AOP_TYPE(left) != AOP_CRY){
2329 operand *tmp = right ;
2333 if(AOP_TYPE(right) == AOP_LIT)
2334 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2336 size = AOP_SIZE(result);
2340 if (AOP_TYPE(left) == AOP_CRY){
2341 if(AOP_TYPE(right) == AOP_LIT){
2342 // c = bit & literal;
2344 // lit != 0 => result = 1
2345 if(AOP_TYPE(result) == AOP_CRY){
2347 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
2349 continueIfTrue(ifx);
2352 emitcode("setb","c");
2354 // lit == 0 => result = left
2355 if(size && sameRegs(AOP(result),AOP(left)))
2357 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2360 if (AOP_TYPE(right) == AOP_CRY){
2362 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
2363 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
2367 symbol *tlbl = newiTempLabel(NULL);
2368 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
2369 emitcode("setb","c");
2370 emitcode("jb","%s,%05d$",
2371 AOP(left)->aopu.aop_dir,tlbl->key+100);
2373 emitcode("jnz","%05d$",tlbl->key+100);
2374 if((AOP_TYPE(result) == AOP_CRY) && ifx){
2375 jmpTrueOrFalse(ifx, tlbl);
2379 emitcode("","%05d$:",tlbl->key+100);
2388 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
2389 genIfxJump(ifx, "c");
2393 // if(val | 0xZZ) - size = 0, ifx != FALSE -
2394 // bit = val | 0xZZ - size = 1, ifx = FALSE -
2395 if((AOP_TYPE(right) == AOP_LIT) &&
2396 (AOP_TYPE(result) == AOP_CRY) &&
2397 (AOP_TYPE(left) != AOP_CRY)){
2401 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
2403 continueIfTrue(ifx);
2406 // lit = 0, result = boolean(left)
2408 emitcode("setb","c");
2411 symbol *tlbl = newiTempLabel(NULL);
2412 emitcode("jnz","%05d$",tlbl->key+100);
2414 emitcode("","%05d$:",tlbl->key+100);
2416 genIfxJump (ifx,"a");
2424 /* if left is same as result */
2425 if(sameRegs(AOP(result),AOP(left))){
2426 for(;size--; offset++) {
2427 if(AOP_TYPE(right) == AOP_LIT){
2428 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2431 if (IS_AOP_PREG(left)) {
2432 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2433 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
2434 aopPut(AOP(result),"a",offset);
2436 emitcode("orl","%s,%s",
2437 aopGet(AOP(left),offset,FALSE,TRUE),
2438 aopGet(AOP(right),offset,FALSE,FALSE));
2440 if (AOP_TYPE(left) == AOP_ACC)
2441 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
2443 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2444 if (IS_AOP_PREG(left)) {
2445 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
2446 aopPut(AOP(result),"a",offset);
2448 emitcode("orl","%s,a",
2449 aopGet(AOP(left),offset,FALSE,TRUE));
2454 // left & result in different registers
2455 if(AOP_TYPE(result) == AOP_CRY){
2457 // if(size), result in bit
2458 // if(!size && ifx), conditional oper: if(left | right)
2459 symbol *tlbl = newiTempLabel(NULL);
2460 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
2462 emitcode("setb","c");
2464 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2465 emitcode("orl","a,%s",
2466 aopGet(AOP(left),offset,FALSE,FALSE));
2467 emitcode("jnz","%05d$",tlbl->key+100);
2472 emitcode("","%05d$:",tlbl->key+100);
2475 jmpTrueOrFalse(ifx, tlbl);
2476 } else for(;(size--);offset++){
2478 // result = left & right
2479 if(AOP_TYPE(right) == AOP_LIT){
2480 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2482 aopGet(AOP(left),offset,FALSE,FALSE),
2487 // faster than result <- left, anl result,right
2488 // and better if result is SFR
2489 if (AOP_TYPE(left) == AOP_ACC)
2490 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
2492 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2493 emitcode("orl","a,%s",
2494 aopGet(AOP(left),offset,FALSE,FALSE));
2496 aopPut(AOP(result),"a",offset);
2501 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2502 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2503 freeAsmop(result,NULL,ic,TRUE);
2506 /*-----------------------------------------------------------------*/
2507 /* genXor - code for xclusive or */
2508 /*-----------------------------------------------------------------*/
2509 static void genXor (iCode *ic, iCode *ifx)
2511 operand *left, *right, *result;
2513 unsigned long lit = 0L;
2515 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2516 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2517 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2520 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2522 AOP_TYPE(left), AOP_TYPE(right));
2523 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2525 AOP_SIZE(left), AOP_SIZE(right));
2528 /* if left is a literal & right is not ||
2529 if left needs acc & right does not */
2530 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2531 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
2532 operand *tmp = right ;
2537 /* if result = right then exchange them */
2538 if(sameRegs(AOP(result),AOP(right))){
2539 operand *tmp = right ;
2544 /* if right is bit then exchange them */
2545 if (AOP_TYPE(right) == AOP_CRY &&
2546 AOP_TYPE(left) != AOP_CRY){
2547 operand *tmp = right ;
2551 if(AOP_TYPE(right) == AOP_LIT)
2552 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2554 size = AOP_SIZE(result);
2558 if (AOP_TYPE(left) == AOP_CRY){
2559 if(AOP_TYPE(right) == AOP_LIT){
2560 // c = bit & literal;
2562 // lit>>1 != 0 => result = 1
2563 if(AOP_TYPE(result) == AOP_CRY){
2565 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
2567 continueIfTrue(ifx);
2570 emitcode("setb","c");
2574 // lit == 0, result = left
2575 if(size && sameRegs(AOP(result),AOP(left)))
2577 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2579 // lit == 1, result = not(left)
2580 if(size && sameRegs(AOP(result),AOP(left))){
2581 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
2584 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2585 emitcode("cpl","c");
2592 symbol *tlbl = newiTempLabel(NULL);
2593 if (AOP_TYPE(right) == AOP_CRY){
2595 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
2598 int sizer = AOP_SIZE(right);
2600 // if val>>1 != 0, result = 1
2601 emitcode("setb","c");
2603 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
2605 // test the msb of the lsb
2606 emitcode("anl","a,#0xfe");
2607 emitcode("jnz","%05d$",tlbl->key+100);
2611 emitcode("rrc","a");
2613 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
2614 emitcode("cpl","c");
2615 emitcode("","%05d$:",(tlbl->key+100));
2622 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
2623 genIfxJump(ifx, "c");
2627 if(sameRegs(AOP(result),AOP(left))){
2628 /* if left is same as result */
2629 for(;size--; offset++) {
2630 if(AOP_TYPE(right) == AOP_LIT){
2631 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2634 if (IS_AOP_PREG(left)) {
2635 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2636 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
2637 aopPut(AOP(result),"a",offset);
2639 emitcode("xrl","%s,%s",
2640 aopGet(AOP(left),offset,FALSE,TRUE),
2641 aopGet(AOP(right),offset,FALSE,FALSE));
2643 if (AOP_TYPE(left) == AOP_ACC)
2644 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
2646 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2647 if (IS_AOP_PREG(left)) {
2648 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
2649 aopPut(AOP(result),"a",offset);
2651 emitcode("xrl","%s,a",
2652 aopGet(AOP(left),offset,FALSE,TRUE));
2657 // left & result in different registers
2658 if(AOP_TYPE(result) == AOP_CRY){
2660 // if(size), result in bit
2661 // if(!size && ifx), conditional oper: if(left ^ right)
2662 symbol *tlbl = newiTempLabel(NULL);
2663 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
2665 emitcode("setb","c");
2667 if((AOP_TYPE(right) == AOP_LIT) &&
2668 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
2669 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
2671 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2672 emitcode("xrl","a,%s",
2673 aopGet(AOP(left),offset,FALSE,FALSE));
2675 emitcode("jnz","%05d$",tlbl->key+100);
2680 emitcode("","%05d$:",tlbl->key+100);
2683 jmpTrueOrFalse(ifx, tlbl);
2684 } else for(;(size--);offset++){
2686 // result = left & right
2687 if(AOP_TYPE(right) == AOP_LIT){
2688 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2690 aopGet(AOP(left),offset,FALSE,FALSE),
2695 // faster than result <- left, anl result,right
2696 // and better if result is SFR
2697 if (AOP_TYPE(left) == AOP_ACC)
2698 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
2700 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2701 emitcode("xrl","a,%s",
2702 aopGet(AOP(left),offset,FALSE,TRUE));
2704 aopPut(AOP(result),"a",offset);
2709 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2710 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2711 freeAsmop(result,NULL,ic,TRUE);
2714 /*-----------------------------------------------------------------*/
2715 /* genInline - write the inline code out */
2716 /*-----------------------------------------------------------------*/
2717 static void genInline (iCode *ic)
2719 char buffer[MAX_INLINEASM];
2723 _G.inLine += (!options.asmpeep);
2724 strcpy(buffer,IC_INLINE(ic));
2726 /* emit each line as a code */
2745 /* emitcode("",buffer); */
2746 _G.inLine -= (!options.asmpeep);
2749 /*-----------------------------------------------------------------*/
2750 /* genRRC - rotate right with carry */
2751 /*-----------------------------------------------------------------*/
2752 static void genRRC (iCode *ic)
2754 operand *left , *result ;
2755 int size, offset = 0;
2758 /* rotate right with carry */
2760 result=IC_RESULT(ic);
2761 aopOp (left,ic,FALSE);
2762 aopOp (result,ic,FALSE);
2764 /* move it to the result */
2765 size = AOP_SIZE(result);
2769 l = aopGet(AOP(left),offset,FALSE,FALSE);
2771 emitcode("rrc","a");
2772 if (AOP_SIZE(result) > 1)
2773 aopPut(AOP(result),"a",offset--);
2775 /* now we need to put the carry into the
2776 highest order byte of the result */
2777 if (AOP_SIZE(result) > 1) {
2778 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
2781 emitcode("mov","acc.7,c");
2782 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
2783 freeAsmop(left,NULL,ic,TRUE);
2784 freeAsmop(result,NULL,ic,TRUE);
2787 /*-----------------------------------------------------------------*/
2788 /* genRLC - generate code for rotate left with carry */
2789 /*-----------------------------------------------------------------*/
2790 static void genRLC (iCode *ic)
2792 operand *left , *result ;
2793 int size, offset = 0;
2796 /* rotate right with carry */
2798 result=IC_RESULT(ic);
2799 aopOp (left,ic,FALSE);
2800 aopOp (result,ic,FALSE);
2802 /* move it to the result */
2803 size = AOP_SIZE(result);
2806 l = aopGet(AOP(left),offset,FALSE,FALSE);
2808 emitcode("add","a,acc");
2809 if (AOP_SIZE(result) > 1)
2810 aopPut(AOP(result),"a",offset++);
2812 l = aopGet(AOP(left),offset,FALSE,FALSE);
2814 emitcode("rlc","a");
2815 if (AOP_SIZE(result) > 1)
2816 aopPut(AOP(result),"a",offset++);
2819 /* now we need to put the carry into the
2820 highest order byte of the result */
2821 if (AOP_SIZE(result) > 1) {
2822 l = aopGet(AOP(result),0,FALSE,FALSE);
2825 emitcode("mov","acc.0,c");
2826 aopPut(AOP(result),"a",0);
2827 freeAsmop(left,NULL,ic,TRUE);
2828 freeAsmop(result,NULL,ic,TRUE);
2831 /*-----------------------------------------------------------------*/
2832 /* genGetHbit - generates code get highest order bit */
2833 /*-----------------------------------------------------------------*/
2834 static void genGetHbit (iCode *ic)
2836 operand *left, *result;
2838 result=IC_RESULT(ic);
2839 aopOp (left,ic,FALSE);
2840 aopOp (result,ic,FALSE);
2842 /* get the highest order byte into a */
2843 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
2844 if(AOP_TYPE(result) == AOP_CRY){
2845 emitcode("rlc","a");
2850 emitcode("anl","a,#0x01");
2855 freeAsmop(left,NULL,ic,TRUE);
2856 freeAsmop(result,NULL,ic,TRUE);
2859 /*-----------------------------------------------------------------*/
2860 /* AccRol - rotate left accumulator by known count */
2861 /*-----------------------------------------------------------------*/
2862 static void AccRol (int shCount)
2864 shCount &= 0x0007; // shCount : 0..7
2876 emitcode("swap","a");
2880 emitcode("swap","a");
2883 emitcode("swap","a");
2896 /*-----------------------------------------------------------------*/
2897 /* AccLsh - left shift accumulator by known count */
2898 /*-----------------------------------------------------------------*/
2899 static void AccLsh (int shCount)
2903 emitcode("add","a,acc");
2906 emitcode("add","a,acc");
2907 emitcode("add","a,acc");
2909 /* rotate left accumulator */
2911 /* and kill the lower order bits */
2912 emitcode("anl","a,#0x%02x", SLMask[shCount]);
2917 /*-----------------------------------------------------------------*/
2918 /* AccRsh - right shift accumulator by known count */
2919 /*-----------------------------------------------------------------*/
2920 static void AccRsh (int shCount)
2925 emitcode("rrc","a");
2927 /* rotate right accumulator */
2928 AccRol(8 - shCount);
2929 /* and kill the higher order bits */
2930 emitcode("anl","a,#0x%02x", SRMask[shCount]);
2935 /*-----------------------------------------------------------------*/
2936 /* AccSRsh - signed right shift accumulator by known count */
2937 /*-----------------------------------------------------------------*/
2938 static void AccSRsh (int shCount)
2943 emitcode("mov","c,acc.7");
2944 emitcode("rrc","a");
2945 } else if(shCount == 2){
2946 emitcode("mov","c,acc.7");
2947 emitcode("rrc","a");
2948 emitcode("mov","c,acc.7");
2949 emitcode("rrc","a");
2951 tlbl = newiTempLabel(NULL);
2952 /* rotate right accumulator */
2953 AccRol(8 - shCount);
2954 /* and kill the higher order bits */
2955 emitcode("anl","a,#0x%02x", SRMask[shCount]);
2956 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
2957 emitcode("orl","a,#0x%02x",
2958 (unsigned char)~SRMask[shCount]);
2959 emitcode("","%05d$:",tlbl->key+100);
2964 /*-----------------------------------------------------------------*/
2965 /* shiftR1Left2Result - shift right one byte from left to result */
2966 /*-----------------------------------------------------------------*/
2967 static void shiftR1Left2Result (operand *left, int offl,
2968 operand *result, int offr,
2969 int shCount, int sign)
2971 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
2972 /* shift right accumulator */
2977 aopPut(AOP(result),"a",offr);
2980 /*-----------------------------------------------------------------*/
2981 /* shiftL1Left2Result - shift left one byte from left to result */
2982 /*-----------------------------------------------------------------*/
2983 static void shiftL1Left2Result (operand *left, int offl,
2984 operand *result, int offr, int shCount)
2987 l = aopGet(AOP(left),offl,FALSE,FALSE);
2989 /* shift left accumulator */
2991 aopPut(AOP(result),"a",offr);
2994 /*-----------------------------------------------------------------*/
2995 /* movLeft2Result - move byte from left to result */
2996 /*-----------------------------------------------------------------*/
2997 static void movLeft2Result (operand *left, int offl,
2998 operand *result, int offr, int sign)
3001 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
3002 l = aopGet(AOP(left),offl,FALSE,FALSE);
3004 if (*l == '@' && (IS_AOP_PREG(result))) {
3005 emitcode("mov","a,%s",l);
3006 aopPut(AOP(result),"a",offr);
3009 aopPut(AOP(result),l,offr);
3011 /* MSB sign in acc.7 ! */
3012 if(getDataSize(left) == offl+1){
3013 emitcode("mov","a,%s",l);
3014 aopPut(AOP(result),"a",offr);
3021 /*-----------------------------------------------------------------*/
3022 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
3023 /*-----------------------------------------------------------------*/
3024 static void AccAXRrl1 (char *x)
3026 emitcode("rrc","a");
3027 emitcode("xch","a,%s", x);
3028 emitcode("rrc","a");
3029 emitcode("xch","a,%s", x);
3032 /*-----------------------------------------------------------------*/
3033 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
3034 /*-----------------------------------------------------------------*/
3035 static void AccAXLrl1 (char *x)
3037 emitcode("xch","a,%s",x);
3038 emitcode("rlc","a");
3039 emitcode("xch","a,%s",x);
3040 emitcode("rlc","a");
3043 /*-----------------------------------------------------------------*/
3044 /* AccAXLsh1 - left shift a:x<-0 by 1 */
3045 /*-----------------------------------------------------------------*/
3046 static void AccAXLsh1 (char *x)
3048 emitcode("xch","a,%s",x);
3049 emitcode("add","a,acc");
3050 emitcode("xch","a,%s",x);
3051 emitcode("rlc","a");
3054 /*-----------------------------------------------------------------*/
3055 /* AccAXLsh - left shift a:x by known count (0..7) */
3056 /*-----------------------------------------------------------------*/
3057 static void AccAXLsh (char *x, int shCount)
3071 case 5 : // AAAAABBB:CCCCCDDD
3072 AccRol(shCount); // BBBAAAAA:CCCCCDDD
3073 emitcode("anl","a,#0x%02x",
3074 SLMask[shCount]); // BBB00000:CCCCCDDD
3075 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
3076 AccRol(shCount); // DDDCCCCC:BBB00000
3077 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
3078 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
3079 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
3080 emitcode("anl","a,#0x%02x",
3081 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
3082 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
3083 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
3085 case 6 : // AAAAAABB:CCCCCCDD
3086 emitcode("anl","a,#0x%02x",
3087 SRMask[shCount]); // 000000BB:CCCCCCDD
3088 emitcode("mov","c,acc.0"); // c = B
3089 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
3090 AccAXRrl1(x); // BCCCCCCD:D000000B
3091 AccAXRrl1(x); // BBCCCCCC:DD000000
3093 case 7 : // a:x <<= 7
3094 emitcode("anl","a,#0x%02x",
3095 SRMask[shCount]); // 0000000B:CCCCCCCD
3096 emitcode("mov","c,acc.0"); // c = B
3097 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
3098 AccAXRrl1(x); // BCCCCCCC:D0000000
3105 /*-----------------------------------------------------------------*/
3106 /* AccAXRsh - right shift a:x known count (0..7) */
3107 /*-----------------------------------------------------------------*/
3108 static void AccAXRsh (char *x, int shCount)
3115 AccAXRrl1(x); // 0->a:x
3119 AccAXRrl1(x); // 0->a:x
3121 AccAXRrl1(x); // 0->a:x
3125 case 5 : // AAAAABBB:CCCCCDDD = a:x
3126 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
3127 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
3128 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
3129 emitcode("anl","a,#0x%02x",
3130 SRMask[shCount]); // 000CCCCC:BBBAAAAA
3131 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
3132 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
3133 emitcode("anl","a,#0x%02x",
3134 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
3135 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
3136 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
3137 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
3139 case 6 : // AABBBBBB:CCDDDDDD
3140 emitcode("mov","c,acc.7");
3141 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
3142 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
3143 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
3144 emitcode("anl","a,#0x%02x",
3145 SRMask[shCount]); // 000000AA:BBBBBBCC
3147 case 7 : // ABBBBBBB:CDDDDDDD
3148 emitcode("mov","c,acc.7"); // c = A
3149 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
3150 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
3151 emitcode("anl","a,#0x%02x",
3152 SRMask[shCount]); // 0000000A:BBBBBBBC
3159 /*-----------------------------------------------------------------*/
3160 /* AccAXRshS - right shift signed a:x known count (0..7) */
3161 /*-----------------------------------------------------------------*/
3162 static void AccAXRshS (char *x, int shCount)
3169 emitcode("mov","c,acc.7");
3170 AccAXRrl1(x); // s->a:x
3173 emitcode("mov","c,acc.7");
3174 AccAXRrl1(x); // s->a:x
3175 emitcode("mov","c,acc.7");
3176 AccAXRrl1(x); // s->a:x
3180 case 5 : // AAAAABBB:CCCCCDDD = a:x
3181 tlbl = newiTempLabel(NULL);
3182 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
3183 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
3184 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
3185 emitcode("anl","a,#0x%02x",
3186 SRMask[shCount]); // 000CCCCC:BBBAAAAA
3187 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
3188 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
3189 emitcode("anl","a,#0x%02x",
3190 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
3191 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
3192 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
3193 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
3194 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
3195 emitcode("orl","a,#0x%02x",
3196 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
3197 emitcode("","%05d$:",tlbl->key+100);
3198 break; // SSSSAAAA:BBBCCCCC
3199 case 6 : // AABBBBBB:CCDDDDDD
3200 tlbl = newiTempLabel(NULL);
3201 emitcode("mov","c,acc.7");
3202 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
3203 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
3204 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
3205 emitcode("anl","a,#0x%02x",
3206 SRMask[shCount]); // 000000AA:BBBBBBCC
3207 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
3208 emitcode("orl","a,#0x%02x",
3209 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
3210 emitcode("","%05d$:",tlbl->key+100);
3212 case 7 : // ABBBBBBB:CDDDDDDD
3213 tlbl = newiTempLabel(NULL);
3214 emitcode("mov","c,acc.7"); // c = A
3215 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
3216 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
3217 emitcode("anl","a,#0x%02x",
3218 SRMask[shCount]); // 0000000A:BBBBBBBC
3219 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
3220 emitcode("orl","a,#0x%02x",
3221 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
3222 emitcode("","%05d$:",tlbl->key+100);
3229 /*-----------------------------------------------------------------*/
3230 /* shiftL2Left2Result - shift left two bytes from left to result */
3231 /*-----------------------------------------------------------------*/
3232 static void shiftL2Left2Result (operand *left, int offl,
3233 operand *result, int offr, int shCount)
3235 if(sameRegs(AOP(result), AOP(left)) &&
3236 ((offl + MSB16) == offr)){
3237 /* don't crash result[offr] */
3238 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
3239 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
3241 movLeft2Result(left,offl, result, offr, 0);
3242 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
3244 /* ax << shCount (x = lsb(result))*/
3245 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
3246 aopPut(AOP(result),"a",offr+MSB16);
3250 /*-----------------------------------------------------------------*/
3251 /* shiftR2Left2Result - shift right two bytes from left to result */
3252 /*-----------------------------------------------------------------*/
3253 static void shiftR2Left2Result (operand *left, int offl,
3254 operand *result, int offr,
3255 int shCount, int sign)
3257 if(sameRegs(AOP(result), AOP(left)) &&
3258 ((offl + MSB16) == offr)){
3259 /* don't crash result[offr] */
3260 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
3261 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
3263 movLeft2Result(left,offl, result, offr, 0);
3264 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
3266 /* a:x >> shCount (x = lsb(result))*/
3268 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
3270 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
3271 if(getDataSize(result) > 1)
3272 aopPut(AOP(result),"a",offr+MSB16);
3275 /*-----------------------------------------------------------------*/
3276 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
3277 /*-----------------------------------------------------------------*/
3278 static void shiftLLeftOrResult (operand *left, int offl,
3279 operand *result, int offr, int shCount)
3281 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
3282 /* shift left accumulator */
3284 /* or with result */
3285 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
3286 /* back to result */
3287 aopPut(AOP(result),"a",offr);
3290 /*-----------------------------------------------------------------*/
3291 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
3292 /*-----------------------------------------------------------------*/
3293 static void shiftRLeftOrResult (operand *left, int offl,
3294 operand *result, int offr, int shCount)
3296 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
3297 /* shift right accumulator */
3299 /* or with result */
3300 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
3301 /* back to result */
3302 aopPut(AOP(result),"a",offr);
3305 /*-----------------------------------------------------------------*/
3306 /* genlshOne - left shift a one byte quantity by known count */
3307 /*-----------------------------------------------------------------*/
3308 static void genlshOne (operand *result, operand *left, int shCount)
3310 shiftL1Left2Result(left, LSB, result, LSB, shCount);
3313 /*-----------------------------------------------------------------*/
3314 /* genlshTwo - left shift two bytes by known amount != 0 */
3315 /*-----------------------------------------------------------------*/
3316 static void genlshTwo (operand *result,operand *left, int shCount)
3320 size = getDataSize(result);
3322 /* if shCount >= 8 */
3328 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
3330 movLeft2Result(left, LSB, result, MSB16, 0);
3332 aopPut(AOP(result),zero,LSB);
3335 /* 1 <= shCount <= 7 */
3338 shiftL1Left2Result(left, LSB, result, LSB, shCount);
3340 shiftL2Left2Result(left, LSB, result, LSB, shCount);
3344 /*-----------------------------------------------------------------*/
3345 /* shiftLLong - shift left one long from left to result */
3346 /* offl = LSB or MSB16 */
3347 /*-----------------------------------------------------------------*/
3348 static void shiftLLong (operand *left, operand *result, int offr )
3351 int size = AOP_SIZE(result);
3353 if(size >= LSB+offr){
3354 l = aopGet(AOP(left),LSB,FALSE,FALSE);
3356 emitcode("add","a,acc");
3357 if (sameRegs(AOP(left),AOP(result)) &&
3358 size >= MSB16+offr && offr != LSB )
3359 emitcode("xch","a,%s",
3360 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
3362 aopPut(AOP(result),"a",LSB+offr);
3365 if(size >= MSB16+offr){
3366 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
3367 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
3370 emitcode("rlc","a");
3371 if (sameRegs(AOP(left),AOP(result)) &&
3372 size >= MSB24+offr && offr != LSB)
3373 emitcode("xch","a,%s",
3374 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
3376 aopPut(AOP(result),"a",MSB16+offr);
3379 if(size >= MSB24+offr){
3380 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
3381 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
3384 emitcode("rlc","a");
3385 if (sameRegs(AOP(left),AOP(result)) &&
3386 size >= MSB32+offr && offr != LSB )
3387 emitcode("xch","a,%s",
3388 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
3390 aopPut(AOP(result),"a",MSB24+offr);
3393 if(size > MSB32+offr){
3394 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
3395 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
3398 emitcode("rlc","a");
3399 aopPut(AOP(result),"a",MSB32+offr);
3402 aopPut(AOP(result),zero,LSB);
3405 /*-----------------------------------------------------------------*/
3406 /* genlshFour - shift four byte by a known amount != 0 */
3407 /*-----------------------------------------------------------------*/
3408 static void genlshFour (operand *result, operand *left, int shCount)
3412 size = AOP_SIZE(result);
3414 /* if shifting more that 3 bytes */
3415 if (shCount >= 24 ) {
3418 /* lowest order of left goes to the highest
3419 order of the destination */
3420 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
3422 movLeft2Result(left, LSB, result, MSB32, 0);
3423 aopPut(AOP(result),zero,LSB);
3424 aopPut(AOP(result),zero,MSB16);
3425 aopPut(AOP(result),zero,MSB32);
3429 /* more than two bytes */
3430 else if ( shCount >= 16 ) {
3431 /* lower order two bytes goes to higher order two bytes */
3433 /* if some more remaining */
3435 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
3437 movLeft2Result(left, MSB16, result, MSB32, 0);
3438 movLeft2Result(left, LSB, result, MSB24, 0);
3440 aopPut(AOP(result),zero,MSB16);
3441 aopPut(AOP(result),zero,LSB);
3445 /* if more than 1 byte */
3446 else if ( shCount >= 8 ) {
3447 /* lower order three bytes goes to higher order three bytes */
3451 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
3453 movLeft2Result(left, LSB, result, MSB16, 0);
3455 else{ /* size = 4 */
3457 movLeft2Result(left, MSB24, result, MSB32, 0);
3458 movLeft2Result(left, MSB16, result, MSB24, 0);
3459 movLeft2Result(left, LSB, result, MSB16, 0);
3460 aopPut(AOP(result),zero,LSB);
3462 else if(shCount == 1)
3463 shiftLLong(left, result, MSB16);
3465 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
3466 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
3467 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
3468 aopPut(AOP(result),zero,LSB);
3473 /* 1 <= shCount <= 7 */
3474 else if(shCount <= 2){
3475 shiftLLong(left, result, LSB);
3477 shiftLLong(result, result, LSB);
3479 /* 3 <= shCount <= 7, optimize */
3481 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
3482 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
3483 shiftL2Left2Result(left, LSB, result, LSB, shCount);
3487 /*-----------------------------------------------------------------*/
3488 /* genLeftShiftLiteral - left shifting by known count */
3489 /*-----------------------------------------------------------------*/
3490 static void genLeftShiftLiteral (operand *left,
3495 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3498 freeAsmop(right,NULL,ic,TRUE);
3500 aopOp(left,ic,FALSE);
3501 aopOp(result,ic,FALSE);
3503 size = getSize(operandType(result));
3506 emitcode("; shift left ","result %d, left %d",size,
3510 /* I suppose that the left size >= result size */
3513 movLeft2Result(left, size, result, size, 0);
3517 else if(shCount >= (size * 8))
3519 aopPut(AOP(result),zero,size);
3523 genlshOne (result,left,shCount);
3528 genlshTwo (result,left,shCount);
3532 genlshFour (result,left,shCount);
3536 freeAsmop(left,NULL,ic,TRUE);
3537 freeAsmop(result,NULL,ic,TRUE);
3540 /*-----------------------------------------------------------------*/
3541 /* genLeftShift - generates code for left shifting */
3542 /*-----------------------------------------------------------------*/
3543 static void genLeftShift (iCode *ic)
3545 operand *left,*right, *result;
3548 symbol *tlbl , *tlbl1;
3550 right = IC_RIGHT(ic);
3552 result = IC_RESULT(ic);
3554 aopOp(right,ic,FALSE);
3556 /* if the shift count is known then do it
3557 as efficiently as possible */
3558 if (AOP_TYPE(right) == AOP_LIT) {
3559 genLeftShiftLiteral (left,right,result,ic);
3563 /* shift count is unknown then we have to form
3564 a loop get the loop count in B : Note: we take
3565 only the lower order byte since shifting
3566 more that 32 bits make no sense anyway, ( the
3567 largest size of an object can be only 32 bits ) */
3569 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3570 emitcode("inc","b");
3571 freeAsmop (right,NULL,ic,TRUE);
3572 aopOp(left,ic,FALSE);
3573 aopOp(result,ic,FALSE);
3575 /* now move the left to the result if they are not the
3577 if (!sameRegs(AOP(left),AOP(result)) &&
3578 AOP_SIZE(result) > 1) {
3580 size = AOP_SIZE(result);
3583 l = aopGet(AOP(left),offset,FALSE,TRUE);
3584 if (*l == '@' && (IS_AOP_PREG(result))) {
3586 emitcode("mov","a,%s",l);
3587 aopPut(AOP(result),"a",offset);
3589 aopPut(AOP(result),l,offset);
3594 tlbl = newiTempLabel(NULL);
3595 size = AOP_SIZE(result);
3597 tlbl1 = newiTempLabel(NULL);
3599 /* if it is only one byte then */
3601 symbol *tlbl1 = newiTempLabel(NULL);
3603 l = aopGet(AOP(left),0,FALSE,FALSE);
3605 emitcode("sjmp","%05d$",tlbl1->key+100);
3606 emitcode("","%05d$:",tlbl->key+100);
3607 emitcode("add","a,acc");
3608 emitcode("","%05d$:",tlbl1->key+100);
3609 emitcode("djnz","b,%05d$",tlbl->key+100);
3610 aopPut(AOP(result),"a",0);
3614 reAdjustPreg(AOP(result));
3616 emitcode("sjmp","%05d$",tlbl1->key+100);
3617 emitcode("","%05d$:",tlbl->key+100);
3618 l = aopGet(AOP(result),offset,FALSE,FALSE);
3620 emitcode("add","a,acc");
3621 aopPut(AOP(result),"a",offset++);
3623 l = aopGet(AOP(result),offset,FALSE,FALSE);
3625 emitcode("rlc","a");
3626 aopPut(AOP(result),"a",offset++);
3628 reAdjustPreg(AOP(result));
3630 emitcode("","%05d$:",tlbl1->key+100);
3631 emitcode("djnz","b,%05d$",tlbl->key+100);
3633 freeAsmop(left,NULL,ic,TRUE);
3634 freeAsmop(result,NULL,ic,TRUE);
3637 /*-----------------------------------------------------------------*/
3638 /* genrshOne - right shift a one byte quantity by known count */
3639 /*-----------------------------------------------------------------*/
3640 static void genrshOne (operand *result, operand *left,
3641 int shCount, int sign)
3643 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
3646 /*-----------------------------------------------------------------*/
3647 /* genrshTwo - right shift two bytes by known amount != 0 */
3648 /*-----------------------------------------------------------------*/
3649 static void genrshTwo (operand *result,operand *left,
3650 int shCount, int sign)
3652 /* if shCount >= 8 */
3656 shiftR1Left2Result(left, MSB16, result, LSB,
3659 movLeft2Result(left, MSB16, result, LSB, sign);
3660 addSign(result, MSB16, sign);
3663 /* 1 <= shCount <= 7 */
3665 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
3668 /*-----------------------------------------------------------------*/
3669 /* shiftRLong - shift right one long from left to result */
3670 /* offl = LSB or MSB16 */
3671 /*-----------------------------------------------------------------*/
3672 static void shiftRLong (operand *left, int offl,
3673 operand *result, int sign)
3676 emitcode("clr","c");
3677 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
3679 emitcode("mov","c,acc.7");
3680 emitcode("rrc","a");
3681 aopPut(AOP(result),"a",MSB32-offl);
3683 /* add sign of "a" */
3684 addSign(result, MSB32, sign);
3686 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
3687 emitcode("rrc","a");
3688 aopPut(AOP(result),"a",MSB24-offl);
3690 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
3691 emitcode("rrc","a");
3692 aopPut(AOP(result),"a",MSB16-offl);
3695 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
3696 emitcode("rrc","a");
3697 aopPut(AOP(result),"a",LSB);
3701 /*-----------------------------------------------------------------*/
3702 /* genrshFour - shift four byte by a known amount != 0 */
3703 /*-----------------------------------------------------------------*/
3704 static void genrshFour (operand *result, operand *left,
3705 int shCount, int sign)
3707 /* if shifting more that 3 bytes */
3708 if(shCount >= 24 ) {
3711 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
3713 movLeft2Result(left, MSB32, result, LSB, sign);
3714 addSign(result, MSB16, sign);
3716 else if(shCount >= 16){
3719 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
3721 movLeft2Result(left, MSB24, result, LSB, 0);
3722 movLeft2Result(left, MSB32, result, MSB16, sign);
3724 addSign(result, MSB24, sign);
3726 else if(shCount >= 8){
3729 shiftRLong(left, MSB16, result, sign);
3730 else if(shCount == 0){
3731 movLeft2Result(left, MSB16, result, LSB, 0);
3732 movLeft2Result(left, MSB24, result, MSB16, 0);
3733 movLeft2Result(left, MSB32, result, MSB24, sign);
3734 addSign(result, MSB32, sign);
3737 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
3738 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
3739 /* the last shift is signed */
3740 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
3741 addSign(result, MSB32, sign);
3744 else{ /* 1 <= shCount <= 7 */
3746 shiftRLong(left, LSB, result, sign);
3748 shiftRLong(result, LSB, result, sign);
3751 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
3752 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
3753 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
3758 /*-----------------------------------------------------------------*/
3759 /* genRightShiftLiteral - right shifting by known count */
3760 /*-----------------------------------------------------------------*/
3761 static void genRightShiftLiteral (operand *left,
3767 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3770 freeAsmop(right,NULL,ic,TRUE);
3772 aopOp(left,ic,FALSE);
3773 aopOp(result,ic,FALSE);
3776 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
3780 size = getDataSize(left);
3781 /* test the LEFT size !!! */
3783 /* I suppose that the left size >= result size */
3785 size = getDataSize(result);
3787 movLeft2Result(left, size, result, size, 0);
3790 else if(shCount >= (size * 8)){
3792 /* get sign in acc.7 */
3793 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
3794 addSign(result, LSB, sign);
3798 genrshOne (result,left,shCount,sign);
3802 genrshTwo (result,left,shCount,sign);
3806 genrshFour (result,left,shCount,sign);
3812 freeAsmop(left,NULL,ic,TRUE);
3813 freeAsmop(result,NULL,ic,TRUE);
3817 /*-----------------------------------------------------------------*/
3818 /* genSignedRightShift - right shift of signed number */
3819 /*-----------------------------------------------------------------*/
3820 static void genSignedRightShift (iCode *ic)
3822 operand *right, *left, *result;
3825 symbol *tlbl, *tlbl1 ;
3827 /* we do it the hard way put the shift count in b
3828 and loop thru preserving the sign */
3830 right = IC_RIGHT(ic);
3832 result = IC_RESULT(ic);
3834 aopOp(right,ic,FALSE);
3837 if ( AOP_TYPE(right) == AOP_LIT) {
3838 genRightShiftLiteral (left,right,result,ic,1);
3841 /* shift count is unknown then we have to form
3842 a loop get the loop count in B : Note: we take
3843 only the lower order byte since shifting
3844 more that 32 bits make no sense anyway, ( the
3845 largest size of an object can be only 32 bits ) */
3847 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3848 emitcode("inc","b");
3849 freeAsmop (right,NULL,ic,TRUE);
3850 aopOp(left,ic,FALSE);
3851 aopOp(result,ic,FALSE);
3853 /* now move the left to the result if they are not the
3855 if (!sameRegs(AOP(left),AOP(result)) &&
3856 AOP_SIZE(result) > 1) {
3858 size = AOP_SIZE(result);
3861 l = aopGet(AOP(left),offset,FALSE,TRUE);
3862 if (*l == '@' && IS_AOP_PREG(result)) {
3864 emitcode("mov","a,%s",l);
3865 aopPut(AOP(result),"a",offset);
3867 aopPut(AOP(result),l,offset);
3872 /* mov the highest order bit to OVR */
3873 tlbl = newiTempLabel(NULL);
3874 tlbl1= newiTempLabel(NULL);
3876 size = AOP_SIZE(result);
3878 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
3879 emitcode("rlc","a");
3880 emitcode("mov","ov,c");
3881 /* if it is only one byte then */
3883 l = aopGet(AOP(left),0,FALSE,FALSE);
3885 emitcode("sjmp","%05d$",tlbl1->key+100);
3886 emitcode("","%05d$:",tlbl->key+100);
3887 emitcode("mov","c,ov");
3888 emitcode("rrc","a");
3889 emitcode("","%05d$:",tlbl1->key+100);
3890 emitcode("djnz","b,%05d$",tlbl->key+100);
3891 aopPut(AOP(result),"a",0);
3895 reAdjustPreg(AOP(result));
3896 emitcode("sjmp","%05d$",tlbl1->key+100);
3897 emitcode("","%05d$:",tlbl->key+100);
3898 emitcode("mov","c,ov");
3900 l = aopGet(AOP(result),offset,FALSE,FALSE);
3902 emitcode("rrc","a");
3903 aopPut(AOP(result),"a",offset--);
3905 reAdjustPreg(AOP(result));
3906 emitcode("","%05d$:",tlbl1->key+100);
3907 emitcode("djnz","b,%05d$",tlbl->key+100);
3910 freeAsmop(left,NULL,ic,TRUE);
3911 freeAsmop(result,NULL,ic,TRUE);
3914 /*-----------------------------------------------------------------*/
3915 /* genRightShift - generate code for right shifting */
3916 /*-----------------------------------------------------------------*/
3917 static void genRightShift (iCode *ic)
3919 operand *right, *left, *result;
3923 symbol *tlbl, *tlbl1 ;
3925 /* if signed then we do it the hard way preserve the
3926 sign bit moving it inwards */
3927 retype = getSpec(operandType(IC_RESULT(ic)));
3929 if (!SPEC_USIGN(retype)) {
3930 genSignedRightShift (ic);
3934 /* signed & unsigned types are treated the same : i.e. the
3935 signed is NOT propagated inwards : quoting from the
3936 ANSI - standard : "for E1 >> E2, is equivalent to division
3937 by 2**E2 if unsigned or if it has a non-negative value,
3938 otherwise the result is implementation defined ", MY definition
3939 is that the sign does not get propagated */
3941 right = IC_RIGHT(ic);
3943 result = IC_RESULT(ic);
3945 aopOp(right,ic,FALSE);
3947 /* if the shift count is known then do it
3948 as efficiently as possible */
3949 if (AOP_TYPE(right) == AOP_LIT) {
3950 genRightShiftLiteral (left,right,result,ic, 0);
3954 /* shift count is unknown then we have to form
3955 a loop get the loop count in B : Note: we take
3956 only the lower order byte since shifting
3957 more that 32 bits make no sense anyway, ( the
3958 largest size of an object can be only 32 bits ) */
3960 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3961 emitcode("inc","b");
3962 freeAsmop (right,NULL,ic,TRUE);
3963 aopOp(left,ic,FALSE);
3964 aopOp(result,ic,FALSE);
3966 /* now move the left to the result if they are not the
3968 if (!sameRegs(AOP(left),AOP(result)) &&
3969 AOP_SIZE(result) > 1) {
3971 size = AOP_SIZE(result);
3974 l = aopGet(AOP(left),offset,FALSE,TRUE);
3975 if (*l == '@' && IS_AOP_PREG(result)) {
3977 emitcode("mov","a,%s",l);
3978 aopPut(AOP(result),"a",offset);
3980 aopPut(AOP(result),l,offset);
3985 tlbl = newiTempLabel(NULL);
3986 tlbl1= newiTempLabel(NULL);
3987 size = AOP_SIZE(result);
3990 /* if it is only one byte then */
3992 l = aopGet(AOP(left),0,FALSE,FALSE);
3994 emitcode("sjmp","%05d$",tlbl1->key+100);
3995 emitcode("","%05d$:",tlbl->key+100);
3997 emitcode("rrc","a");
3998 emitcode("","%05d$:",tlbl1->key+100);
3999 emitcode("djnz","b,%05d$",tlbl->key+100);
4000 aopPut(AOP(result),"a",0);
4004 reAdjustPreg(AOP(result));
4005 emitcode("sjmp","%05d$",tlbl1->key+100);
4006 emitcode("","%05d$:",tlbl->key+100);
4009 l = aopGet(AOP(result),offset,FALSE,FALSE);
4011 emitcode("rrc","a");
4012 aopPut(AOP(result),"a",offset--);
4014 reAdjustPreg(AOP(result));
4016 emitcode("","%05d$:",tlbl1->key+100);
4017 emitcode("djnz","b,%05d$",tlbl->key+100);
4020 freeAsmop(left,NULL,ic,TRUE);
4021 freeAsmop(result,NULL,ic,TRUE);
4024 /*-----------------------------------------------------------------*/
4025 /* genUnpackBits - generates code for unpacking bits */
4026 /*-----------------------------------------------------------------*/
4027 static void genUnpackBits (operand *result, char *rname, int ptype)
4034 etype = getSpec(operandType(result));
4036 /* read the first byte */
4041 emitcode("mov","a,@%s",rname);
4045 emitcode("movx","a,@%s",rname);
4049 emitcode("movx","a,@dptr");
4053 emitcode("clr","a");
4054 emitcode("movc","a","@a+dptr");
4058 emitcode("lcall","__gptrget");
4062 /* if we have bitdisplacement then it fits */
4063 /* into this byte completely or if length is */
4064 /* less than a byte */
4065 if ((shCnt = SPEC_BSTR(etype)) ||
4066 (SPEC_BLEN(etype) <= 8)) {
4068 /* shift right acc */
4071 emitcode("anl","a,#0x%02x",
4072 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
4073 aopPut(AOP(result),"a",offset);
4077 /* bit field did not fit in a byte */
4078 rlen = SPEC_BLEN(etype) - 8;
4079 aopPut(AOP(result),"a",offset++);
4086 emitcode("inc","%s",rname);
4087 emitcode("mov","a,@%s",rname);
4091 emitcode("inc","%s",rname);
4092 emitcode("movx","a,@%s",rname);
4096 emitcode("inc","dptr");
4097 emitcode("movx","a,@dptr");
4101 emitcode("clr","a");
4102 emitcode("inc","dptr");
4103 emitcode("movc","a","@a+dptr");
4107 emitcode("inc","dptr");
4108 emitcode("lcall","__gptrget");
4113 /* if we are done */
4117 aopPut(AOP(result),"a",offset++);
4122 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
4123 aopPut(AOP(result),"a",offset);
4130 /*-----------------------------------------------------------------*/
4131 /* genDataPointerGet - generates code when ptr offset is known */
4132 /*-----------------------------------------------------------------*/
4133 static void genDataPointerGet (operand *left,
4139 int size , offset = 0;
4140 aopOp(result,ic,TRUE);
4142 /* get the string representation of the name */
4143 l = aopGet(AOP(left),0,FALSE,TRUE);
4144 size = AOP_SIZE(result);
4147 sprintf(buffer,"(%s + %d)",l+1,offset);
4149 sprintf(buffer,"%s",l+1);
4150 aopPut(AOP(result),buffer,offset++);
4153 freeAsmop(left,NULL,ic,TRUE);
4154 freeAsmop(result,NULL,ic,TRUE);
4157 /*-----------------------------------------------------------------*/
4158 /* genNearPointerGet - emitcode for near pointer fetch */
4159 /*-----------------------------------------------------------------*/
4160 static void genNearPointerGet (operand *left,
4167 link *rtype, *retype;
4168 link *ltype = operandType(left);
4171 rtype = operandType(result);
4172 retype= getSpec(rtype);
4174 aopOp(left,ic,FALSE);
4176 /* if left is rematerialisable and
4177 result is not bit variable type and
4178 the left is pointer to data space i.e
4179 lower 128 bytes of space */
4180 if (AOP_TYPE(left) == AOP_IMMD &&
4181 !IS_BITVAR(retype) &&
4182 DCL_TYPE(ltype) == POINTER) {
4183 genDataPointerGet (left,result,ic);
4187 /* if the value is already in a pointer register
4188 then don't need anything more */
4189 if (!AOP_INPREG(AOP(left))) {
4190 /* otherwise get a free pointer register */
4192 preg = getFreePtr(ic,&aop,FALSE);
4193 emitcode("mov","%s,%s",
4195 aopGet(AOP(left),0,FALSE,TRUE));
4196 rname = preg->name ;
4198 rname = aopGet(AOP(left),0,FALSE,FALSE);
4200 freeAsmop(left,NULL,ic,TRUE);
4201 aopOp (result,ic,FALSE);
4203 /* if bitfield then unpack the bits */
4204 if (IS_BITVAR(retype))
4205 genUnpackBits (result,rname,POINTER);
4207 /* we have can just get the values */
4208 int size = AOP_SIZE(result);
4212 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
4214 emitcode("mov","a,@%s",rname);
4215 aopPut(AOP(result),"a",offset);
4217 sprintf(buffer,"@%s",rname);
4218 aopPut(AOP(result),buffer,offset);
4222 emitcode("inc","%s",rname);
4226 /* now some housekeeping stuff */
4228 /* we had to allocate for this iCode */
4229 freeAsmop(NULL,aop,ic,TRUE);
4231 /* we did not allocate which means left
4232 already in a pointer register, then
4233 if size > 0 && this could be used again
4234 we have to point it back to where it
4236 if (AOP_SIZE(result) > 1 &&
4237 !OP_SYMBOL(left)->remat &&
4238 ( OP_SYMBOL(left)->liveTo > ic->seq ||
4240 int size = AOP_SIZE(result) - 1;
4242 emitcode("dec","%s",rname);
4247 freeAsmop(result,NULL,ic,TRUE);
4251 /*-----------------------------------------------------------------*/
4252 /* genPagedPointerGet - emitcode for paged pointer fetch */
4253 /*-----------------------------------------------------------------*/
4254 static void genPagedPointerGet (operand *left,
4261 link *rtype, *retype;
4263 rtype = operandType(result);
4264 retype= getSpec(rtype);
4266 aopOp(left,ic,FALSE);
4268 /* if the value is already in a pointer register
4269 then don't need anything more */
4270 if (!AOP_INPREG(AOP(left))) {
4271 /* otherwise get a free pointer register */
4273 preg = getFreePtr(ic,&aop,FALSE);
4274 emitcode("mov","%s,%s",
4276 aopGet(AOP(left),0,FALSE,TRUE));
4277 rname = preg->name ;
4279 rname = aopGet(AOP(left),0,FALSE,FALSE);
4281 freeAsmop(left,NULL,ic,TRUE);
4282 aopOp (result,ic,FALSE);
4284 /* if bitfield then unpack the bits */
4285 if (IS_BITVAR(retype))
4286 genUnpackBits (result,rname,PPOINTER);
4288 /* we have can just get the values */
4289 int size = AOP_SIZE(result);
4294 emitcode("movx","a,@%s",rname);
4295 aopPut(AOP(result),"a",offset);
4300 emitcode("inc","%s",rname);
4304 /* now some housekeeping stuff */
4306 /* we had to allocate for this iCode */
4307 freeAsmop(NULL,aop,ic,TRUE);
4309 /* we did not allocate which means left
4310 already in a pointer register, then
4311 if size > 0 && this could be used again
4312 we have to point it back to where it
4314 if (AOP_SIZE(result) > 1 &&
4315 !OP_SYMBOL(left)->remat &&
4316 ( OP_SYMBOL(left)->liveTo > ic->seq ||
4318 int size = AOP_SIZE(result) - 1;
4320 emitcode("dec","%s",rname);
4325 freeAsmop(result,NULL,ic,TRUE);
4330 /*-----------------------------------------------------------------*/
4331 /* genFarPointerGet - gget value from far space */
4332 /*-----------------------------------------------------------------*/
4333 static void genFarPointerGet (operand *left,
4334 operand *result, iCode *ic)
4337 link *retype = getSpec(operandType(result));
4339 aopOp(left,ic,FALSE);
4341 /* if the operand is already in dptr
4342 then we do nothing else we move the value to dptr */
4343 if (AOP_TYPE(left) != AOP_STR) {
4344 /* if this is remateriazable */
4345 if (AOP_TYPE(left) == AOP_IMMD)
4346 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
4347 else { /* we need to get it byte by byte */
4348 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
4349 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
4350 if (options.model == MODEL_FLAT24)
4352 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
4356 /* so dptr know contains the address */
4357 freeAsmop(left,NULL,ic,TRUE);
4358 aopOp(result,ic,FALSE);
4360 /* if bit then unpack */
4361 if (IS_BITVAR(retype))
4362 genUnpackBits(result,"dptr",FPOINTER);
4364 size = AOP_SIZE(result);
4368 emitcode("movx","a,@dptr");
4369 aopPut(AOP(result),"a",offset++);
4371 emitcode("inc","dptr");
4375 freeAsmop(result,NULL,ic,TRUE);
4378 /*-----------------------------------------------------------------*/
4379 /* emitcodePointerGet - gget value from code space */
4380 /*-----------------------------------------------------------------*/
4381 static void emitcodePointerGet (operand *left,
4382 operand *result, iCode *ic)
4385 link *retype = getSpec(operandType(result));
4387 aopOp(left,ic,FALSE);
4389 /* if the operand is already in dptr
4390 then we do nothing else we move the value to dptr */
4391 if (AOP_TYPE(left) != AOP_STR) {
4392 /* if this is remateriazable */
4393 if (AOP_TYPE(left) == AOP_IMMD)
4394 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
4395 else { /* we need to get it byte by byte */
4396 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
4397 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
4398 if (options.model == MODEL_FLAT24)
4400 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
4404 /* so dptr know contains the address */
4405 freeAsmop(left,NULL,ic,TRUE);
4406 aopOp(result,ic,FALSE);
4408 /* if bit then unpack */
4409 if (IS_BITVAR(retype))
4410 genUnpackBits(result,"dptr",CPOINTER);
4412 size = AOP_SIZE(result);
4416 emitcode("clr","a");
4417 emitcode("movc","a,@a+dptr");
4418 aopPut(AOP(result),"a",offset++);
4420 emitcode("inc","dptr");
4424 freeAsmop(result,NULL,ic,TRUE);
4427 /*-----------------------------------------------------------------*/
4428 /* genGenPointerGet - gget value from generic pointer space */
4429 /*-----------------------------------------------------------------*/
4430 static void genGenPointerGet (operand *left,
4431 operand *result, iCode *ic)
4434 link *retype = getSpec(operandType(result));
4436 aopOp(left,ic,FALSE);
4438 /* if the operand is already in dptr
4439 then we do nothing else we move the value to dptr */
4440 if (AOP_TYPE(left) != AOP_STR) {
4441 /* if this is remateriazable */
4442 if (AOP_TYPE(left) == AOP_IMMD) {
4443 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
4444 emitcode("mov","b,#%d",pointerCode(retype));
4446 else { /* we need to get it byte by byte */
4447 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
4448 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
4449 if (options.model == MODEL_FLAT24)
4451 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
4452 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
4456 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
4460 /* so dptr know contains the address */
4461 freeAsmop(left,NULL,ic,TRUE);
4462 aopOp(result,ic,FALSE);
4464 /* if bit then unpack */
4465 if (IS_BITVAR(retype))
4466 genUnpackBits(result,"dptr",GPOINTER);
4468 size = AOP_SIZE(result);
4472 emitcode("lcall","__gptrget");
4473 aopPut(AOP(result),"a",offset++);
4475 emitcode("inc","dptr");
4479 freeAsmop(result,NULL,ic,TRUE);
4482 /*-----------------------------------------------------------------*/
4483 /* genPointerGet - generate code for pointer get */
4484 /*-----------------------------------------------------------------*/
4485 static void genPointerGet (iCode *ic)
4487 operand *left, *result ;
4492 result = IC_RESULT(ic) ;
4494 /* depending on the type of pointer we need to
4495 move it to the correct pointer register */
4496 type = operandType(left);
4497 etype = getSpec(type);
4498 /* if left is of type of pointer then it is simple */
4499 if (IS_PTR(type) && !IS_FUNC(type->next))
4500 p_type = DCL_TYPE(type);
4502 /* we have to go by the storage class */
4503 p_type = PTR_TYPE(SPEC_OCLS(etype));
4505 /* if (SPEC_OCLS(etype)->codesp ) { */
4506 /* p_type = CPOINTER ; */
4509 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
4510 /* p_type = FPOINTER ; */
4512 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
4513 /* p_type = PPOINTER; */
4515 /* if (SPEC_OCLS(etype) == idata ) */
4516 /* p_type = IPOINTER; */
4518 /* p_type = POINTER ; */
4521 /* now that we have the pointer type we assign
4522 the pointer values */
4527 genNearPointerGet (left,result,ic);
4531 genPagedPointerGet(left,result,ic);
4535 genFarPointerGet (left,result,ic);
4539 emitcodePointerGet (left,result,ic);
4543 genGenPointerGet (left,result,ic);
4549 /*-----------------------------------------------------------------*/
4550 /* genPackBits - generates code for packed bit storage */
4551 /*-----------------------------------------------------------------*/
4552 static void genPackBits (link *etype ,
4554 char *rname, int p_type)
4562 blen = SPEC_BLEN(etype);
4563 bstr = SPEC_BSTR(etype);
4565 l = aopGet(AOP(right),offset++,FALSE,FALSE);
4568 /* if the bit lenth is less than or */
4569 /* it exactly fits a byte then */
4570 if (SPEC_BLEN(etype) <= 8 ) {
4571 shCount = SPEC_BSTR(etype) ;
4573 /* shift left acc */
4576 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
4581 emitcode ("mov","b,a");
4582 emitcode("mov","a,@%s",rname);
4586 emitcode ("mov","b,a");
4587 emitcode("movx","a,@dptr");
4591 emitcode ("push","b");
4592 emitcode ("push","acc");
4593 emitcode ("lcall","__gptrget");
4594 emitcode ("pop","b");
4598 emitcode ("anl","a,#0x%02x",(unsigned char)
4599 ((unsigned char)(0xFF << (blen+bstr)) |
4600 (unsigned char)(0xFF >> (8-bstr)) ) );
4601 emitcode ("orl","a,b");
4602 if (p_type == GPOINTER)
4603 emitcode("pop","b");
4609 emitcode("mov","@%s,a",rname);
4613 emitcode("movx","@dptr,a");
4617 emitcode("lcall","__gptrput");
4622 if ( SPEC_BLEN(etype) <= 8 )
4625 emitcode("inc","%s",rname);
4626 rLen = SPEC_BLEN(etype) ;
4628 /* now generate for lengths greater than one byte */
4631 l = aopGet(AOP(right),offset++,FALSE,TRUE);
4641 emitcode("mov","@%s,a",rname);
4643 emitcode("mov","@%s,%s",rname,l);
4648 emitcode("movx","@dptr,a");
4653 emitcode("lcall","__gptrput");
4656 emitcode ("inc","%s",rname);
4661 /* last last was not complete */
4663 /* save the byte & read byte */
4666 emitcode ("mov","b,a");
4667 emitcode("mov","a,@%s",rname);
4671 emitcode ("mov","b,a");
4672 emitcode("movx","a,@dptr");
4676 emitcode ("push","b");
4677 emitcode ("push","acc");
4678 emitcode ("lcall","__gptrget");
4679 emitcode ("pop","b");
4683 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
4684 emitcode ("orl","a,b");
4687 if (p_type == GPOINTER)
4688 emitcode("pop","b");
4693 emitcode("mov","@%s,a",rname);
4697 emitcode("movx","@dptr,a");
4701 emitcode("lcall","__gptrput");
4705 /*-----------------------------------------------------------------*/
4706 /* genDataPointerSet - remat pointer to data space */
4707 /*-----------------------------------------------------------------*/
4708 static void genDataPointerSet(operand *right,
4712 int size, offset = 0 ;
4713 char *l, buffer[256];
4715 aopOp(right,ic,FALSE);
4717 l = aopGet(AOP(result),0,FALSE,TRUE);
4718 size = AOP_SIZE(right);
4721 sprintf(buffer,"(%s + %d)",l+1,offset);
4723 sprintf(buffer,"%s",l+1);
4724 emitcode("mov","%s,%s",buffer,
4725 aopGet(AOP(right),offset++,FALSE,FALSE));
4728 freeAsmop(right,NULL,ic,TRUE);
4729 freeAsmop(result,NULL,ic,TRUE);
4732 /*-----------------------------------------------------------------*/
4733 /* genNearPointerSet - emitcode for near pointer put */
4734 /*-----------------------------------------------------------------*/
4735 static void genNearPointerSet (operand *right,
4743 link *ptype = operandType(result);
4745 retype= getSpec(operandType(right));
4747 aopOp(result,ic,FALSE);
4749 /* if the result is rematerializable &
4750 in data space & not a bit variable */
4751 if (AOP_TYPE(result) == AOP_IMMD &&
4752 DCL_TYPE(ptype) == POINTER &&
4753 !IS_BITVAR(retype)) {
4754 genDataPointerSet (right,result,ic);
4758 /* if the value is already in a pointer register
4759 then don't need anything more */
4760 if (!AOP_INPREG(AOP(result))) {
4761 /* otherwise get a free pointer register */
4763 preg = getFreePtr(ic,&aop,FALSE);
4764 emitcode("mov","%s,%s",
4766 aopGet(AOP(result),0,FALSE,TRUE));
4767 rname = preg->name ;
4769 rname = aopGet(AOP(result),0,FALSE,FALSE);
4771 freeAsmop(result,NULL,ic,TRUE);
4772 aopOp (right,ic,FALSE);
4774 /* if bitfield then unpack the bits */
4775 if (IS_BITVAR(retype))
4776 genPackBits (retype,right,rname,POINTER);
4778 /* we have can just get the values */
4779 int size = AOP_SIZE(right);
4783 l = aopGet(AOP(right),offset,FALSE,TRUE);
4786 emitcode("mov","@%s,a",rname);
4788 emitcode("mov","@%s,%s",rname,l);
4790 emitcode("inc","%s",rname);
4795 /* now some housekeeping stuff */
4797 /* we had to allocate for this iCode */
4798 freeAsmop(NULL,aop,ic,TRUE);
4800 /* we did not allocate which means left
4801 already in a pointer register, then
4802 if size > 0 && this could be used again
4803 we have to point it back to where it
4805 if (AOP_SIZE(right) > 1 &&
4806 !OP_SYMBOL(result)->remat &&
4807 ( OP_SYMBOL(result)->liveTo > ic->seq ||
4809 int size = AOP_SIZE(right) - 1;
4811 emitcode("dec","%s",rname);
4816 freeAsmop(right,NULL,ic,TRUE);
4821 /*-----------------------------------------------------------------*/
4822 /* genPagedPointerSet - emitcode for Paged pointer put */
4823 /*-----------------------------------------------------------------*/
4824 static void genPagedPointerSet (operand *right,
4833 retype= getSpec(operandType(right));
4835 aopOp(result,ic,FALSE);
4837 /* if the value is already in a pointer register
4838 then don't need anything more */
4839 if (!AOP_INPREG(AOP(result))) {
4840 /* otherwise get a free pointer register */
4842 preg = getFreePtr(ic,&aop,FALSE);
4843 emitcode("mov","%s,%s",
4845 aopGet(AOP(result),0,FALSE,TRUE));
4846 rname = preg->name ;
4848 rname = aopGet(AOP(result),0,FALSE,FALSE);
4850 freeAsmop(result,NULL,ic,TRUE);
4851 aopOp (right,ic,FALSE);
4853 /* if bitfield then unpack the bits */
4854 if (IS_BITVAR(retype))
4855 genPackBits (retype,right,rname,PPOINTER);
4857 /* we have can just get the values */
4858 int size = AOP_SIZE(right);
4862 l = aopGet(AOP(right),offset,FALSE,TRUE);
4865 emitcode("movx","@%s,a",rname);
4868 emitcode("inc","%s",rname);
4874 /* now some housekeeping stuff */
4876 /* we had to allocate for this iCode */
4877 freeAsmop(NULL,aop,ic,TRUE);
4879 /* we did not allocate which means left
4880 already in a pointer register, then
4881 if size > 0 && this could be used again
4882 we have to point it back to where it
4884 if (AOP_SIZE(right) > 1 &&
4885 !OP_SYMBOL(result)->remat &&
4886 ( OP_SYMBOL(result)->liveTo > ic->seq ||
4888 int size = AOP_SIZE(right) - 1;
4890 emitcode("dec","%s",rname);
4895 freeAsmop(right,NULL,ic,TRUE);
4900 /*-----------------------------------------------------------------*/
4901 /* genFarPointerSet - set value from far space */
4902 /*-----------------------------------------------------------------*/
4903 static void genFarPointerSet (operand *right,
4904 operand *result, iCode *ic)
4907 link *retype = getSpec(operandType(right));
4909 aopOp(result,ic,FALSE);
4911 /* if the operand is already in dptr
4912 then we do nothing else we move the value to dptr */
4913 if (AOP_TYPE(result) != AOP_STR) {
4914 /* if this is remateriazable */
4915 if (AOP_TYPE(result) == AOP_IMMD)
4916 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
4917 else { /* we need to get it byte by byte */
4918 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
4919 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
4920 if (options.model == MODEL_FLAT24)
4922 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
4926 /* so dptr know contains the address */
4927 freeAsmop(result,NULL,ic,TRUE);
4928 aopOp(right,ic,FALSE);
4930 /* if bit then unpack */
4931 if (IS_BITVAR(retype))
4932 genPackBits(retype,right,"dptr",FPOINTER);
4934 size = AOP_SIZE(right);
4938 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
4940 emitcode("movx","@dptr,a");
4942 emitcode("inc","dptr");
4946 freeAsmop(right,NULL,ic,TRUE);
4949 /*-----------------------------------------------------------------*/
4950 /* genGenPointerSet - set value from generic pointer space */
4951 /*-----------------------------------------------------------------*/
4952 static void genGenPointerSet (operand *right,
4953 operand *result, iCode *ic)
4956 link *retype = getSpec(operandType(right));
4958 aopOp(result,ic,FALSE);
4960 /* if the operand is already in dptr
4961 then we do nothing else we move the value to dptr */
4962 if (AOP_TYPE(result) != AOP_STR) {
4963 /* if this is remateriazable */
4964 if (AOP_TYPE(result) == AOP_IMMD) {
4965 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
4966 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
4968 else { /* we need to get it byte by byte */
4969 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
4970 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
4971 if (options.model == MODEL_FLAT24)
4973 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
4974 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
4978 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
4982 /* so dptr know contains the address */
4983 freeAsmop(result,NULL,ic,TRUE);
4984 aopOp(right,ic,FALSE);
4986 /* if bit then unpack */
4987 if (IS_BITVAR(retype))
4988 genPackBits(retype,right,"dptr",GPOINTER);
4990 size = AOP_SIZE(right);
4994 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
4996 emitcode("lcall","__gptrput");
4998 emitcode("inc","dptr");
5002 freeAsmop(right,NULL,ic,TRUE);
5005 /*-----------------------------------------------------------------*/
5006 /* genPointerSet - stores the value into a pointer location */
5007 /*-----------------------------------------------------------------*/
5008 static void genPointerSet (iCode *ic)
5010 operand *right, *result ;
5014 right = IC_RIGHT(ic);
5015 result = IC_RESULT(ic) ;
5017 /* depending on the type of pointer we need to
5018 move it to the correct pointer register */
5019 type = operandType(result);
5020 etype = getSpec(type);
5021 /* if left is of type of pointer then it is simple */
5022 if (IS_PTR(type) && !IS_FUNC(type->next)) {
5023 p_type = DCL_TYPE(type);
5026 /* we have to go by the storage class */
5027 p_type = PTR_TYPE(SPEC_OCLS(etype));
5029 /* if (SPEC_OCLS(etype)->codesp ) { */
5030 /* p_type = CPOINTER ; */
5033 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
5034 /* p_type = FPOINTER ; */
5036 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
5037 /* p_type = PPOINTER ; */
5039 /* if (SPEC_OCLS(etype) == idata ) */
5040 /* p_type = IPOINTER ; */
5042 /* p_type = POINTER ; */
5045 /* now that we have the pointer type we assign
5046 the pointer values */
5051 genNearPointerSet (right,result,ic);
5055 genPagedPointerSet (right,result,ic);
5059 genFarPointerSet (right,result,ic);
5063 genGenPointerSet (right,result,ic);
5069 /*-----------------------------------------------------------------*/
5070 /* genIfx - generate code for Ifx statement */
5071 /*-----------------------------------------------------------------*/
5072 static void genIfx (iCode *ic, iCode *popIc)
5074 operand *cond = IC_COND(ic);
5077 aopOp(cond,ic,FALSE);
5079 /* get the value into acc */
5080 if (AOP_TYPE(cond) != AOP_CRY)
5084 /* the result is now in the accumulator */
5085 freeAsmop(cond,NULL,ic,TRUE);
5087 /* if there was something to be popped then do it */
5091 /* if the condition is a bit variable */
5092 if (isbit && IS_ITEMP(cond) &&
5094 genIfxJump(ic,SPIL_LOC(cond)->rname);
5096 if (isbit && !IS_ITEMP(cond))
5097 genIfxJump(ic,OP_SYMBOL(cond)->rname);
5104 /*-----------------------------------------------------------------*/
5105 /* genAddrOf - generates code for address of */
5106 /*-----------------------------------------------------------------*/
5107 static void genAddrOf (iCode *ic)
5109 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
5112 aopOp(IC_RESULT(ic),ic,FALSE);
5114 /* if the operand is on the stack then we
5115 need to get the stack offset of this
5118 /* if it has an offset then we need to compute
5121 emitcode("mov","a,_bp");
5122 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
5123 aopPut(AOP(IC_RESULT(ic)),"a",0);
5125 /* we can just move _bp */
5126 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
5128 /* fill the result with zero */
5129 size = AOP_SIZE(IC_RESULT(ic)) - 1;
5132 if (options.stack10bit && size < (FPTRSIZE - 1))
5135 "*** warning: pointer to stack var truncated.\n");
5142 if (options.stack10bit && offset == 2)
5144 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
5148 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
5155 /* object not on stack then we need the name */
5156 size = AOP_SIZE(IC_RESULT(ic));
5160 char s[SDCC_NAME_MAX];
5162 sprintf(s,"#(%s >> %d)",
5166 sprintf(s,"#%s",sym->rname);
5167 aopPut(AOP(IC_RESULT(ic)),s,offset++);
5171 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
5175 /*-----------------------------------------------------------------*/
5176 /* genFarFarAssign - assignment when both are in far space */
5177 /*-----------------------------------------------------------------*/
5178 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
5180 int size = AOP_SIZE(right);
5183 /* first push the right side on to the stack */
5185 l = aopGet(AOP(right),offset++,FALSE,FALSE);
5187 emitcode ("push","acc");
5190 freeAsmop(right,NULL,ic,FALSE);
5191 /* now assign DPTR to result */
5192 aopOp(result,ic,FALSE);
5193 size = AOP_SIZE(result);
5195 emitcode ("pop","acc");
5196 aopPut(AOP(result),"a",--offset);
5198 freeAsmop(result,NULL,ic,FALSE);
5202 /*-----------------------------------------------------------------*/
5203 /* genAssign - generate code for assignment */
5204 /*-----------------------------------------------------------------*/
5205 static void genAssign (iCode *ic)
5207 operand *result, *right;
5209 unsigned long lit = 0L;
5211 result = IC_RESULT(ic);
5212 right = IC_RIGHT(ic) ;
5214 /* if they are the same */
5215 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
5218 aopOp(right,ic,FALSE);
5220 /* special case both in far space */
5221 if ((AOP_TYPE(right) == AOP_DPTR ||
5222 AOP_TYPE(right) == AOP_DPTR2) &&
5223 IS_TRUE_SYMOP(result) &&
5224 isOperandInFarSpace(result)) {
5226 genFarFarAssign (result,right,ic);
5230 aopOp(result,ic,TRUE);
5232 /* if they are the same registers */
5233 if (sameRegs(AOP(right),AOP(result)))
5236 /* if the result is a bit */
5237 if (AOP_TYPE(result) == AOP_CRY) {
5239 /* if the right size is a literal then
5240 we know what the value is */
5241 if (AOP_TYPE(right) == AOP_LIT) {
5242 if (((int) operandLitValue(right)))
5243 aopPut(AOP(result),one,0);
5245 aopPut(AOP(result),zero,0);
5249 /* the right is also a bit variable */
5250 if (AOP_TYPE(right) == AOP_CRY) {
5251 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5252 aopPut(AOP(result),"c",0);
5258 aopPut(AOP(result),"a",0);
5262 /* bit variables done */
5264 size = AOP_SIZE(result);
5266 if(AOP_TYPE(right) == AOP_LIT)
5267 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5269 (AOP_TYPE(result) != AOP_REG) &&
5270 (AOP_TYPE(right) == AOP_LIT) &&
5271 !IS_FLOAT(operandType(right)) &&
5273 emitcode("clr","a");
5275 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
5276 aopPut(AOP(result),"a",size);
5279 aopGet(AOP(right),size,FALSE,FALSE),
5285 aopGet(AOP(right),offset,FALSE,FALSE),
5292 freeAsmop (right,NULL,ic,FALSE);
5293 freeAsmop (result,NULL,ic,TRUE);
5296 /*-----------------------------------------------------------------*/
5297 /* genJumpTab - genrates code for jump table */
5298 /*-----------------------------------------------------------------*/
5299 static void genJumpTab (iCode *ic)
5304 aopOp(IC_JTCOND(ic),ic,FALSE);
5305 /* get the condition into accumulator */
5306 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
5308 /* multiply by three */
5309 emitcode("add","a,acc");
5310 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
5311 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
5313 jtab = newiTempLabel(NULL);
5314 emitcode("mov","dptr,#%05d$",jtab->key+100);
5315 emitcode("jmp","@a+dptr");
5316 emitcode("","%05d$:",jtab->key+100);
5317 /* now generate the jump labels */
5318 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
5319 jtab = setNextItem(IC_JTLABELS(ic)))
5320 emitcode("ljmp","%05d$",jtab->key+100);
5324 /*-----------------------------------------------------------------*/
5325 /* genCast - gen code for casting */
5326 /*-----------------------------------------------------------------*/
5327 static void genCast (iCode *ic)
5329 operand *result = IC_RESULT(ic);
5330 link *ctype = operandType(IC_LEFT(ic));
5331 link *rtype = operandType(IC_RIGHT(ic));
5332 operand *right = IC_RIGHT(ic);
5335 /* if they are equivalent then do nothing */
5336 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
5339 aopOp(right,ic,FALSE) ;
5340 aopOp(result,ic,FALSE);
5342 /* if the result is a bit */
5343 if (AOP_TYPE(result) == AOP_CRY) {
5344 /* if the right size is a literal then
5345 we know what the value is */
5346 if (AOP_TYPE(right) == AOP_LIT) {
5347 if (((int) operandLitValue(right)))
5348 aopPut(AOP(result),one,0);
5350 aopPut(AOP(result),zero,0);
5355 /* the right is also a bit variable */
5356 if (AOP_TYPE(right) == AOP_CRY) {
5357 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5358 aopPut(AOP(result),"c",0);
5364 aopPut(AOP(result),"a",0);
5368 /* if they are the same size : or less */
5369 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
5371 /* if they are in the same place */
5372 if (sameRegs(AOP(right),AOP(result)))
5375 /* if they in different places then copy */
5376 size = AOP_SIZE(result);
5380 aopGet(AOP(right),offset,FALSE,FALSE),
5388 /* if the result is of type pointer */
5389 if (IS_PTR(ctype)) {
5392 link *type = operandType(right);
5393 link *etype = getSpec(type);
5395 /* pointer to generic pointer */
5396 if (IS_GENPTR(ctype)) {
5400 p_type = DCL_TYPE(type);
5402 /* we have to go by the storage class */
5403 p_type = PTR_TYPE(SPEC_OCLS(etype));
5406 /* the first two bytes are known */
5407 size = GPTRSIZE - 1;
5411 aopGet(AOP(right),offset,FALSE,FALSE),
5415 /* the last byte depending on type */
5432 /* this should never happen */
5433 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
5434 "got unknown pointer type");
5437 aopPut(AOP(result),l, GPTRSIZE - 1);
5441 /* just copy the pointers */
5442 size = AOP_SIZE(result);
5446 aopGet(AOP(right),offset,FALSE,FALSE),
5453 /* so we now know that the size of destination is greater
5454 than the size of the source */
5455 /* we move to result for the size of source */
5456 size = AOP_SIZE(right);
5460 aopGet(AOP(right),offset,FALSE,FALSE),
5465 /* now depending on the sign of the source && destination */
5466 size = AOP_SIZE(result) - AOP_SIZE(right);
5467 /* if unsigned or not an integral type */
5468 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
5470 aopPut(AOP(result),zero,offset++);
5472 /* we need to extend the sign :{ */
5473 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
5476 emitcode("rlc","a");
5477 emitcode("subb","a,acc");
5479 aopPut(AOP(result),"a",offset++);
5482 /* we are done hurray !!!! */
5485 freeAsmop(right,NULL,ic,TRUE);
5486 freeAsmop(result,NULL,ic,TRUE);
5490 /*-----------------------------------------------------------------*/
5491 /* genDjnz - generate decrement & jump if not zero instrucion */
5492 /*-----------------------------------------------------------------*/
5493 static int genDjnz (iCode *ic, iCode *ifx)
5499 /* if the if condition has a false label
5500 then we cannot save */
5504 /* if the minus is not of the form
5506 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
5507 !IS_OP_LITERAL(IC_RIGHT(ic)))
5510 if (operandLitValue(IC_RIGHT(ic)) != 1)
5513 /* if the size of this greater than one then no
5515 if (getSize(operandType(IC_RESULT(ic))) > 1)
5518 /* otherwise we can save BIG */
5519 lbl = newiTempLabel(NULL);
5520 lbl1= newiTempLabel(NULL);
5522 aopOp(IC_RESULT(ic),ic,FALSE);
5524 if (IS_AOP_PREG(IC_RESULT(ic))) {
5525 emitcode("dec","%s",
5526 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
5527 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
5528 emitcode("jnz","%05d$",lbl->key+100);
5530 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
5533 emitcode ("sjmp","%05d$",lbl1->key+100);
5534 emitcode ("","%05d$:",lbl->key+100);
5535 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
5536 emitcode ("","%05d$:",lbl1->key+100);
5538 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
5543 /*-----------------------------------------------------------------*/
5544 /* genReceive - generate code for a receive iCode */
5545 /*-----------------------------------------------------------------*/
5546 static void genReceive (iCode *ic)
5548 if (isOperandInFarSpace(IC_RESULT(ic)) &&
5549 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
5550 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
5552 int size = getSize(operandType(IC_RESULT(ic)));
5553 int offset = fReturnSize - size;
5555 emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
5556 fReturn[fReturnSize - offset - 1] : "acc"));
5559 aopOp(IC_RESULT(ic),ic,FALSE);
5560 size = AOP_SIZE(IC_RESULT(ic));
5563 emitcode ("pop","acc");
5564 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
5569 aopOp(IC_RESULT(ic),ic,FALSE);
5571 assignResultValue(IC_RESULT(ic));
5574 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
5577 /*-----------------------------------------------------------------*/
5578 /* gen51Code - generate code for 8051 based controllers */
5579 /*-----------------------------------------------------------------*/
5580 void gen51Code (iCode *lic)
5585 lineHead = lineCurr = NULL;
5587 /* print the allocation information */
5589 printAllocInfo( currFunc, codeOutFile);
5590 /* if debug information required */
5591 /* if (options.debug && currFunc) { */
5593 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
5595 if (IS_STATIC(currFunc->etype))
5596 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
5598 emitcode("","G$%s$0$0 ==.",currFunc->name);
5601 /* stack pointer name */
5602 if (options.useXstack)
5608 for (ic = lic ; ic ; ic = ic->next ) {
5610 if ( cln != ic->lineno ) {
5611 if ( options.debug ) {
5613 emitcode("","C$%s$%d$%d$%d ==.",
5614 ic->filename,ic->lineno,
5615 ic->level,ic->block);
5618 emitcode(";","%s %d",ic->filename,ic->lineno);
5621 /* if the result is marked as
5622 spilt and rematerializable or code for
5623 this has already been generated then
5625 if (resultRemat(ic) || ic->generated )
5628 /* depending on the operation */
5647 /* IPOP happens only when trying to restore a
5648 spilt live range, if there is an ifx statement
5649 following this pop then the if statement might
5650 be using some of the registers being popped which
5651 would destory the contents of the register so
5652 we need to check for this condition and handle it */
5654 ic->next->op == IFX &&
5655 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
5656 genIfx (ic->next,ic);
5674 genEndFunction (ic);
5694 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
5711 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
5715 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
5719 genCmpLe (ic,ifxForOp(IC_RESULT(ic),ic));
5723 genCmpGe (ic,ifxForOp(IC_RESULT(ic),ic));
5727 genCmpNe (ic,ifxForOp(IC_RESULT(ic),ic));
5731 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
5743 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
5747 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
5751 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
5778 case GET_VALUE_AT_ADDRESS:
5783 if (POINTER_SET(ic))
5810 addSet(&_G.sendSet,ic);
5815 /* piCode(ic,stdout); */
5821 /* now we are ready to call the
5822 peep hole optimizer */
5823 if (!options.nopeep)
5824 peepHole (&lineHead);
5826 /* now do the actual printing */
5827 printLine (lineHead,codeOutFile);