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 bit variable */
861 assert("bit variable cannot be AOP_CRY\n");
866 if (strcmp(aop->aopu.aop_str[offset],s))
867 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
871 emitcode ("std","y+%d,%s",offset,s);
875 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
876 "aopPut got unsupported aop->type");
884 /*-----------------------------------------------------------------*/
885 /* pointToEnd :- points to the last byte of the operand */
886 /*-----------------------------------------------------------------*/
887 static void pointToEnd (asmop *aop)
893 aop->coff = count = (aop->size - 1);
897 emitcode("adiw","%s,%d",aop->aopu.aop_ptr->name,count);
904 /*-----------------------------------------------------------------*/
905 /* reAdjustPreg - points a register back to where it should */
906 /*-----------------------------------------------------------------*/
907 static void reAdjustPreg (asmop *aop)
912 if ((size = aop->size) <= 1)
918 emitcode("sbiw","%s,%d",aop->aopu.aop_ptr->name,size);
924 #define AOP(op) op->aop
925 #define AOP_TYPE(op) AOP(op)->type
926 #define AOP_SIZE(op) AOP(op)->size
927 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_X || \
928 AOP_TYPE(x) == AOP_Z))
929 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
930 (x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) || \
931 x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) )))
933 /*-----------------------------------------------------------------*/
934 /* genNotFloat - generates not for float operations */
935 /*-----------------------------------------------------------------*/
936 static void genNotFloat (operand *op, operand *res)
942 /* we will put 127 in the first byte of
944 aopPut(AOP(res),"127",0);
945 size = AOP_SIZE(op) - 1;
948 l = aopGet(op->aop,offset++);
952 emitcode("or","R0,%s", aopGet(op->aop, offset++);
954 tlbl = newiTempLabel(NULL);
956 tlbl = newiTempLabel(NULL);
957 aopPut(res->aop,zero,1);
958 emitcode("cpi","r0,0");
959 emitcode("breq","L%05d",tlbl->key);
960 aopPut(res->aop,one,1);
961 emitcode("","L%05d:",tlbl->key);
963 size = res->aop->size - 2;
965 /* put zeros in the rest */
967 aopPut(res->aop,zero,offset++);
970 /*-----------------------------------------------------------------*/
971 /* opIsGptr: returns non-zero if the passed operand is */
972 /* a generic pointer type. */
973 /*-----------------------------------------------------------------*/
974 static int opIsGptr(operand *op)
976 link *type = operandType(op);
978 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
985 /*-----------------------------------------------------------------*/
986 /* getDataSize - get the operand data size */
987 /*-----------------------------------------------------------------*/
988 static int getDataSize(operand *op)
992 if (size == GPTRSIZE)
994 link *type = operandType(op);
997 /* generic pointer; arithmetic operations
998 * should ignore the high byte (pointer type).
1006 /*-----------------------------------------------------------------*/
1007 /* outAcc - output Acc */
1008 /*-----------------------------------------------------------------*/
1009 static void outAcc(operand *result)
1012 size = getDataSize(result);
1014 aopPut(AOP(result),"r0",0);
1017 /* unsigned or positive */
1019 aopPut(AOP(result),zero,offset++);
1024 /*-----------------------------------------------------------------*/
1025 /* outBitC - output a bit C */
1026 /*-----------------------------------------------------------------*/
1027 static void outBitC(operand *result)
1029 emitcode("clr","r0");
1030 emitcode("rol","r0");
1034 /*-----------------------------------------------------------------*/
1035 /* toBoolean - emit code for orl a,operator(sizeop) */
1036 /*-----------------------------------------------------------------*/
1037 static void toBoolean(operand *oper)
1039 int size = AOP_SIZE(oper) ;
1041 emitcode ("clr","r0");
1043 emitcode("or","r0,%s",aopGet(AOP(oper),offset++));
1047 /*-----------------------------------------------------------------*/
1048 /* genNot - generate code for ! operation */
1049 /*-----------------------------------------------------------------*/
1050 static void genNot (iCode *ic)
1053 link *optype = operandType(IC_LEFT(ic));
1054 int size, offset = 1;
1056 /* assign asmOps to operand & result */
1057 aopOp (IC_LEFT(ic),ic,FALSE);
1058 aopOp (IC_RESULT(ic),ic,TRUE);
1060 /* if type float then do float */
1061 if (IS_FLOAT(optype)) {
1062 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1065 emitcode("clr","r24");
1066 tlbl = newiTempLabel(NULL);
1067 toBoolean(IC_LEFT(ic));
1068 emitcode("bne","L%05d",tlbl->key);
1069 emitcode("ldi","r24,1");
1070 emitcode("","L%05d:",tlbl->key);
1071 aopPut(AOP(IC_RESULT(ic)),"r24",0);
1072 size = AOP_SIZE(IC_RESULT(ic)) -1;
1073 while (size--) aopPut(AOP(IC_RESULT(ic)),zero,offset++);
1077 /* release the aops */
1078 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1079 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1083 /*-----------------------------------------------------------------*/
1084 /* genCpl - generate code for complement */
1085 /*-----------------------------------------------------------------*/
1086 static void genCpl (iCode *ic)
1092 /* assign asmOps to operand & result */
1093 aopOp (IC_LEFT(ic),ic,FALSE);
1094 aopOp (IC_RESULT(ic),ic,TRUE);
1095 samer = sameRegs(AOP(IC_LEFT(ic),AOP(IC_RESULT(ic))));
1096 size = AOP_SIZE(IC_RESULT(ic));
1098 char *l = aopGet(AOP(IC_LEFT(ic)),offset);
1100 emitcode ("com","%s",l);
1102 aopPut(AOP(IC_RESULT(ic)),l,offset);
1103 emitcode ("com","%s",aopGet(AOP(IC_RESULT(ic)),offset++));
1109 /* release the aops */
1110 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1111 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1114 /*-----------------------------------------------------------------*/
1115 /* genUminusFloat - unary minus for floating points */
1116 /*-----------------------------------------------------------------*/
1117 static void genUminusFloat(operand *op,operand *result)
1119 int size ,offset =0 ;
1121 /* for this we just need to flip the
1122 first it then copy the rest in place */
1123 size = AOP_SIZE(op) - 1;
1124 l = aopGet(AOP(op),3);
1126 emitcode("ldi","r24,0x80");
1127 if (sameRegs(AOP(op),AOP(result))) {
1128 emitcode("eor","%s,r24",l);
1130 aopPut(AOP(result),l,3);
1131 emitcode("eor","%s,r24",aopGet(AOP(result),3));
1134 aopPut(AOP(result), aopGet(AOP(op),offset), offset);
1139 /*-----------------------------------------------------------------*/
1140 /* genUminus - unary minus code generation */
1141 /*-----------------------------------------------------------------*/
1142 static void genUminus (iCode *ic)
1145 link *optype, *rtype;
1149 aopOp(IC_LEFT(ic),ic,FALSE);
1150 aopOp(IC_RESULT(ic),ic,TRUE);
1152 optype = operandType(IC_LEFT(ic));
1153 rtype = operandType(IC_RESULT(ic));
1155 /* if float then do float stuff */
1156 if (IS_FLOAT(optype)) {
1157 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1161 /* otherwise subtract from zero */
1162 size = AOP_SIZE(IC_LEFT(ic));
1164 samer = sameRegs(AOP(IC_LEFT(ic)),AOP(IC_RESULT(ic)));
1167 char *l = aopGet(AOP(IC_LEFT(ic)),offset);
1169 emitcode("clr","r0");
1170 emitcode("sbc","r0,%s",l);
1171 aopPut(AOP(IC_RESULT(ic)),"r0",offset++);
1174 emitcode("clr","%s",s=aopGet(IC_RESULT(ic),offset++));
1175 emitcode("sbc","%s,%s",s,l);
1179 /* if any remaining bytes in the result */
1180 /* we just need to propagate the sign */
1181 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1182 symbol *tlbl = newiTempLabel(NULL);
1183 emitcode("clr","r0");
1184 emitcode("brcc","L%05d",tlbl->key);
1185 emitcode("com","r0");
1186 emitcode("","L%05d:",tlbl->key);
1188 aopPut(AOP(IC_RESULT(ic)),"r0",offset++);
1192 /* release the aops */
1193 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1194 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1197 /*-----------------------------------------------------------------*/
1198 /* assignResultValue - */
1199 /*-----------------------------------------------------------------*/
1200 static void assignResultValue(operand * oper)
1203 int size = AOP_SIZE(oper);
1205 aopPut(AOP(oper),fReturn[offset],offset);
1210 /*-----------------------------------------------------------------*/
1211 /* saveZreg - if indirect call then save z-pointer register */
1212 /*-----------------------------------------------------------------*/
1213 static void saveZreg (iCode *ic)
1215 /* only if live accross this call */
1216 if (ic->regSaved == 0 &&
1217 (bitVectBitValue(ic->rMask,R30_IDX) ||
1218 bitVectBitValue(ic->rMask,R31_IDX))) {
1220 emitcode("push","r30");
1221 emitcode("push","r31");
1225 /*-----------------------------------------------------------------*/
1226 /* popZreg - restore values of zreg */
1227 /*-----------------------------------------------------------------*/
1228 static void popZreg (iCode *ic)
1230 if (ic->regsSaved) {
1231 emitcode ("pop","r31");
1232 emitcode ("pop","r30");
1236 /*-----------------------------------------------------------------*/
1237 /* genIpush - genrate code for pushing this gets a little complex */
1238 /*-----------------------------------------------------------------*/
1239 static void genIpush (iCode *ic)
1241 int size, offset = 0 ;
1245 if (!ic->parmPush) {
1246 /* and the item is spilt then do nothing */
1247 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1251 for (lic = ic->next ; lic ; lic = lic->next)
1252 if (lic->op == PCALL) break;
1253 if (lic) saveZreg(lic);
1256 /* this is a paramter push */
1257 aopOp(IC_LEFT(ic),ic,FALSE);
1258 size = AOP_SIZE(IC_LEFT(ic));
1260 l = aopGet(AOP(IC_LEFT(ic)),offset++);
1261 emitcode("push","%s",l);
1264 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1267 /*-----------------------------------------------------------------*/
1268 /* genIpop - recover the registers: can happen only for spilling */
1269 /*-----------------------------------------------------------------*/
1270 static void genIpop (iCode *ic)
1275 /* if the temp was not pushed then */
1276 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1279 aopOp(IC_LEFT(ic),ic,FALSE);
1280 size = AOP_SIZE(IC_LEFT(ic));
1283 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--));
1285 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1288 /*-----------------------------------------------------------------*/
1289 /* genCall - generates a call statement */
1290 /*-----------------------------------------------------------------*/
1291 static void genCall (iCode *ic)
1295 /* if send set is not empty the assign */
1299 for (sic = setFirstItem(_G.sendSet) ; sic ;
1300 sic = setNextItem(_G.sendSet)) {
1301 int size, offset = 0;
1302 aopOp(IC_LEFT(sic),sic,FALSE);
1303 size = AOP_SIZE(IC_LEFT(sic));
1305 char *l = aopGet(AOP(IC_LEFT(sic)),offset);
1306 if (strcmp(l,fReturn[offset]))
1307 emitcode("mov","%s,%s",
1312 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1317 emitcode("call","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1318 OP_SYMBOL(IC_LEFT(ic))->rname :
1319 OP_SYMBOL(IC_LEFT(ic))->name));
1321 /* if we need assign a result value */
1322 if ((IS_ITEMP(IC_RESULT(ic)) &&
1323 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1324 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1325 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1327 aopOp(IC_RESULT(ic),ic,FALSE);
1328 assignResultValue(IC_RESULT(ic));
1329 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1332 /* adjust the stack for parameters if required */
1333 if (IC_LEFT(ic)->parmBytes) {
1334 if (IC_LEFT(ic)->parmBytes > 63) {
1335 emitcode("sbiw","r28,%d",IC_LEFT(ic)->parmBytes);
1337 emitcode("subi","r28,lo8(%d)",IC_LEFT(ic)->parmBytes);
1338 emitcode("sbci","r29,hi8(%d)",IC_LEFT(ic)->parmBytes);
1344 /*-----------------------------------------------------------------*/
1345 /* genPcall - generates a call by pointer statement */
1346 /*-----------------------------------------------------------------*/
1347 static void genPcall (iCode *ic)
1351 if (!ic->regsSaved) saveZreg(ic);
1353 aopOp(IC_LEFT(ic),ic,FALSE);
1354 emitcode("mov","r30",aopGet(AOP(IC_LEFT(ic)),0));
1355 emitcode("mov","r31",aopGet(AOP(IC_RIGHT(ic)),0));
1356 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1358 /* if send set is not empty the assign */
1362 for (sic = setFirstItem(_G.sendSet) ; sic ;
1363 sic = setNextItem(_G.sendSet)) {
1364 int size, offset = 0;
1365 aopOp(IC_LEFT(sic),sic,FALSE);
1366 size = AOP_SIZE(IC_LEFT(sic));
1368 char *l = aopGet(AOP(IC_LEFT(sic)),offset);
1369 if (strcmp(l,fReturn[offset]))
1370 emitcode("mov","%s,%s",
1375 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1380 emitcode("icall","");
1382 /* if we need assign a result value */
1383 if ((IS_ITEMP(IC_RESULT(ic)) &&
1384 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1385 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
1386 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1388 aopOp(IC_RESULT(ic),ic,FALSE);
1390 assignResultValue(IC_RESULT(ic));
1391 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1394 /* adjust the stack for parameters if
1396 if (IC_LEFT(ic)->parmBytes) {
1398 if (IC_LEFT(ic)->parmBytes > 3) {
1399 emitcode("mov","a,%s",spname);
1400 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1401 emitcode("mov","%s,a",spname);
1403 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1404 emitcode("dec","%s",spname);
1408 /* adjust the stack for parameters if required */
1409 if (IC_LEFT(ic)->parmBytes) {
1410 if (IC_LEFT(ic)->parmBytes > 63) {
1411 emitcode("sbiw","r28,%d",IC_LEFT(ic)->parmBytes);
1413 emitcode("subi","r28,lo8(%d)",IC_LEFT(ic)->parmBytes);
1414 emitcode("sbci","r29,hi8(%d)",IC_LEFT(ic)->parmBytes);
1417 if (ic->regsSaved) popZregs(ic);
1420 /*-----------------------------------------------------------------*/
1421 /* resultRemat - result is rematerializable */
1422 /*-----------------------------------------------------------------*/
1423 static int resultRemat (iCode *ic)
1425 if (SKIP_IC(ic) || ic->op == IFX)
1428 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1429 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1430 if (sym->remat && !POINTER_SET(ic))
1438 #define STRCASECMP stricmp
1440 #define STRCASECMP strcasecmp
1443 /*-----------------------------------------------------------------*/
1444 /* inExcludeList - return 1 if the string is in exclude Reg list */
1445 /*-----------------------------------------------------------------*/
1446 static bool inExcludeList(char *s)
1450 if (options.excludeRegs[i] &&
1451 STRCASECMP(options.excludeRegs[i],"none") == 0)
1454 for ( i = 0 ; options.excludeRegs[i]; i++) {
1455 if (options.excludeRegs[i] &&
1456 STRCASECMP(s,options.excludeRegs[i]) == 0)
1462 /*-----------------------------------------------------------------*/
1463 /* genFunction - generated code for function entry */
1464 /*-----------------------------------------------------------------*/
1465 static void genFunction (iCode *ic)
1472 /* create the function header */
1473 emitcode(";","-----------------------------------------");
1474 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1475 emitcode(";","-----------------------------------------");
1477 emitcode("","%s:",sym->rname);
1478 fetype = getSpec(operandType(IC_LEFT(ic)));
1480 /* if critical function then turn interrupts off */
1481 if (SPEC_CRTCL(fetype))
1484 if (IS_ISR(sym->etype)) {
1487 /* save the preserved registers that are used in this function */
1488 for (i = R2_IDX ; i <= R15_IDX ; i++ ) {
1489 if (bitVectBitValue(sym->regsUsed,i)) {
1491 emitcode("push","%s",avr_regWithIdx(i)->name);
1494 /* now for the pointer registers */
1495 if (bitVectBitValue(sym->regsUsed,R26_IDX)) {
1497 emitcode("push","r26");
1499 if (bitVectBitValue(sym->regsUsed,R27_IDX)) {
1501 emitcode("push","r27");
1503 if (bitVectBitValue(sym->regsUsed,R30_IDX)) {
1505 emitcode("push","r30");
1507 if (bitVectBitValue(sym->regsUsed,R31_IDX)) {
1509 emitcode("push","r31");
1511 /* adjust the stack for the function */
1513 emitcode ("push","r28");
1514 emitcode ("push","r29");
1515 emitcode ("in","r28,__SP_L__");
1516 emitcode ("in","r29,__SP_H__");
1517 if (sym->stack <= 63) {
1518 emitcode("sbiw","r28,%d",sym->stack);
1520 emitcode ("subi","r28,lo8(%d)",sym->stack);
1521 emitcode ("sbci","r29,hi8(%d)",sym->stack);
1523 emitcode("out","__SP_L__,r28");
1524 emitcode("out","__SP_H__,r29");
1528 /*-----------------------------------------------------------------*/
1529 /* genEndFunction - generates epilogue for functions */
1530 /*-----------------------------------------------------------------*/
1531 static void genEndFunction (iCode *ic)
1533 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1535 /* restore stack pointer */
1536 if (sym->stack <= 63) {
1537 emitcode("adiw","r28,%d",sym->stack);
1539 emitcode ("subi","r28,lo8(-%d)",sym->stack);
1540 emitcode ("sbci","r29,hi8(-%d)",sym->stack);
1542 emitcode("out","__SP_L__,r28");
1543 emitcode("out","__SP_H__,r29");
1545 /* pop frame pointer */
1546 emitcode ("pop","r29");
1547 emitcode ("pop","r28");
1549 /* restore preserved registers */
1550 if (bitVectBitValue(sym->regsUsed,R31_IDX)) {
1552 emitcode("pop","r31");
1554 if (bitVectBitValue(sym->regsUsed,R30_IDX)) {
1556 emitcode("pop","r30");
1558 if (bitVectBitValue(sym->regsUsed,R27_IDX)) {
1560 emitcode("push","r27");
1562 if (bitVectBitValue(sym->regsUsed,R26_IDX)) {
1564 emitcode("push","r26");
1566 for (i = R15_IDX ; i >= R2_IDX ; i-- ) {
1567 if (bitVectBitValue(sym->regsUsed,i)) {
1569 emitcode("pop","%s",avr_regWithIdx(i)->name);
1573 if (IS_ISR(sym->etype)) {
1576 if (SPEC_CRTCL(fetype))
1580 /*-----------------------------------------------------------------*/
1581 /* genRet - generate code for return statement */
1582 /*-----------------------------------------------------------------*/
1583 static void genRet (iCode *ic)
1585 int size,offset = 0 , pushed = 0;
1587 /* if we have no return value then
1588 just generate the "ret" */
1592 /* we have something to return then
1593 move the return value into place */
1594 aopOp(IC_LEFT(ic),ic,FALSE);
1595 size = AOP_SIZE(IC_LEFT(ic));
1599 l = aopGet(AOP(IC_LEFT(ic)),offset);
1600 if (strcmp(fReturn[offset],l))
1601 emitcode("mov","%s,%s",fReturn[offset++],l);
1604 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
1607 /* generate a jump to the return label
1608 if the next is not the return statement */
1609 if (!(ic->next && ic->next->op == LABEL &&
1610 IC_LABEL(ic->next) == returnLabel))
1612 emitcode("rjmp","L%05d",returnLabel->key);
1616 /*-----------------------------------------------------------------*/
1617 /* genLabel - generates a label */
1618 /*-----------------------------------------------------------------*/
1619 static void genLabel (iCode *ic)
1621 /* special case never generate */
1622 if (IC_LABEL(ic) == entryLabel)
1625 emitcode("","L%05d:",IC_LABEL(ic)->key);
1628 /*-----------------------------------------------------------------*/
1629 /* genGoto - generates a ljmp */
1630 /*-----------------------------------------------------------------*/
1631 static void genGoto (iCode *ic)
1633 emitcode ("rjmp","L%05d:",(IC_LABEL(ic)->key+100));
1636 /*-----------------------------------------------------------------*/
1637 /* findLabelBackwards: walks back through the iCode chain looking */
1638 /* for the given label. Returns number of iCode instructions */
1639 /* between that label and given ic. */
1640 /* Returns zero if label not found. */
1641 /*-----------------------------------------------------------------*/
1642 static int findLabelBackwards(iCode *ic, int key)
1651 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
1653 /* printf("findLabelBackwards = %d\n", count); */
1661 /*-----------------------------------------------------------------*/
1662 /* genPlusIncr :- does addition with increment if possible */
1663 /*-----------------------------------------------------------------*/
1664 static bool genPlusIncr (iCode *ic)
1666 unsigned int icount ;
1668 /* will try to generate an increment */
1669 /* if the right side is not a literal
1671 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1674 icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
1676 /* if the sizes are greater than 2 or they are not the same regs
1678 if (AOP_SIZE(IC_RESULT(ic)) > 2 ||
1679 AOP_SIZE(IC_LEFT(ic)) > 2 ||
1680 !sameRegs(AOP(IC_LEFT(ic)),AOP(IC_RIGHT(ic))))
1683 /* so we know LEFT & RESULT in the same registers and add
1685 /* for short & char types */
1686 if (AOP_SIZE(IC_RESULT(ic)) < 2) {
1688 emitcode("inc","%s",aopGet(AOP(IC_LEFT(ic)),0));
1691 emicode("subi","%s,lo8(%d)",aopGet(AOP(IC_LEFT(ic)),0),-icount);
1695 /* if register pair and starts with 26/30 then adiw */
1696 if (isRegPair(AOP(IC_RESULT(ic))) && icount > 0 && icount < 64 &&
1697 ( IS_REGIDX(AOP(IC_RESULT(ic)),R26_IDX) ||
1698 IS_REGIDX(AOP(IC_RESULT(ic)),R30_IDX) )) {
1699 emitcode("adiw","%s,%d",aopGet(AOP(IC_RESULT(ic)),0),icount);
1704 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_RESULT(ic)),0),-icount);
1705 emitcode("sbci","%s,hi8(%d)",aopGet(AOP(IC_RESULT(ic)),1),-icount);
1709 /* This is the pure and virtuous version of this code.
1710 * I'm pretty certain it's right, but not enough to toss the old
1713 static void adjustArithmeticResult(iCode *ic)
1715 if (opIsGptr(IC_RESULT(ic)) &&
1716 opIsGptr(IC_LEFT(ic)) &&
1717 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1719 aopPut(AOP(IC_RESULT(ic)),
1720 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1),
1724 if (opIsGptr(IC_RESULT(ic)) &&
1725 opIsGptr(IC_RIGHT(ic)) &&
1726 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
1728 aopPut(AOP(IC_RESULT(ic)),
1729 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1),
1733 if (opIsGptr(IC_RESULT(ic)) &&
1734 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
1735 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
1736 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
1737 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
1739 sprintf(buffer,"%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
1740 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
1744 /*-----------------------------------------------------------------*/
1745 /* genPlus - generates code for addition */
1746 /*-----------------------------------------------------------------*/
1747 static void genPlus (iCode *ic)
1749 int size, offset = 0;
1751 /* special cases :- */
1753 aopOp (IC_LEFT(ic),ic,FALSE);
1754 aopOp (IC_RIGHT(ic),ic,FALSE);
1755 aopOp (IC_RESULT(ic),ic,TRUE);
1757 /* if I can do an increment instead
1758 of add then GOOD for ME */
1759 if (genPlusIncr (ic) == TRUE)
1762 size = getDataSize(IC_RESULT(ic));
1765 aopPut(AOP(IC_RESULT(ic)),aopGet(AOP(IC_RIGHT(ic)),offset),offset);
1767 emitcode("add","%s,%s",aopGet(AOP(IC_RESULT(ic)),offset),
1768 aopGet(AOP(IC_LEFT(ic)),offset));
1770 emitcode("adc","%s,%s",aopGet(AOP(IC_RESULT(ic)),offset),
1771 aopGet(AOP(IC_LEFT(ic)),offset));
1775 adjustArithmeticResult(ic);
1778 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1779 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1780 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1783 /*-----------------------------------------------------------------*/
1784 /* genMinusDec :- does subtraction with deccrement if possible */
1785 /*-----------------------------------------------------------------*/
1786 static bool genMinusDec (iCode *ic)
1788 unsigned int icount ;
1790 /* will try to generate an increment */
1791 /* if the right side is not a literal
1793 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1796 icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
1798 /* if the sizes are greater than 2 or they are not the same regs
1800 if (AOP_SIZE(IC_RESULT(ic)) > 2 ||
1801 AOP_SIZE(IC_LEFT(ic)) > 2 ||
1802 !sameRegs(AOP(IC_LEFT(ic)),AOP(IC_RIGHT(ic))))
1805 /* so we know LEFT & RESULT in the same registers and add
1807 /* for short & char types */
1808 if (AOP_SIZE(IC_RESULT(ic)) < 2) {
1810 emitcode("dec","%s",aopGet(AOP(IC_LEFT(ic)),0));
1813 emicode("subi","%s,lo8(%d)",aopGet(AOP(IC_LEFT(ic)),0),icount);
1817 /* if register pair and starts with 26/30 then adiw */
1818 if (isRegPair(AOP(IC_RESULT(ic))) && icount > 0 && icount < 64 &&
1819 ( IS_REGIDX(AOP(IC_RESULT(ic)),R26_IDX) ||
1820 IS_REGIDX(AOP(IC_RESULT(ic)),R30_IDX) )) {
1821 emitcode("sbiw","%s,%d",aopGet(AOP(IC_RESULT(ic)),0),icount);
1826 emitcode("subi","%s,lo8(%d)",aopGet(AOP(IC_RESULT(ic)),0),icount);
1827 emitcode("sbci","%s,hi8(%d)",aopGet(AOP(IC_RESULT(ic)),1),icount);
1831 /*-----------------------------------------------------------------*/
1832 /* addSign - complete with sign */
1833 /*-----------------------------------------------------------------*/
1834 static void addSign(operand *result, int offset, int sign)
1836 int size = (getDataSize(result) - offset);
1839 emitcode("rlc","a");
1840 emitcode("subb","a,acc");
1842 aopPut(AOP(result),"a",offset++);
1845 aopPut(AOP(result),zero,offset++);
1849 /*-----------------------------------------------------------------*/
1850 /* genMinus - generates code for subtraction */
1851 /*-----------------------------------------------------------------*/
1852 static void genMinus (iCode *ic)
1854 int size, offset = 0;
1855 unsigned long lit = 0L;
1857 aopOp (IC_LEFT(ic),ic,FALSE);
1858 aopOp (IC_RIGHT(ic),ic,FALSE);
1859 aopOp (IC_RESULT(ic),ic,TRUE);
1861 /* if I can do an decrement instead
1862 of subtract then GOOD for ME */
1863 if (genMinusDec (ic) == TRUE)
1866 size = getDataSize(IC_RESULT(ic));
1869 aopPut(AOP(IC_RESULT(ic)),aopGet(AOP(IC_RIGHT(ic)),offset),offset);
1871 emitcode("sub","%s,%s",aopGet(AOP(IC_RESULT(ic)),offset),
1872 aopGet(AOP(IC_LEFT(ic)),offset));
1874 emitcode("sbc","%s,%s",aopGet(AOP(IC_RESULT(ic)),offset),
1875 aopGet(AOP(IC_LEFT(ic)),offset));
1878 adjustArithmeticResult(ic);
1881 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1882 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1883 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1886 /*-----------------------------------------------------------------*/
1887 /* genMultOneByte : 8 bit multiplication & division */
1888 /*-----------------------------------------------------------------*/
1889 static void genMultOneByte (operand *left,
1893 link *opetype = operandType(result);
1898 /* (if two literals, the value is computed before) */
1899 /* if one literal, literal on the right */
1900 if (AOP_TYPE(left) == AOP_LIT){
1906 size = AOP_SIZE(result);
1908 if (SPEC_USIGN(opetype)) {
1909 emitcode("mul","%s,%s",
1910 aopGet(IC_LEFT(ic),0),
1911 aopGet(IC_RIGHT(ic),0));
1913 emitcode("muls","%s,%s",
1914 aopGet(IC_LEFT(ic),0),
1915 aopGet(IC_RIGHT(ic),0));
1917 aopPut(AOP(IC_RESULT(ic)),"r0",0);
1919 aopPut(AOP(IC_RESULT(ic)),"r1",1);
1922 if (SPEC_USIGN(opetype)) {
1924 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
1927 lbl = newiTempLabel(NULL);
1928 emitcode("ldi","r24,0");
1929 emitcode("brcc","L%05d",lbl->key);
1930 emitcode("ldi","r24,lo8(-1)");
1931 emitcode("","L%05d:",lbl->key);
1932 while (size--) aopPut(AOP(IC_RESULT(ic)),"r24",offset++);
1938 /*-----------------------------------------------------------------*/
1939 /* genMult - generates code for multiplication */
1940 /*-----------------------------------------------------------------*/
1941 static void genMult (iCode *ic)
1943 operand *left = IC_LEFT(ic);
1944 operand *right = IC_RIGHT(ic);
1945 operand *result= IC_RESULT(ic);
1947 /* assign the amsops */
1948 aopOp (left,ic,FALSE);
1949 aopOp (right,ic,FALSE);
1950 aopOp (result,ic,TRUE);
1952 /* if both are of size == 1 */
1953 if (AOP_SIZE(left) == 1 &&
1954 AOP_SIZE(right) == 1 ) {
1955 genMultOneByte(left,right,result);
1959 /* should have been converted to function call */
1963 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1964 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1965 freeAsmop(result,NULL,ic,TRUE);
1968 /*-----------------------------------------------------------------*/
1969 /* genDiv - generates code for division */
1970 /*-----------------------------------------------------------------*/
1971 static void genDiv (iCode *ic)
1973 /* should have been converted to function call */
1977 /*-----------------------------------------------------------------*/
1978 /* genMod - generates code for division */
1979 /*-----------------------------------------------------------------*/
1980 static void genMod (iCode *ic)
1982 /* should have been converted to function call */
1987 /*-----------------------------------------------------------------*/
1988 /* genCmpGt :- greater than comparison */
1989 /*-----------------------------------------------------------------*/
1990 static void genCmpGt (iCode *ic, iCode *ifx)
1992 operand *left, *right, *result;
1993 link *letype , *retype;
1994 int lsize,rsize,offset;
1999 right= IC_RIGHT(ic);
2000 result = IC_RESULT(ic);
2002 letype = getSpec(operandType(left));
2003 retype =getSpec(operandType(right));
2004 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2005 /* assign the amsops */
2006 aopOp (left,ic,FALSE);
2007 aopOp (right,ic,FALSE);
2009 lsize = AOP_SIZE(AOP(left));
2010 rsize = AOP_SIZE(AOP(right));
2011 /* ifx present then result used for jump only */
2014 if (AOP_TYPE(AOP(right)) == AOP_LIT) {
2015 emitcode("cpi","%s,lo8(%d+1)",aopGet(AOP(left),0),(int)
2016 floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit));
2018 } else if (AOP_TYPE(AOP(left)) == AOP_LIT) {
2023 aopOp (result,ic,TRUE);
2024 /* result used for computation */
2029 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2030 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2031 freeAsmop(result,NULL,ic,TRUE);
2034 /*-----------------------------------------------------------------*/
2035 /* genCmpLt - less than comparisons */
2036 /*-----------------------------------------------------------------*/
2037 static void genCmpLt (iCode *ic, iCode *ifx)
2039 operand *left, *right, *result;
2040 link *letype , *retype;
2044 right= IC_RIGHT(ic);
2045 result = IC_RESULT(ic);
2047 letype = getSpec(operandType(left));
2048 retype =getSpec(operandType(right));
2049 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2051 /* assign the amsops */
2052 aopOp (left,ic,FALSE);
2053 aopOp (right,ic,FALSE);
2054 aopOp (result,ic,TRUE);
2056 genCmp(left, right, result, ifx, sign);
2058 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2059 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2060 freeAsmop(result,NULL,ic,TRUE);
2063 /*-----------------------------------------------------------------*/
2064 /* gencjneshort - compare and jump if not equal */
2065 /*-----------------------------------------------------------------*/
2066 static void gencjneshort(operand *left, operand *right, symbol *lbl)
2068 int size = max(AOP_SIZE(left),AOP_SIZE(right));
2070 unsigned long lit = 0L;
2072 /* if the left side is a literal or
2073 if the right is in a pointer register and left
2075 if ((AOP_TYPE(left) == AOP_LIT) ||
2076 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
2081 if(AOP_TYPE(right) == AOP_LIT)
2082 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
2084 /* if the right side is a literal then anything goes */
2085 if (AOP_TYPE(right) == AOP_LIT &&
2086 AOP_TYPE(left) != AOP_DIR ) {
2088 emitcode("cjne","%s,%s,%05d$",
2089 aopGet(AOP(left),offset,FALSE,FALSE),
2090 aopGet(AOP(right),offset,FALSE,FALSE),
2096 /* if the right side is in a register or in direct space or
2097 if the left is a pointer register & right is not */
2098 else if (AOP_TYPE(right) == AOP_REG ||
2099 AOP_TYPE(right) == AOP_DIR ||
2100 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
2101 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
2103 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
2104 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
2105 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
2106 emitcode("jnz","%05d$",lbl->key+100);
2108 emitcode("cjne","a,%s,%05d$",
2109 aopGet(AOP(right),offset,FALSE,TRUE),
2114 /* right is a pointer reg need both a & b */
2116 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
2118 emitcode("mov","b,%s",l);
2119 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2120 emitcode("cjne","a,b,%05d$",lbl->key+100);
2126 /*-----------------------------------------------------------------*/
2127 /* gencjne - compare and jump if not equal */
2128 /*-----------------------------------------------------------------*/
2129 static void gencjne(operand *left, operand *right, symbol *lbl)
2131 symbol *tlbl = newiTempLabel(NULL);
2133 gencjneshort(left, right, lbl);
2135 emitcode("mov","a,%s",one);
2136 emitcode("sjmp","%05d$",tlbl->key+100);
2137 emitcode("","%05d$:",lbl->key+100);
2138 emitcode("clr","a");
2139 emitcode("","%05d$:",tlbl->key+100);
2142 /*-----------------------------------------------------------------*/
2143 /* genCmpEq - generates code for equal to */
2144 /*-----------------------------------------------------------------*/
2145 static void genCmpEq (iCode *ic, iCode *ifx)
2147 operand *left, *right, *result;
2149 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2150 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2151 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2153 /* if literal, literal on the right or
2154 if the right is in a pointer register and left
2156 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2157 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
2158 operand *t = IC_RIGHT(ic);
2159 IC_RIGHT(ic) = IC_LEFT(ic);
2163 if(ifx && !AOP_SIZE(result)){
2165 /* if they are both bit variables */
2166 if (AOP_TYPE(left) == AOP_CRY &&
2167 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2168 if(AOP_TYPE(right) == AOP_LIT){
2169 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2171 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2172 emitcode("cpl","c");
2173 } else if(lit == 1L) {
2174 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2176 emitcode("clr","c");
2178 /* AOP_TYPE(right) == AOP_CRY */
2180 symbol *lbl = newiTempLabel(NULL);
2181 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2182 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
2183 emitcode("cpl","c");
2184 emitcode("","%05d$:",(lbl->key+100));
2186 /* if true label then we jump if condition
2188 tlbl = newiTempLabel(NULL);
2189 if ( IC_TRUE(ifx) ) {
2190 emitcode("jnc","%05d$",tlbl->key+100);
2191 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
2193 emitcode("jc","%05d$",tlbl->key+100);
2194 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
2196 emitcode("","%05d$:",tlbl->key+100);
2198 tlbl = newiTempLabel(NULL);
2199 gencjneshort(left, right, tlbl);
2200 if ( IC_TRUE(ifx) ) {
2201 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
2202 emitcode("","%05d$:",tlbl->key+100);
2204 symbol *lbl = newiTempLabel(NULL);
2205 emitcode("sjmp","%05d$",lbl->key+100);
2206 emitcode("","%05d$:",tlbl->key+100);
2207 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
2208 emitcode("","%05d$:",lbl->key+100);
2211 /* mark the icode as generated */
2216 /* if they are both bit variables */
2217 if (AOP_TYPE(left) == AOP_CRY &&
2218 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2219 if(AOP_TYPE(right) == AOP_LIT){
2220 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2222 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2223 emitcode("cpl","c");
2224 } else if(lit == 1L) {
2225 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2227 emitcode("clr","c");
2229 /* AOP_TYPE(right) == AOP_CRY */
2231 symbol *lbl = newiTempLabel(NULL);
2232 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2233 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
2234 emitcode("cpl","c");
2235 emitcode("","%05d$:",(lbl->key+100));
2238 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
2243 genIfxJump (ifx,"c");
2246 /* if the result is used in an arithmetic operation
2247 then put the result in place */
2250 gencjne(left,right,newiTempLabel(NULL));
2251 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2252 aopPut(AOP(result),"a",0);
2256 genIfxJump (ifx,"a");
2259 /* if the result is used in an arithmetic operation
2260 then put the result in place */
2261 if (AOP_TYPE(result) != AOP_CRY)
2263 /* leave the result in acc */
2267 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2268 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2269 freeAsmop(result,NULL,ic,TRUE);
2272 /*-----------------------------------------------------------------*/
2273 /* ifxForOp - returns the icode containing the ifx for operand */
2274 /*-----------------------------------------------------------------*/
2275 static iCode *ifxForOp ( operand *op, iCode *ic )
2277 /* if true symbol then needs to be assigned */
2278 if (IS_TRUE_SYMOP(op))
2281 /* if this has register type condition and
2282 the next instruction is ifx with the same operand
2283 and live to of the operand is upto the ifx only then */
2285 ic->next->op == IFX &&
2286 IC_COND(ic->next)->key == op->key &&
2287 OP_SYMBOL(op)->liveTo <= ic->next->seq )
2292 /*-----------------------------------------------------------------*/
2293 /* genAndOp - for && operation */
2294 /*-----------------------------------------------------------------*/
2295 static void genAndOp (iCode *ic)
2297 operand *left,*right, *result;
2300 /* note here that && operations that are in an
2301 if statement are taken away by backPatchLabels
2302 only those used in arthmetic operations remain */
2303 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2304 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2305 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2307 /* if both are bit variables */
2308 if (AOP_TYPE(left) == AOP_CRY &&
2309 AOP_TYPE(right) == AOP_CRY ) {
2310 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2311 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
2314 tlbl = newiTempLabel(NULL);
2316 emitcode("jz","%05d$",tlbl->key+100);
2318 emitcode("","%05d$:",tlbl->key+100);
2322 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2323 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2324 freeAsmop(result,NULL,ic,TRUE);
2328 /*-----------------------------------------------------------------*/
2329 /* genOrOp - for || operation */
2330 /*-----------------------------------------------------------------*/
2331 static void genOrOp (iCode *ic)
2333 operand *left,*right, *result;
2336 /* note here that || operations that are in an
2337 if statement are taken away by backPatchLabels
2338 only those used in arthmetic operations remain */
2339 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2340 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2341 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2343 /* if both are bit variables */
2344 if (AOP_TYPE(left) == AOP_CRY &&
2345 AOP_TYPE(right) == AOP_CRY ) {
2346 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2347 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
2350 tlbl = newiTempLabel(NULL);
2352 emitcode("jnz","%05d$",tlbl->key+100);
2354 emitcode("","%05d$:",tlbl->key+100);
2358 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2359 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2360 freeAsmop(result,NULL,ic,TRUE);
2363 /*-----------------------------------------------------------------*/
2364 /* isLiteralBit - test if lit == 2^n */
2365 /*-----------------------------------------------------------------*/
2366 static int isLiteralBit(unsigned long lit)
2368 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
2369 0x100L,0x200L,0x400L,0x800L,
2370 0x1000L,0x2000L,0x4000L,0x8000L,
2371 0x10000L,0x20000L,0x40000L,0x80000L,
2372 0x100000L,0x200000L,0x400000L,0x800000L,
2373 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
2374 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
2377 for(idx = 0; idx < 32; idx++)
2383 /*-----------------------------------------------------------------*/
2384 /* continueIfTrue - */
2385 /*-----------------------------------------------------------------*/
2386 static void continueIfTrue (iCode *ic)
2389 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
2393 /*-----------------------------------------------------------------*/
2395 /*-----------------------------------------------------------------*/
2396 static void jumpIfTrue (iCode *ic)
2399 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
2403 /*-----------------------------------------------------------------*/
2404 /* jmpTrueOrFalse - */
2405 /*-----------------------------------------------------------------*/
2406 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
2408 // ugly but optimized by peephole
2410 symbol *nlbl = newiTempLabel(NULL);
2411 emitcode("sjmp","%05d$",nlbl->key+100);
2412 emitcode("","%05d$:",tlbl->key+100);
2413 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
2414 emitcode("","%05d$:",nlbl->key+100);
2417 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
2418 emitcode("","%05d$:",tlbl->key+100);
2423 /*-----------------------------------------------------------------*/
2424 /* genAnd - code for and */
2425 /*-----------------------------------------------------------------*/
2426 static void genAnd (iCode *ic, iCode *ifx)
2428 operand *left, *right, *result;
2430 unsigned long lit = 0L;
2434 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2435 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2436 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2439 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2441 AOP_TYPE(left), AOP_TYPE(right));
2442 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2444 AOP_SIZE(left), AOP_SIZE(right));
2447 /* if left is a literal & right is not then exchange them */
2448 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2449 AOP_NEEDSACC(left)) {
2450 operand *tmp = right ;
2455 /* if result = right then exchange them */
2456 if(sameRegs(AOP(result),AOP(right))){
2457 operand *tmp = right ;
2462 /* if right is bit then exchange them */
2463 if (AOP_TYPE(right) == AOP_CRY &&
2464 AOP_TYPE(left) != AOP_CRY){
2465 operand *tmp = right ;
2469 if(AOP_TYPE(right) == AOP_LIT)
2470 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2472 size = AOP_SIZE(result);
2475 // result = bit & yy;
2476 if (AOP_TYPE(left) == AOP_CRY){
2477 // c = bit & literal;
2478 if(AOP_TYPE(right) == AOP_LIT){
2480 if(size && sameRegs(AOP(result),AOP(left)))
2483 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2486 if(size && (AOP_TYPE(result) == AOP_CRY)){
2487 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
2490 if((AOP_TYPE(result) == AOP_CRY) && ifx){
2494 emitcode("clr","c");
2497 if (AOP_TYPE(right) == AOP_CRY){
2499 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
2500 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
2503 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
2505 emitcode("rrc","a");
2506 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
2514 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
2515 genIfxJump(ifx, "c");
2519 // if(val & 0xZZ) - size = 0, ifx != FALSE -
2520 // bit = val & 0xZZ - size = 1, ifx = FALSE -
2521 if((AOP_TYPE(right) == AOP_LIT) &&
2522 (AOP_TYPE(result) == AOP_CRY) &&
2523 (AOP_TYPE(left) != AOP_CRY)){
2524 int posbit = isLiteralBit(lit);
2528 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
2531 emitcode("mov","c,acc.%d",posbit&0x07);
2535 sprintf(buffer,"acc.%d",posbit&0x07);
2536 genIfxJump(ifx, buffer);
2541 symbol *tlbl = newiTempLabel(NULL);
2542 int sizel = AOP_SIZE(left);
2544 emitcode("setb","c");
2546 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
2547 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
2549 if((posbit = isLiteralBit(bytelit)) != 0)
2550 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
2552 if(bytelit != 0x0FFL)
2553 emitcode("anl","a,%s",
2554 aopGet(AOP(right),offset,FALSE,TRUE));
2555 emitcode("jnz","%05d$",tlbl->key+100);
2560 // bit = left & literal
2562 emitcode("clr","c");
2563 emitcode("","%05d$:",tlbl->key+100);
2565 // if(left & literal)
2568 jmpTrueOrFalse(ifx, tlbl);
2576 /* if left is same as result */
2577 if(sameRegs(AOP(result),AOP(left))){
2578 for(;size--; offset++) {
2579 if(AOP_TYPE(right) == AOP_LIT){
2580 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
2584 aopPut(AOP(result),zero,offset);
2586 if (IS_AOP_PREG(result)) {
2587 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2588 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
2589 aopPut(AOP(result),"a",offset);
2591 emitcode("anl","%s,%s",
2592 aopGet(AOP(left),offset,FALSE,TRUE),
2593 aopGet(AOP(right),offset,FALSE,FALSE));
2595 if (AOP_TYPE(left) == AOP_ACC)
2596 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
2598 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2599 if (IS_AOP_PREG(result)) {
2600 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
2601 aopPut(AOP(result),"a",offset);
2604 emitcode("anl","%s,a",
2605 aopGet(AOP(left),offset,FALSE,TRUE));
2610 // left & result in different registers
2611 if(AOP_TYPE(result) == AOP_CRY){
2613 // if(size), result in bit
2614 // if(!size && ifx), conditional oper: if(left & right)
2615 symbol *tlbl = newiTempLabel(NULL);
2616 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
2618 emitcode("setb","c");
2620 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2621 emitcode("anl","a,%s",
2622 aopGet(AOP(left),offset,FALSE,FALSE));
2623 emitcode("jnz","%05d$",tlbl->key+100);
2628 emitcode("","%05d$:",tlbl->key+100);
2631 jmpTrueOrFalse(ifx, tlbl);
2633 for(;(size--);offset++) {
2635 // result = left & right
2636 if(AOP_TYPE(right) == AOP_LIT){
2637 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
2639 aopGet(AOP(left),offset,FALSE,FALSE),
2642 } else if(bytelit == 0){
2643 aopPut(AOP(result),zero,offset);
2647 // faster than result <- left, anl result,right
2648 // and better if result is SFR
2649 if (AOP_TYPE(left) == AOP_ACC)
2650 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
2652 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2653 emitcode("anl","a,%s",
2654 aopGet(AOP(left),offset,FALSE,FALSE));
2656 aopPut(AOP(result),"a",offset);
2662 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2663 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2664 freeAsmop(result,NULL,ic,TRUE);
2667 /*-----------------------------------------------------------------*/
2668 /* genOr - code for or */
2669 /*-----------------------------------------------------------------*/
2670 static void genOr (iCode *ic, iCode *ifx)
2672 operand *left, *right, *result;
2674 unsigned long lit = 0L;
2676 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2677 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2678 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2681 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2683 AOP_TYPE(left), AOP_TYPE(right));
2684 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2686 AOP_SIZE(left), AOP_SIZE(right));
2689 /* if left is a literal & right is not then exchange them */
2690 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2691 AOP_NEEDSACC(left)) {
2692 operand *tmp = right ;
2697 /* if result = right then exchange them */
2698 if(sameRegs(AOP(result),AOP(right))){
2699 operand *tmp = right ;
2704 /* if right is bit then exchange them */
2705 if (AOP_TYPE(right) == AOP_CRY &&
2706 AOP_TYPE(left) != AOP_CRY){
2707 operand *tmp = right ;
2711 if(AOP_TYPE(right) == AOP_LIT)
2712 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2714 size = AOP_SIZE(result);
2718 if (AOP_TYPE(left) == AOP_CRY){
2719 if(AOP_TYPE(right) == AOP_LIT){
2720 // c = bit & literal;
2722 // lit != 0 => result = 1
2723 if(AOP_TYPE(result) == AOP_CRY){
2725 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
2727 continueIfTrue(ifx);
2730 emitcode("setb","c");
2732 // lit == 0 => result = left
2733 if(size && sameRegs(AOP(result),AOP(left)))
2735 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2738 if (AOP_TYPE(right) == AOP_CRY){
2740 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
2741 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
2745 symbol *tlbl = newiTempLabel(NULL);
2746 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
2747 emitcode("setb","c");
2748 emitcode("jb","%s,%05d$",
2749 AOP(left)->aopu.aop_dir,tlbl->key+100);
2751 emitcode("jnz","%05d$",tlbl->key+100);
2752 if((AOP_TYPE(result) == AOP_CRY) && ifx){
2753 jmpTrueOrFalse(ifx, tlbl);
2757 emitcode("","%05d$:",tlbl->key+100);
2766 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
2767 genIfxJump(ifx, "c");
2771 // if(val | 0xZZ) - size = 0, ifx != FALSE -
2772 // bit = val | 0xZZ - size = 1, ifx = FALSE -
2773 if((AOP_TYPE(right) == AOP_LIT) &&
2774 (AOP_TYPE(result) == AOP_CRY) &&
2775 (AOP_TYPE(left) != AOP_CRY)){
2779 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
2781 continueIfTrue(ifx);
2784 // lit = 0, result = boolean(left)
2786 emitcode("setb","c");
2789 symbol *tlbl = newiTempLabel(NULL);
2790 emitcode("jnz","%05d$",tlbl->key+100);
2792 emitcode("","%05d$:",tlbl->key+100);
2794 genIfxJump (ifx,"a");
2802 /* if left is same as result */
2803 if(sameRegs(AOP(result),AOP(left))){
2804 for(;size--; offset++) {
2805 if(AOP_TYPE(right) == AOP_LIT){
2806 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2809 if (IS_AOP_PREG(left)) {
2810 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2811 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
2812 aopPut(AOP(result),"a",offset);
2814 emitcode("orl","%s,%s",
2815 aopGet(AOP(left),offset,FALSE,TRUE),
2816 aopGet(AOP(right),offset,FALSE,FALSE));
2818 if (AOP_TYPE(left) == AOP_ACC)
2819 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
2821 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2822 if (IS_AOP_PREG(left)) {
2823 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
2824 aopPut(AOP(result),"a",offset);
2826 emitcode("orl","%s,a",
2827 aopGet(AOP(left),offset,FALSE,TRUE));
2832 // left & result in different registers
2833 if(AOP_TYPE(result) == AOP_CRY){
2835 // if(size), result in bit
2836 // if(!size && ifx), conditional oper: if(left | right)
2837 symbol *tlbl = newiTempLabel(NULL);
2838 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
2840 emitcode("setb","c");
2842 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2843 emitcode("orl","a,%s",
2844 aopGet(AOP(left),offset,FALSE,FALSE));
2845 emitcode("jnz","%05d$",tlbl->key+100);
2850 emitcode("","%05d$:",tlbl->key+100);
2853 jmpTrueOrFalse(ifx, tlbl);
2854 } else for(;(size--);offset++){
2856 // result = left & right
2857 if(AOP_TYPE(right) == AOP_LIT){
2858 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2860 aopGet(AOP(left),offset,FALSE,FALSE),
2865 // faster than result <- left, anl result,right
2866 // and better if result is SFR
2867 if (AOP_TYPE(left) == AOP_ACC)
2868 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
2870 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2871 emitcode("orl","a,%s",
2872 aopGet(AOP(left),offset,FALSE,FALSE));
2874 aopPut(AOP(result),"a",offset);
2879 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2880 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2881 freeAsmop(result,NULL,ic,TRUE);
2884 /*-----------------------------------------------------------------*/
2885 /* genXor - code for xclusive or */
2886 /*-----------------------------------------------------------------*/
2887 static void genXor (iCode *ic, iCode *ifx)
2889 operand *left, *right, *result;
2891 unsigned long lit = 0L;
2893 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2894 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2895 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2898 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2900 AOP_TYPE(left), AOP_TYPE(right));
2901 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2903 AOP_SIZE(left), AOP_SIZE(right));
2906 /* if left is a literal & right is not ||
2907 if left needs acc & right does not */
2908 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2909 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
2910 operand *tmp = right ;
2915 /* if result = right then exchange them */
2916 if(sameRegs(AOP(result),AOP(right))){
2917 operand *tmp = right ;
2922 /* if right is bit then exchange them */
2923 if (AOP_TYPE(right) == AOP_CRY &&
2924 AOP_TYPE(left) != AOP_CRY){
2925 operand *tmp = right ;
2929 if(AOP_TYPE(right) == AOP_LIT)
2930 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2932 size = AOP_SIZE(result);
2936 if (AOP_TYPE(left) == AOP_CRY){
2937 if(AOP_TYPE(right) == AOP_LIT){
2938 // c = bit & literal;
2940 // lit>>1 != 0 => result = 1
2941 if(AOP_TYPE(result) == AOP_CRY){
2943 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
2945 continueIfTrue(ifx);
2948 emitcode("setb","c");
2952 // lit == 0, result = left
2953 if(size && sameRegs(AOP(result),AOP(left)))
2955 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2957 // lit == 1, result = not(left)
2958 if(size && sameRegs(AOP(result),AOP(left))){
2959 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
2962 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2963 emitcode("cpl","c");
2970 symbol *tlbl = newiTempLabel(NULL);
2971 if (AOP_TYPE(right) == AOP_CRY){
2973 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
2976 int sizer = AOP_SIZE(right);
2978 // if val>>1 != 0, result = 1
2979 emitcode("setb","c");
2981 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
2983 // test the msb of the lsb
2984 emitcode("anl","a,#0xfe");
2985 emitcode("jnz","%05d$",tlbl->key+100);
2989 emitcode("rrc","a");
2991 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
2992 emitcode("cpl","c");
2993 emitcode("","%05d$:",(tlbl->key+100));
3000 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
3001 genIfxJump(ifx, "c");
3005 if(sameRegs(AOP(result),AOP(left))){
3006 /* if left is same as result */
3007 for(;size--; offset++) {
3008 if(AOP_TYPE(right) == AOP_LIT){
3009 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
3012 if (IS_AOP_PREG(left)) {
3013 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3014 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
3015 aopPut(AOP(result),"a",offset);
3017 emitcode("xrl","%s,%s",
3018 aopGet(AOP(left),offset,FALSE,TRUE),
3019 aopGet(AOP(right),offset,FALSE,FALSE));
3021 if (AOP_TYPE(left) == AOP_ACC)
3022 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
3024 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3025 if (IS_AOP_PREG(left)) {
3026 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
3027 aopPut(AOP(result),"a",offset);
3029 emitcode("xrl","%s,a",
3030 aopGet(AOP(left),offset,FALSE,TRUE));
3035 // left & result in different registers
3036 if(AOP_TYPE(result) == AOP_CRY){
3038 // if(size), result in bit
3039 // if(!size && ifx), conditional oper: if(left ^ right)
3040 symbol *tlbl = newiTempLabel(NULL);
3041 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
3043 emitcode("setb","c");
3045 if((AOP_TYPE(right) == AOP_LIT) &&
3046 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
3047 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3049 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3050 emitcode("xrl","a,%s",
3051 aopGet(AOP(left),offset,FALSE,FALSE));
3053 emitcode("jnz","%05d$",tlbl->key+100);
3058 emitcode("","%05d$:",tlbl->key+100);
3061 jmpTrueOrFalse(ifx, tlbl);
3062 } else for(;(size--);offset++){
3064 // result = left & right
3065 if(AOP_TYPE(right) == AOP_LIT){
3066 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
3068 aopGet(AOP(left),offset,FALSE,FALSE),
3073 // faster than result <- left, anl result,right
3074 // and better if result is SFR
3075 if (AOP_TYPE(left) == AOP_ACC)
3076 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
3078 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3079 emitcode("xrl","a,%s",
3080 aopGet(AOP(left),offset,FALSE,TRUE));
3082 aopPut(AOP(result),"a",offset);
3087 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3088 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3089 freeAsmop(result,NULL,ic,TRUE);
3092 /*-----------------------------------------------------------------*/
3093 /* genInline - write the inline code out */
3094 /*-----------------------------------------------------------------*/
3095 static void genInline (iCode *ic)
3097 char buffer[MAX_INLINEASM];
3101 _G.inLine += (!options.asmpeep);
3102 strcpy(buffer,IC_INLINE(ic));
3104 /* emit each line as a code */
3123 /* emitcode("",buffer); */
3124 _G.inLine -= (!options.asmpeep);
3127 /*-----------------------------------------------------------------*/
3128 /* genRRC - rotate right with carry */
3129 /*-----------------------------------------------------------------*/
3130 static void genRRC (iCode *ic)
3132 operand *left , *result ;
3133 int size, offset = 0;
3136 /* rotate right with carry */
3138 result=IC_RESULT(ic);
3139 aopOp (left,ic,FALSE);
3140 aopOp (result,ic,FALSE);
3142 /* move it to the result */
3143 size = AOP_SIZE(result);
3147 l = aopGet(AOP(left),offset,FALSE,FALSE);
3149 emitcode("rrc","a");
3150 if (AOP_SIZE(result) > 1)
3151 aopPut(AOP(result),"a",offset--);
3153 /* now we need to put the carry into the
3154 highest order byte of the result */
3155 if (AOP_SIZE(result) > 1) {
3156 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
3159 emitcode("mov","acc.7,c");
3160 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
3161 freeAsmop(left,NULL,ic,TRUE);
3162 freeAsmop(result,NULL,ic,TRUE);
3165 /*-----------------------------------------------------------------*/
3166 /* genRLC - generate code for rotate left with carry */
3167 /*-----------------------------------------------------------------*/
3168 static void genRLC (iCode *ic)
3170 operand *left , *result ;
3171 int size, offset = 0;
3174 /* rotate right with carry */
3176 result=IC_RESULT(ic);
3177 aopOp (left,ic,FALSE);
3178 aopOp (result,ic,FALSE);
3180 /* move it to the result */
3181 size = AOP_SIZE(result);
3184 l = aopGet(AOP(left),offset,FALSE,FALSE);
3186 emitcode("add","a,acc");
3187 if (AOP_SIZE(result) > 1)
3188 aopPut(AOP(result),"a",offset++);
3190 l = aopGet(AOP(left),offset,FALSE,FALSE);
3192 emitcode("rlc","a");
3193 if (AOP_SIZE(result) > 1)
3194 aopPut(AOP(result),"a",offset++);
3197 /* now we need to put the carry into the
3198 highest order byte of the result */
3199 if (AOP_SIZE(result) > 1) {
3200 l = aopGet(AOP(result),0,FALSE,FALSE);
3203 emitcode("mov","acc.0,c");
3204 aopPut(AOP(result),"a",0);
3205 freeAsmop(left,NULL,ic,TRUE);
3206 freeAsmop(result,NULL,ic,TRUE);
3209 /*-----------------------------------------------------------------*/
3210 /* genGetHbit - generates code get highest order bit */
3211 /*-----------------------------------------------------------------*/
3212 static void genGetHbit (iCode *ic)
3214 operand *left, *result;
3216 result=IC_RESULT(ic);
3217 aopOp (left,ic,FALSE);
3218 aopOp (result,ic,FALSE);
3220 /* get the highest order byte into a */
3221 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
3222 if(AOP_TYPE(result) == AOP_CRY){
3223 emitcode("rlc","a");
3228 emitcode("anl","a,#0x01");
3233 freeAsmop(left,NULL,ic,TRUE);
3234 freeAsmop(result,NULL,ic,TRUE);
3237 /*-----------------------------------------------------------------*/
3238 /* AccRol - rotate left accumulator by known count */
3239 /*-----------------------------------------------------------------*/
3240 static void AccRol (int shCount)
3242 shCount &= 0x0007; // shCount : 0..7
3254 emitcode("swap","a");
3258 emitcode("swap","a");
3261 emitcode("swap","a");
3274 /*-----------------------------------------------------------------*/
3275 /* AccLsh - left shift accumulator by known count */
3276 /*-----------------------------------------------------------------*/
3277 static void AccLsh (int shCount)
3281 emitcode("add","a,acc");
3284 emitcode("add","a,acc");
3285 emitcode("add","a,acc");
3287 /* rotate left accumulator */
3289 /* and kill the lower order bits */
3290 emitcode("anl","a,#0x%02x", SLMask[shCount]);
3295 /*-----------------------------------------------------------------*/
3296 /* AccRsh - right shift accumulator by known count */
3297 /*-----------------------------------------------------------------*/
3298 static void AccRsh (int shCount)
3303 emitcode("rrc","a");
3305 /* rotate right accumulator */
3306 AccRol(8 - shCount);
3307 /* and kill the higher order bits */
3308 emitcode("anl","a,#0x%02x", SRMask[shCount]);
3313 /*-----------------------------------------------------------------*/
3314 /* AccSRsh - signed right shift accumulator by known count */
3315 /*-----------------------------------------------------------------*/
3316 static void AccSRsh (int shCount)
3321 emitcode("mov","c,acc.7");
3322 emitcode("rrc","a");
3323 } else if(shCount == 2){
3324 emitcode("mov","c,acc.7");
3325 emitcode("rrc","a");
3326 emitcode("mov","c,acc.7");
3327 emitcode("rrc","a");
3329 tlbl = newiTempLabel(NULL);
3330 /* rotate right accumulator */
3331 AccRol(8 - shCount);
3332 /* and kill the higher order bits */
3333 emitcode("anl","a,#0x%02x", SRMask[shCount]);
3334 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
3335 emitcode("orl","a,#0x%02x",
3336 (unsigned char)~SRMask[shCount]);
3337 emitcode("","%05d$:",tlbl->key+100);
3342 /*-----------------------------------------------------------------*/
3343 /* shiftR1Left2Result - shift right one byte from left to result */
3344 /*-----------------------------------------------------------------*/
3345 static void shiftR1Left2Result (operand *left, int offl,
3346 operand *result, int offr,
3347 int shCount, int sign)
3349 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
3350 /* shift right accumulator */
3355 aopPut(AOP(result),"a",offr);
3358 /*-----------------------------------------------------------------*/
3359 /* shiftL1Left2Result - shift left one byte from left to result */
3360 /*-----------------------------------------------------------------*/
3361 static void shiftL1Left2Result (operand *left, int offl,
3362 operand *result, int offr, int shCount)
3365 l = aopGet(AOP(left),offl,FALSE,FALSE);
3367 /* shift left accumulator */
3369 aopPut(AOP(result),"a",offr);
3372 /*-----------------------------------------------------------------*/
3373 /* movLeft2Result - move byte from left to result */
3374 /*-----------------------------------------------------------------*/
3375 static void movLeft2Result (operand *left, int offl,
3376 operand *result, int offr, int sign)
3379 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
3380 l = aopGet(AOP(left),offl,FALSE,FALSE);
3382 if (*l == '@' && (IS_AOP_PREG(result))) {
3383 emitcode("mov","a,%s",l);
3384 aopPut(AOP(result),"a",offr);
3387 aopPut(AOP(result),l,offr);
3389 /* MSB sign in acc.7 ! */
3390 if(getDataSize(left) == offl+1){
3391 emitcode("mov","a,%s",l);
3392 aopPut(AOP(result),"a",offr);
3399 /*-----------------------------------------------------------------*/
3400 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
3401 /*-----------------------------------------------------------------*/
3402 static void AccAXRrl1 (char *x)
3404 emitcode("rrc","a");
3405 emitcode("xch","a,%s", x);
3406 emitcode("rrc","a");
3407 emitcode("xch","a,%s", x);
3410 /*-----------------------------------------------------------------*/
3411 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
3412 /*-----------------------------------------------------------------*/
3413 static void AccAXLrl1 (char *x)
3415 emitcode("xch","a,%s",x);
3416 emitcode("rlc","a");
3417 emitcode("xch","a,%s",x);
3418 emitcode("rlc","a");
3421 /*-----------------------------------------------------------------*/
3422 /* AccAXLsh1 - left shift a:x<-0 by 1 */
3423 /*-----------------------------------------------------------------*/
3424 static void AccAXLsh1 (char *x)
3426 emitcode("xch","a,%s",x);
3427 emitcode("add","a,acc");
3428 emitcode("xch","a,%s",x);
3429 emitcode("rlc","a");
3432 /*-----------------------------------------------------------------*/
3433 /* AccAXLsh - left shift a:x by known count (0..7) */
3434 /*-----------------------------------------------------------------*/
3435 static void AccAXLsh (char *x, int shCount)
3449 case 5 : // AAAAABBB:CCCCCDDD
3450 AccRol(shCount); // BBBAAAAA:CCCCCDDD
3451 emitcode("anl","a,#0x%02x",
3452 SLMask[shCount]); // BBB00000:CCCCCDDD
3453 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
3454 AccRol(shCount); // DDDCCCCC:BBB00000
3455 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
3456 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
3457 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
3458 emitcode("anl","a,#0x%02x",
3459 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
3460 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
3461 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
3463 case 6 : // AAAAAABB:CCCCCCDD
3464 emitcode("anl","a,#0x%02x",
3465 SRMask[shCount]); // 000000BB:CCCCCCDD
3466 emitcode("mov","c,acc.0"); // c = B
3467 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
3468 AccAXRrl1(x); // BCCCCCCD:D000000B
3469 AccAXRrl1(x); // BBCCCCCC:DD000000
3471 case 7 : // a:x <<= 7
3472 emitcode("anl","a,#0x%02x",
3473 SRMask[shCount]); // 0000000B:CCCCCCCD
3474 emitcode("mov","c,acc.0"); // c = B
3475 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
3476 AccAXRrl1(x); // BCCCCCCC:D0000000
3483 /*-----------------------------------------------------------------*/
3484 /* AccAXRsh - right shift a:x known count (0..7) */
3485 /*-----------------------------------------------------------------*/
3486 static void AccAXRsh (char *x, int shCount)
3493 AccAXRrl1(x); // 0->a:x
3497 AccAXRrl1(x); // 0->a:x
3499 AccAXRrl1(x); // 0->a:x
3503 case 5 : // AAAAABBB:CCCCCDDD = a:x
3504 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
3505 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
3506 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
3507 emitcode("anl","a,#0x%02x",
3508 SRMask[shCount]); // 000CCCCC:BBBAAAAA
3509 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
3510 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
3511 emitcode("anl","a,#0x%02x",
3512 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
3513 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
3514 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
3515 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
3517 case 6 : // AABBBBBB:CCDDDDDD
3518 emitcode("mov","c,acc.7");
3519 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
3520 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
3521 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
3522 emitcode("anl","a,#0x%02x",
3523 SRMask[shCount]); // 000000AA:BBBBBBCC
3525 case 7 : // ABBBBBBB:CDDDDDDD
3526 emitcode("mov","c,acc.7"); // c = A
3527 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
3528 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
3529 emitcode("anl","a,#0x%02x",
3530 SRMask[shCount]); // 0000000A:BBBBBBBC
3537 /*-----------------------------------------------------------------*/
3538 /* AccAXRshS - right shift signed a:x known count (0..7) */
3539 /*-----------------------------------------------------------------*/
3540 static void AccAXRshS (char *x, int shCount)
3547 emitcode("mov","c,acc.7");
3548 AccAXRrl1(x); // s->a:x
3551 emitcode("mov","c,acc.7");
3552 AccAXRrl1(x); // s->a:x
3553 emitcode("mov","c,acc.7");
3554 AccAXRrl1(x); // s->a:x
3558 case 5 : // AAAAABBB:CCCCCDDD = a:x
3559 tlbl = newiTempLabel(NULL);
3560 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
3561 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
3562 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
3563 emitcode("anl","a,#0x%02x",
3564 SRMask[shCount]); // 000CCCCC:BBBAAAAA
3565 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
3566 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
3567 emitcode("anl","a,#0x%02x",
3568 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
3569 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
3570 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
3571 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
3572 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
3573 emitcode("orl","a,#0x%02x",
3574 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
3575 emitcode("","%05d$:",tlbl->key+100);
3576 break; // SSSSAAAA:BBBCCCCC
3577 case 6 : // AABBBBBB:CCDDDDDD
3578 tlbl = newiTempLabel(NULL);
3579 emitcode("mov","c,acc.7");
3580 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
3581 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
3582 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
3583 emitcode("anl","a,#0x%02x",
3584 SRMask[shCount]); // 000000AA:BBBBBBCC
3585 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
3586 emitcode("orl","a,#0x%02x",
3587 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
3588 emitcode("","%05d$:",tlbl->key+100);
3590 case 7 : // ABBBBBBB:CDDDDDDD
3591 tlbl = newiTempLabel(NULL);
3592 emitcode("mov","c,acc.7"); // c = A
3593 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
3594 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
3595 emitcode("anl","a,#0x%02x",
3596 SRMask[shCount]); // 0000000A:BBBBBBBC
3597 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
3598 emitcode("orl","a,#0x%02x",
3599 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
3600 emitcode("","%05d$:",tlbl->key+100);
3607 /*-----------------------------------------------------------------*/
3608 /* shiftL2Left2Result - shift left two bytes from left to result */
3609 /*-----------------------------------------------------------------*/
3610 static void shiftL2Left2Result (operand *left, int offl,
3611 operand *result, int offr, int shCount)
3613 if(sameRegs(AOP(result), AOP(left)) &&
3614 ((offl + MSB16) == offr)){
3615 /* don't crash result[offr] */
3616 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
3617 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
3619 movLeft2Result(left,offl, result, offr, 0);
3620 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
3622 /* ax << shCount (x = lsb(result))*/
3623 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
3624 aopPut(AOP(result),"a",offr+MSB16);
3628 /*-----------------------------------------------------------------*/
3629 /* shiftR2Left2Result - shift right two bytes from left to result */
3630 /*-----------------------------------------------------------------*/
3631 static void shiftR2Left2Result (operand *left, int offl,
3632 operand *result, int offr,
3633 int shCount, int sign)
3635 if(sameRegs(AOP(result), AOP(left)) &&
3636 ((offl + MSB16) == offr)){
3637 /* don't crash result[offr] */
3638 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
3639 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
3641 movLeft2Result(left,offl, result, offr, 0);
3642 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
3644 /* a:x >> shCount (x = lsb(result))*/
3646 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
3648 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
3649 if(getDataSize(result) > 1)
3650 aopPut(AOP(result),"a",offr+MSB16);
3653 /*-----------------------------------------------------------------*/
3654 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
3655 /*-----------------------------------------------------------------*/
3656 static void shiftLLeftOrResult (operand *left, int offl,
3657 operand *result, int offr, int shCount)
3659 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
3660 /* shift left accumulator */
3662 /* or with result */
3663 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
3664 /* back to result */
3665 aopPut(AOP(result),"a",offr);
3668 /*-----------------------------------------------------------------*/
3669 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
3670 /*-----------------------------------------------------------------*/
3671 static void shiftRLeftOrResult (operand *left, int offl,
3672 operand *result, int offr, int shCount)
3674 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
3675 /* shift right accumulator */
3677 /* or with result */
3678 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
3679 /* back to result */
3680 aopPut(AOP(result),"a",offr);
3683 /*-----------------------------------------------------------------*/
3684 /* genlshOne - left shift a one byte quantity by known count */
3685 /*-----------------------------------------------------------------*/
3686 static void genlshOne (operand *result, operand *left, int shCount)
3688 shiftL1Left2Result(left, LSB, result, LSB, shCount);
3691 /*-----------------------------------------------------------------*/
3692 /* genlshTwo - left shift two bytes by known amount != 0 */
3693 /*-----------------------------------------------------------------*/
3694 static void genlshTwo (operand *result,operand *left, int shCount)
3698 size = getDataSize(result);
3700 /* if shCount >= 8 */
3706 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
3708 movLeft2Result(left, LSB, result, MSB16, 0);
3710 aopPut(AOP(result),zero,LSB);
3713 /* 1 <= shCount <= 7 */
3716 shiftL1Left2Result(left, LSB, result, LSB, shCount);
3718 shiftL2Left2Result(left, LSB, result, LSB, shCount);
3722 /*-----------------------------------------------------------------*/
3723 /* shiftLLong - shift left one long from left to result */
3724 /* offl = LSB or MSB16 */
3725 /*-----------------------------------------------------------------*/
3726 static void shiftLLong (operand *left, operand *result, int offr )
3729 int size = AOP_SIZE(result);
3731 if(size >= LSB+offr){
3732 l = aopGet(AOP(left),LSB,FALSE,FALSE);
3734 emitcode("add","a,acc");
3735 if (sameRegs(AOP(left),AOP(result)) &&
3736 size >= MSB16+offr && offr != LSB )
3737 emitcode("xch","a,%s",
3738 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
3740 aopPut(AOP(result),"a",LSB+offr);
3743 if(size >= MSB16+offr){
3744 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
3745 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
3748 emitcode("rlc","a");
3749 if (sameRegs(AOP(left),AOP(result)) &&
3750 size >= MSB24+offr && offr != LSB)
3751 emitcode("xch","a,%s",
3752 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
3754 aopPut(AOP(result),"a",MSB16+offr);
3757 if(size >= MSB24+offr){
3758 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
3759 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
3762 emitcode("rlc","a");
3763 if (sameRegs(AOP(left),AOP(result)) &&
3764 size >= MSB32+offr && offr != LSB )
3765 emitcode("xch","a,%s",
3766 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
3768 aopPut(AOP(result),"a",MSB24+offr);
3771 if(size > MSB32+offr){
3772 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
3773 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
3776 emitcode("rlc","a");
3777 aopPut(AOP(result),"a",MSB32+offr);
3780 aopPut(AOP(result),zero,LSB);
3783 /*-----------------------------------------------------------------*/
3784 /* genlshFour - shift four byte by a known amount != 0 */
3785 /*-----------------------------------------------------------------*/
3786 static void genlshFour (operand *result, operand *left, int shCount)
3790 size = AOP_SIZE(result);
3792 /* if shifting more that 3 bytes */
3793 if (shCount >= 24 ) {
3796 /* lowest order of left goes to the highest
3797 order of the destination */
3798 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
3800 movLeft2Result(left, LSB, result, MSB32, 0);
3801 aopPut(AOP(result),zero,LSB);
3802 aopPut(AOP(result),zero,MSB16);
3803 aopPut(AOP(result),zero,MSB32);
3807 /* more than two bytes */
3808 else if ( shCount >= 16 ) {
3809 /* lower order two bytes goes to higher order two bytes */
3811 /* if some more remaining */
3813 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
3815 movLeft2Result(left, MSB16, result, MSB32, 0);
3816 movLeft2Result(left, LSB, result, MSB24, 0);
3818 aopPut(AOP(result),zero,MSB16);
3819 aopPut(AOP(result),zero,LSB);
3823 /* if more than 1 byte */
3824 else if ( shCount >= 8 ) {
3825 /* lower order three bytes goes to higher order three bytes */
3829 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
3831 movLeft2Result(left, LSB, result, MSB16, 0);
3833 else{ /* size = 4 */
3835 movLeft2Result(left, MSB24, result, MSB32, 0);
3836 movLeft2Result(left, MSB16, result, MSB24, 0);
3837 movLeft2Result(left, LSB, result, MSB16, 0);
3838 aopPut(AOP(result),zero,LSB);
3840 else if(shCount == 1)
3841 shiftLLong(left, result, MSB16);
3843 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
3844 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
3845 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
3846 aopPut(AOP(result),zero,LSB);
3851 /* 1 <= shCount <= 7 */
3852 else if(shCount <= 2){
3853 shiftLLong(left, result, LSB);
3855 shiftLLong(result, result, LSB);
3857 /* 3 <= shCount <= 7, optimize */
3859 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
3860 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
3861 shiftL2Left2Result(left, LSB, result, LSB, shCount);
3865 /*-----------------------------------------------------------------*/
3866 /* genLeftShiftLiteral - left shifting by known count */
3867 /*-----------------------------------------------------------------*/
3868 static void genLeftShiftLiteral (operand *left,
3873 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3876 freeAsmop(right,NULL,ic,TRUE);
3878 aopOp(left,ic,FALSE);
3879 aopOp(result,ic,FALSE);
3881 size = getSize(operandType(result));
3884 emitcode("; shift left ","result %d, left %d",size,
3888 /* I suppose that the left size >= result size */
3891 movLeft2Result(left, size, result, size, 0);
3895 else if(shCount >= (size * 8))
3897 aopPut(AOP(result),zero,size);
3901 genlshOne (result,left,shCount);
3906 genlshTwo (result,left,shCount);
3910 genlshFour (result,left,shCount);
3914 freeAsmop(left,NULL,ic,TRUE);
3915 freeAsmop(result,NULL,ic,TRUE);
3918 /*-----------------------------------------------------------------*/
3919 /* genLeftShift - generates code for left shifting */
3920 /*-----------------------------------------------------------------*/
3921 static void genLeftShift (iCode *ic)
3923 operand *left,*right, *result;
3926 symbol *tlbl , *tlbl1;
3928 right = IC_RIGHT(ic);
3930 result = IC_RESULT(ic);
3932 aopOp(right,ic,FALSE);
3934 /* if the shift count is known then do it
3935 as efficiently as possible */
3936 if (AOP_TYPE(right) == AOP_LIT) {
3937 genLeftShiftLiteral (left,right,result,ic);
3941 /* shift count is unknown then we have to form
3942 a loop get the loop count in B : Note: we take
3943 only the lower order byte since shifting
3944 more that 32 bits make no sense anyway, ( the
3945 largest size of an object can be only 32 bits ) */
3947 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3948 emitcode("inc","b");
3949 freeAsmop (right,NULL,ic,TRUE);
3950 aopOp(left,ic,FALSE);
3951 aopOp(result,ic,FALSE);
3953 /* now move the left to the result if they are not the
3955 if (!sameRegs(AOP(left),AOP(result)) &&
3956 AOP_SIZE(result) > 1) {
3958 size = AOP_SIZE(result);
3961 l = aopGet(AOP(left),offset,FALSE,TRUE);
3962 if (*l == '@' && (IS_AOP_PREG(result))) {
3964 emitcode("mov","a,%s",l);
3965 aopPut(AOP(result),"a",offset);
3967 aopPut(AOP(result),l,offset);
3972 tlbl = newiTempLabel(NULL);
3973 size = AOP_SIZE(result);
3975 tlbl1 = newiTempLabel(NULL);
3977 /* if it is only one byte then */
3979 symbol *tlbl1 = newiTempLabel(NULL);
3981 l = aopGet(AOP(left),0,FALSE,FALSE);
3983 emitcode("sjmp","%05d$",tlbl1->key+100);
3984 emitcode("","%05d$:",tlbl->key+100);
3985 emitcode("add","a,acc");
3986 emitcode("","%05d$:",tlbl1->key+100);
3987 emitcode("djnz","b,%05d$",tlbl->key+100);
3988 aopPut(AOP(result),"a",0);
3992 reAdjustPreg(AOP(result));
3994 emitcode("sjmp","%05d$",tlbl1->key+100);
3995 emitcode("","%05d$:",tlbl->key+100);
3996 l = aopGet(AOP(result),offset,FALSE,FALSE);
3998 emitcode("add","a,acc");
3999 aopPut(AOP(result),"a",offset++);
4001 l = aopGet(AOP(result),offset,FALSE,FALSE);
4003 emitcode("rlc","a");
4004 aopPut(AOP(result),"a",offset++);
4006 reAdjustPreg(AOP(result));
4008 emitcode("","%05d$:",tlbl1->key+100);
4009 emitcode("djnz","b,%05d$",tlbl->key+100);
4011 freeAsmop(left,NULL,ic,TRUE);
4012 freeAsmop(result,NULL,ic,TRUE);
4015 /*-----------------------------------------------------------------*/
4016 /* genrshOne - right shift a one byte quantity by known count */
4017 /*-----------------------------------------------------------------*/
4018 static void genrshOne (operand *result, operand *left,
4019 int shCount, int sign)
4021 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
4024 /*-----------------------------------------------------------------*/
4025 /* genrshTwo - right shift two bytes by known amount != 0 */
4026 /*-----------------------------------------------------------------*/
4027 static void genrshTwo (operand *result,operand *left,
4028 int shCount, int sign)
4030 /* if shCount >= 8 */
4034 shiftR1Left2Result(left, MSB16, result, LSB,
4037 movLeft2Result(left, MSB16, result, LSB, sign);
4038 addSign(result, MSB16, sign);
4041 /* 1 <= shCount <= 7 */
4043 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
4046 /*-----------------------------------------------------------------*/
4047 /* shiftRLong - shift right one long from left to result */
4048 /* offl = LSB or MSB16 */
4049 /*-----------------------------------------------------------------*/
4050 static void shiftRLong (operand *left, int offl,
4051 operand *result, int sign)
4054 emitcode("clr","c");
4055 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
4057 emitcode("mov","c,acc.7");
4058 emitcode("rrc","a");
4059 aopPut(AOP(result),"a",MSB32-offl);
4061 /* add sign of "a" */
4062 addSign(result, MSB32, sign);
4064 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
4065 emitcode("rrc","a");
4066 aopPut(AOP(result),"a",MSB24-offl);
4068 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
4069 emitcode("rrc","a");
4070 aopPut(AOP(result),"a",MSB16-offl);
4073 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
4074 emitcode("rrc","a");
4075 aopPut(AOP(result),"a",LSB);
4079 /*-----------------------------------------------------------------*/
4080 /* genrshFour - shift four byte by a known amount != 0 */
4081 /*-----------------------------------------------------------------*/
4082 static void genrshFour (operand *result, operand *left,
4083 int shCount, int sign)
4085 /* if shifting more that 3 bytes */
4086 if(shCount >= 24 ) {
4089 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
4091 movLeft2Result(left, MSB32, result, LSB, sign);
4092 addSign(result, MSB16, sign);
4094 else if(shCount >= 16){
4097 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
4099 movLeft2Result(left, MSB24, result, LSB, 0);
4100 movLeft2Result(left, MSB32, result, MSB16, sign);
4102 addSign(result, MSB24, sign);
4104 else if(shCount >= 8){
4107 shiftRLong(left, MSB16, result, sign);
4108 else if(shCount == 0){
4109 movLeft2Result(left, MSB16, result, LSB, 0);
4110 movLeft2Result(left, MSB24, result, MSB16, 0);
4111 movLeft2Result(left, MSB32, result, MSB24, sign);
4112 addSign(result, MSB32, sign);
4115 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
4116 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
4117 /* the last shift is signed */
4118 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
4119 addSign(result, MSB32, sign);
4122 else{ /* 1 <= shCount <= 7 */
4124 shiftRLong(left, LSB, result, sign);
4126 shiftRLong(result, LSB, result, sign);
4129 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
4130 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
4131 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
4136 /*-----------------------------------------------------------------*/
4137 /* genRightShiftLiteral - right shifting by known count */
4138 /*-----------------------------------------------------------------*/
4139 static void genRightShiftLiteral (operand *left,
4145 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
4148 freeAsmop(right,NULL,ic,TRUE);
4150 aopOp(left,ic,FALSE);
4151 aopOp(result,ic,FALSE);
4154 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
4158 size = getDataSize(left);
4159 /* test the LEFT size !!! */
4161 /* I suppose that the left size >= result size */
4163 size = getDataSize(result);
4165 movLeft2Result(left, size, result, size, 0);
4168 else if(shCount >= (size * 8)){
4170 /* get sign in acc.7 */
4171 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
4172 addSign(result, LSB, sign);
4176 genrshOne (result,left,shCount,sign);
4180 genrshTwo (result,left,shCount,sign);
4184 genrshFour (result,left,shCount,sign);
4190 freeAsmop(left,NULL,ic,TRUE);
4191 freeAsmop(result,NULL,ic,TRUE);
4195 /*-----------------------------------------------------------------*/
4196 /* genSignedRightShift - right shift of signed number */
4197 /*-----------------------------------------------------------------*/
4198 static void genSignedRightShift (iCode *ic)
4200 operand *right, *left, *result;
4203 symbol *tlbl, *tlbl1 ;
4205 /* we do it the hard way put the shift count in b
4206 and loop thru preserving the sign */
4208 right = IC_RIGHT(ic);
4210 result = IC_RESULT(ic);
4212 aopOp(right,ic,FALSE);
4215 if ( AOP_TYPE(right) == AOP_LIT) {
4216 genRightShiftLiteral (left,right,result,ic,1);
4219 /* shift count is unknown then we have to form
4220 a loop get the loop count in B : Note: we take
4221 only the lower order byte since shifting
4222 more that 32 bits make no sense anyway, ( the
4223 largest size of an object can be only 32 bits ) */
4225 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
4226 emitcode("inc","b");
4227 freeAsmop (right,NULL,ic,TRUE);
4228 aopOp(left,ic,FALSE);
4229 aopOp(result,ic,FALSE);
4231 /* now move the left to the result if they are not the
4233 if (!sameRegs(AOP(left),AOP(result)) &&
4234 AOP_SIZE(result) > 1) {
4236 size = AOP_SIZE(result);
4239 l = aopGet(AOP(left),offset,FALSE,TRUE);
4240 if (*l == '@' && IS_AOP_PREG(result)) {
4242 emitcode("mov","a,%s",l);
4243 aopPut(AOP(result),"a",offset);
4245 aopPut(AOP(result),l,offset);
4250 /* mov the highest order bit to OVR */
4251 tlbl = newiTempLabel(NULL);
4252 tlbl1= newiTempLabel(NULL);
4254 size = AOP_SIZE(result);
4256 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
4257 emitcode("rlc","a");
4258 emitcode("mov","ov,c");
4259 /* if it is only one byte then */
4261 l = aopGet(AOP(left),0,FALSE,FALSE);
4263 emitcode("sjmp","%05d$",tlbl1->key+100);
4264 emitcode("","%05d$:",tlbl->key+100);
4265 emitcode("mov","c,ov");
4266 emitcode("rrc","a");
4267 emitcode("","%05d$:",tlbl1->key+100);
4268 emitcode("djnz","b,%05d$",tlbl->key+100);
4269 aopPut(AOP(result),"a",0);
4273 reAdjustPreg(AOP(result));
4274 emitcode("sjmp","%05d$",tlbl1->key+100);
4275 emitcode("","%05d$:",tlbl->key+100);
4276 emitcode("mov","c,ov");
4278 l = aopGet(AOP(result),offset,FALSE,FALSE);
4280 emitcode("rrc","a");
4281 aopPut(AOP(result),"a",offset--);
4283 reAdjustPreg(AOP(result));
4284 emitcode("","%05d$:",tlbl1->key+100);
4285 emitcode("djnz","b,%05d$",tlbl->key+100);
4288 freeAsmop(left,NULL,ic,TRUE);
4289 freeAsmop(result,NULL,ic,TRUE);
4292 /*-----------------------------------------------------------------*/
4293 /* genRightShift - generate code for right shifting */
4294 /*-----------------------------------------------------------------*/
4295 static void genRightShift (iCode *ic)
4297 operand *right, *left, *result;
4301 symbol *tlbl, *tlbl1 ;
4303 /* if signed then we do it the hard way preserve the
4304 sign bit moving it inwards */
4305 retype = getSpec(operandType(IC_RESULT(ic)));
4307 if (!SPEC_USIGN(retype)) {
4308 genSignedRightShift (ic);
4312 /* signed & unsigned types are treated the same : i.e. the
4313 signed is NOT propagated inwards : quoting from the
4314 ANSI - standard : "for E1 >> E2, is equivalent to division
4315 by 2**E2 if unsigned or if it has a non-negative value,
4316 otherwise the result is implementation defined ", MY definition
4317 is that the sign does not get propagated */
4319 right = IC_RIGHT(ic);
4321 result = IC_RESULT(ic);
4323 aopOp(right,ic,FALSE);
4325 /* if the shift count is known then do it
4326 as efficiently as possible */
4327 if (AOP_TYPE(right) == AOP_LIT) {
4328 genRightShiftLiteral (left,right,result,ic, 0);
4332 /* shift count is unknown then we have to form
4333 a loop get the loop count in B : Note: we take
4334 only the lower order byte since shifting
4335 more that 32 bits make no sense anyway, ( the
4336 largest size of an object can be only 32 bits ) */
4338 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
4339 emitcode("inc","b");
4340 freeAsmop (right,NULL,ic,TRUE);
4341 aopOp(left,ic,FALSE);
4342 aopOp(result,ic,FALSE);
4344 /* now move the left to the result if they are not the
4346 if (!sameRegs(AOP(left),AOP(result)) &&
4347 AOP_SIZE(result) > 1) {
4349 size = AOP_SIZE(result);
4352 l = aopGet(AOP(left),offset,FALSE,TRUE);
4353 if (*l == '@' && IS_AOP_PREG(result)) {
4355 emitcode("mov","a,%s",l);
4356 aopPut(AOP(result),"a",offset);
4358 aopPut(AOP(result),l,offset);
4363 tlbl = newiTempLabel(NULL);
4364 tlbl1= newiTempLabel(NULL);
4365 size = AOP_SIZE(result);
4368 /* if it is only one byte then */
4370 l = aopGet(AOP(left),0,FALSE,FALSE);
4372 emitcode("sjmp","%05d$",tlbl1->key+100);
4373 emitcode("","%05d$:",tlbl->key+100);
4375 emitcode("rrc","a");
4376 emitcode("","%05d$:",tlbl1->key+100);
4377 emitcode("djnz","b,%05d$",tlbl->key+100);
4378 aopPut(AOP(result),"a",0);
4382 reAdjustPreg(AOP(result));
4383 emitcode("sjmp","%05d$",tlbl1->key+100);
4384 emitcode("","%05d$:",tlbl->key+100);
4387 l = aopGet(AOP(result),offset,FALSE,FALSE);
4389 emitcode("rrc","a");
4390 aopPut(AOP(result),"a",offset--);
4392 reAdjustPreg(AOP(result));
4394 emitcode("","%05d$:",tlbl1->key+100);
4395 emitcode("djnz","b,%05d$",tlbl->key+100);
4398 freeAsmop(left,NULL,ic,TRUE);
4399 freeAsmop(result,NULL,ic,TRUE);
4402 /*-----------------------------------------------------------------*/
4403 /* genUnpackBits - generates code for unpacking bits */
4404 /*-----------------------------------------------------------------*/
4405 static void genUnpackBits (operand *result, char *rname, int ptype)
4412 etype = getSpec(operandType(result));
4414 /* read the first byte */
4419 emitcode("mov","a,@%s",rname);
4423 emitcode("movx","a,@%s",rname);
4427 emitcode("movx","a,@dptr");
4431 emitcode("clr","a");
4432 emitcode("movc","a","@a+dptr");
4436 emitcode("lcall","__gptrget");
4440 /* if we have bitdisplacement then it fits */
4441 /* into this byte completely or if length is */
4442 /* less than a byte */
4443 if ((shCnt = SPEC_BSTR(etype)) ||
4444 (SPEC_BLEN(etype) <= 8)) {
4446 /* shift right acc */
4449 emitcode("anl","a,#0x%02x",
4450 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
4451 aopPut(AOP(result),"a",offset);
4455 /* bit field did not fit in a byte */
4456 rlen = SPEC_BLEN(etype) - 8;
4457 aopPut(AOP(result),"a",offset++);
4464 emitcode("inc","%s",rname);
4465 emitcode("mov","a,@%s",rname);
4469 emitcode("inc","%s",rname);
4470 emitcode("movx","a,@%s",rname);
4474 emitcode("inc","dptr");
4475 emitcode("movx","a,@dptr");
4479 emitcode("clr","a");
4480 emitcode("inc","dptr");
4481 emitcode("movc","a","@a+dptr");
4485 emitcode("inc","dptr");
4486 emitcode("lcall","__gptrget");
4491 /* if we are done */
4495 aopPut(AOP(result),"a",offset++);
4500 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
4501 aopPut(AOP(result),"a",offset);
4508 /*-----------------------------------------------------------------*/
4509 /* genDataPointerGet - generates code when ptr offset is known */
4510 /*-----------------------------------------------------------------*/
4511 static void genDataPointerGet (operand *left,
4517 int size , offset = 0;
4518 aopOp(result,ic,TRUE);
4520 /* get the string representation of the name */
4521 l = aopGet(AOP(left),0,FALSE,TRUE);
4522 size = AOP_SIZE(result);
4525 sprintf(buffer,"(%s + %d)",l+1,offset);
4527 sprintf(buffer,"%s",l+1);
4528 aopPut(AOP(result),buffer,offset++);
4531 freeAsmop(left,NULL,ic,TRUE);
4532 freeAsmop(result,NULL,ic,TRUE);
4535 /*-----------------------------------------------------------------*/
4536 /* genNearPointerGet - emitcode for near pointer fetch */
4537 /*-----------------------------------------------------------------*/
4538 static void genNearPointerGet (operand *left,
4545 link *rtype, *retype;
4546 link *ltype = operandType(left);
4549 rtype = operandType(result);
4550 retype= getSpec(rtype);
4552 aopOp(left,ic,FALSE);
4554 /* if left is rematerialisable and
4555 result is not bit variable type and
4556 the left is pointer to data space i.e
4557 lower 128 bytes of space */
4558 if (AOP_TYPE(left) == AOP_IMMD &&
4559 !IS_BITVAR(retype) &&
4560 DCL_TYPE(ltype) == POINTER) {
4561 genDataPointerGet (left,result,ic);
4565 /* if the value is already in a pointer register
4566 then don't need anything more */
4567 if (!AOP_INPREG(AOP(left))) {
4568 /* otherwise get a free pointer register */
4570 preg = getFreePtr(ic,&aop,FALSE);
4571 emitcode("mov","%s,%s",
4573 aopGet(AOP(left),0,FALSE,TRUE));
4574 rname = preg->name ;
4576 rname = aopGet(AOP(left),0,FALSE,FALSE);
4578 freeAsmop(left,NULL,ic,TRUE);
4579 aopOp (result,ic,FALSE);
4581 /* if bitfield then unpack the bits */
4582 if (IS_BITVAR(retype))
4583 genUnpackBits (result,rname,POINTER);
4585 /* we have can just get the values */
4586 int size = AOP_SIZE(result);
4590 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
4592 emitcode("mov","a,@%s",rname);
4593 aopPut(AOP(result),"a",offset);
4595 sprintf(buffer,"@%s",rname);
4596 aopPut(AOP(result),buffer,offset);
4600 emitcode("inc","%s",rname);
4604 /* now some housekeeping stuff */
4606 /* we had to allocate for this iCode */
4607 freeAsmop(NULL,aop,ic,TRUE);
4609 /* we did not allocate which means left
4610 already in a pointer register, then
4611 if size > 0 && this could be used again
4612 we have to point it back to where it
4614 if (AOP_SIZE(result) > 1 &&
4615 !OP_SYMBOL(left)->remat &&
4616 ( OP_SYMBOL(left)->liveTo > ic->seq ||
4618 int size = AOP_SIZE(result) - 1;
4620 emitcode("dec","%s",rname);
4625 freeAsmop(result,NULL,ic,TRUE);
4629 /*-----------------------------------------------------------------*/
4630 /* genPagedPointerGet - emitcode for paged pointer fetch */
4631 /*-----------------------------------------------------------------*/
4632 static void genPagedPointerGet (operand *left,
4639 link *rtype, *retype;
4641 rtype = operandType(result);
4642 retype= getSpec(rtype);
4644 aopOp(left,ic,FALSE);
4646 /* if the value is already in a pointer register
4647 then don't need anything more */
4648 if (!AOP_INPREG(AOP(left))) {
4649 /* otherwise get a free pointer register */
4651 preg = getFreePtr(ic,&aop,FALSE);
4652 emitcode("mov","%s,%s",
4654 aopGet(AOP(left),0,FALSE,TRUE));
4655 rname = preg->name ;
4657 rname = aopGet(AOP(left),0,FALSE,FALSE);
4659 freeAsmop(left,NULL,ic,TRUE);
4660 aopOp (result,ic,FALSE);
4662 /* if bitfield then unpack the bits */
4663 if (IS_BITVAR(retype))
4664 genUnpackBits (result,rname,PPOINTER);
4666 /* we have can just get the values */
4667 int size = AOP_SIZE(result);
4672 emitcode("movx","a,@%s",rname);
4673 aopPut(AOP(result),"a",offset);
4678 emitcode("inc","%s",rname);
4682 /* now some housekeeping stuff */
4684 /* we had to allocate for this iCode */
4685 freeAsmop(NULL,aop,ic,TRUE);
4687 /* we did not allocate which means left
4688 already in a pointer register, then
4689 if size > 0 && this could be used again
4690 we have to point it back to where it
4692 if (AOP_SIZE(result) > 1 &&
4693 !OP_SYMBOL(left)->remat &&
4694 ( OP_SYMBOL(left)->liveTo > ic->seq ||
4696 int size = AOP_SIZE(result) - 1;
4698 emitcode("dec","%s",rname);
4703 freeAsmop(result,NULL,ic,TRUE);
4708 /*-----------------------------------------------------------------*/
4709 /* genFarPointerGet - gget value from far space */
4710 /*-----------------------------------------------------------------*/
4711 static void genFarPointerGet (operand *left,
4712 operand *result, iCode *ic)
4715 link *retype = getSpec(operandType(result));
4717 aopOp(left,ic,FALSE);
4719 /* if the operand is already in dptr
4720 then we do nothing else we move the value to dptr */
4721 if (AOP_TYPE(left) != AOP_STR) {
4722 /* if this is remateriazable */
4723 if (AOP_TYPE(left) == AOP_IMMD)
4724 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
4725 else { /* we need to get it byte by byte */
4726 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
4727 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
4728 if (options.model == MODEL_FLAT24)
4730 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
4734 /* so dptr know contains the address */
4735 freeAsmop(left,NULL,ic,TRUE);
4736 aopOp(result,ic,FALSE);
4738 /* if bit then unpack */
4739 if (IS_BITVAR(retype))
4740 genUnpackBits(result,"dptr",FPOINTER);
4742 size = AOP_SIZE(result);
4746 emitcode("movx","a,@dptr");
4747 aopPut(AOP(result),"a",offset++);
4749 emitcode("inc","dptr");
4753 freeAsmop(result,NULL,ic,TRUE);
4756 /*-----------------------------------------------------------------*/
4757 /* emitcodePointerGet - gget value from code space */
4758 /*-----------------------------------------------------------------*/
4759 static void emitcodePointerGet (operand *left,
4760 operand *result, iCode *ic)
4763 link *retype = getSpec(operandType(result));
4765 aopOp(left,ic,FALSE);
4767 /* if the operand is already in dptr
4768 then we do nothing else we move the value to dptr */
4769 if (AOP_TYPE(left) != AOP_STR) {
4770 /* if this is remateriazable */
4771 if (AOP_TYPE(left) == AOP_IMMD)
4772 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
4773 else { /* we need to get it byte by byte */
4774 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
4775 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
4776 if (options.model == MODEL_FLAT24)
4778 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
4782 /* so dptr know contains the address */
4783 freeAsmop(left,NULL,ic,TRUE);
4784 aopOp(result,ic,FALSE);
4786 /* if bit then unpack */
4787 if (IS_BITVAR(retype))
4788 genUnpackBits(result,"dptr",CPOINTER);
4790 size = AOP_SIZE(result);
4794 emitcode("clr","a");
4795 emitcode("movc","a,@a+dptr");
4796 aopPut(AOP(result),"a",offset++);
4798 emitcode("inc","dptr");
4802 freeAsmop(result,NULL,ic,TRUE);
4805 /*-----------------------------------------------------------------*/
4806 /* genGenPointerGet - gget value from generic pointer space */
4807 /*-----------------------------------------------------------------*/
4808 static void genGenPointerGet (operand *left,
4809 operand *result, iCode *ic)
4812 link *retype = getSpec(operandType(result));
4814 aopOp(left,ic,FALSE);
4816 /* if the operand is already in dptr
4817 then we do nothing else we move the value to dptr */
4818 if (AOP_TYPE(left) != AOP_STR) {
4819 /* if this is remateriazable */
4820 if (AOP_TYPE(left) == AOP_IMMD) {
4821 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
4822 emitcode("mov","b,#%d",pointerCode(retype));
4824 else { /* we need to get it byte by byte */
4825 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
4826 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
4827 if (options.model == MODEL_FLAT24)
4829 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
4830 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
4834 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
4838 /* so dptr know contains the address */
4839 freeAsmop(left,NULL,ic,TRUE);
4840 aopOp(result,ic,FALSE);
4842 /* if bit then unpack */
4843 if (IS_BITVAR(retype))
4844 genUnpackBits(result,"dptr",GPOINTER);
4846 size = AOP_SIZE(result);
4850 emitcode("lcall","__gptrget");
4851 aopPut(AOP(result),"a",offset++);
4853 emitcode("inc","dptr");
4857 freeAsmop(result,NULL,ic,TRUE);
4860 /*-----------------------------------------------------------------*/
4861 /* genPointerGet - generate code for pointer get */
4862 /*-----------------------------------------------------------------*/
4863 static void genPointerGet (iCode *ic)
4865 operand *left, *result ;
4870 result = IC_RESULT(ic) ;
4872 /* depending on the type of pointer we need to
4873 move it to the correct pointer register */
4874 type = operandType(left);
4875 etype = getSpec(type);
4876 /* if left is of type of pointer then it is simple */
4877 if (IS_PTR(type) && !IS_FUNC(type->next))
4878 p_type = DCL_TYPE(type);
4880 /* we have to go by the storage class */
4881 p_type = PTR_TYPE(SPEC_OCLS(etype));
4883 /* if (SPEC_OCLS(etype)->codesp ) { */
4884 /* p_type = CPOINTER ; */
4887 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
4888 /* p_type = FPOINTER ; */
4890 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
4891 /* p_type = PPOINTER; */
4893 /* if (SPEC_OCLS(etype) == idata ) */
4894 /* p_type = IPOINTER; */
4896 /* p_type = POINTER ; */
4899 /* now that we have the pointer type we assign
4900 the pointer values */
4905 genNearPointerGet (left,result,ic);
4909 genPagedPointerGet(left,result,ic);
4913 genFarPointerGet (left,result,ic);
4917 emitcodePointerGet (left,result,ic);
4921 genGenPointerGet (left,result,ic);
4927 /*-----------------------------------------------------------------*/
4928 /* genPackBits - generates code for packed bit storage */
4929 /*-----------------------------------------------------------------*/
4930 static void genPackBits (link *etype ,
4932 char *rname, int p_type)
4940 blen = SPEC_BLEN(etype);
4941 bstr = SPEC_BSTR(etype);
4943 l = aopGet(AOP(right),offset++,FALSE,FALSE);
4946 /* if the bit lenth is less than or */
4947 /* it exactly fits a byte then */
4948 if (SPEC_BLEN(etype) <= 8 ) {
4949 shCount = SPEC_BSTR(etype) ;
4951 /* shift left acc */
4954 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
4959 emitcode ("mov","b,a");
4960 emitcode("mov","a,@%s",rname);
4964 emitcode ("mov","b,a");
4965 emitcode("movx","a,@dptr");
4969 emitcode ("push","b");
4970 emitcode ("push","acc");
4971 emitcode ("lcall","__gptrget");
4972 emitcode ("pop","b");
4976 emitcode ("anl","a,#0x%02x",(unsigned char)
4977 ((unsigned char)(0xFF << (blen+bstr)) |
4978 (unsigned char)(0xFF >> (8-bstr)) ) );
4979 emitcode ("orl","a,b");
4980 if (p_type == GPOINTER)
4981 emitcode("pop","b");
4987 emitcode("mov","@%s,a",rname);
4991 emitcode("movx","@dptr,a");
4995 emitcode("lcall","__gptrput");
5000 if ( SPEC_BLEN(etype) <= 8 )
5003 emitcode("inc","%s",rname);
5004 rLen = SPEC_BLEN(etype) ;
5006 /* now generate for lengths greater than one byte */
5009 l = aopGet(AOP(right),offset++,FALSE,TRUE);
5019 emitcode("mov","@%s,a",rname);
5021 emitcode("mov","@%s,%s",rname,l);
5026 emitcode("movx","@dptr,a");
5031 emitcode("lcall","__gptrput");
5034 emitcode ("inc","%s",rname);
5039 /* last last was not complete */
5041 /* save the byte & read byte */
5044 emitcode ("mov","b,a");
5045 emitcode("mov","a,@%s",rname);
5049 emitcode ("mov","b,a");
5050 emitcode("movx","a,@dptr");
5054 emitcode ("push","b");
5055 emitcode ("push","acc");
5056 emitcode ("lcall","__gptrget");
5057 emitcode ("pop","b");
5061 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
5062 emitcode ("orl","a,b");
5065 if (p_type == GPOINTER)
5066 emitcode("pop","b");
5071 emitcode("mov","@%s,a",rname);
5075 emitcode("movx","@dptr,a");
5079 emitcode("lcall","__gptrput");
5083 /*-----------------------------------------------------------------*/
5084 /* genDataPointerSet - remat pointer to data space */
5085 /*-----------------------------------------------------------------*/
5086 static void genDataPointerSet(operand *right,
5090 int size, offset = 0 ;
5091 char *l, buffer[256];
5093 aopOp(right,ic,FALSE);
5095 l = aopGet(AOP(result),0,FALSE,TRUE);
5096 size = AOP_SIZE(right);
5099 sprintf(buffer,"(%s + %d)",l+1,offset);
5101 sprintf(buffer,"%s",l+1);
5102 emitcode("mov","%s,%s",buffer,
5103 aopGet(AOP(right),offset++,FALSE,FALSE));
5106 freeAsmop(right,NULL,ic,TRUE);
5107 freeAsmop(result,NULL,ic,TRUE);
5110 /*-----------------------------------------------------------------*/
5111 /* genNearPointerSet - emitcode for near pointer put */
5112 /*-----------------------------------------------------------------*/
5113 static void genNearPointerSet (operand *right,
5121 link *ptype = operandType(result);
5123 retype= getSpec(operandType(right));
5125 aopOp(result,ic,FALSE);
5127 /* if the result is rematerializable &
5128 in data space & not a bit variable */
5129 if (AOP_TYPE(result) == AOP_IMMD &&
5130 DCL_TYPE(ptype) == POINTER &&
5131 !IS_BITVAR(retype)) {
5132 genDataPointerSet (right,result,ic);
5136 /* if the value is already in a pointer register
5137 then don't need anything more */
5138 if (!AOP_INPREG(AOP(result))) {
5139 /* otherwise get a free pointer register */
5141 preg = getFreePtr(ic,&aop,FALSE);
5142 emitcode("mov","%s,%s",
5144 aopGet(AOP(result),0,FALSE,TRUE));
5145 rname = preg->name ;
5147 rname = aopGet(AOP(result),0,FALSE,FALSE);
5149 freeAsmop(result,NULL,ic,TRUE);
5150 aopOp (right,ic,FALSE);
5152 /* if bitfield then unpack the bits */
5153 if (IS_BITVAR(retype))
5154 genPackBits (retype,right,rname,POINTER);
5156 /* we have can just get the values */
5157 int size = AOP_SIZE(right);
5161 l = aopGet(AOP(right),offset,FALSE,TRUE);
5164 emitcode("mov","@%s,a",rname);
5166 emitcode("mov","@%s,%s",rname,l);
5168 emitcode("inc","%s",rname);
5173 /* now some housekeeping stuff */
5175 /* we had to allocate for this iCode */
5176 freeAsmop(NULL,aop,ic,TRUE);
5178 /* we did not allocate which means left
5179 already in a pointer register, then
5180 if size > 0 && this could be used again
5181 we have to point it back to where it
5183 if (AOP_SIZE(right) > 1 &&
5184 !OP_SYMBOL(result)->remat &&
5185 ( OP_SYMBOL(result)->liveTo > ic->seq ||
5187 int size = AOP_SIZE(right) - 1;
5189 emitcode("dec","%s",rname);
5194 freeAsmop(right,NULL,ic,TRUE);
5199 /*-----------------------------------------------------------------*/
5200 /* genPagedPointerSet - emitcode for Paged pointer put */
5201 /*-----------------------------------------------------------------*/
5202 static void genPagedPointerSet (operand *right,
5211 retype= getSpec(operandType(right));
5213 aopOp(result,ic,FALSE);
5215 /* if the value is already in a pointer register
5216 then don't need anything more */
5217 if (!AOP_INPREG(AOP(result))) {
5218 /* otherwise get a free pointer register */
5220 preg = getFreePtr(ic,&aop,FALSE);
5221 emitcode("mov","%s,%s",
5223 aopGet(AOP(result),0,FALSE,TRUE));
5224 rname = preg->name ;
5226 rname = aopGet(AOP(result),0,FALSE,FALSE);
5228 freeAsmop(result,NULL,ic,TRUE);
5229 aopOp (right,ic,FALSE);
5231 /* if bitfield then unpack the bits */
5232 if (IS_BITVAR(retype))
5233 genPackBits (retype,right,rname,PPOINTER);
5235 /* we have can just get the values */
5236 int size = AOP_SIZE(right);
5240 l = aopGet(AOP(right),offset,FALSE,TRUE);
5243 emitcode("movx","@%s,a",rname);
5246 emitcode("inc","%s",rname);
5252 /* now some housekeeping stuff */
5254 /* we had to allocate for this iCode */
5255 freeAsmop(NULL,aop,ic,TRUE);
5257 /* we did not allocate which means left
5258 already in a pointer register, then
5259 if size > 0 && this could be used again
5260 we have to point it back to where it
5262 if (AOP_SIZE(right) > 1 &&
5263 !OP_SYMBOL(result)->remat &&
5264 ( OP_SYMBOL(result)->liveTo > ic->seq ||
5266 int size = AOP_SIZE(right) - 1;
5268 emitcode("dec","%s",rname);
5273 freeAsmop(right,NULL,ic,TRUE);
5278 /*-----------------------------------------------------------------*/
5279 /* genFarPointerSet - set value from far space */
5280 /*-----------------------------------------------------------------*/
5281 static void genFarPointerSet (operand *right,
5282 operand *result, iCode *ic)
5285 link *retype = getSpec(operandType(right));
5287 aopOp(result,ic,FALSE);
5289 /* if the operand is already in dptr
5290 then we do nothing else we move the value to dptr */
5291 if (AOP_TYPE(result) != AOP_STR) {
5292 /* if this is remateriazable */
5293 if (AOP_TYPE(result) == AOP_IMMD)
5294 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
5295 else { /* we need to get it byte by byte */
5296 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
5297 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
5298 if (options.model == MODEL_FLAT24)
5300 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
5304 /* so dptr know contains the address */
5305 freeAsmop(result,NULL,ic,TRUE);
5306 aopOp(right,ic,FALSE);
5308 /* if bit then unpack */
5309 if (IS_BITVAR(retype))
5310 genPackBits(retype,right,"dptr",FPOINTER);
5312 size = AOP_SIZE(right);
5316 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
5318 emitcode("movx","@dptr,a");
5320 emitcode("inc","dptr");
5324 freeAsmop(right,NULL,ic,TRUE);
5327 /*-----------------------------------------------------------------*/
5328 /* genGenPointerSet - set value from generic pointer space */
5329 /*-----------------------------------------------------------------*/
5330 static void genGenPointerSet (operand *right,
5331 operand *result, iCode *ic)
5334 link *retype = getSpec(operandType(right));
5336 aopOp(result,ic,FALSE);
5338 /* if the operand is already in dptr
5339 then we do nothing else we move the value to dptr */
5340 if (AOP_TYPE(result) != AOP_STR) {
5341 /* if this is remateriazable */
5342 if (AOP_TYPE(result) == AOP_IMMD) {
5343 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
5344 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
5346 else { /* we need to get it byte by byte */
5347 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
5348 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
5349 if (options.model == MODEL_FLAT24)
5351 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
5352 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
5356 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
5360 /* so dptr know contains the address */
5361 freeAsmop(result,NULL,ic,TRUE);
5362 aopOp(right,ic,FALSE);
5364 /* if bit then unpack */
5365 if (IS_BITVAR(retype))
5366 genPackBits(retype,right,"dptr",GPOINTER);
5368 size = AOP_SIZE(right);
5372 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
5374 emitcode("lcall","__gptrput");
5376 emitcode("inc","dptr");
5380 freeAsmop(right,NULL,ic,TRUE);
5383 /*-----------------------------------------------------------------*/
5384 /* genPointerSet - stores the value into a pointer location */
5385 /*-----------------------------------------------------------------*/
5386 static void genPointerSet (iCode *ic)
5388 operand *right, *result ;
5392 right = IC_RIGHT(ic);
5393 result = IC_RESULT(ic) ;
5395 /* depending on the type of pointer we need to
5396 move it to the correct pointer register */
5397 type = operandType(result);
5398 etype = getSpec(type);
5399 /* if left is of type of pointer then it is simple */
5400 if (IS_PTR(type) && !IS_FUNC(type->next)) {
5401 p_type = DCL_TYPE(type);
5404 /* we have to go by the storage class */
5405 p_type = PTR_TYPE(SPEC_OCLS(etype));
5407 /* if (SPEC_OCLS(etype)->codesp ) { */
5408 /* p_type = CPOINTER ; */
5411 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
5412 /* p_type = FPOINTER ; */
5414 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
5415 /* p_type = PPOINTER ; */
5417 /* if (SPEC_OCLS(etype) == idata ) */
5418 /* p_type = IPOINTER ; */
5420 /* p_type = POINTER ; */
5423 /* now that we have the pointer type we assign
5424 the pointer values */
5429 genNearPointerSet (right,result,ic);
5433 genPagedPointerSet (right,result,ic);
5437 genFarPointerSet (right,result,ic);
5441 genGenPointerSet (right,result,ic);
5447 /*-----------------------------------------------------------------*/
5448 /* genIfx - generate code for Ifx statement */
5449 /*-----------------------------------------------------------------*/
5450 static void genIfx (iCode *ic, iCode *popIc)
5452 operand *cond = IC_COND(ic);
5455 aopOp(cond,ic,FALSE);
5457 /* get the value into acc */
5458 if (AOP_TYPE(cond) != AOP_CRY)
5462 /* the result is now in the accumulator */
5463 freeAsmop(cond,NULL,ic,TRUE);
5465 /* if there was something to be popped then do it */
5469 /* if the condition is a bit variable */
5470 if (isbit && IS_ITEMP(cond) &&
5472 genIfxJump(ic,SPIL_LOC(cond)->rname);
5474 if (isbit && !IS_ITEMP(cond))
5475 genIfxJump(ic,OP_SYMBOL(cond)->rname);
5482 /*-----------------------------------------------------------------*/
5483 /* genAddrOf - generates code for address of */
5484 /*-----------------------------------------------------------------*/
5485 static void genAddrOf (iCode *ic)
5487 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
5490 aopOp(IC_RESULT(ic),ic,FALSE);
5492 /* if the operand is on the stack then we
5493 need to get the stack offset of this
5496 /* if it has an offset then we need to compute
5499 emitcode("mov","a,_bp");
5500 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
5501 aopPut(AOP(IC_RESULT(ic)),"a",0);
5503 /* we can just move _bp */
5504 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
5506 /* fill the result with zero */
5507 size = AOP_SIZE(IC_RESULT(ic)) - 1;
5510 if (options.stack10bit && size < (FPTRSIZE - 1))
5513 "*** warning: pointer to stack var truncated.\n");
5520 if (options.stack10bit && offset == 2)
5522 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
5526 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
5533 /* object not on stack then we need the name */
5534 size = AOP_SIZE(IC_RESULT(ic));
5538 char s[SDCC_NAME_MAX];
5540 sprintf(s,"#(%s >> %d)",
5544 sprintf(s,"#%s",sym->rname);
5545 aopPut(AOP(IC_RESULT(ic)),s,offset++);
5549 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
5553 /*-----------------------------------------------------------------*/
5554 /* genFarFarAssign - assignment when both are in far space */
5555 /*-----------------------------------------------------------------*/
5556 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
5558 int size = AOP_SIZE(right);
5561 /* first push the right side on to the stack */
5563 l = aopGet(AOP(right),offset++,FALSE,FALSE);
5565 emitcode ("push","acc");
5568 freeAsmop(right,NULL,ic,FALSE);
5569 /* now assign DPTR to result */
5570 aopOp(result,ic,FALSE);
5571 size = AOP_SIZE(result);
5573 emitcode ("pop","acc");
5574 aopPut(AOP(result),"a",--offset);
5576 freeAsmop(result,NULL,ic,FALSE);
5580 /*-----------------------------------------------------------------*/
5581 /* genAssign - generate code for assignment */
5582 /*-----------------------------------------------------------------*/
5583 static void genAssign (iCode *ic)
5585 operand *result, *right;
5587 unsigned long lit = 0L;
5589 result = IC_RESULT(ic);
5590 right = IC_RIGHT(ic) ;
5592 /* if they are the same */
5593 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
5596 aopOp(right,ic,FALSE);
5598 /* special case both in far space */
5599 if ((AOP_TYPE(right) == AOP_DPTR ||
5600 AOP_TYPE(right) == AOP_DPTR2) &&
5601 IS_TRUE_SYMOP(result) &&
5602 isOperandInFarSpace(result)) {
5604 genFarFarAssign (result,right,ic);
5608 aopOp(result,ic,TRUE);
5610 /* if they are the same registers */
5611 if (sameRegs(AOP(right),AOP(result)))
5614 /* if the result is a bit */
5615 if (AOP_TYPE(result) == AOP_CRY) {
5617 /* if the right size is a literal then
5618 we know what the value is */
5619 if (AOP_TYPE(right) == AOP_LIT) {
5620 if (((int) operandLitValue(right)))
5621 aopPut(AOP(result),one,0);
5623 aopPut(AOP(result),zero,0);
5627 /* the right is also a bit variable */
5628 if (AOP_TYPE(right) == AOP_CRY) {
5629 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5630 aopPut(AOP(result),"c",0);
5636 aopPut(AOP(result),"a",0);
5640 /* bit variables done */
5642 size = AOP_SIZE(result);
5644 if(AOP_TYPE(right) == AOP_LIT)
5645 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5647 (AOP_TYPE(result) != AOP_REG) &&
5648 (AOP_TYPE(right) == AOP_LIT) &&
5649 !IS_FLOAT(operandType(right)) &&
5651 emitcode("clr","a");
5653 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
5654 aopPut(AOP(result),"a",size);
5657 aopGet(AOP(right),size,FALSE,FALSE),
5663 aopGet(AOP(right),offset,FALSE,FALSE),
5670 freeAsmop (right,NULL,ic,FALSE);
5671 freeAsmop (result,NULL,ic,TRUE);
5674 /*-----------------------------------------------------------------*/
5675 /* genJumpTab - genrates code for jump table */
5676 /*-----------------------------------------------------------------*/
5677 static void genJumpTab (iCode *ic)
5682 aopOp(IC_JTCOND(ic),ic,FALSE);
5683 /* get the condition into accumulator */
5684 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
5686 /* multiply by three */
5687 emitcode("add","a,acc");
5688 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
5689 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
5691 jtab = newiTempLabel(NULL);
5692 emitcode("mov","dptr,#%05d$",jtab->key+100);
5693 emitcode("jmp","@a+dptr");
5694 emitcode("","%05d$:",jtab->key+100);
5695 /* now generate the jump labels */
5696 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
5697 jtab = setNextItem(IC_JTLABELS(ic)))
5698 emitcode("ljmp","%05d$",jtab->key+100);
5702 /*-----------------------------------------------------------------*/
5703 /* genCast - gen code for casting */
5704 /*-----------------------------------------------------------------*/
5705 static void genCast (iCode *ic)
5707 operand *result = IC_RESULT(ic);
5708 link *ctype = operandType(IC_LEFT(ic));
5709 link *rtype = operandType(IC_RIGHT(ic));
5710 operand *right = IC_RIGHT(ic);
5713 /* if they are equivalent then do nothing */
5714 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
5717 aopOp(right,ic,FALSE) ;
5718 aopOp(result,ic,FALSE);
5720 /* if the result is a bit */
5721 if (AOP_TYPE(result) == AOP_CRY) {
5722 /* if the right size is a literal then
5723 we know what the value is */
5724 if (AOP_TYPE(right) == AOP_LIT) {
5725 if (((int) operandLitValue(right)))
5726 aopPut(AOP(result),one,0);
5728 aopPut(AOP(result),zero,0);
5733 /* the right is also a bit variable */
5734 if (AOP_TYPE(right) == AOP_CRY) {
5735 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5736 aopPut(AOP(result),"c",0);
5742 aopPut(AOP(result),"a",0);
5746 /* if they are the same size : or less */
5747 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
5749 /* if they are in the same place */
5750 if (sameRegs(AOP(right),AOP(result)))
5753 /* if they in different places then copy */
5754 size = AOP_SIZE(result);
5758 aopGet(AOP(right),offset,FALSE,FALSE),
5766 /* if the result is of type pointer */
5767 if (IS_PTR(ctype)) {
5770 link *type = operandType(right);
5771 link *etype = getSpec(type);
5773 /* pointer to generic pointer */
5774 if (IS_GENPTR(ctype)) {
5778 p_type = DCL_TYPE(type);
5780 /* we have to go by the storage class */
5781 p_type = PTR_TYPE(SPEC_OCLS(etype));
5784 /* the first two bytes are known */
5785 size = GPTRSIZE - 1;
5789 aopGet(AOP(right),offset,FALSE,FALSE),
5793 /* the last byte depending on type */
5810 /* this should never happen */
5811 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
5812 "got unknown pointer type");
5815 aopPut(AOP(result),l, GPTRSIZE - 1);
5819 /* just copy the pointers */
5820 size = AOP_SIZE(result);
5824 aopGet(AOP(right),offset,FALSE,FALSE),
5831 /* so we now know that the size of destination is greater
5832 than the size of the source */
5833 /* we move to result for the size of source */
5834 size = AOP_SIZE(right);
5838 aopGet(AOP(right),offset,FALSE,FALSE),
5843 /* now depending on the sign of the source && destination */
5844 size = AOP_SIZE(result) - AOP_SIZE(right);
5845 /* if unsigned or not an integral type */
5846 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
5848 aopPut(AOP(result),zero,offset++);
5850 /* we need to extend the sign :{ */
5851 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
5854 emitcode("rlc","a");
5855 emitcode("subb","a,acc");
5857 aopPut(AOP(result),"a",offset++);
5860 /* we are done hurray !!!! */
5863 freeAsmop(right,NULL,ic,TRUE);
5864 freeAsmop(result,NULL,ic,TRUE);
5868 /*-----------------------------------------------------------------*/
5869 /* genDjnz - generate decrement & jump if not zero instrucion */
5870 /*-----------------------------------------------------------------*/
5871 static int genDjnz (iCode *ic, iCode *ifx)
5877 /* if the if condition has a false label
5878 then we cannot save */
5882 /* if the minus is not of the form
5884 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
5885 !IS_OP_LITERAL(IC_RIGHT(ic)))
5888 if (operandLitValue(IC_RIGHT(ic)) != 1)
5891 /* if the size of this greater than one then no
5893 if (getSize(operandType(IC_RESULT(ic))) > 1)
5896 /* otherwise we can save BIG */
5897 lbl = newiTempLabel(NULL);
5898 lbl1= newiTempLabel(NULL);
5900 aopOp(IC_RESULT(ic),ic,FALSE);
5902 if (IS_AOP_PREG(IC_RESULT(ic))) {
5903 emitcode("dec","%s",
5904 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
5905 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
5906 emitcode("jnz","%05d$",lbl->key+100);
5908 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
5911 emitcode ("sjmp","%05d$",lbl1->key+100);
5912 emitcode ("","%05d$:",lbl->key+100);
5913 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
5914 emitcode ("","%05d$:",lbl1->key+100);
5916 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
5921 /*-----------------------------------------------------------------*/
5922 /* genReceive - generate code for a receive iCode */
5923 /*-----------------------------------------------------------------*/
5924 static void genReceive (iCode *ic)
5926 if (isOperandInFarSpace(IC_RESULT(ic)) &&
5927 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
5928 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
5930 int size = getSize(operandType(IC_RESULT(ic)));
5931 int offset = fReturnSize - size;
5933 emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
5934 fReturn[fReturnSize - offset - 1] : "acc"));
5937 aopOp(IC_RESULT(ic),ic,FALSE);
5938 size = AOP_SIZE(IC_RESULT(ic));
5941 emitcode ("pop","acc");
5942 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
5947 aopOp(IC_RESULT(ic),ic,FALSE);
5949 assignResultValue(IC_RESULT(ic));
5952 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
5955 /*-----------------------------------------------------------------*/
5956 /* gen51Code - generate code for 8051 based controllers */
5957 /*-----------------------------------------------------------------*/
5958 void gen51Code (iCode *lic)
5963 lineHead = lineCurr = NULL;
5965 /* print the allocation information */
5967 printAllocInfo( currFunc, codeOutFile);
5968 /* if debug information required */
5969 /* if (options.debug && currFunc) { */
5971 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
5973 if (IS_STATIC(currFunc->etype))
5974 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
5976 emitcode("","G$%s$0$0 ==.",currFunc->name);
5979 /* stack pointer name */
5980 if (options.useXstack)
5986 for (ic = lic ; ic ; ic = ic->next ) {
5988 if ( cln != ic->lineno ) {
5989 if ( options.debug ) {
5991 emitcode("","C$%s$%d$%d$%d ==.",
5992 ic->filename,ic->lineno,
5993 ic->level,ic->block);
5996 emitcode(";","%s %d",ic->filename,ic->lineno);
5999 /* if the result is marked as
6000 spilt and rematerializable or code for
6001 this has already been generated then
6003 if (resultRemat(ic) || ic->generated )
6006 /* depending on the operation */
6025 /* IPOP happens only when trying to restore a
6026 spilt live range, if there is an ifx statement
6027 following this pop then the if statement might
6028 be using some of the registers being popped which
6029 would destory the contents of the register so
6030 we need to check for this condition and handle it */
6032 ic->next->op == IFX &&
6033 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
6034 genIfx (ic->next,ic);
6052 genEndFunction (ic);
6072 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
6089 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
6093 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
6100 /* note these two are xlated by algebraic equivalence
6101 during parsing SDCC.y */
6102 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
6103 "got '>=' or '<=' shouldn't have come here");
6107 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
6119 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
6123 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
6127 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
6154 case GET_VALUE_AT_ADDRESS:
6159 if (POINTER_SET(ic))
6186 addSet(&_G.sendSet,ic);
6191 /* piCode(ic,stdout); */
6197 /* now we are ready to call the
6198 peep hole optimizer */
6199 if (!options.nopeep)
6200 peepHole (&lineHead);
6202 /* now do the actual printing */
6203 printLine (lineHead,codeOutFile);