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 /* should have transformed by the parser */
2003 /*-----------------------------------------------------------------*/
2004 /* revavrcnd - reverse a conditional for avr */
2005 /*-----------------------------------------------------------------*/
2006 static int revavrcnd(int type)
2010 } rar[] = { { AVR_EQ, AVR_NE}, {AVR_LT, AVR_GE}};
2013 for (i = 0 ; i < (sizeof(rar)/sizeof(rar[0]));i++) {
2014 if (rar[i].type == type) return rar[i].rtype;
2015 if (rar[i].rtype== type) return rar[i].type;
2017 assert(1); /* cannot happen */
2020 static char *br_name[4] = {"breq","brne","brlt","brge"};
2021 static char *br_uname[4]= {"breq","brne","brlo","brcc"};
2023 /*-----------------------------------------------------------------*/
2024 /* genBranch - generate the branch instruction */
2025 /*-----------------------------------------------------------------*/
2026 static void genBranch (iCode *ifx, int br_type, int sign)
2028 int tj = (IC_TRUE(ifx) ? 1 : 0) ;
2030 if (tj) { /* if true jump */
2031 char *nm = (sign ? br_name[br_type] : br_uname[br_type]);
2032 emitcode(nm,"L%05d",IC_TRUE(ifx)->key);
2033 } else { /* if false jump */
2034 int rtype = revavrcnd(br_type);
2035 char *nm = (sign ? br_name[rtype] : br_uname[rtype]);
2036 emitcode(nm,"L%05d",IC_FALSE(ifx)->key);
2041 /*-----------------------------------------------------------------*/
2042 /* genCmpLt - less than comparisons */
2043 /*-----------------------------------------------------------------*/
2044 static void genCmpLt (iCode *ic, iCode *ifx)
2046 operand *left, *right, *result;
2047 link *letype , *retype;
2049 int sign, size, offset =0;
2052 right= IC_RIGHT(ic);
2053 result = IC_RESULT(ic);
2055 letype = getSpec(operandType(left));
2056 retype =getSpec(operandType(right));
2057 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2059 /* assign the amsops */
2060 aopOp (left,ic,FALSE);
2061 aopOp (right,ic,FALSE);
2062 aopOp (result,ic,TRUE);
2063 size = AOP_SIZE(AOP(left));
2067 if (AOP_TYPE(AOP(right)) == AOP_LIT) {
2068 emitcode("cpi","%s,lo8(%d)",aopGet(AOP(left),0),
2069 (int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
2070 genBranch(ifx,AVR_LT);
2071 } else { /* right != literal */
2072 emitcode("cp","%s,%s",aopGet(AOP(left),0),aopGet(AOP(right),0));
2073 genBranch(ifx,AVR_LT);
2074 } else { /* size != 1 */
2077 emitcode("cp","%s,%s",aopGet(AOP(left),0),aopGet(AOP(right),0));
2079 emitcode("cpc","%s,%s",aopGet(AOP(left),offset),aopGet(AOP(right),offset));
2082 genBranch(ifx,AVR_LT);
2084 } else { /* no ifx */
2085 emitCode("clr","r0");
2088 emitcode("cp","%s,%s",aopGet(AOP(left),0),aopGet(AOP(right),0));
2090 emitcode("cpc","%s,%s",aopGet(AOP(left),offset),aopGet(AOP(right),offset));
2093 lbl = newiTempLabel(NULL);
2094 if (sign) emitcode(br_uname[AVR_GE],"L%05d",lbl->key);
2095 else emitcode(br_name[AVR_GE],"L%05d",lbl->key);
2096 emitcode("inc","r0");
2097 emitcode("","L%05d:",lbl->key);
2098 aopPut(AOP(result),"r0",0);
2099 size = AOP_SIZE(AOP(result)) - 1;
2101 while (size--) aopPut(AOP(result),zero,offset++);
2104 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2105 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2106 freeAsmop(result,NULL,ic,TRUE);
2109 /*-----------------------------------------------------------------*/
2110 /* genCmpEq - generates code for equal to */
2111 /*-----------------------------------------------------------------*/
2112 static void genCmpEq (iCode *ic, iCode *ifx)
2114 operand *left, *right, *result;
2116 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2117 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2118 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2120 /* if literal, literal on the right or
2121 if the right is in a pointer register and left
2123 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2124 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
2125 operand *t = IC_RIGHT(ic);
2126 IC_RIGHT(ic) = IC_LEFT(ic);
2132 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2133 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2134 freeAsmop(result,NULL,ic,TRUE);
2137 /*-----------------------------------------------------------------*/
2138 /* ifxForOp - returns the icode containing the ifx for operand */
2139 /*-----------------------------------------------------------------*/
2140 static iCode *ifxForOp ( operand *op, iCode *ic )
2142 /* if true symbol then needs to be assigned */
2143 if (IS_TRUE_SYMOP(op))
2146 /* if this has register type condition and
2147 the next instruction is ifx with the same operand
2148 and live to of the operand is upto the ifx only then */
2150 ic->next->op == IFX &&
2151 IC_COND(ic->next)->key == op->key &&
2152 OP_SYMBOL(op)->liveTo <= ic->next->seq )
2157 /*-----------------------------------------------------------------*/
2158 /* genAndOp - for && operation */
2159 /*-----------------------------------------------------------------*/
2160 static void genAndOp (iCode *ic)
2162 operand *left,*right, *result;
2165 /* note here that && operations that are in an
2166 if statement are taken away by backPatchLabels
2167 only those used in arthmetic operations remain */
2168 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2169 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2170 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2172 /* if both are bit variables */
2173 if (AOP_TYPE(left) == AOP_CRY &&
2174 AOP_TYPE(right) == AOP_CRY ) {
2175 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2176 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
2179 tlbl = newiTempLabel(NULL);
2181 emitcode("jz","%05d$",tlbl->key+100);
2183 emitcode("","%05d$:",tlbl->key+100);
2187 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2188 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2189 freeAsmop(result,NULL,ic,TRUE);
2193 /*-----------------------------------------------------------------*/
2194 /* genOrOp - for || operation */
2195 /*-----------------------------------------------------------------*/
2196 static void genOrOp (iCode *ic)
2198 operand *left,*right, *result;
2201 /* note here that || operations that are in an
2202 if statement are taken away by backPatchLabels
2203 only those used in arthmetic operations remain */
2204 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2205 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2206 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2208 /* if both are bit variables */
2209 if (AOP_TYPE(left) == AOP_CRY &&
2210 AOP_TYPE(right) == AOP_CRY ) {
2211 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2212 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
2215 tlbl = newiTempLabel(NULL);
2217 emitcode("jnz","%05d$",tlbl->key+100);
2219 emitcode("","%05d$:",tlbl->key+100);
2223 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2224 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2225 freeAsmop(result,NULL,ic,TRUE);
2228 /*-----------------------------------------------------------------*/
2229 /* isLiteralBit - test if lit == 2^n */
2230 /*-----------------------------------------------------------------*/
2231 static int isLiteralBit(unsigned long lit)
2233 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
2234 0x100L,0x200L,0x400L,0x800L,
2235 0x1000L,0x2000L,0x4000L,0x8000L,
2236 0x10000L,0x20000L,0x40000L,0x80000L,
2237 0x100000L,0x200000L,0x400000L,0x800000L,
2238 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
2239 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
2242 for(idx = 0; idx < 32; idx++)
2248 /*-----------------------------------------------------------------*/
2249 /* continueIfTrue - */
2250 /*-----------------------------------------------------------------*/
2251 static void continueIfTrue (iCode *ic)
2254 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
2258 /*-----------------------------------------------------------------*/
2260 /*-----------------------------------------------------------------*/
2261 static void jumpIfTrue (iCode *ic)
2264 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
2268 /*-----------------------------------------------------------------*/
2269 /* jmpTrueOrFalse - */
2270 /*-----------------------------------------------------------------*/
2271 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
2273 // ugly but optimized by peephole
2275 symbol *nlbl = newiTempLabel(NULL);
2276 emitcode("sjmp","%05d$",nlbl->key+100);
2277 emitcode("","%05d$:",tlbl->key+100);
2278 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
2279 emitcode("","%05d$:",nlbl->key+100);
2282 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
2283 emitcode("","%05d$:",tlbl->key+100);
2288 /*-----------------------------------------------------------------*/
2289 /* genAnd - code for and */
2290 /*-----------------------------------------------------------------*/
2291 static void genAnd (iCode *ic, iCode *ifx)
2293 operand *left, *right, *result;
2295 unsigned long lit = 0L;
2299 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2300 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2301 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2304 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2306 AOP_TYPE(left), AOP_TYPE(right));
2307 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2309 AOP_SIZE(left), AOP_SIZE(right));
2312 /* if left is a literal & right is not then exchange them */
2313 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2314 AOP_NEEDSACC(left)) {
2315 operand *tmp = right ;
2320 /* if result = right then exchange them */
2321 if(sameRegs(AOP(result),AOP(right))){
2322 operand *tmp = right ;
2327 /* if right is bit then exchange them */
2328 if (AOP_TYPE(right) == AOP_CRY &&
2329 AOP_TYPE(left) != AOP_CRY){
2330 operand *tmp = right ;
2334 if(AOP_TYPE(right) == AOP_LIT)
2335 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2337 size = AOP_SIZE(result);
2340 // result = bit & yy;
2341 if (AOP_TYPE(left) == AOP_CRY){
2342 // c = bit & literal;
2343 if(AOP_TYPE(right) == AOP_LIT){
2345 if(size && sameRegs(AOP(result),AOP(left)))
2348 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2351 if(size && (AOP_TYPE(result) == AOP_CRY)){
2352 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
2355 if((AOP_TYPE(result) == AOP_CRY) && ifx){
2359 emitcode("clr","c");
2362 if (AOP_TYPE(right) == AOP_CRY){
2364 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
2365 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
2368 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
2370 emitcode("rrc","a");
2371 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
2379 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
2380 genIfxJump(ifx, "c");
2384 // if(val & 0xZZ) - size = 0, ifx != FALSE -
2385 // bit = val & 0xZZ - size = 1, ifx = FALSE -
2386 if((AOP_TYPE(right) == AOP_LIT) &&
2387 (AOP_TYPE(result) == AOP_CRY) &&
2388 (AOP_TYPE(left) != AOP_CRY)){
2389 int posbit = isLiteralBit(lit);
2393 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
2396 emitcode("mov","c,acc.%d",posbit&0x07);
2400 sprintf(buffer,"acc.%d",posbit&0x07);
2401 genIfxJump(ifx, buffer);
2406 symbol *tlbl = newiTempLabel(NULL);
2407 int sizel = AOP_SIZE(left);
2409 emitcode("setb","c");
2411 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
2412 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
2414 if((posbit = isLiteralBit(bytelit)) != 0)
2415 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
2417 if(bytelit != 0x0FFL)
2418 emitcode("anl","a,%s",
2419 aopGet(AOP(right),offset,FALSE,TRUE));
2420 emitcode("jnz","%05d$",tlbl->key+100);
2425 // bit = left & literal
2427 emitcode("clr","c");
2428 emitcode("","%05d$:",tlbl->key+100);
2430 // if(left & literal)
2433 jmpTrueOrFalse(ifx, tlbl);
2441 /* if left is same as result */
2442 if(sameRegs(AOP(result),AOP(left))){
2443 for(;size--; offset++) {
2444 if(AOP_TYPE(right) == AOP_LIT){
2445 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
2449 aopPut(AOP(result),zero,offset);
2451 if (IS_AOP_PREG(result)) {
2452 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2453 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
2454 aopPut(AOP(result),"a",offset);
2456 emitcode("anl","%s,%s",
2457 aopGet(AOP(left),offset,FALSE,TRUE),
2458 aopGet(AOP(right),offset,FALSE,FALSE));
2460 if (AOP_TYPE(left) == AOP_ACC)
2461 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
2463 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2464 if (IS_AOP_PREG(result)) {
2465 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
2466 aopPut(AOP(result),"a",offset);
2469 emitcode("anl","%s,a",
2470 aopGet(AOP(left),offset,FALSE,TRUE));
2475 // left & result in different registers
2476 if(AOP_TYPE(result) == AOP_CRY){
2478 // if(size), result in bit
2479 // if(!size && ifx), conditional oper: if(left & right)
2480 symbol *tlbl = newiTempLabel(NULL);
2481 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
2483 emitcode("setb","c");
2485 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2486 emitcode("anl","a,%s",
2487 aopGet(AOP(left),offset,FALSE,FALSE));
2488 emitcode("jnz","%05d$",tlbl->key+100);
2493 emitcode("","%05d$:",tlbl->key+100);
2496 jmpTrueOrFalse(ifx, tlbl);
2498 for(;(size--);offset++) {
2500 // result = left & right
2501 if(AOP_TYPE(right) == AOP_LIT){
2502 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
2504 aopGet(AOP(left),offset,FALSE,FALSE),
2507 } else if(bytelit == 0){
2508 aopPut(AOP(result),zero,offset);
2512 // faster than result <- left, anl result,right
2513 // and better if result is SFR
2514 if (AOP_TYPE(left) == AOP_ACC)
2515 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
2517 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2518 emitcode("anl","a,%s",
2519 aopGet(AOP(left),offset,FALSE,FALSE));
2521 aopPut(AOP(result),"a",offset);
2527 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2528 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2529 freeAsmop(result,NULL,ic,TRUE);
2532 /*-----------------------------------------------------------------*/
2533 /* genOr - code for or */
2534 /*-----------------------------------------------------------------*/
2535 static void genOr (iCode *ic, iCode *ifx)
2537 operand *left, *right, *result;
2539 unsigned long lit = 0L;
2541 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2542 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2543 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2546 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2548 AOP_TYPE(left), AOP_TYPE(right));
2549 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2551 AOP_SIZE(left), AOP_SIZE(right));
2554 /* if left is a literal & right is not then exchange them */
2555 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2556 AOP_NEEDSACC(left)) {
2557 operand *tmp = right ;
2562 /* if result = right then exchange them */
2563 if(sameRegs(AOP(result),AOP(right))){
2564 operand *tmp = right ;
2569 /* if right is bit then exchange them */
2570 if (AOP_TYPE(right) == AOP_CRY &&
2571 AOP_TYPE(left) != AOP_CRY){
2572 operand *tmp = right ;
2576 if(AOP_TYPE(right) == AOP_LIT)
2577 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2579 size = AOP_SIZE(result);
2583 if (AOP_TYPE(left) == AOP_CRY){
2584 if(AOP_TYPE(right) == AOP_LIT){
2585 // c = bit & literal;
2587 // lit != 0 => result = 1
2588 if(AOP_TYPE(result) == AOP_CRY){
2590 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
2592 continueIfTrue(ifx);
2595 emitcode("setb","c");
2597 // lit == 0 => result = left
2598 if(size && sameRegs(AOP(result),AOP(left)))
2600 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2603 if (AOP_TYPE(right) == AOP_CRY){
2605 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
2606 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
2610 symbol *tlbl = newiTempLabel(NULL);
2611 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
2612 emitcode("setb","c");
2613 emitcode("jb","%s,%05d$",
2614 AOP(left)->aopu.aop_dir,tlbl->key+100);
2616 emitcode("jnz","%05d$",tlbl->key+100);
2617 if((AOP_TYPE(result) == AOP_CRY) && ifx){
2618 jmpTrueOrFalse(ifx, tlbl);
2622 emitcode("","%05d$:",tlbl->key+100);
2631 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
2632 genIfxJump(ifx, "c");
2636 // if(val | 0xZZ) - size = 0, ifx != FALSE -
2637 // bit = val | 0xZZ - size = 1, ifx = FALSE -
2638 if((AOP_TYPE(right) == AOP_LIT) &&
2639 (AOP_TYPE(result) == AOP_CRY) &&
2640 (AOP_TYPE(left) != AOP_CRY)){
2644 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
2646 continueIfTrue(ifx);
2649 // lit = 0, result = boolean(left)
2651 emitcode("setb","c");
2654 symbol *tlbl = newiTempLabel(NULL);
2655 emitcode("jnz","%05d$",tlbl->key+100);
2657 emitcode("","%05d$:",tlbl->key+100);
2659 genIfxJump (ifx,"a");
2667 /* if left is same as result */
2668 if(sameRegs(AOP(result),AOP(left))){
2669 for(;size--; offset++) {
2670 if(AOP_TYPE(right) == AOP_LIT){
2671 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2674 if (IS_AOP_PREG(left)) {
2675 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2676 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
2677 aopPut(AOP(result),"a",offset);
2679 emitcode("orl","%s,%s",
2680 aopGet(AOP(left),offset,FALSE,TRUE),
2681 aopGet(AOP(right),offset,FALSE,FALSE));
2683 if (AOP_TYPE(left) == AOP_ACC)
2684 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
2686 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2687 if (IS_AOP_PREG(left)) {
2688 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
2689 aopPut(AOP(result),"a",offset);
2691 emitcode("orl","%s,a",
2692 aopGet(AOP(left),offset,FALSE,TRUE));
2697 // left & result in different registers
2698 if(AOP_TYPE(result) == AOP_CRY){
2700 // if(size), result in bit
2701 // if(!size && ifx), conditional oper: if(left | right)
2702 symbol *tlbl = newiTempLabel(NULL);
2703 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
2705 emitcode("setb","c");
2707 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2708 emitcode("orl","a,%s",
2709 aopGet(AOP(left),offset,FALSE,FALSE));
2710 emitcode("jnz","%05d$",tlbl->key+100);
2715 emitcode("","%05d$:",tlbl->key+100);
2718 jmpTrueOrFalse(ifx, tlbl);
2719 } else for(;(size--);offset++){
2721 // result = left & right
2722 if(AOP_TYPE(right) == AOP_LIT){
2723 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2725 aopGet(AOP(left),offset,FALSE,FALSE),
2730 // faster than result <- left, anl result,right
2731 // and better if result is SFR
2732 if (AOP_TYPE(left) == AOP_ACC)
2733 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
2735 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2736 emitcode("orl","a,%s",
2737 aopGet(AOP(left),offset,FALSE,FALSE));
2739 aopPut(AOP(result),"a",offset);
2744 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2745 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2746 freeAsmop(result,NULL,ic,TRUE);
2749 /*-----------------------------------------------------------------*/
2750 /* genXor - code for xclusive or */
2751 /*-----------------------------------------------------------------*/
2752 static void genXor (iCode *ic, iCode *ifx)
2754 operand *left, *right, *result;
2756 unsigned long lit = 0L;
2758 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2759 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2760 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2763 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2765 AOP_TYPE(left), AOP_TYPE(right));
2766 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2768 AOP_SIZE(left), AOP_SIZE(right));
2771 /* if left is a literal & right is not ||
2772 if left needs acc & right does not */
2773 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2774 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
2775 operand *tmp = right ;
2780 /* if result = right then exchange them */
2781 if(sameRegs(AOP(result),AOP(right))){
2782 operand *tmp = right ;
2787 /* if right is bit then exchange them */
2788 if (AOP_TYPE(right) == AOP_CRY &&
2789 AOP_TYPE(left) != AOP_CRY){
2790 operand *tmp = right ;
2794 if(AOP_TYPE(right) == AOP_LIT)
2795 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2797 size = AOP_SIZE(result);
2801 if (AOP_TYPE(left) == AOP_CRY){
2802 if(AOP_TYPE(right) == AOP_LIT){
2803 // c = bit & literal;
2805 // lit>>1 != 0 => result = 1
2806 if(AOP_TYPE(result) == AOP_CRY){
2808 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
2810 continueIfTrue(ifx);
2813 emitcode("setb","c");
2817 // lit == 0, result = left
2818 if(size && sameRegs(AOP(result),AOP(left)))
2820 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2822 // lit == 1, result = not(left)
2823 if(size && sameRegs(AOP(result),AOP(left))){
2824 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
2827 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2828 emitcode("cpl","c");
2835 symbol *tlbl = newiTempLabel(NULL);
2836 if (AOP_TYPE(right) == AOP_CRY){
2838 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
2841 int sizer = AOP_SIZE(right);
2843 // if val>>1 != 0, result = 1
2844 emitcode("setb","c");
2846 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
2848 // test the msb of the lsb
2849 emitcode("anl","a,#0xfe");
2850 emitcode("jnz","%05d$",tlbl->key+100);
2854 emitcode("rrc","a");
2856 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
2857 emitcode("cpl","c");
2858 emitcode("","%05d$:",(tlbl->key+100));
2865 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
2866 genIfxJump(ifx, "c");
2870 if(sameRegs(AOP(result),AOP(left))){
2871 /* if left is same as result */
2872 for(;size--; offset++) {
2873 if(AOP_TYPE(right) == AOP_LIT){
2874 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2877 if (IS_AOP_PREG(left)) {
2878 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2879 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
2880 aopPut(AOP(result),"a",offset);
2882 emitcode("xrl","%s,%s",
2883 aopGet(AOP(left),offset,FALSE,TRUE),
2884 aopGet(AOP(right),offset,FALSE,FALSE));
2886 if (AOP_TYPE(left) == AOP_ACC)
2887 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
2889 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2890 if (IS_AOP_PREG(left)) {
2891 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
2892 aopPut(AOP(result),"a",offset);
2894 emitcode("xrl","%s,a",
2895 aopGet(AOP(left),offset,FALSE,TRUE));
2900 // left & result in different registers
2901 if(AOP_TYPE(result) == AOP_CRY){
2903 // if(size), result in bit
2904 // if(!size && ifx), conditional oper: if(left ^ right)
2905 symbol *tlbl = newiTempLabel(NULL);
2906 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
2908 emitcode("setb","c");
2910 if((AOP_TYPE(right) == AOP_LIT) &&
2911 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
2912 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
2914 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2915 emitcode("xrl","a,%s",
2916 aopGet(AOP(left),offset,FALSE,FALSE));
2918 emitcode("jnz","%05d$",tlbl->key+100);
2923 emitcode("","%05d$:",tlbl->key+100);
2926 jmpTrueOrFalse(ifx, tlbl);
2927 } else for(;(size--);offset++){
2929 // result = left & right
2930 if(AOP_TYPE(right) == AOP_LIT){
2931 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2933 aopGet(AOP(left),offset,FALSE,FALSE),
2938 // faster than result <- left, anl result,right
2939 // and better if result is SFR
2940 if (AOP_TYPE(left) == AOP_ACC)
2941 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
2943 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
2944 emitcode("xrl","a,%s",
2945 aopGet(AOP(left),offset,FALSE,TRUE));
2947 aopPut(AOP(result),"a",offset);
2952 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2953 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2954 freeAsmop(result,NULL,ic,TRUE);
2957 /*-----------------------------------------------------------------*/
2958 /* genInline - write the inline code out */
2959 /*-----------------------------------------------------------------*/
2960 static void genInline (iCode *ic)
2962 char buffer[MAX_INLINEASM];
2966 _G.inLine += (!options.asmpeep);
2967 strcpy(buffer,IC_INLINE(ic));
2969 /* emit each line as a code */
2988 /* emitcode("",buffer); */
2989 _G.inLine -= (!options.asmpeep);
2992 /*-----------------------------------------------------------------*/
2993 /* genRRC - rotate right with carry */
2994 /*-----------------------------------------------------------------*/
2995 static void genRRC (iCode *ic)
2997 operand *left , *result ;
2998 int size, offset = 0;
3001 /* rotate right with carry */
3003 result=IC_RESULT(ic);
3004 aopOp (left,ic,FALSE);
3005 aopOp (result,ic,FALSE);
3007 /* move it to the result */
3008 size = AOP_SIZE(result);
3012 l = aopGet(AOP(left),offset,FALSE,FALSE);
3014 emitcode("rrc","a");
3015 if (AOP_SIZE(result) > 1)
3016 aopPut(AOP(result),"a",offset--);
3018 /* now we need to put the carry into the
3019 highest order byte of the result */
3020 if (AOP_SIZE(result) > 1) {
3021 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
3024 emitcode("mov","acc.7,c");
3025 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
3026 freeAsmop(left,NULL,ic,TRUE);
3027 freeAsmop(result,NULL,ic,TRUE);
3030 /*-----------------------------------------------------------------*/
3031 /* genRLC - generate code for rotate left with carry */
3032 /*-----------------------------------------------------------------*/
3033 static void genRLC (iCode *ic)
3035 operand *left , *result ;
3036 int size, offset = 0;
3039 /* rotate right with carry */
3041 result=IC_RESULT(ic);
3042 aopOp (left,ic,FALSE);
3043 aopOp (result,ic,FALSE);
3045 /* move it to the result */
3046 size = AOP_SIZE(result);
3049 l = aopGet(AOP(left),offset,FALSE,FALSE);
3051 emitcode("add","a,acc");
3052 if (AOP_SIZE(result) > 1)
3053 aopPut(AOP(result),"a",offset++);
3055 l = aopGet(AOP(left),offset,FALSE,FALSE);
3057 emitcode("rlc","a");
3058 if (AOP_SIZE(result) > 1)
3059 aopPut(AOP(result),"a",offset++);
3062 /* now we need to put the carry into the
3063 highest order byte of the result */
3064 if (AOP_SIZE(result) > 1) {
3065 l = aopGet(AOP(result),0,FALSE,FALSE);
3068 emitcode("mov","acc.0,c");
3069 aopPut(AOP(result),"a",0);
3070 freeAsmop(left,NULL,ic,TRUE);
3071 freeAsmop(result,NULL,ic,TRUE);
3074 /*-----------------------------------------------------------------*/
3075 /* genGetHbit - generates code get highest order bit */
3076 /*-----------------------------------------------------------------*/
3077 static void genGetHbit (iCode *ic)
3079 operand *left, *result;
3081 result=IC_RESULT(ic);
3082 aopOp (left,ic,FALSE);
3083 aopOp (result,ic,FALSE);
3085 /* get the highest order byte into a */
3086 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
3087 if(AOP_TYPE(result) == AOP_CRY){
3088 emitcode("rlc","a");
3093 emitcode("anl","a,#0x01");
3098 freeAsmop(left,NULL,ic,TRUE);
3099 freeAsmop(result,NULL,ic,TRUE);
3102 /*-----------------------------------------------------------------*/
3103 /* AccRol - rotate left accumulator by known count */
3104 /*-----------------------------------------------------------------*/
3105 static void AccRol (int shCount)
3107 shCount &= 0x0007; // shCount : 0..7
3119 emitcode("swap","a");
3123 emitcode("swap","a");
3126 emitcode("swap","a");
3139 /*-----------------------------------------------------------------*/
3140 /* AccLsh - left shift accumulator by known count */
3141 /*-----------------------------------------------------------------*/
3142 static void AccLsh (int shCount)
3146 emitcode("add","a,acc");
3149 emitcode("add","a,acc");
3150 emitcode("add","a,acc");
3152 /* rotate left accumulator */
3154 /* and kill the lower order bits */
3155 emitcode("anl","a,#0x%02x", SLMask[shCount]);
3160 /*-----------------------------------------------------------------*/
3161 /* AccRsh - right shift accumulator by known count */
3162 /*-----------------------------------------------------------------*/
3163 static void AccRsh (int shCount)
3168 emitcode("rrc","a");
3170 /* rotate right accumulator */
3171 AccRol(8 - shCount);
3172 /* and kill the higher order bits */
3173 emitcode("anl","a,#0x%02x", SRMask[shCount]);
3178 /*-----------------------------------------------------------------*/
3179 /* AccSRsh - signed right shift accumulator by known count */
3180 /*-----------------------------------------------------------------*/
3181 static void AccSRsh (int shCount)
3186 emitcode("mov","c,acc.7");
3187 emitcode("rrc","a");
3188 } else if(shCount == 2){
3189 emitcode("mov","c,acc.7");
3190 emitcode("rrc","a");
3191 emitcode("mov","c,acc.7");
3192 emitcode("rrc","a");
3194 tlbl = newiTempLabel(NULL);
3195 /* rotate right accumulator */
3196 AccRol(8 - shCount);
3197 /* and kill the higher order bits */
3198 emitcode("anl","a,#0x%02x", SRMask[shCount]);
3199 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
3200 emitcode("orl","a,#0x%02x",
3201 (unsigned char)~SRMask[shCount]);
3202 emitcode("","%05d$:",tlbl->key+100);
3207 /*-----------------------------------------------------------------*/
3208 /* shiftR1Left2Result - shift right one byte from left to result */
3209 /*-----------------------------------------------------------------*/
3210 static void shiftR1Left2Result (operand *left, int offl,
3211 operand *result, int offr,
3212 int shCount, int sign)
3214 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
3215 /* shift right accumulator */
3220 aopPut(AOP(result),"a",offr);
3223 /*-----------------------------------------------------------------*/
3224 /* shiftL1Left2Result - shift left one byte from left to result */
3225 /*-----------------------------------------------------------------*/
3226 static void shiftL1Left2Result (operand *left, int offl,
3227 operand *result, int offr, int shCount)
3230 l = aopGet(AOP(left),offl,FALSE,FALSE);
3232 /* shift left accumulator */
3234 aopPut(AOP(result),"a",offr);
3237 /*-----------------------------------------------------------------*/
3238 /* movLeft2Result - move byte from left to result */
3239 /*-----------------------------------------------------------------*/
3240 static void movLeft2Result (operand *left, int offl,
3241 operand *result, int offr, int sign)
3244 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
3245 l = aopGet(AOP(left),offl,FALSE,FALSE);
3247 if (*l == '@' && (IS_AOP_PREG(result))) {
3248 emitcode("mov","a,%s",l);
3249 aopPut(AOP(result),"a",offr);
3252 aopPut(AOP(result),l,offr);
3254 /* MSB sign in acc.7 ! */
3255 if(getDataSize(left) == offl+1){
3256 emitcode("mov","a,%s",l);
3257 aopPut(AOP(result),"a",offr);
3264 /*-----------------------------------------------------------------*/
3265 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
3266 /*-----------------------------------------------------------------*/
3267 static void AccAXRrl1 (char *x)
3269 emitcode("rrc","a");
3270 emitcode("xch","a,%s", x);
3271 emitcode("rrc","a");
3272 emitcode("xch","a,%s", x);
3275 /*-----------------------------------------------------------------*/
3276 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
3277 /*-----------------------------------------------------------------*/
3278 static void AccAXLrl1 (char *x)
3280 emitcode("xch","a,%s",x);
3281 emitcode("rlc","a");
3282 emitcode("xch","a,%s",x);
3283 emitcode("rlc","a");
3286 /*-----------------------------------------------------------------*/
3287 /* AccAXLsh1 - left shift a:x<-0 by 1 */
3288 /*-----------------------------------------------------------------*/
3289 static void AccAXLsh1 (char *x)
3291 emitcode("xch","a,%s",x);
3292 emitcode("add","a,acc");
3293 emitcode("xch","a,%s",x);
3294 emitcode("rlc","a");
3297 /*-----------------------------------------------------------------*/
3298 /* AccAXLsh - left shift a:x by known count (0..7) */
3299 /*-----------------------------------------------------------------*/
3300 static void AccAXLsh (char *x, int shCount)
3314 case 5 : // AAAAABBB:CCCCCDDD
3315 AccRol(shCount); // BBBAAAAA:CCCCCDDD
3316 emitcode("anl","a,#0x%02x",
3317 SLMask[shCount]); // BBB00000:CCCCCDDD
3318 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
3319 AccRol(shCount); // DDDCCCCC:BBB00000
3320 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
3321 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
3322 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
3323 emitcode("anl","a,#0x%02x",
3324 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
3325 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
3326 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
3328 case 6 : // AAAAAABB:CCCCCCDD
3329 emitcode("anl","a,#0x%02x",
3330 SRMask[shCount]); // 000000BB:CCCCCCDD
3331 emitcode("mov","c,acc.0"); // c = B
3332 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
3333 AccAXRrl1(x); // BCCCCCCD:D000000B
3334 AccAXRrl1(x); // BBCCCCCC:DD000000
3336 case 7 : // a:x <<= 7
3337 emitcode("anl","a,#0x%02x",
3338 SRMask[shCount]); // 0000000B:CCCCCCCD
3339 emitcode("mov","c,acc.0"); // c = B
3340 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
3341 AccAXRrl1(x); // BCCCCCCC:D0000000
3348 /*-----------------------------------------------------------------*/
3349 /* AccAXRsh - right shift a:x known count (0..7) */
3350 /*-----------------------------------------------------------------*/
3351 static void AccAXRsh (char *x, int shCount)
3358 AccAXRrl1(x); // 0->a:x
3362 AccAXRrl1(x); // 0->a:x
3364 AccAXRrl1(x); // 0->a:x
3368 case 5 : // AAAAABBB:CCCCCDDD = a:x
3369 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
3370 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
3371 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
3372 emitcode("anl","a,#0x%02x",
3373 SRMask[shCount]); // 000CCCCC:BBBAAAAA
3374 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
3375 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
3376 emitcode("anl","a,#0x%02x",
3377 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
3378 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
3379 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
3380 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
3382 case 6 : // AABBBBBB:CCDDDDDD
3383 emitcode("mov","c,acc.7");
3384 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
3385 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
3386 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
3387 emitcode("anl","a,#0x%02x",
3388 SRMask[shCount]); // 000000AA:BBBBBBCC
3390 case 7 : // ABBBBBBB:CDDDDDDD
3391 emitcode("mov","c,acc.7"); // c = A
3392 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
3393 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
3394 emitcode("anl","a,#0x%02x",
3395 SRMask[shCount]); // 0000000A:BBBBBBBC
3402 /*-----------------------------------------------------------------*/
3403 /* AccAXRshS - right shift signed a:x known count (0..7) */
3404 /*-----------------------------------------------------------------*/
3405 static void AccAXRshS (char *x, int shCount)
3412 emitcode("mov","c,acc.7");
3413 AccAXRrl1(x); // s->a:x
3416 emitcode("mov","c,acc.7");
3417 AccAXRrl1(x); // s->a:x
3418 emitcode("mov","c,acc.7");
3419 AccAXRrl1(x); // s->a:x
3423 case 5 : // AAAAABBB:CCCCCDDD = a:x
3424 tlbl = newiTempLabel(NULL);
3425 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
3426 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
3427 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
3428 emitcode("anl","a,#0x%02x",
3429 SRMask[shCount]); // 000CCCCC:BBBAAAAA
3430 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
3431 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
3432 emitcode("anl","a,#0x%02x",
3433 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
3434 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
3435 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
3436 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
3437 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
3438 emitcode("orl","a,#0x%02x",
3439 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
3440 emitcode("","%05d$:",tlbl->key+100);
3441 break; // SSSSAAAA:BBBCCCCC
3442 case 6 : // AABBBBBB:CCDDDDDD
3443 tlbl = newiTempLabel(NULL);
3444 emitcode("mov","c,acc.7");
3445 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
3446 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
3447 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
3448 emitcode("anl","a,#0x%02x",
3449 SRMask[shCount]); // 000000AA:BBBBBBCC
3450 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
3451 emitcode("orl","a,#0x%02x",
3452 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
3453 emitcode("","%05d$:",tlbl->key+100);
3455 case 7 : // ABBBBBBB:CDDDDDDD
3456 tlbl = newiTempLabel(NULL);
3457 emitcode("mov","c,acc.7"); // c = A
3458 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
3459 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
3460 emitcode("anl","a,#0x%02x",
3461 SRMask[shCount]); // 0000000A:BBBBBBBC
3462 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
3463 emitcode("orl","a,#0x%02x",
3464 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
3465 emitcode("","%05d$:",tlbl->key+100);
3472 /*-----------------------------------------------------------------*/
3473 /* shiftL2Left2Result - shift left two bytes from left to result */
3474 /*-----------------------------------------------------------------*/
3475 static void shiftL2Left2Result (operand *left, int offl,
3476 operand *result, int offr, int shCount)
3478 if(sameRegs(AOP(result), AOP(left)) &&
3479 ((offl + MSB16) == offr)){
3480 /* don't crash result[offr] */
3481 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
3482 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
3484 movLeft2Result(left,offl, result, offr, 0);
3485 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
3487 /* ax << shCount (x = lsb(result))*/
3488 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
3489 aopPut(AOP(result),"a",offr+MSB16);
3493 /*-----------------------------------------------------------------*/
3494 /* shiftR2Left2Result - shift right two bytes from left to result */
3495 /*-----------------------------------------------------------------*/
3496 static void shiftR2Left2Result (operand *left, int offl,
3497 operand *result, int offr,
3498 int shCount, int sign)
3500 if(sameRegs(AOP(result), AOP(left)) &&
3501 ((offl + MSB16) == offr)){
3502 /* don't crash result[offr] */
3503 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
3504 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
3506 movLeft2Result(left,offl, result, offr, 0);
3507 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
3509 /* a:x >> shCount (x = lsb(result))*/
3511 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
3513 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
3514 if(getDataSize(result) > 1)
3515 aopPut(AOP(result),"a",offr+MSB16);
3518 /*-----------------------------------------------------------------*/
3519 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
3520 /*-----------------------------------------------------------------*/
3521 static void shiftLLeftOrResult (operand *left, int offl,
3522 operand *result, int offr, int shCount)
3524 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
3525 /* shift left accumulator */
3527 /* or with result */
3528 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
3529 /* back to result */
3530 aopPut(AOP(result),"a",offr);
3533 /*-----------------------------------------------------------------*/
3534 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
3535 /*-----------------------------------------------------------------*/
3536 static void shiftRLeftOrResult (operand *left, int offl,
3537 operand *result, int offr, int shCount)
3539 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
3540 /* shift right accumulator */
3542 /* or with result */
3543 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
3544 /* back to result */
3545 aopPut(AOP(result),"a",offr);
3548 /*-----------------------------------------------------------------*/
3549 /* genlshOne - left shift a one byte quantity by known count */
3550 /*-----------------------------------------------------------------*/
3551 static void genlshOne (operand *result, operand *left, int shCount)
3553 shiftL1Left2Result(left, LSB, result, LSB, shCount);
3556 /*-----------------------------------------------------------------*/
3557 /* genlshTwo - left shift two bytes by known amount != 0 */
3558 /*-----------------------------------------------------------------*/
3559 static void genlshTwo (operand *result,operand *left, int shCount)
3563 size = getDataSize(result);
3565 /* if shCount >= 8 */
3571 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
3573 movLeft2Result(left, LSB, result, MSB16, 0);
3575 aopPut(AOP(result),zero,LSB);
3578 /* 1 <= shCount <= 7 */
3581 shiftL1Left2Result(left, LSB, result, LSB, shCount);
3583 shiftL2Left2Result(left, LSB, result, LSB, shCount);
3587 /*-----------------------------------------------------------------*/
3588 /* shiftLLong - shift left one long from left to result */
3589 /* offl = LSB or MSB16 */
3590 /*-----------------------------------------------------------------*/
3591 static void shiftLLong (operand *left, operand *result, int offr )
3594 int size = AOP_SIZE(result);
3596 if(size >= LSB+offr){
3597 l = aopGet(AOP(left),LSB,FALSE,FALSE);
3599 emitcode("add","a,acc");
3600 if (sameRegs(AOP(left),AOP(result)) &&
3601 size >= MSB16+offr && offr != LSB )
3602 emitcode("xch","a,%s",
3603 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
3605 aopPut(AOP(result),"a",LSB+offr);
3608 if(size >= MSB16+offr){
3609 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
3610 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
3613 emitcode("rlc","a");
3614 if (sameRegs(AOP(left),AOP(result)) &&
3615 size >= MSB24+offr && offr != LSB)
3616 emitcode("xch","a,%s",
3617 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
3619 aopPut(AOP(result),"a",MSB16+offr);
3622 if(size >= MSB24+offr){
3623 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
3624 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
3627 emitcode("rlc","a");
3628 if (sameRegs(AOP(left),AOP(result)) &&
3629 size >= MSB32+offr && offr != LSB )
3630 emitcode("xch","a,%s",
3631 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
3633 aopPut(AOP(result),"a",MSB24+offr);
3636 if(size > MSB32+offr){
3637 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
3638 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
3641 emitcode("rlc","a");
3642 aopPut(AOP(result),"a",MSB32+offr);
3645 aopPut(AOP(result),zero,LSB);
3648 /*-----------------------------------------------------------------*/
3649 /* genlshFour - shift four byte by a known amount != 0 */
3650 /*-----------------------------------------------------------------*/
3651 static void genlshFour (operand *result, operand *left, int shCount)
3655 size = AOP_SIZE(result);
3657 /* if shifting more that 3 bytes */
3658 if (shCount >= 24 ) {
3661 /* lowest order of left goes to the highest
3662 order of the destination */
3663 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
3665 movLeft2Result(left, LSB, result, MSB32, 0);
3666 aopPut(AOP(result),zero,LSB);
3667 aopPut(AOP(result),zero,MSB16);
3668 aopPut(AOP(result),zero,MSB32);
3672 /* more than two bytes */
3673 else if ( shCount >= 16 ) {
3674 /* lower order two bytes goes to higher order two bytes */
3676 /* if some more remaining */
3678 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
3680 movLeft2Result(left, MSB16, result, MSB32, 0);
3681 movLeft2Result(left, LSB, result, MSB24, 0);
3683 aopPut(AOP(result),zero,MSB16);
3684 aopPut(AOP(result),zero,LSB);
3688 /* if more than 1 byte */
3689 else if ( shCount >= 8 ) {
3690 /* lower order three bytes goes to higher order three bytes */
3694 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
3696 movLeft2Result(left, LSB, result, MSB16, 0);
3698 else{ /* size = 4 */
3700 movLeft2Result(left, MSB24, result, MSB32, 0);
3701 movLeft2Result(left, MSB16, result, MSB24, 0);
3702 movLeft2Result(left, LSB, result, MSB16, 0);
3703 aopPut(AOP(result),zero,LSB);
3705 else if(shCount == 1)
3706 shiftLLong(left, result, MSB16);
3708 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
3709 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
3710 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
3711 aopPut(AOP(result),zero,LSB);
3716 /* 1 <= shCount <= 7 */
3717 else if(shCount <= 2){
3718 shiftLLong(left, result, LSB);
3720 shiftLLong(result, result, LSB);
3722 /* 3 <= shCount <= 7, optimize */
3724 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
3725 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
3726 shiftL2Left2Result(left, LSB, result, LSB, shCount);
3730 /*-----------------------------------------------------------------*/
3731 /* genLeftShiftLiteral - left shifting by known count */
3732 /*-----------------------------------------------------------------*/
3733 static void genLeftShiftLiteral (operand *left,
3738 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3741 freeAsmop(right,NULL,ic,TRUE);
3743 aopOp(left,ic,FALSE);
3744 aopOp(result,ic,FALSE);
3746 size = getSize(operandType(result));
3749 emitcode("; shift left ","result %d, left %d",size,
3753 /* I suppose that the left size >= result size */
3756 movLeft2Result(left, size, result, size, 0);
3760 else if(shCount >= (size * 8))
3762 aopPut(AOP(result),zero,size);
3766 genlshOne (result,left,shCount);
3771 genlshTwo (result,left,shCount);
3775 genlshFour (result,left,shCount);
3779 freeAsmop(left,NULL,ic,TRUE);
3780 freeAsmop(result,NULL,ic,TRUE);
3783 /*-----------------------------------------------------------------*/
3784 /* genLeftShift - generates code for left shifting */
3785 /*-----------------------------------------------------------------*/
3786 static void genLeftShift (iCode *ic)
3788 operand *left,*right, *result;
3791 symbol *tlbl , *tlbl1;
3793 right = IC_RIGHT(ic);
3795 result = IC_RESULT(ic);
3797 aopOp(right,ic,FALSE);
3799 /* if the shift count is known then do it
3800 as efficiently as possible */
3801 if (AOP_TYPE(right) == AOP_LIT) {
3802 genLeftShiftLiteral (left,right,result,ic);
3806 /* shift count is unknown then we have to form
3807 a loop get the loop count in B : Note: we take
3808 only the lower order byte since shifting
3809 more that 32 bits make no sense anyway, ( the
3810 largest size of an object can be only 32 bits ) */
3812 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3813 emitcode("inc","b");
3814 freeAsmop (right,NULL,ic,TRUE);
3815 aopOp(left,ic,FALSE);
3816 aopOp(result,ic,FALSE);
3818 /* now move the left to the result if they are not the
3820 if (!sameRegs(AOP(left),AOP(result)) &&
3821 AOP_SIZE(result) > 1) {
3823 size = AOP_SIZE(result);
3826 l = aopGet(AOP(left),offset,FALSE,TRUE);
3827 if (*l == '@' && (IS_AOP_PREG(result))) {
3829 emitcode("mov","a,%s",l);
3830 aopPut(AOP(result),"a",offset);
3832 aopPut(AOP(result),l,offset);
3837 tlbl = newiTempLabel(NULL);
3838 size = AOP_SIZE(result);
3840 tlbl1 = newiTempLabel(NULL);
3842 /* if it is only one byte then */
3844 symbol *tlbl1 = newiTempLabel(NULL);
3846 l = aopGet(AOP(left),0,FALSE,FALSE);
3848 emitcode("sjmp","%05d$",tlbl1->key+100);
3849 emitcode("","%05d$:",tlbl->key+100);
3850 emitcode("add","a,acc");
3851 emitcode("","%05d$:",tlbl1->key+100);
3852 emitcode("djnz","b,%05d$",tlbl->key+100);
3853 aopPut(AOP(result),"a",0);
3857 reAdjustPreg(AOP(result));
3859 emitcode("sjmp","%05d$",tlbl1->key+100);
3860 emitcode("","%05d$:",tlbl->key+100);
3861 l = aopGet(AOP(result),offset,FALSE,FALSE);
3863 emitcode("add","a,acc");
3864 aopPut(AOP(result),"a",offset++);
3866 l = aopGet(AOP(result),offset,FALSE,FALSE);
3868 emitcode("rlc","a");
3869 aopPut(AOP(result),"a",offset++);
3871 reAdjustPreg(AOP(result));
3873 emitcode("","%05d$:",tlbl1->key+100);
3874 emitcode("djnz","b,%05d$",tlbl->key+100);
3876 freeAsmop(left,NULL,ic,TRUE);
3877 freeAsmop(result,NULL,ic,TRUE);
3880 /*-----------------------------------------------------------------*/
3881 /* genrshOne - right shift a one byte quantity by known count */
3882 /*-----------------------------------------------------------------*/
3883 static void genrshOne (operand *result, operand *left,
3884 int shCount, int sign)
3886 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
3889 /*-----------------------------------------------------------------*/
3890 /* genrshTwo - right shift two bytes by known amount != 0 */
3891 /*-----------------------------------------------------------------*/
3892 static void genrshTwo (operand *result,operand *left,
3893 int shCount, int sign)
3895 /* if shCount >= 8 */
3899 shiftR1Left2Result(left, MSB16, result, LSB,
3902 movLeft2Result(left, MSB16, result, LSB, sign);
3903 addSign(result, MSB16, sign);
3906 /* 1 <= shCount <= 7 */
3908 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
3911 /*-----------------------------------------------------------------*/
3912 /* shiftRLong - shift right one long from left to result */
3913 /* offl = LSB or MSB16 */
3914 /*-----------------------------------------------------------------*/
3915 static void shiftRLong (operand *left, int offl,
3916 operand *result, int sign)
3919 emitcode("clr","c");
3920 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
3922 emitcode("mov","c,acc.7");
3923 emitcode("rrc","a");
3924 aopPut(AOP(result),"a",MSB32-offl);
3926 /* add sign of "a" */
3927 addSign(result, MSB32, sign);
3929 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
3930 emitcode("rrc","a");
3931 aopPut(AOP(result),"a",MSB24-offl);
3933 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
3934 emitcode("rrc","a");
3935 aopPut(AOP(result),"a",MSB16-offl);
3938 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
3939 emitcode("rrc","a");
3940 aopPut(AOP(result),"a",LSB);
3944 /*-----------------------------------------------------------------*/
3945 /* genrshFour - shift four byte by a known amount != 0 */
3946 /*-----------------------------------------------------------------*/
3947 static void genrshFour (operand *result, operand *left,
3948 int shCount, int sign)
3950 /* if shifting more that 3 bytes */
3951 if(shCount >= 24 ) {
3954 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
3956 movLeft2Result(left, MSB32, result, LSB, sign);
3957 addSign(result, MSB16, sign);
3959 else if(shCount >= 16){
3962 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
3964 movLeft2Result(left, MSB24, result, LSB, 0);
3965 movLeft2Result(left, MSB32, result, MSB16, sign);
3967 addSign(result, MSB24, sign);
3969 else if(shCount >= 8){
3972 shiftRLong(left, MSB16, result, sign);
3973 else if(shCount == 0){
3974 movLeft2Result(left, MSB16, result, LSB, 0);
3975 movLeft2Result(left, MSB24, result, MSB16, 0);
3976 movLeft2Result(left, MSB32, result, MSB24, sign);
3977 addSign(result, MSB32, sign);
3980 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
3981 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
3982 /* the last shift is signed */
3983 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
3984 addSign(result, MSB32, sign);
3987 else{ /* 1 <= shCount <= 7 */
3989 shiftRLong(left, LSB, result, sign);
3991 shiftRLong(result, LSB, result, sign);
3994 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
3995 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
3996 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
4001 /*-----------------------------------------------------------------*/
4002 /* genRightShiftLiteral - right shifting by known count */
4003 /*-----------------------------------------------------------------*/
4004 static void genRightShiftLiteral (operand *left,
4010 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
4013 freeAsmop(right,NULL,ic,TRUE);
4015 aopOp(left,ic,FALSE);
4016 aopOp(result,ic,FALSE);
4019 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
4023 size = getDataSize(left);
4024 /* test the LEFT size !!! */
4026 /* I suppose that the left size >= result size */
4028 size = getDataSize(result);
4030 movLeft2Result(left, size, result, size, 0);
4033 else if(shCount >= (size * 8)){
4035 /* get sign in acc.7 */
4036 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
4037 addSign(result, LSB, sign);
4041 genrshOne (result,left,shCount,sign);
4045 genrshTwo (result,left,shCount,sign);
4049 genrshFour (result,left,shCount,sign);
4055 freeAsmop(left,NULL,ic,TRUE);
4056 freeAsmop(result,NULL,ic,TRUE);
4060 /*-----------------------------------------------------------------*/
4061 /* genSignedRightShift - right shift of signed number */
4062 /*-----------------------------------------------------------------*/
4063 static void genSignedRightShift (iCode *ic)
4065 operand *right, *left, *result;
4068 symbol *tlbl, *tlbl1 ;
4070 /* we do it the hard way put the shift count in b
4071 and loop thru preserving the sign */
4073 right = IC_RIGHT(ic);
4075 result = IC_RESULT(ic);
4077 aopOp(right,ic,FALSE);
4080 if ( AOP_TYPE(right) == AOP_LIT) {
4081 genRightShiftLiteral (left,right,result,ic,1);
4084 /* shift count is unknown then we have to form
4085 a loop get the loop count in B : Note: we take
4086 only the lower order byte since shifting
4087 more that 32 bits make no sense anyway, ( the
4088 largest size of an object can be only 32 bits ) */
4090 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
4091 emitcode("inc","b");
4092 freeAsmop (right,NULL,ic,TRUE);
4093 aopOp(left,ic,FALSE);
4094 aopOp(result,ic,FALSE);
4096 /* now move the left to the result if they are not the
4098 if (!sameRegs(AOP(left),AOP(result)) &&
4099 AOP_SIZE(result) > 1) {
4101 size = AOP_SIZE(result);
4104 l = aopGet(AOP(left),offset,FALSE,TRUE);
4105 if (*l == '@' && IS_AOP_PREG(result)) {
4107 emitcode("mov","a,%s",l);
4108 aopPut(AOP(result),"a",offset);
4110 aopPut(AOP(result),l,offset);
4115 /* mov the highest order bit to OVR */
4116 tlbl = newiTempLabel(NULL);
4117 tlbl1= newiTempLabel(NULL);
4119 size = AOP_SIZE(result);
4121 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
4122 emitcode("rlc","a");
4123 emitcode("mov","ov,c");
4124 /* if it is only one byte then */
4126 l = aopGet(AOP(left),0,FALSE,FALSE);
4128 emitcode("sjmp","%05d$",tlbl1->key+100);
4129 emitcode("","%05d$:",tlbl->key+100);
4130 emitcode("mov","c,ov");
4131 emitcode("rrc","a");
4132 emitcode("","%05d$:",tlbl1->key+100);
4133 emitcode("djnz","b,%05d$",tlbl->key+100);
4134 aopPut(AOP(result),"a",0);
4138 reAdjustPreg(AOP(result));
4139 emitcode("sjmp","%05d$",tlbl1->key+100);
4140 emitcode("","%05d$:",tlbl->key+100);
4141 emitcode("mov","c,ov");
4143 l = aopGet(AOP(result),offset,FALSE,FALSE);
4145 emitcode("rrc","a");
4146 aopPut(AOP(result),"a",offset--);
4148 reAdjustPreg(AOP(result));
4149 emitcode("","%05d$:",tlbl1->key+100);
4150 emitcode("djnz","b,%05d$",tlbl->key+100);
4153 freeAsmop(left,NULL,ic,TRUE);
4154 freeAsmop(result,NULL,ic,TRUE);
4157 /*-----------------------------------------------------------------*/
4158 /* genRightShift - generate code for right shifting */
4159 /*-----------------------------------------------------------------*/
4160 static void genRightShift (iCode *ic)
4162 operand *right, *left, *result;
4166 symbol *tlbl, *tlbl1 ;
4168 /* if signed then we do it the hard way preserve the
4169 sign bit moving it inwards */
4170 retype = getSpec(operandType(IC_RESULT(ic)));
4172 if (!SPEC_USIGN(retype)) {
4173 genSignedRightShift (ic);
4177 /* signed & unsigned types are treated the same : i.e. the
4178 signed is NOT propagated inwards : quoting from the
4179 ANSI - standard : "for E1 >> E2, is equivalent to division
4180 by 2**E2 if unsigned or if it has a non-negative value,
4181 otherwise the result is implementation defined ", MY definition
4182 is that the sign does not get propagated */
4184 right = IC_RIGHT(ic);
4186 result = IC_RESULT(ic);
4188 aopOp(right,ic,FALSE);
4190 /* if the shift count is known then do it
4191 as efficiently as possible */
4192 if (AOP_TYPE(right) == AOP_LIT) {
4193 genRightShiftLiteral (left,right,result,ic, 0);
4197 /* shift count is unknown then we have to form
4198 a loop get the loop count in B : Note: we take
4199 only the lower order byte since shifting
4200 more that 32 bits make no sense anyway, ( the
4201 largest size of an object can be only 32 bits ) */
4203 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
4204 emitcode("inc","b");
4205 freeAsmop (right,NULL,ic,TRUE);
4206 aopOp(left,ic,FALSE);
4207 aopOp(result,ic,FALSE);
4209 /* now move the left to the result if they are not the
4211 if (!sameRegs(AOP(left),AOP(result)) &&
4212 AOP_SIZE(result) > 1) {
4214 size = AOP_SIZE(result);
4217 l = aopGet(AOP(left),offset,FALSE,TRUE);
4218 if (*l == '@' && IS_AOP_PREG(result)) {
4220 emitcode("mov","a,%s",l);
4221 aopPut(AOP(result),"a",offset);
4223 aopPut(AOP(result),l,offset);
4228 tlbl = newiTempLabel(NULL);
4229 tlbl1= newiTempLabel(NULL);
4230 size = AOP_SIZE(result);
4233 /* if it is only one byte then */
4235 l = aopGet(AOP(left),0,FALSE,FALSE);
4237 emitcode("sjmp","%05d$",tlbl1->key+100);
4238 emitcode("","%05d$:",tlbl->key+100);
4240 emitcode("rrc","a");
4241 emitcode("","%05d$:",tlbl1->key+100);
4242 emitcode("djnz","b,%05d$",tlbl->key+100);
4243 aopPut(AOP(result),"a",0);
4247 reAdjustPreg(AOP(result));
4248 emitcode("sjmp","%05d$",tlbl1->key+100);
4249 emitcode("","%05d$:",tlbl->key+100);
4252 l = aopGet(AOP(result),offset,FALSE,FALSE);
4254 emitcode("rrc","a");
4255 aopPut(AOP(result),"a",offset--);
4257 reAdjustPreg(AOP(result));
4259 emitcode("","%05d$:",tlbl1->key+100);
4260 emitcode("djnz","b,%05d$",tlbl->key+100);
4263 freeAsmop(left,NULL,ic,TRUE);
4264 freeAsmop(result,NULL,ic,TRUE);
4267 /*-----------------------------------------------------------------*/
4268 /* genUnpackBits - generates code for unpacking bits */
4269 /*-----------------------------------------------------------------*/
4270 static void genUnpackBits (operand *result, char *rname, int ptype)
4277 etype = getSpec(operandType(result));
4279 /* read the first byte */
4284 emitcode("mov","a,@%s",rname);
4288 emitcode("movx","a,@%s",rname);
4292 emitcode("movx","a,@dptr");
4296 emitcode("clr","a");
4297 emitcode("movc","a","@a+dptr");
4301 emitcode("lcall","__gptrget");
4305 /* if we have bitdisplacement then it fits */
4306 /* into this byte completely or if length is */
4307 /* less than a byte */
4308 if ((shCnt = SPEC_BSTR(etype)) ||
4309 (SPEC_BLEN(etype) <= 8)) {
4311 /* shift right acc */
4314 emitcode("anl","a,#0x%02x",
4315 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
4316 aopPut(AOP(result),"a",offset);
4320 /* bit field did not fit in a byte */
4321 rlen = SPEC_BLEN(etype) - 8;
4322 aopPut(AOP(result),"a",offset++);
4329 emitcode("inc","%s",rname);
4330 emitcode("mov","a,@%s",rname);
4334 emitcode("inc","%s",rname);
4335 emitcode("movx","a,@%s",rname);
4339 emitcode("inc","dptr");
4340 emitcode("movx","a,@dptr");
4344 emitcode("clr","a");
4345 emitcode("inc","dptr");
4346 emitcode("movc","a","@a+dptr");
4350 emitcode("inc","dptr");
4351 emitcode("lcall","__gptrget");
4356 /* if we are done */
4360 aopPut(AOP(result),"a",offset++);
4365 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
4366 aopPut(AOP(result),"a",offset);
4373 /*-----------------------------------------------------------------*/
4374 /* genDataPointerGet - generates code when ptr offset is known */
4375 /*-----------------------------------------------------------------*/
4376 static void genDataPointerGet (operand *left,
4382 int size , offset = 0;
4383 aopOp(result,ic,TRUE);
4385 /* get the string representation of the name */
4386 l = aopGet(AOP(left),0,FALSE,TRUE);
4387 size = AOP_SIZE(result);
4390 sprintf(buffer,"(%s + %d)",l+1,offset);
4392 sprintf(buffer,"%s",l+1);
4393 aopPut(AOP(result),buffer,offset++);
4396 freeAsmop(left,NULL,ic,TRUE);
4397 freeAsmop(result,NULL,ic,TRUE);
4400 /*-----------------------------------------------------------------*/
4401 /* genNearPointerGet - emitcode for near pointer fetch */
4402 /*-----------------------------------------------------------------*/
4403 static void genNearPointerGet (operand *left,
4410 link *rtype, *retype;
4411 link *ltype = operandType(left);
4414 rtype = operandType(result);
4415 retype= getSpec(rtype);
4417 aopOp(left,ic,FALSE);
4419 /* if left is rematerialisable and
4420 result is not bit variable type and
4421 the left is pointer to data space i.e
4422 lower 128 bytes of space */
4423 if (AOP_TYPE(left) == AOP_IMMD &&
4424 !IS_BITVAR(retype) &&
4425 DCL_TYPE(ltype) == POINTER) {
4426 genDataPointerGet (left,result,ic);
4430 /* if the value is already in a pointer register
4431 then don't need anything more */
4432 if (!AOP_INPREG(AOP(left))) {
4433 /* otherwise get a free pointer register */
4435 preg = getFreePtr(ic,&aop,FALSE);
4436 emitcode("mov","%s,%s",
4438 aopGet(AOP(left),0,FALSE,TRUE));
4439 rname = preg->name ;
4441 rname = aopGet(AOP(left),0,FALSE,FALSE);
4443 freeAsmop(left,NULL,ic,TRUE);
4444 aopOp (result,ic,FALSE);
4446 /* if bitfield then unpack the bits */
4447 if (IS_BITVAR(retype))
4448 genUnpackBits (result,rname,POINTER);
4450 /* we have can just get the values */
4451 int size = AOP_SIZE(result);
4455 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
4457 emitcode("mov","a,@%s",rname);
4458 aopPut(AOP(result),"a",offset);
4460 sprintf(buffer,"@%s",rname);
4461 aopPut(AOP(result),buffer,offset);
4465 emitcode("inc","%s",rname);
4469 /* now some housekeeping stuff */
4471 /* we had to allocate for this iCode */
4472 freeAsmop(NULL,aop,ic,TRUE);
4474 /* we did not allocate which means left
4475 already in a pointer register, then
4476 if size > 0 && this could be used again
4477 we have to point it back to where it
4479 if (AOP_SIZE(result) > 1 &&
4480 !OP_SYMBOL(left)->remat &&
4481 ( OP_SYMBOL(left)->liveTo > ic->seq ||
4483 int size = AOP_SIZE(result) - 1;
4485 emitcode("dec","%s",rname);
4490 freeAsmop(result,NULL,ic,TRUE);
4494 /*-----------------------------------------------------------------*/
4495 /* genPagedPointerGet - emitcode for paged pointer fetch */
4496 /*-----------------------------------------------------------------*/
4497 static void genPagedPointerGet (operand *left,
4504 link *rtype, *retype;
4506 rtype = operandType(result);
4507 retype= getSpec(rtype);
4509 aopOp(left,ic,FALSE);
4511 /* if the value is already in a pointer register
4512 then don't need anything more */
4513 if (!AOP_INPREG(AOP(left))) {
4514 /* otherwise get a free pointer register */
4516 preg = getFreePtr(ic,&aop,FALSE);
4517 emitcode("mov","%s,%s",
4519 aopGet(AOP(left),0,FALSE,TRUE));
4520 rname = preg->name ;
4522 rname = aopGet(AOP(left),0,FALSE,FALSE);
4524 freeAsmop(left,NULL,ic,TRUE);
4525 aopOp (result,ic,FALSE);
4527 /* if bitfield then unpack the bits */
4528 if (IS_BITVAR(retype))
4529 genUnpackBits (result,rname,PPOINTER);
4531 /* we have can just get the values */
4532 int size = AOP_SIZE(result);
4537 emitcode("movx","a,@%s",rname);
4538 aopPut(AOP(result),"a",offset);
4543 emitcode("inc","%s",rname);
4547 /* now some housekeeping stuff */
4549 /* we had to allocate for this iCode */
4550 freeAsmop(NULL,aop,ic,TRUE);
4552 /* we did not allocate which means left
4553 already in a pointer register, then
4554 if size > 0 && this could be used again
4555 we have to point it back to where it
4557 if (AOP_SIZE(result) > 1 &&
4558 !OP_SYMBOL(left)->remat &&
4559 ( OP_SYMBOL(left)->liveTo > ic->seq ||
4561 int size = AOP_SIZE(result) - 1;
4563 emitcode("dec","%s",rname);
4568 freeAsmop(result,NULL,ic,TRUE);
4573 /*-----------------------------------------------------------------*/
4574 /* genFarPointerGet - gget value from far space */
4575 /*-----------------------------------------------------------------*/
4576 static void genFarPointerGet (operand *left,
4577 operand *result, iCode *ic)
4580 link *retype = getSpec(operandType(result));
4582 aopOp(left,ic,FALSE);
4584 /* if the operand is already in dptr
4585 then we do nothing else we move the value to dptr */
4586 if (AOP_TYPE(left) != AOP_STR) {
4587 /* if this is remateriazable */
4588 if (AOP_TYPE(left) == AOP_IMMD)
4589 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
4590 else { /* we need to get it byte by byte */
4591 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
4592 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
4593 if (options.model == MODEL_FLAT24)
4595 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
4599 /* so dptr know contains the address */
4600 freeAsmop(left,NULL,ic,TRUE);
4601 aopOp(result,ic,FALSE);
4603 /* if bit then unpack */
4604 if (IS_BITVAR(retype))
4605 genUnpackBits(result,"dptr",FPOINTER);
4607 size = AOP_SIZE(result);
4611 emitcode("movx","a,@dptr");
4612 aopPut(AOP(result),"a",offset++);
4614 emitcode("inc","dptr");
4618 freeAsmop(result,NULL,ic,TRUE);
4621 /*-----------------------------------------------------------------*/
4622 /* emitcodePointerGet - gget value from code space */
4623 /*-----------------------------------------------------------------*/
4624 static void emitcodePointerGet (operand *left,
4625 operand *result, iCode *ic)
4628 link *retype = getSpec(operandType(result));
4630 aopOp(left,ic,FALSE);
4632 /* if the operand is already in dptr
4633 then we do nothing else we move the value to dptr */
4634 if (AOP_TYPE(left) != AOP_STR) {
4635 /* if this is remateriazable */
4636 if (AOP_TYPE(left) == AOP_IMMD)
4637 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
4638 else { /* we need to get it byte by byte */
4639 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
4640 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
4641 if (options.model == MODEL_FLAT24)
4643 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
4647 /* so dptr know contains the address */
4648 freeAsmop(left,NULL,ic,TRUE);
4649 aopOp(result,ic,FALSE);
4651 /* if bit then unpack */
4652 if (IS_BITVAR(retype))
4653 genUnpackBits(result,"dptr",CPOINTER);
4655 size = AOP_SIZE(result);
4659 emitcode("clr","a");
4660 emitcode("movc","a,@a+dptr");
4661 aopPut(AOP(result),"a",offset++);
4663 emitcode("inc","dptr");
4667 freeAsmop(result,NULL,ic,TRUE);
4670 /*-----------------------------------------------------------------*/
4671 /* genGenPointerGet - gget value from generic pointer space */
4672 /*-----------------------------------------------------------------*/
4673 static void genGenPointerGet (operand *left,
4674 operand *result, iCode *ic)
4677 link *retype = getSpec(operandType(result));
4679 aopOp(left,ic,FALSE);
4681 /* if the operand is already in dptr
4682 then we do nothing else we move the value to dptr */
4683 if (AOP_TYPE(left) != AOP_STR) {
4684 /* if this is remateriazable */
4685 if (AOP_TYPE(left) == AOP_IMMD) {
4686 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
4687 emitcode("mov","b,#%d",pointerCode(retype));
4689 else { /* we need to get it byte by byte */
4690 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
4691 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
4692 if (options.model == MODEL_FLAT24)
4694 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
4695 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
4699 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
4703 /* so dptr know contains the address */
4704 freeAsmop(left,NULL,ic,TRUE);
4705 aopOp(result,ic,FALSE);
4707 /* if bit then unpack */
4708 if (IS_BITVAR(retype))
4709 genUnpackBits(result,"dptr",GPOINTER);
4711 size = AOP_SIZE(result);
4715 emitcode("lcall","__gptrget");
4716 aopPut(AOP(result),"a",offset++);
4718 emitcode("inc","dptr");
4722 freeAsmop(result,NULL,ic,TRUE);
4725 /*-----------------------------------------------------------------*/
4726 /* genPointerGet - generate code for pointer get */
4727 /*-----------------------------------------------------------------*/
4728 static void genPointerGet (iCode *ic)
4730 operand *left, *result ;
4735 result = IC_RESULT(ic) ;
4737 /* depending on the type of pointer we need to
4738 move it to the correct pointer register */
4739 type = operandType(left);
4740 etype = getSpec(type);
4741 /* if left is of type of pointer then it is simple */
4742 if (IS_PTR(type) && !IS_FUNC(type->next))
4743 p_type = DCL_TYPE(type);
4745 /* we have to go by the storage class */
4746 p_type = PTR_TYPE(SPEC_OCLS(etype));
4748 /* if (SPEC_OCLS(etype)->codesp ) { */
4749 /* p_type = CPOINTER ; */
4752 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
4753 /* p_type = FPOINTER ; */
4755 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
4756 /* p_type = PPOINTER; */
4758 /* if (SPEC_OCLS(etype) == idata ) */
4759 /* p_type = IPOINTER; */
4761 /* p_type = POINTER ; */
4764 /* now that we have the pointer type we assign
4765 the pointer values */
4770 genNearPointerGet (left,result,ic);
4774 genPagedPointerGet(left,result,ic);
4778 genFarPointerGet (left,result,ic);
4782 emitcodePointerGet (left,result,ic);
4786 genGenPointerGet (left,result,ic);
4792 /*-----------------------------------------------------------------*/
4793 /* genPackBits - generates code for packed bit storage */
4794 /*-----------------------------------------------------------------*/
4795 static void genPackBits (link *etype ,
4797 char *rname, int p_type)
4805 blen = SPEC_BLEN(etype);
4806 bstr = SPEC_BSTR(etype);
4808 l = aopGet(AOP(right),offset++,FALSE,FALSE);
4811 /* if the bit lenth is less than or */
4812 /* it exactly fits a byte then */
4813 if (SPEC_BLEN(etype) <= 8 ) {
4814 shCount = SPEC_BSTR(etype) ;
4816 /* shift left acc */
4819 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
4824 emitcode ("mov","b,a");
4825 emitcode("mov","a,@%s",rname);
4829 emitcode ("mov","b,a");
4830 emitcode("movx","a,@dptr");
4834 emitcode ("push","b");
4835 emitcode ("push","acc");
4836 emitcode ("lcall","__gptrget");
4837 emitcode ("pop","b");
4841 emitcode ("anl","a,#0x%02x",(unsigned char)
4842 ((unsigned char)(0xFF << (blen+bstr)) |
4843 (unsigned char)(0xFF >> (8-bstr)) ) );
4844 emitcode ("orl","a,b");
4845 if (p_type == GPOINTER)
4846 emitcode("pop","b");
4852 emitcode("mov","@%s,a",rname);
4856 emitcode("movx","@dptr,a");
4860 emitcode("lcall","__gptrput");
4865 if ( SPEC_BLEN(etype) <= 8 )
4868 emitcode("inc","%s",rname);
4869 rLen = SPEC_BLEN(etype) ;
4871 /* now generate for lengths greater than one byte */
4874 l = aopGet(AOP(right),offset++,FALSE,TRUE);
4884 emitcode("mov","@%s,a",rname);
4886 emitcode("mov","@%s,%s",rname,l);
4891 emitcode("movx","@dptr,a");
4896 emitcode("lcall","__gptrput");
4899 emitcode ("inc","%s",rname);
4904 /* last last was not complete */
4906 /* save the byte & read byte */
4909 emitcode ("mov","b,a");
4910 emitcode("mov","a,@%s",rname);
4914 emitcode ("mov","b,a");
4915 emitcode("movx","a,@dptr");
4919 emitcode ("push","b");
4920 emitcode ("push","acc");
4921 emitcode ("lcall","__gptrget");
4922 emitcode ("pop","b");
4926 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
4927 emitcode ("orl","a,b");
4930 if (p_type == GPOINTER)
4931 emitcode("pop","b");
4936 emitcode("mov","@%s,a",rname);
4940 emitcode("movx","@dptr,a");
4944 emitcode("lcall","__gptrput");
4948 /*-----------------------------------------------------------------*/
4949 /* genDataPointerSet - remat pointer to data space */
4950 /*-----------------------------------------------------------------*/
4951 static void genDataPointerSet(operand *right,
4955 int size, offset = 0 ;
4956 char *l, buffer[256];
4958 aopOp(right,ic,FALSE);
4960 l = aopGet(AOP(result),0,FALSE,TRUE);
4961 size = AOP_SIZE(right);
4964 sprintf(buffer,"(%s + %d)",l+1,offset);
4966 sprintf(buffer,"%s",l+1);
4967 emitcode("mov","%s,%s",buffer,
4968 aopGet(AOP(right),offset++,FALSE,FALSE));
4971 freeAsmop(right,NULL,ic,TRUE);
4972 freeAsmop(result,NULL,ic,TRUE);
4975 /*-----------------------------------------------------------------*/
4976 /* genNearPointerSet - emitcode for near pointer put */
4977 /*-----------------------------------------------------------------*/
4978 static void genNearPointerSet (operand *right,
4986 link *ptype = operandType(result);
4988 retype= getSpec(operandType(right));
4990 aopOp(result,ic,FALSE);
4992 /* if the result is rematerializable &
4993 in data space & not a bit variable */
4994 if (AOP_TYPE(result) == AOP_IMMD &&
4995 DCL_TYPE(ptype) == POINTER &&
4996 !IS_BITVAR(retype)) {
4997 genDataPointerSet (right,result,ic);
5001 /* if the value is already in a pointer register
5002 then don't need anything more */
5003 if (!AOP_INPREG(AOP(result))) {
5004 /* otherwise get a free pointer register */
5006 preg = getFreePtr(ic,&aop,FALSE);
5007 emitcode("mov","%s,%s",
5009 aopGet(AOP(result),0,FALSE,TRUE));
5010 rname = preg->name ;
5012 rname = aopGet(AOP(result),0,FALSE,FALSE);
5014 freeAsmop(result,NULL,ic,TRUE);
5015 aopOp (right,ic,FALSE);
5017 /* if bitfield then unpack the bits */
5018 if (IS_BITVAR(retype))
5019 genPackBits (retype,right,rname,POINTER);
5021 /* we have can just get the values */
5022 int size = AOP_SIZE(right);
5026 l = aopGet(AOP(right),offset,FALSE,TRUE);
5029 emitcode("mov","@%s,a",rname);
5031 emitcode("mov","@%s,%s",rname,l);
5033 emitcode("inc","%s",rname);
5038 /* now some housekeeping stuff */
5040 /* we had to allocate for this iCode */
5041 freeAsmop(NULL,aop,ic,TRUE);
5043 /* we did not allocate which means left
5044 already in a pointer register, then
5045 if size > 0 && this could be used again
5046 we have to point it back to where it
5048 if (AOP_SIZE(right) > 1 &&
5049 !OP_SYMBOL(result)->remat &&
5050 ( OP_SYMBOL(result)->liveTo > ic->seq ||
5052 int size = AOP_SIZE(right) - 1;
5054 emitcode("dec","%s",rname);
5059 freeAsmop(right,NULL,ic,TRUE);
5064 /*-----------------------------------------------------------------*/
5065 /* genPagedPointerSet - emitcode for Paged pointer put */
5066 /*-----------------------------------------------------------------*/
5067 static void genPagedPointerSet (operand *right,
5076 retype= getSpec(operandType(right));
5078 aopOp(result,ic,FALSE);
5080 /* if the value is already in a pointer register
5081 then don't need anything more */
5082 if (!AOP_INPREG(AOP(result))) {
5083 /* otherwise get a free pointer register */
5085 preg = getFreePtr(ic,&aop,FALSE);
5086 emitcode("mov","%s,%s",
5088 aopGet(AOP(result),0,FALSE,TRUE));
5089 rname = preg->name ;
5091 rname = aopGet(AOP(result),0,FALSE,FALSE);
5093 freeAsmop(result,NULL,ic,TRUE);
5094 aopOp (right,ic,FALSE);
5096 /* if bitfield then unpack the bits */
5097 if (IS_BITVAR(retype))
5098 genPackBits (retype,right,rname,PPOINTER);
5100 /* we have can just get the values */
5101 int size = AOP_SIZE(right);
5105 l = aopGet(AOP(right),offset,FALSE,TRUE);
5108 emitcode("movx","@%s,a",rname);
5111 emitcode("inc","%s",rname);
5117 /* now some housekeeping stuff */
5119 /* we had to allocate for this iCode */
5120 freeAsmop(NULL,aop,ic,TRUE);
5122 /* we did not allocate which means left
5123 already in a pointer register, then
5124 if size > 0 && this could be used again
5125 we have to point it back to where it
5127 if (AOP_SIZE(right) > 1 &&
5128 !OP_SYMBOL(result)->remat &&
5129 ( OP_SYMBOL(result)->liveTo > ic->seq ||
5131 int size = AOP_SIZE(right) - 1;
5133 emitcode("dec","%s",rname);
5138 freeAsmop(right,NULL,ic,TRUE);
5143 /*-----------------------------------------------------------------*/
5144 /* genFarPointerSet - set value from far space */
5145 /*-----------------------------------------------------------------*/
5146 static void genFarPointerSet (operand *right,
5147 operand *result, iCode *ic)
5150 link *retype = getSpec(operandType(right));
5152 aopOp(result,ic,FALSE);
5154 /* if the operand is already in dptr
5155 then we do nothing else we move the value to dptr */
5156 if (AOP_TYPE(result) != AOP_STR) {
5157 /* if this is remateriazable */
5158 if (AOP_TYPE(result) == AOP_IMMD)
5159 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
5160 else { /* we need to get it byte by byte */
5161 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
5162 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
5163 if (options.model == MODEL_FLAT24)
5165 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
5169 /* so dptr know contains the address */
5170 freeAsmop(result,NULL,ic,TRUE);
5171 aopOp(right,ic,FALSE);
5173 /* if bit then unpack */
5174 if (IS_BITVAR(retype))
5175 genPackBits(retype,right,"dptr",FPOINTER);
5177 size = AOP_SIZE(right);
5181 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
5183 emitcode("movx","@dptr,a");
5185 emitcode("inc","dptr");
5189 freeAsmop(right,NULL,ic,TRUE);
5192 /*-----------------------------------------------------------------*/
5193 /* genGenPointerSet - set value from generic pointer space */
5194 /*-----------------------------------------------------------------*/
5195 static void genGenPointerSet (operand *right,
5196 operand *result, iCode *ic)
5199 link *retype = getSpec(operandType(right));
5201 aopOp(result,ic,FALSE);
5203 /* if the operand is already in dptr
5204 then we do nothing else we move the value to dptr */
5205 if (AOP_TYPE(result) != AOP_STR) {
5206 /* if this is remateriazable */
5207 if (AOP_TYPE(result) == AOP_IMMD) {
5208 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
5209 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
5211 else { /* we need to get it byte by byte */
5212 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
5213 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
5214 if (options.model == MODEL_FLAT24)
5216 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
5217 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
5221 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
5225 /* so dptr know contains the address */
5226 freeAsmop(result,NULL,ic,TRUE);
5227 aopOp(right,ic,FALSE);
5229 /* if bit then unpack */
5230 if (IS_BITVAR(retype))
5231 genPackBits(retype,right,"dptr",GPOINTER);
5233 size = AOP_SIZE(right);
5237 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
5239 emitcode("lcall","__gptrput");
5241 emitcode("inc","dptr");
5245 freeAsmop(right,NULL,ic,TRUE);
5248 /*-----------------------------------------------------------------*/
5249 /* genPointerSet - stores the value into a pointer location */
5250 /*-----------------------------------------------------------------*/
5251 static void genPointerSet (iCode *ic)
5253 operand *right, *result ;
5257 right = IC_RIGHT(ic);
5258 result = IC_RESULT(ic) ;
5260 /* depending on the type of pointer we need to
5261 move it to the correct pointer register */
5262 type = operandType(result);
5263 etype = getSpec(type);
5264 /* if left is of type of pointer then it is simple */
5265 if (IS_PTR(type) && !IS_FUNC(type->next)) {
5266 p_type = DCL_TYPE(type);
5269 /* we have to go by the storage class */
5270 p_type = PTR_TYPE(SPEC_OCLS(etype));
5272 /* if (SPEC_OCLS(etype)->codesp ) { */
5273 /* p_type = CPOINTER ; */
5276 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
5277 /* p_type = FPOINTER ; */
5279 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
5280 /* p_type = PPOINTER ; */
5282 /* if (SPEC_OCLS(etype) == idata ) */
5283 /* p_type = IPOINTER ; */
5285 /* p_type = POINTER ; */
5288 /* now that we have the pointer type we assign
5289 the pointer values */
5294 genNearPointerSet (right,result,ic);
5298 genPagedPointerSet (right,result,ic);
5302 genFarPointerSet (right,result,ic);
5306 genGenPointerSet (right,result,ic);
5312 /*-----------------------------------------------------------------*/
5313 /* genIfx - generate code for Ifx statement */
5314 /*-----------------------------------------------------------------*/
5315 static void genIfx (iCode *ic, iCode *popIc)
5317 operand *cond = IC_COND(ic);
5320 aopOp(cond,ic,FALSE);
5322 /* get the value into acc */
5323 if (AOP_TYPE(cond) != AOP_CRY)
5327 /* the result is now in the accumulator */
5328 freeAsmop(cond,NULL,ic,TRUE);
5330 /* if there was something to be popped then do it */
5334 /* if the condition is a bit variable */
5335 if (isbit && IS_ITEMP(cond) &&
5337 genIfxJump(ic,SPIL_LOC(cond)->rname);
5339 if (isbit && !IS_ITEMP(cond))
5340 genIfxJump(ic,OP_SYMBOL(cond)->rname);
5347 /*-----------------------------------------------------------------*/
5348 /* genAddrOf - generates code for address of */
5349 /*-----------------------------------------------------------------*/
5350 static void genAddrOf (iCode *ic)
5352 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
5355 aopOp(IC_RESULT(ic),ic,FALSE);
5357 /* if the operand is on the stack then we
5358 need to get the stack offset of this
5361 /* if it has an offset then we need to compute
5364 emitcode("mov","a,_bp");
5365 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
5366 aopPut(AOP(IC_RESULT(ic)),"a",0);
5368 /* we can just move _bp */
5369 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
5371 /* fill the result with zero */
5372 size = AOP_SIZE(IC_RESULT(ic)) - 1;
5375 if (options.stack10bit && size < (FPTRSIZE - 1))
5378 "*** warning: pointer to stack var truncated.\n");
5385 if (options.stack10bit && offset == 2)
5387 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
5391 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
5398 /* object not on stack then we need the name */
5399 size = AOP_SIZE(IC_RESULT(ic));
5403 char s[SDCC_NAME_MAX];
5405 sprintf(s,"#(%s >> %d)",
5409 sprintf(s,"#%s",sym->rname);
5410 aopPut(AOP(IC_RESULT(ic)),s,offset++);
5414 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
5418 /*-----------------------------------------------------------------*/
5419 /* genFarFarAssign - assignment when both are in far space */
5420 /*-----------------------------------------------------------------*/
5421 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
5423 int size = AOP_SIZE(right);
5426 /* first push the right side on to the stack */
5428 l = aopGet(AOP(right),offset++,FALSE,FALSE);
5430 emitcode ("push","acc");
5433 freeAsmop(right,NULL,ic,FALSE);
5434 /* now assign DPTR to result */
5435 aopOp(result,ic,FALSE);
5436 size = AOP_SIZE(result);
5438 emitcode ("pop","acc");
5439 aopPut(AOP(result),"a",--offset);
5441 freeAsmop(result,NULL,ic,FALSE);
5445 /*-----------------------------------------------------------------*/
5446 /* genAssign - generate code for assignment */
5447 /*-----------------------------------------------------------------*/
5448 static void genAssign (iCode *ic)
5450 operand *result, *right;
5452 unsigned long lit = 0L;
5454 result = IC_RESULT(ic);
5455 right = IC_RIGHT(ic) ;
5457 /* if they are the same */
5458 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
5461 aopOp(right,ic,FALSE);
5463 /* special case both in far space */
5464 if ((AOP_TYPE(right) == AOP_DPTR ||
5465 AOP_TYPE(right) == AOP_DPTR2) &&
5466 IS_TRUE_SYMOP(result) &&
5467 isOperandInFarSpace(result)) {
5469 genFarFarAssign (result,right,ic);
5473 aopOp(result,ic,TRUE);
5475 /* if they are the same registers */
5476 if (sameRegs(AOP(right),AOP(result)))
5479 /* if the result is a bit */
5480 if (AOP_TYPE(result) == AOP_CRY) {
5482 /* if the right size is a literal then
5483 we know what the value is */
5484 if (AOP_TYPE(right) == AOP_LIT) {
5485 if (((int) operandLitValue(right)))
5486 aopPut(AOP(result),one,0);
5488 aopPut(AOP(result),zero,0);
5492 /* the right is also a bit variable */
5493 if (AOP_TYPE(right) == AOP_CRY) {
5494 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5495 aopPut(AOP(result),"c",0);
5501 aopPut(AOP(result),"a",0);
5505 /* bit variables done */
5507 size = AOP_SIZE(result);
5509 if(AOP_TYPE(right) == AOP_LIT)
5510 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5512 (AOP_TYPE(result) != AOP_REG) &&
5513 (AOP_TYPE(right) == AOP_LIT) &&
5514 !IS_FLOAT(operandType(right)) &&
5516 emitcode("clr","a");
5518 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
5519 aopPut(AOP(result),"a",size);
5522 aopGet(AOP(right),size,FALSE,FALSE),
5528 aopGet(AOP(right),offset,FALSE,FALSE),
5535 freeAsmop (right,NULL,ic,FALSE);
5536 freeAsmop (result,NULL,ic,TRUE);
5539 /*-----------------------------------------------------------------*/
5540 /* genJumpTab - genrates code for jump table */
5541 /*-----------------------------------------------------------------*/
5542 static void genJumpTab (iCode *ic)
5547 aopOp(IC_JTCOND(ic),ic,FALSE);
5548 /* get the condition into accumulator */
5549 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
5551 /* multiply by three */
5552 emitcode("add","a,acc");
5553 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
5554 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
5556 jtab = newiTempLabel(NULL);
5557 emitcode("mov","dptr,#%05d$",jtab->key+100);
5558 emitcode("jmp","@a+dptr");
5559 emitcode("","%05d$:",jtab->key+100);
5560 /* now generate the jump labels */
5561 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
5562 jtab = setNextItem(IC_JTLABELS(ic)))
5563 emitcode("ljmp","%05d$",jtab->key+100);
5567 /*-----------------------------------------------------------------*/
5568 /* genCast - gen code for casting */
5569 /*-----------------------------------------------------------------*/
5570 static void genCast (iCode *ic)
5572 operand *result = IC_RESULT(ic);
5573 link *ctype = operandType(IC_LEFT(ic));
5574 link *rtype = operandType(IC_RIGHT(ic));
5575 operand *right = IC_RIGHT(ic);
5578 /* if they are equivalent then do nothing */
5579 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
5582 aopOp(right,ic,FALSE) ;
5583 aopOp(result,ic,FALSE);
5585 /* if the result is a bit */
5586 if (AOP_TYPE(result) == AOP_CRY) {
5587 /* if the right size is a literal then
5588 we know what the value is */
5589 if (AOP_TYPE(right) == AOP_LIT) {
5590 if (((int) operandLitValue(right)))
5591 aopPut(AOP(result),one,0);
5593 aopPut(AOP(result),zero,0);
5598 /* the right is also a bit variable */
5599 if (AOP_TYPE(right) == AOP_CRY) {
5600 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5601 aopPut(AOP(result),"c",0);
5607 aopPut(AOP(result),"a",0);
5611 /* if they are the same size : or less */
5612 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
5614 /* if they are in the same place */
5615 if (sameRegs(AOP(right),AOP(result)))
5618 /* if they in different places then copy */
5619 size = AOP_SIZE(result);
5623 aopGet(AOP(right),offset,FALSE,FALSE),
5631 /* if the result is of type pointer */
5632 if (IS_PTR(ctype)) {
5635 link *type = operandType(right);
5636 link *etype = getSpec(type);
5638 /* pointer to generic pointer */
5639 if (IS_GENPTR(ctype)) {
5643 p_type = DCL_TYPE(type);
5645 /* we have to go by the storage class */
5646 p_type = PTR_TYPE(SPEC_OCLS(etype));
5649 /* the first two bytes are known */
5650 size = GPTRSIZE - 1;
5654 aopGet(AOP(right),offset,FALSE,FALSE),
5658 /* the last byte depending on type */
5675 /* this should never happen */
5676 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
5677 "got unknown pointer type");
5680 aopPut(AOP(result),l, GPTRSIZE - 1);
5684 /* just copy the pointers */
5685 size = AOP_SIZE(result);
5689 aopGet(AOP(right),offset,FALSE,FALSE),
5696 /* so we now know that the size of destination is greater
5697 than the size of the source */
5698 /* we move to result for the size of source */
5699 size = AOP_SIZE(right);
5703 aopGet(AOP(right),offset,FALSE,FALSE),
5708 /* now depending on the sign of the source && destination */
5709 size = AOP_SIZE(result) - AOP_SIZE(right);
5710 /* if unsigned or not an integral type */
5711 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
5713 aopPut(AOP(result),zero,offset++);
5715 /* we need to extend the sign :{ */
5716 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
5719 emitcode("rlc","a");
5720 emitcode("subb","a,acc");
5722 aopPut(AOP(result),"a",offset++);
5725 /* we are done hurray !!!! */
5728 freeAsmop(right,NULL,ic,TRUE);
5729 freeAsmop(result,NULL,ic,TRUE);
5733 /*-----------------------------------------------------------------*/
5734 /* genDjnz - generate decrement & jump if not zero instrucion */
5735 /*-----------------------------------------------------------------*/
5736 static int genDjnz (iCode *ic, iCode *ifx)
5742 /* if the if condition has a false label
5743 then we cannot save */
5747 /* if the minus is not of the form
5749 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
5750 !IS_OP_LITERAL(IC_RIGHT(ic)))
5753 if (operandLitValue(IC_RIGHT(ic)) != 1)
5756 /* if the size of this greater than one then no
5758 if (getSize(operandType(IC_RESULT(ic))) > 1)
5761 /* otherwise we can save BIG */
5762 lbl = newiTempLabel(NULL);
5763 lbl1= newiTempLabel(NULL);
5765 aopOp(IC_RESULT(ic),ic,FALSE);
5767 if (IS_AOP_PREG(IC_RESULT(ic))) {
5768 emitcode("dec","%s",
5769 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
5770 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
5771 emitcode("jnz","%05d$",lbl->key+100);
5773 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
5776 emitcode ("sjmp","%05d$",lbl1->key+100);
5777 emitcode ("","%05d$:",lbl->key+100);
5778 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
5779 emitcode ("","%05d$:",lbl1->key+100);
5781 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
5786 /*-----------------------------------------------------------------*/
5787 /* genReceive - generate code for a receive iCode */
5788 /*-----------------------------------------------------------------*/
5789 static void genReceive (iCode *ic)
5791 if (isOperandInFarSpace(IC_RESULT(ic)) &&
5792 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
5793 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
5795 int size = getSize(operandType(IC_RESULT(ic)));
5796 int offset = fReturnSize - size;
5798 emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
5799 fReturn[fReturnSize - offset - 1] : "acc"));
5802 aopOp(IC_RESULT(ic),ic,FALSE);
5803 size = AOP_SIZE(IC_RESULT(ic));
5806 emitcode ("pop","acc");
5807 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
5812 aopOp(IC_RESULT(ic),ic,FALSE);
5814 assignResultValue(IC_RESULT(ic));
5817 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
5820 /*-----------------------------------------------------------------*/
5821 /* gen51Code - generate code for 8051 based controllers */
5822 /*-----------------------------------------------------------------*/
5823 void gen51Code (iCode *lic)
5828 lineHead = lineCurr = NULL;
5830 /* print the allocation information */
5832 printAllocInfo( currFunc, codeOutFile);
5833 /* if debug information required */
5834 /* if (options.debug && currFunc) { */
5836 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
5838 if (IS_STATIC(currFunc->etype))
5839 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
5841 emitcode("","G$%s$0$0 ==.",currFunc->name);
5844 /* stack pointer name */
5845 if (options.useXstack)
5851 for (ic = lic ; ic ; ic = ic->next ) {
5853 if ( cln != ic->lineno ) {
5854 if ( options.debug ) {
5856 emitcode("","C$%s$%d$%d$%d ==.",
5857 ic->filename,ic->lineno,
5858 ic->level,ic->block);
5861 emitcode(";","%s %d",ic->filename,ic->lineno);
5864 /* if the result is marked as
5865 spilt and rematerializable or code for
5866 this has already been generated then
5868 if (resultRemat(ic) || ic->generated )
5871 /* depending on the operation */
5890 /* IPOP happens only when trying to restore a
5891 spilt live range, if there is an ifx statement
5892 following this pop then the if statement might
5893 be using some of the registers being popped which
5894 would destory the contents of the register so
5895 we need to check for this condition and handle it */
5897 ic->next->op == IFX &&
5898 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
5899 genIfx (ic->next,ic);
5917 genEndFunction (ic);
5937 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
5954 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
5958 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
5962 genCmpLe (ic,ifxForOp(IC_RESULT(ic),ic));
5966 genCmpGe (ic,ifxForOp(IC_RESULT(ic),ic));
5970 genCmpNe (ic,ifxForOp(IC_RESULT(ic),ic));
5974 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
5986 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
5990 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
5994 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
6021 case GET_VALUE_AT_ADDRESS:
6026 if (POINTER_SET(ic))
6053 addSet(&_G.sendSet,ic);
6058 /* piCode(ic,stdout); */
6064 /* now we are ready to call the
6065 peep hole optimizer */
6066 if (!options.nopeep)
6067 peepHole (&lineHead);
6069 /* now do the actual printing */
6070 printLine (lineHead,codeOutFile);