1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
35 #include "SDCCglobl.h"
37 #ifdef HAVE_SYS_ISA_DEFS_H
38 #include <sys/isa_defs.h>
44 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
45 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
51 #include "SDCCpeeph.h"
55 char *aopLiteral (value *val, int offset);
57 /* this is the down and dirty file with all kinds of
58 kludgy & hacky stuff. This is what it is all about
59 CODE GENERATION for a specific MCU . some of the
60 routines may be reusable, will have to see */
62 static char *zero = "#0x00";
63 static char *one = "#0x01";
66 char *fReturn8051[] = {"dpl","dph","b","a" };
67 char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
68 unsigned fReturnSize = 4; /* shared with ralloc.c */
69 char **fReturn = fReturn8051;
70 static char *accUse[] = {"a","b"};
72 static short rbank = -1;
84 extern int mcs51_ptrRegReq ;
85 extern int mcs51_nRegs;
86 extern FILE *codeOutFile;
87 static void saverbank (int, iCode *,bool);
88 #define RESULTONSTACK(x) \
89 (IC_RESULT(x) && IC_RESULT(x)->aop && \
90 IC_RESULT(x)->aop->type == AOP_STK )
92 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x);
93 #define CLRC emitcode("clr","c");
95 static lineNode *lineHead = NULL;
96 static lineNode *lineCurr = NULL;
98 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
99 0xE0, 0xC0, 0x80, 0x00};
100 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
101 0x07, 0x03, 0x01, 0x00};
108 /*-----------------------------------------------------------------*/
109 /* emitcode - writes the code into a file : for now it is simple */
110 /*-----------------------------------------------------------------*/
111 static void emitcode (char *inst,char *fmt, ...)
114 char lb[MAX_INLINEASM];
121 sprintf(lb,"%s\t",inst);
123 sprintf(lb,"%s",inst);
124 vsprintf(lb+(strlen(lb)),fmt,ap);
128 while (isspace(*lbp)) lbp++;
131 lineCurr = (lineCurr ?
132 connectLine(lineCurr,newLineNode(lb)) :
133 (lineHead = newLineNode(lb)));
134 lineCurr->isInline = _G.inLine;
135 lineCurr->isDebug = _G.debugLine;
139 /*-----------------------------------------------------------------*/
140 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
141 /*-----------------------------------------------------------------*/
142 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
144 bool r0iu = FALSE , r1iu = FALSE;
145 bool r0ou = FALSE , r1ou = FALSE;
147 /* the logic: if r0 & r1 used in the instruction
148 then we are in trouble otherwise */
150 /* first check if r0 & r1 are used by this
151 instruction, in which case we are in trouble */
152 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
153 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
158 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
159 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
161 /* if no usage of r0 then return it */
162 if (!r0iu && !r0ou) {
163 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
164 (*aopp)->type = AOP_R0;
166 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R0_IDX);
169 /* if no usage of r1 then return it */
170 if (!r1iu && !r1ou) {
171 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
172 (*aopp)->type = AOP_R1;
174 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R1_IDX);
177 /* now we know they both have usage */
178 /* if r0 not used in this instruction */
180 /* push it if not already pushed */
182 emitcode ("push","%s",
183 mcs51_regWithIdx(R0_IDX)->dname);
187 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
188 (*aopp)->type = AOP_R0;
190 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R0_IDX);
193 /* if r1 not used then */
196 /* push it if not already pushed */
198 emitcode ("push","%s",
199 mcs51_regWithIdx(R1_IDX)->dname);
203 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
204 (*aopp)->type = AOP_R1;
205 return mcs51_regWithIdx(R1_IDX);
209 /* I said end of world but not quite end of world yet */
210 /* if this is a result then we can push it on the stack*/
212 (*aopp)->type = AOP_STK;
217 /* other wise this is true end of the world */
218 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
219 "getFreePtr should never reach here");
223 /*-----------------------------------------------------------------*/
224 /* newAsmop - creates a new asmOp */
225 /*-----------------------------------------------------------------*/
226 static asmop *newAsmop (short type)
230 ALLOC(aop,sizeof(asmop));
235 /*-----------------------------------------------------------------*/
236 /* pointerCode - returns the code for a pointer type */
237 /*-----------------------------------------------------------------*/
238 static int pointerCode (link *etype)
242 return PTR_TYPE(SPEC_OCLS(etype));
244 /* if (SPEC_OCLS(etype)->codesp ) { */
245 /* p_type = CPOINTER ; */
248 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
249 /* p_type = FPOINTER ; */
251 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
252 /* p_type = PPOINTER; */
254 /* if (SPEC_OCLS(etype) == idata ) */
255 /* p_type = IPOINTER; */
257 /* p_type = POINTER ; */
261 /*-----------------------------------------------------------------*/
262 /* aopForSym - for a true symbol */
263 /*-----------------------------------------------------------------*/
264 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
267 memmap *space= SPEC_OCLS(sym->etype);
269 /* if already has one */
273 /* assign depending on the storage class */
274 /* if it is on the stack or indirectly addressable */
275 /* space we need to assign either r0 or r1 to it */
276 if (sym->onStack || sym->iaccess) {
277 sym->aop = aop = newAsmop(0);
278 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
279 aop->size = getSize(sym->type);
281 /* now assign the address of the variable to
282 the pointer register */
283 if (aop->type != AOP_STK) {
288 emitcode("push","acc");
290 emitcode("mov","a,_bp");
291 emitcode("add","a,#0x%02x",
293 ((char)(sym->stack - _G.nRegsSaved )) :
294 ((char)sym->stack)) & 0xff);
295 emitcode("mov","%s,a",
296 aop->aopu.aop_ptr->name);
299 emitcode("pop","acc");
302 emitcode("mov","%s,#%s",
303 aop->aopu.aop_ptr->name,
305 aop->paged = space->paged;
307 aop->aopu.aop_stk = sym->stack;
311 /* if in bit space */
312 if (IN_BITSPACE(space)) {
313 sym->aop = aop = newAsmop (AOP_CRY);
314 aop->aopu.aop_dir = sym->rname ;
315 aop->size = getSize(sym->type);
318 /* if it is in direct space */
319 if (IN_DIRSPACE(space)) {
320 sym->aop = aop = newAsmop (AOP_DIR);
321 aop->aopu.aop_dir = sym->rname ;
322 aop->size = getSize(sym->type);
326 /* special case for a function */
327 if (IS_FUNC(sym->type)) {
328 sym->aop = aop = newAsmop(AOP_IMMD);
329 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
330 strcpy(aop->aopu.aop_immd,sym->rname);
331 aop->size = FPTRSIZE;
335 /* only remaining is far space */
336 /* in which case DPTR gets the address */
337 sym->aop = aop = newAsmop(AOP_DPTR);
338 emitcode ("mov","dptr,#%s", sym->rname);
339 aop->size = getSize(sym->type);
341 /* if it is in code space */
342 if (IN_CODESPACE(space))
348 /*-----------------------------------------------------------------*/
349 /* aopForRemat - rematerialzes an object */
350 /*-----------------------------------------------------------------*/
351 static asmop *aopForRemat (symbol *sym)
354 iCode *ic = sym->rematiCode;
355 asmop *aop = newAsmop(AOP_IMMD);
359 /* if plus or minus print the right hand side */
360 if (ic->op == '+' || ic->op == '-') {
361 sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
364 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
368 /* we reached the end */
369 sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
373 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
374 strcpy(aop->aopu.aop_immd,buffer);
378 /*-----------------------------------------------------------------*/
379 /* regsInCommon - two operands have some registers in common */
380 /*-----------------------------------------------------------------*/
381 static bool regsInCommon (operand *op1, operand *op2)
386 /* if they have registers in common */
387 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
390 sym1 = OP_SYMBOL(op1);
391 sym2 = OP_SYMBOL(op2);
393 if (sym1->nRegs == 0 || sym2->nRegs == 0)
396 for (i = 0 ; i < sym1->nRegs ; i++) {
401 for (j = 0 ; j < sym2->nRegs ;j++ ) {
405 if (sym2->regs[j] == sym1->regs[i])
413 /*-----------------------------------------------------------------*/
414 /* operandsEqu - equivalent */
415 /*-----------------------------------------------------------------*/
416 static bool operandsEqu ( operand *op1, operand *op2)
420 /* if they not symbols */
421 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
424 sym1 = OP_SYMBOL(op1);
425 sym2 = OP_SYMBOL(op2);
427 /* if both are itemps & one is spilt
428 and the other is not then false */
429 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
430 sym1->isspilt != sym2->isspilt )
433 /* if they are the same */
437 if (strcmp(sym1->rname,sym2->rname) == 0)
441 /* if left is a tmp & right is not */
445 (sym1->usl.spillLoc == sym2))
452 (sym2->usl.spillLoc == sym1))
458 /*-----------------------------------------------------------------*/
459 /* sameRegs - two asmops have the same registers */
460 /*-----------------------------------------------------------------*/
461 static bool sameRegs (asmop *aop1, asmop *aop2 )
468 if (aop1->type != AOP_REG ||
469 aop2->type != AOP_REG )
472 if (aop1->size != aop2->size )
475 for (i = 0 ; i < aop1->size ; i++ )
476 if (aop1->aopu.aop_reg[i] !=
477 aop2->aopu.aop_reg[i] )
483 /*-----------------------------------------------------------------*/
484 /* aopOp - allocates an asmop for an operand : */
485 /*-----------------------------------------------------------------*/
486 static void aopOp (operand *op, iCode *ic, bool result)
495 /* if this a literal */
496 if (IS_OP_LITERAL(op)) {
497 op->aop = aop = newAsmop(AOP_LIT);
498 aop->aopu.aop_lit = op->operand.valOperand;
499 aop->size = getSize(operandType(op));
503 /* if already has a asmop then continue */
507 /* if the underlying symbol has a aop */
508 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
509 op->aop = OP_SYMBOL(op)->aop;
513 /* if this is a true symbol */
514 if (IS_TRUE_SYMOP(op)) {
515 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
519 /* this is a temporary : this has
525 e) can be a return use only */
530 /* if the type is a conditional */
531 if (sym->regType == REG_CND) {
532 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
537 /* if it is spilt then two situations
539 b) has a spill location */
540 if (sym->isspilt || sym->nRegs == 0) {
542 /* rematerialize it NOW */
544 sym->aop = op->aop = aop =
546 aop->size = getSize(sym->type);
552 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
553 aop->size = getSize(sym->type);
554 for ( i = 0 ; i < 2 ; i++ )
555 aop->aopu.aop_str[i] = accUse[i];
561 aop = op->aop = sym->aop = newAsmop(AOP_STR);
562 aop->size = getSize(sym->type);
563 for ( i = 0 ; i < fReturnSize ; i++ )
564 aop->aopu.aop_str[i] = fReturn[i];
568 /* else spill location */
569 sym->aop = op->aop = aop =
570 aopForSym(ic,sym->usl.spillLoc,result);
571 aop->size = getSize(sym->type);
575 /* must be in a register */
576 sym->aop = op->aop = aop = newAsmop(AOP_REG);
577 aop->size = sym->nRegs;
578 for ( i = 0 ; i < sym->nRegs ;i++)
579 aop->aopu.aop_reg[i] = sym->regs[i];
582 /*-----------------------------------------------------------------*/
583 /* freeAsmop - free up the asmop given to an operand */
584 /*----------------------------------------------------------------*/
585 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
602 /* depending on the asmop type only three cases need work AOP_RO
603 , AOP_R1 && AOP_STK */
608 emitcode ("pop","ar0");
612 bitVectUnSetBit(ic->rUsed,R0_IDX);
618 emitcode ("pop","ar1");
622 bitVectUnSetBit(ic->rUsed,R1_IDX);
628 int stk = aop->aopu.aop_stk + aop->size;
629 bitVectUnSetBit(ic->rUsed,R0_IDX);
630 bitVectUnSetBit(ic->rUsed,R1_IDX);
632 getFreePtr(ic,&aop,FALSE);
634 emitcode ("mov","a,_bp");
635 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
636 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
638 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
641 emitcode("pop","acc");
642 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
644 emitcode("dec","%s",aop->aopu.aop_ptr->name);
647 freeAsmop(op,NULL,ic,TRUE);
649 emitcode("pop","ar0");
654 emitcode("pop","ar1");
661 /* all other cases just dealloc */
665 OP_SYMBOL(op)->aop = NULL;
666 /* if the symbol has a spill */
668 SPIL_LOC(op)->aop = NULL;
673 /*-----------------------------------------------------------------*/
674 /* aopGet - for fetching value of the aop */
675 /*-----------------------------------------------------------------*/
676 static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
681 /* offset is greater than
683 if (offset > (aop->size - 1) &&
684 aop->type != AOP_LIT)
687 /* depending on type */
692 /* if we need to increment it */
693 while (offset > aop->coff) {
694 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
698 while (offset < aop->coff) {
699 emitcode("dec","%s",aop->aopu.aop_ptr->name);
705 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
706 return (dname ? "acc" : "a");
708 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
709 ALLOC_ATOMIC(rs,strlen(s)+1);
714 while (offset > aop->coff) {
715 emitcode ("inc","dptr");
719 while (offset < aop->coff) {
720 emitcode("lcall","__decdptr");
727 emitcode("movc","a,@a+dptr");
730 emitcode("movx","a,@dptr");
731 return (dname ? "acc" : "a");
736 sprintf (s,"#(%s)",aop->aopu.aop_immd);
739 sprintf(s,"#(%s >> %d)",
745 ALLOC_ATOMIC(rs,strlen(s)+1);
751 sprintf(s,"(%s + %d)",
755 sprintf(s,"%s",aop->aopu.aop_dir);
756 ALLOC_ATOMIC(rs,strlen(s)+1);
762 return aop->aopu.aop_reg[offset]->dname;
764 return aop->aopu.aop_reg[offset]->name;
768 emitcode("mov","c,%s",aop->aopu.aop_dir);
769 emitcode("rlc","a") ;
770 return (dname ? "acc" : "a");
773 if (!offset && dname)
775 return aop->aopu.aop_str[offset];
778 return aopLiteral (aop->aopu.aop_lit,offset);
782 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
786 return aop->aopu.aop_str[offset];
790 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
791 "aopget got unsupported aop->type");
794 /*-----------------------------------------------------------------*/
795 /* aopPut - puts a string for a aop */
796 /*-----------------------------------------------------------------*/
797 static void aopPut (asmop *aop, char *s, int offset)
802 if (aop->size && offset > ( aop->size - 1)) {
803 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
804 "aopPut got offset > aop->size");
808 /* will assign value to value */
809 /* depending on where it is ofcourse */
813 sprintf(d,"(%s + %d)",
814 aop->aopu.aop_dir,offset);
816 sprintf(d,"%s",aop->aopu.aop_dir);
819 emitcode("mov","%s,%s",d,s);
824 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
825 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
827 strcmp(s,"r0") == 0 ||
828 strcmp(s,"r1") == 0 ||
829 strcmp(s,"r2") == 0 ||
830 strcmp(s,"r3") == 0 ||
831 strcmp(s,"r4") == 0 ||
832 strcmp(s,"r5") == 0 ||
833 strcmp(s,"r6") == 0 ||
834 strcmp(s,"r7") == 0 )
835 emitcode("mov","%s,%s",
836 aop->aopu.aop_reg[offset]->dname,s);
838 emitcode("mov","%s,%s",
839 aop->aopu.aop_reg[offset]->name,s);
845 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
846 "aopPut writting to code space");
850 while (offset > aop->coff) {
852 emitcode ("inc","dptr");
855 while (offset < aop->coff) {
857 emitcode("lcall","__decdptr");
862 /* if not in accumulater */
865 emitcode ("movx","@dptr,a");
870 while (offset > aop->coff) {
872 emitcode("inc","%s",aop->aopu.aop_ptr->name);
874 while (offset < aop->coff) {
876 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
882 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
887 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
889 if (strcmp(s,"r0") == 0 ||
890 strcmp(s,"r1") == 0 ||
891 strcmp(s,"r2") == 0 ||
892 strcmp(s,"r3") == 0 ||
893 strcmp(s,"r4") == 0 ||
894 strcmp(s,"r5") == 0 ||
895 strcmp(s,"r6") == 0 ||
896 strcmp(s,"r7") == 0 ) {
898 sprintf(buffer,"a%s",s);
899 emitcode("mov","@%s,%s",
900 aop->aopu.aop_ptr->name,buffer);
902 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
907 if (strcmp(s,"a") == 0)
908 emitcode("push","acc");
910 emitcode("push","%s",s);
915 /* if bit variable */
916 if (!aop->aopu.aop_dir) {
921 emitcode("clr","%s",aop->aopu.aop_dir);
924 emitcode("setb","%s",aop->aopu.aop_dir);
927 emitcode("mov","%s,c",aop->aopu.aop_dir);
929 lbl = newiTempLabel(NULL);
935 emitcode("jz","%05d$",lbl->key+100);
937 emitcode("","%05d$:",lbl->key+100);
938 emitcode("mov","%s,c",aop->aopu.aop_dir);
945 if (strcmp(aop->aopu.aop_str[offset],s))
946 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
951 if (!offset && (strcmp(s,"acc") == 0))
954 if (strcmp(aop->aopu.aop_str[offset],s))
955 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
959 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
960 "aopPut got unsupported aop->type");
968 /*-----------------------------------------------------------------*/
969 /* pointToEnd :- points to the last byte of the operand */
970 /*-----------------------------------------------------------------*/
971 static void pointToEnd (asmop *aop)
977 aop->coff = count = (aop->size - 1);
982 emitcode("inc","%s",aop->aopu.aop_ptr->name);
986 emitcode("inc","dptr");
993 /*-----------------------------------------------------------------*/
994 /* reAdjustPreg - points a register back to where it should */
995 /*-----------------------------------------------------------------*/
996 static void reAdjustPreg (asmop *aop)
1001 if ((size = aop->size) <= 1)
1004 switch (aop->type) {
1008 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1012 emitcode("lcall","__decdptr");
1019 #define AOP(op) op->aop
1020 #define AOP_TYPE(op) AOP(op)->type
1021 #define AOP_SIZE(op) AOP(op)->size
1022 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1023 AOP_TYPE(x) == AOP_R0))
1025 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1026 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1028 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1029 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1030 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1032 /*-----------------------------------------------------------------*/
1033 /* genNotFloat - generates not for float operations */
1034 /*-----------------------------------------------------------------*/
1035 static void genNotFloat (operand *op, operand *res)
1041 /* we will put 127 in the first byte of
1043 aopPut(AOP(res),"#127",0);
1044 size = AOP_SIZE(op) - 1;
1047 l = aopGet(op->aop,offset++,FALSE,FALSE);
1051 emitcode("orl","a,%s",
1053 offset++,FALSE,FALSE));
1055 tlbl = newiTempLabel(NULL);
1057 tlbl = newiTempLabel(NULL);
1058 aopPut(res->aop,one,1);
1059 emitcode("jz","%05d$",(tlbl->key+100));
1060 aopPut(res->aop,zero,1);
1061 emitcode("","%05d$:",(tlbl->key+100));
1063 size = res->aop->size - 2;
1065 /* put zeros in the rest */
1067 aopPut(res->aop,zero,offset++);
1070 /*-----------------------------------------------------------------*/
1071 /* opIsGptr: returns non-zero if the passed operand is */
1072 /* a generic pointer type. */
1073 /*-----------------------------------------------------------------*/
1074 static int opIsGptr(operand *op)
1076 link *type = operandType(op);
1078 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1085 /*-----------------------------------------------------------------*/
1086 /* getDataSize - get the operand data size */
1087 /*-----------------------------------------------------------------*/
1088 static int getDataSize(operand *op)
1091 size = AOP_SIZE(op);
1092 if (size == GPTRSIZE)
1094 link *type = operandType(op);
1095 if (IS_GENPTR(type))
1097 /* generic pointer; arithmetic operations
1098 * should ignore the high byte (pointer type).
1106 /*-----------------------------------------------------------------*/
1107 /* outAcc - output Acc */
1108 /*-----------------------------------------------------------------*/
1109 static void outAcc(operand *result)
1112 size = getDataSize(result);
1114 aopPut(AOP(result),"a",0);
1117 /* unsigned or positive */
1119 aopPut(AOP(result),zero,offset++);
1124 /*-----------------------------------------------------------------*/
1125 /* outBitC - output a bit C */
1126 /*-----------------------------------------------------------------*/
1127 static void outBitC(operand *result)
1129 /* if the result is bit */
1130 if (AOP_TYPE(result) == AOP_CRY)
1131 aopPut(AOP(result),"c",0);
1133 emitcode("clr","a");
1134 emitcode("rlc","a");
1139 /*-----------------------------------------------------------------*/
1140 /* toBoolean - emit code for orl a,operator(sizeop) */
1141 /*-----------------------------------------------------------------*/
1142 static void toBoolean(operand *oper)
1144 int size = AOP_SIZE(oper) - 1;
1146 MOVA(aopGet(AOP(oper),0,FALSE,FALSE));
1148 emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE));
1152 /*-----------------------------------------------------------------*/
1153 /* genNot - generate code for ! operation */
1154 /*-----------------------------------------------------------------*/
1155 static void genNot (iCode *ic)
1158 link *optype = operandType(IC_LEFT(ic));
1160 /* assign asmOps to operand & result */
1161 aopOp (IC_LEFT(ic),ic,FALSE);
1162 aopOp (IC_RESULT(ic),ic,TRUE);
1164 /* if in bit space then a special case */
1165 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1166 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1167 emitcode("cpl","c");
1168 outBitC(IC_RESULT(ic));
1172 /* if type float then do float */
1173 if (IS_FLOAT(optype)) {
1174 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1178 toBoolean(IC_LEFT(ic));
1180 tlbl = newiTempLabel(NULL);
1181 emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1182 emitcode("","%05d$:",tlbl->key+100);
1183 outBitC(IC_RESULT(ic));
1186 /* release the aops */
1187 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1188 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1192 /*-----------------------------------------------------------------*/
1193 /* genCpl - generate code for complement */
1194 /*-----------------------------------------------------------------*/
1195 static void genCpl (iCode *ic)
1201 /* assign asmOps to operand & result */
1202 aopOp (IC_LEFT(ic),ic,FALSE);
1203 aopOp (IC_RESULT(ic),ic,TRUE);
1205 /* if both are in bit space then
1207 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1208 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1210 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1211 emitcode("cpl","c");
1212 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1216 size = AOP_SIZE(IC_RESULT(ic));
1218 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1220 emitcode("cpl","a");
1221 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1226 /* release the aops */
1227 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1228 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1231 /*-----------------------------------------------------------------*/
1232 /* genUminusFloat - unary minus for floating points */
1233 /*-----------------------------------------------------------------*/
1234 static void genUminusFloat(operand *op,operand *result)
1236 int size ,offset =0 ;
1238 /* for this we just need to flip the
1239 first it then copy the rest in place */
1240 size = AOP_SIZE(op) - 1;
1241 l = aopGet(AOP(op),3,FALSE,FALSE);
1245 emitcode("cpl","acc.7");
1246 aopPut(AOP(result),"a",3);
1250 aopGet(AOP(op),offset,FALSE,FALSE),
1256 /*-----------------------------------------------------------------*/
1257 /* genUminus - unary minus code generation */
1258 /*-----------------------------------------------------------------*/
1259 static void genUminus (iCode *ic)
1262 link *optype, *rtype;
1266 aopOp(IC_LEFT(ic),ic,FALSE);
1267 aopOp(IC_RESULT(ic),ic,TRUE);
1269 /* if both in bit space then special
1271 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1272 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1274 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1275 emitcode("cpl","c");
1276 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1280 optype = operandType(IC_LEFT(ic));
1281 rtype = operandType(IC_RESULT(ic));
1283 /* if float then do float stuff */
1284 if (IS_FLOAT(optype)) {
1285 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1289 /* otherwise subtract from zero */
1290 size = AOP_SIZE(IC_LEFT(ic));
1294 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1295 if (!strcmp(l,"a")) {
1296 emitcode("cpl","a");
1297 emitcode("inc","a");
1299 emitcode("clr","a");
1300 emitcode("subb","a,%s",l);
1302 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1305 /* if any remaining bytes in the result */
1306 /* we just need to propagate the sign */
1307 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1308 emitcode("rlc","a");
1309 emitcode("subb","a,acc");
1311 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1315 /* release the aops */
1316 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1317 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1320 /*-----------------------------------------------------------------*/
1321 /* saveRegisters - will look for a call and save the registers */
1322 /*-----------------------------------------------------------------*/
1323 static void saveRegisters(iCode *lic)
1331 for (ic = lic ; ic ; ic = ic->next)
1332 if (ic->op == CALL || ic->op == PCALL)
1336 fprintf(stderr,"found parameter push with no function call\n");
1340 /* if the registers have been saved already then
1342 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1345 /* find the registers in use at this time
1346 and push them away to safety */
1347 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1351 if (options.useXstack) {
1352 if (bitVectBitValue(rsave,R0_IDX))
1353 emitcode("mov","b,r0");
1354 emitcode("mov","r0,%s",spname);
1355 for (i = 0 ; i < mcs51_nRegs ; i++) {
1356 if (bitVectBitValue(rsave,i)) {
1358 emitcode("mov","a,b");
1360 emitcode("mov","a,%s",mcs51_regWithIdx(i)->name);
1361 emitcode("movx","@r0,a");
1362 emitcode("inc","r0");
1365 emitcode("mov","%s,r0",spname);
1366 if (bitVectBitValue(rsave,R0_IDX))
1367 emitcode("mov","r0,b");
1369 for (i = 0 ; i < mcs51_nRegs ; i++) {
1370 if (bitVectBitValue(rsave,i))
1371 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
1374 detype = getSpec(operandType(IC_LEFT(ic)));
1376 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1377 IS_ISR(currFunc->etype) &&
1380 saverbank(SPEC_BANK(detype),ic,TRUE);
1383 /*-----------------------------------------------------------------*/
1384 /* unsaveRegisters - pop the pushed registers */
1385 /*-----------------------------------------------------------------*/
1386 static void unsaveRegisters (iCode *ic)
1390 /* find the registers in use at this time
1391 and push them away to safety */
1392 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1395 if (options.useXstack) {
1396 emitcode("mov","r0,%s",spname);
1397 for (i = mcs51_nRegs ; i >= 0 ; i--) {
1398 if (bitVectBitValue(rsave,i)) {
1399 emitcode("dec","r0");
1400 emitcode("movx","a,@r0");
1402 emitcode("mov","b,a");
1404 emitcode("mov","%s,a",mcs51_regWithIdx(i)->name);
1408 emitcode("mov","%s,r0",spname);
1409 if (bitVectBitValue(rsave,R0_IDX))
1410 emitcode("mov","r0,b");
1412 for (i = mcs51_nRegs ; i >= 0 ; i--) {
1413 if (bitVectBitValue(rsave,i))
1414 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
1420 /*-----------------------------------------------------------------*/
1422 /*-----------------------------------------------------------------*/
1423 static void pushSide(operand * oper, int size)
1427 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1428 if (AOP_TYPE(oper) != AOP_REG &&
1429 AOP_TYPE(oper) != AOP_DIR &&
1431 emitcode("mov","a,%s",l);
1432 emitcode("push","acc");
1434 emitcode("push","%s",l);
1438 /*-----------------------------------------------------------------*/
1439 /* assignResultValue - */
1440 /*-----------------------------------------------------------------*/
1441 static void assignResultValue(operand * oper)
1444 int size = AOP_SIZE(oper);
1446 aopPut(AOP(oper),fReturn[offset],offset);
1452 /*-----------------------------------------------------------------*/
1453 /* genXpush - pushes onto the external stack */
1454 /*-----------------------------------------------------------------*/
1455 static void genXpush (iCode *ic)
1457 asmop *aop = newAsmop(0);
1459 int size,offset = 0;
1461 aopOp(IC_LEFT(ic),ic,FALSE);
1462 r = getFreePtr(ic,&aop,FALSE);
1465 emitcode("mov","%s,_spx",r->name);
1467 size = AOP_SIZE(IC_LEFT(ic));
1470 char *l = aopGet(AOP(IC_LEFT(ic)),
1471 offset++,FALSE,FALSE);
1473 emitcode("movx","@%s,a",r->name);
1474 emitcode("inc","%s",r->name);
1479 emitcode("mov","_spx,%s",r->name);
1481 freeAsmop(NULL,aop,ic,TRUE);
1482 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1485 /*-----------------------------------------------------------------*/
1486 /* genIpush - genrate code for pushing this gets a little complex */
1487 /*-----------------------------------------------------------------*/
1488 static void genIpush (iCode *ic)
1490 int size, offset = 0 ;
1494 /* if this is not a parm push : ie. it is spill push
1495 and spill push is always done on the local stack */
1496 if (!ic->parmPush) {
1498 /* and the item is spilt then do nothing */
1499 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1502 aopOp(IC_LEFT(ic),ic,FALSE);
1503 size = AOP_SIZE(IC_LEFT(ic));
1504 /* push it on the stack */
1506 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1511 emitcode("push","%s",l);
1516 /* this is a paramter push: in this case we call
1517 the routine to find the call and save those
1518 registers that need to be saved */
1521 /* if use external stack then call the external
1522 stack pushing routine */
1523 if (options.useXstack) {
1528 /* then do the push */
1529 aopOp(IC_LEFT(ic),ic,FALSE);
1532 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1533 size = AOP_SIZE(IC_LEFT(ic));
1536 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1537 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1538 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1540 emitcode("mov","a,%s",l);
1541 emitcode("push","acc");
1543 emitcode("push","%s",l);
1546 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1549 /*-----------------------------------------------------------------*/
1550 /* genIpop - recover the registers: can happen only for spilling */
1551 /*-----------------------------------------------------------------*/
1552 static void genIpop (iCode *ic)
1557 /* if the temp was not pushed then */
1558 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1561 aopOp(IC_LEFT(ic),ic,FALSE);
1562 size = AOP_SIZE(IC_LEFT(ic));
1565 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1568 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1571 /*-----------------------------------------------------------------*/
1572 /* unsaverbank - restores the resgister bank from stack */
1573 /*-----------------------------------------------------------------*/
1574 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1581 if (options.useXstack) {
1583 r = getFreePtr(ic,&aop,FALSE);
1586 emitcode("mov","%s,_spx",r->name);
1587 emitcode("movx","a,@%s",r->name);
1588 emitcode("mov","psw,a");
1589 emitcode("dec","%s",r->name);
1592 emitcode ("pop","psw");
1595 for (i = (mcs51_nRegs - 1) ; i >= 0 ;i--) {
1596 if (options.useXstack) {
1597 emitcode("movx","a,@%s",r->name);
1598 emitcode("mov","(%s+%d),a",
1599 regs8051[i].base,8*bank+regs8051[i].offset);
1600 emitcode("dec","%s",r->name);
1603 emitcode("pop","(%s+%d)",
1604 regs8051[i].base,8*bank+regs8051[i].offset);
1607 if (options.useXstack) {
1609 emitcode("mov","_spx,%s",r->name);
1610 freeAsmop(NULL,aop,ic,TRUE);
1615 /*-----------------------------------------------------------------*/
1616 /* saverbank - saves an entire register bank on the stack */
1617 /*-----------------------------------------------------------------*/
1618 static void saverbank (int bank, iCode *ic, bool pushPsw)
1624 if (options.useXstack) {
1627 r = getFreePtr(ic,&aop,FALSE);
1628 emitcode("mov","%s,_spx",r->name);
1632 for (i = 0 ; i < mcs51_nRegs ;i++) {
1633 if (options.useXstack) {
1634 emitcode("inc","%s",r->name);
1635 emitcode("mov","a,(%s+%d)",
1636 regs8051[i].base,8*bank+regs8051[i].offset);
1637 emitcode("movx","@%s,a",r->name);
1639 emitcode("push","(%s+%d)",
1640 regs8051[i].base,8*bank+regs8051[i].offset);
1644 if (options.useXstack) {
1645 emitcode("mov","a,psw");
1646 emitcode("movx","@%s,a",r->name);
1647 emitcode("inc","%s",r->name);
1648 emitcode("mov","_spx,%s",r->name);
1649 freeAsmop (NULL,aop,ic,TRUE);
1652 emitcode("push","psw");
1654 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1660 /*-----------------------------------------------------------------*/
1661 /* genCall - generates a call statement */
1662 /*-----------------------------------------------------------------*/
1663 static void genCall (iCode *ic)
1667 /* if caller saves & we have not saved then */
1671 /* if we are calling a function that is not using
1672 the same register bank then we need to save the
1673 destination registers on the stack */
1674 detype = getSpec(operandType(IC_LEFT(ic)));
1676 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1677 IS_ISR(currFunc->etype) &&
1680 saverbank(SPEC_BANK(detype),ic,TRUE);
1682 /* if send set is not empty the assign */
1686 for (sic = setFirstItem(_G.sendSet) ; sic ;
1687 sic = setNextItem(_G.sendSet)) {
1688 int size, offset = 0;
1689 aopOp(IC_LEFT(sic),sic,FALSE);
1690 size = AOP_SIZE(IC_LEFT(sic));
1692 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1694 if (strcmp(l,fReturn[offset]))
1695 emitcode("mov","%s,%s",
1700 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1705 emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1706 OP_SYMBOL(IC_LEFT(ic))->rname :
1707 OP_SYMBOL(IC_LEFT(ic))->name));
1709 /* if we need assign a result value */
1710 if ((IS_ITEMP(IC_RESULT(ic)) &&
1711 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1712 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1713 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1716 aopOp(IC_RESULT(ic),ic,FALSE);
1719 assignResultValue(IC_RESULT(ic));
1721 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1724 /* adjust the stack for parameters if
1726 if (IC_LEFT(ic)->parmBytes) {
1728 if (IC_LEFT(ic)->parmBytes > 3) {
1729 emitcode("mov","a,%s",spname);
1730 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1731 emitcode("mov","%s,a",spname);
1733 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1734 emitcode("dec","%s",spname);
1738 /* if register bank was saved then pop them */
1740 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1742 /* if we hade saved some registers then unsave them */
1743 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1744 unsaveRegisters (ic);
1749 /*-----------------------------------------------------------------*/
1750 /* genPcall - generates a call by pointer statement */
1751 /*-----------------------------------------------------------------*/
1752 static void genPcall (iCode *ic)
1755 symbol *rlbl = newiTempLabel(NULL);
1758 /* if caller saves & we have not saved then */
1762 /* if we are calling a function that is not using
1763 the same register bank then we need to save the
1764 destination registers on the stack */
1765 detype = getSpec(operandType(IC_LEFT(ic)));
1767 IS_ISR(currFunc->etype) &&
1768 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
1769 saverbank(SPEC_BANK(detype),ic,TRUE);
1772 /* push the return address on to the stack */
1773 emitcode("mov","a,#%05d$",(rlbl->key+100));
1774 emitcode("push","acc");
1775 emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
1776 emitcode("push","acc");
1778 if (options.model == MODEL_FLAT24)
1780 emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
1781 emitcode("push","acc");
1784 /* now push the calling address */
1785 aopOp(IC_LEFT(ic),ic,FALSE);
1787 pushSide(IC_LEFT(ic), FPTRSIZE);
1789 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1791 /* if send set is not empty the assign */
1795 for (sic = setFirstItem(_G.sendSet) ; sic ;
1796 sic = setNextItem(_G.sendSet)) {
1797 int size, offset = 0;
1798 aopOp(IC_LEFT(sic),sic,FALSE);
1799 size = AOP_SIZE(IC_LEFT(sic));
1801 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1803 if (strcmp(l,fReturn[offset]))
1804 emitcode("mov","%s,%s",
1809 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1815 emitcode("","%05d$:",(rlbl->key+100));
1818 /* if we need assign a result value */
1819 if ((IS_ITEMP(IC_RESULT(ic)) &&
1820 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1821 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
1822 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1825 aopOp(IC_RESULT(ic),ic,FALSE);
1828 assignResultValue(IC_RESULT(ic));
1830 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1833 /* adjust the stack for parameters if
1835 if (IC_LEFT(ic)->parmBytes) {
1837 if (IC_LEFT(ic)->parmBytes > 3) {
1838 emitcode("mov","a,%s",spname);
1839 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1840 emitcode("mov","%s,a",spname);
1842 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1843 emitcode("dec","%s",spname);
1847 /* if register bank was saved then unsave them */
1849 (SPEC_BANK(currFunc->etype) !=
1851 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1853 /* if we hade saved some registers then
1856 unsaveRegisters (ic);
1860 /*-----------------------------------------------------------------*/
1861 /* resultRemat - result is rematerializable */
1862 /*-----------------------------------------------------------------*/
1863 static int resultRemat (iCode *ic)
1865 if (SKIP_IC(ic) || ic->op == IFX)
1868 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1869 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1870 if (sym->remat && !POINTER_SET(ic))
1878 #define STRCASECMP stricmp
1880 #define STRCASECMP strcasecmp
1883 /*-----------------------------------------------------------------*/
1884 /* inExcludeList - return 1 if the string is in exclude Reg list */
1885 /*-----------------------------------------------------------------*/
1886 static bool inExcludeList(char *s)
1890 if (options.excludeRegs[i] &&
1891 STRCASECMP(options.excludeRegs[i],"none") == 0)
1894 for ( i = 0 ; options.excludeRegs[i]; i++) {
1895 if (options.excludeRegs[i] &&
1896 STRCASECMP(s,options.excludeRegs[i]) == 0)
1902 /*-----------------------------------------------------------------*/
1903 /* genFunction - generated code for function entry */
1904 /*-----------------------------------------------------------------*/
1905 static void genFunction (iCode *ic)
1911 /* create the function header */
1912 emitcode(";","-----------------------------------------");
1913 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1914 emitcode(";","-----------------------------------------");
1916 emitcode("","%s:",sym->rname);
1917 fetype = getSpec(operandType(IC_LEFT(ic)));
1919 /* if critical function then turn interrupts off */
1920 if (SPEC_CRTCL(fetype))
1921 emitcode("clr","ea");
1923 /* here we need to generate the equates for the
1924 register bank if required */
1925 if (SPEC_BANK(fetype) != rbank) {
1928 rbank = SPEC_BANK(fetype);
1929 for ( i = 0 ; i < mcs51_nRegs ; i++ ) {
1930 if (strcmp(regs8051[i].base,"0") == 0)
1931 emitcode("","%s = 0x%02x",
1933 8*rbank+regs8051[i].offset);
1935 emitcode ("","%s = %s + 0x%02x",
1938 8*rbank+regs8051[i].offset);
1942 /* if this is an interrupt service routine then
1943 save acc, b, dpl, dph */
1944 if (IS_ISR(sym->etype)) {
1946 if (!inExcludeList("acc"))
1947 emitcode ("push","acc");
1948 if (!inExcludeList("b"))
1949 emitcode ("push","b");
1950 if (!inExcludeList("dpl"))
1951 emitcode ("push","dpl");
1952 if (!inExcludeList("dph"))
1953 emitcode ("push","dph");
1954 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
1955 emitcode ("push", "dpx");
1956 /* if this isr has no bank i.e. is going to
1957 run with bank 0 , then we need to save more
1959 if (!SPEC_BANK(sym->etype)) {
1961 /* if this function does not call any other
1962 function then we can be economical and
1963 save only those registers that are used */
1964 if (! sym->hasFcall) {
1967 /* if any registers used */
1968 if (sym->regsUsed) {
1969 /* save the registers used */
1970 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
1971 if (bitVectBitValue(sym->regsUsed,i) ||
1972 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
1973 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
1978 /* this function has a function call cannot
1979 determines register usage so we will have the
1981 saverbank(0,ic,FALSE);
1985 /* if callee-save to be used for this function
1986 then save the registers being used in this function */
1987 if (sym->calleeSave) {
1990 /* if any registers used */
1991 if (sym->regsUsed) {
1992 /* save the registers used */
1993 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
1994 if (bitVectBitValue(sym->regsUsed,i) ||
1995 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
1996 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
2004 /* set the register bank to the desired value */
2005 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2006 emitcode("push","psw");
2007 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2010 if (IS_RENT(sym->etype) || options.stackAuto) {
2012 if (options.useXstack) {
2013 emitcode("mov","r0,%s",spname);
2014 emitcode("mov","a,_bp");
2015 emitcode("movx","@r0,a");
2016 emitcode("inc","%s",spname);
2019 /* set up the stack */
2020 emitcode ("push","_bp"); /* save the callers stack */
2021 emitcode ("mov","_bp,%s",spname);
2024 /* adjust the stack for the function */
2029 werror(W_STACK_OVERFLOW,sym->name);
2031 if (i > 3 && sym->recvSize < 4) {
2033 emitcode ("mov","a,sp");
2034 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2035 emitcode ("mov","sp,a");
2040 emitcode("inc","sp");
2045 emitcode ("mov","a,_spx");
2046 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2047 emitcode ("mov","_spx,a");
2052 /*-----------------------------------------------------------------*/
2053 /* genEndFunction - generates epilogue for functions */
2054 /*-----------------------------------------------------------------*/
2055 static void genEndFunction (iCode *ic)
2057 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2059 if (IS_RENT(sym->etype) || options.stackAuto)
2060 emitcode ("mov","%s,_bp",spname);
2062 /* if use external stack but some variables were
2063 added to the local stack then decrement the
2065 if (options.useXstack && sym->stack) {
2066 emitcode("mov","a,sp");
2067 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2068 emitcode("mov","sp,a");
2072 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2073 if (options.useXstack) {
2074 emitcode("mov","r0,%s",spname);
2075 emitcode("movx","a,@r0");
2076 emitcode("mov","_bp,a");
2077 emitcode("dec","%s",spname);
2080 emitcode ("pop","_bp");
2083 /* restore the register bank */
2084 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2085 emitcode ("pop","psw");
2087 if (IS_ISR(sym->etype)) {
2089 /* now we need to restore the registers */
2090 /* if this isr has no bank i.e. is going to
2091 run with bank 0 , then we need to save more
2093 if (!SPEC_BANK(sym->etype)) {
2095 /* if this function does not call any other
2096 function then we can be economical and
2097 save only those registers that are used */
2098 if (! sym->hasFcall) {
2101 /* if any registers used */
2102 if (sym->regsUsed) {
2103 /* save the registers used */
2104 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2105 if (bitVectBitValue(sym->regsUsed,i) ||
2106 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2107 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
2112 /* this function has a function call cannot
2113 determines register usage so we will have the
2115 unsaverbank(0,ic,FALSE);
2119 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2120 emitcode ("pop", "dpx");
2121 if (!inExcludeList("dph"))
2122 emitcode ("pop","dph");
2123 if (!inExcludeList("dpl"))
2124 emitcode ("pop","dpl");
2125 if (!inExcludeList("b"))
2126 emitcode ("pop","b");
2127 if (!inExcludeList("acc"))
2128 emitcode ("pop","acc");
2130 if (SPEC_CRTCL(sym->etype))
2131 emitcode("setb","ea");
2133 /* if debug then send end of function */
2134 /* if (options.debug && currFunc) { */
2137 emitcode("","C$%s$%d$%d$%d ==.",
2138 ic->filename,currFunc->lastLine,
2139 ic->level,ic->block);
2140 if (IS_STATIC(currFunc->etype))
2141 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2143 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2147 emitcode ("reti","");
2150 if (SPEC_CRTCL(sym->etype))
2151 emitcode("setb","ea");
2153 if (sym->calleeSave) {
2156 /* if any registers used */
2157 if (sym->regsUsed) {
2158 /* save the registers used */
2159 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2160 if (bitVectBitValue(sym->regsUsed,i) ||
2161 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2162 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
2168 /* if debug then send end of function */
2169 /* if (options.debug && currFunc) { */
2172 emitcode("","C$%s$%d$%d$%d ==.",
2173 ic->filename,currFunc->lastLine,
2174 ic->level,ic->block);
2175 if (IS_STATIC(currFunc->etype))
2176 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2178 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2182 emitcode ("ret","");
2187 /*-----------------------------------------------------------------*/
2188 /* genRet - generate code for return statement */
2189 /*-----------------------------------------------------------------*/
2190 static void genRet (iCode *ic)
2192 int size,offset = 0 , pushed = 0;
2194 /* if we have no return value then
2195 just generate the "ret" */
2199 /* we have something to return then
2200 move the return value into place */
2201 aopOp(IC_LEFT(ic),ic,FALSE);
2202 size = AOP_SIZE(IC_LEFT(ic));
2206 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2207 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2209 emitcode("push","%s",l);
2212 l = aopGet(AOP(IC_LEFT(ic)),offset,
2214 if (strcmp(fReturn[offset],l))
2215 emitcode("mov","%s,%s",fReturn[offset++],l);
2222 if (strcmp(fReturn[pushed],"a"))
2223 emitcode("pop",fReturn[pushed]);
2225 emitcode("pop","acc");
2228 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2231 /* generate a jump to the return label
2232 if the next is not the return statement */
2233 if (!(ic->next && ic->next->op == LABEL &&
2234 IC_LABEL(ic->next) == returnLabel))
2236 emitcode("ljmp","%05d$",(returnLabel->key+100));
2240 /*-----------------------------------------------------------------*/
2241 /* genLabel - generates a label */
2242 /*-----------------------------------------------------------------*/
2243 static void genLabel (iCode *ic)
2245 /* special case never generate */
2246 if (IC_LABEL(ic) == entryLabel)
2249 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2252 /*-----------------------------------------------------------------*/
2253 /* genGoto - generates a ljmp */
2254 /*-----------------------------------------------------------------*/
2255 static void genGoto (iCode *ic)
2257 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2260 /*-----------------------------------------------------------------*/
2261 /* findLabelBackwards: walks back through the iCode chain looking */
2262 /* for the given label. Returns number of iCode instructions */
2263 /* between that label and given ic. */
2264 /* Returns zero if label not found. */
2265 /*-----------------------------------------------------------------*/
2266 static int findLabelBackwards(iCode *ic, int key)
2275 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2277 /* printf("findLabelBackwards = %d\n", count); */
2282 /* printf("findLabelBackwards: not found.\n"); */
2287 /*-----------------------------------------------------------------*/
2288 /* genPlusIncr :- does addition with increment if possible */
2289 /*-----------------------------------------------------------------*/
2290 static bool genPlusIncr (iCode *ic)
2292 unsigned int icount ;
2293 unsigned int size = getDataSize(IC_RESULT(ic));
2295 /* will try to generate an increment */
2296 /* if the right side is not a literal
2298 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2301 /* if the literal value of the right hand side
2302 is greater than 4 then it is not worth it */
2303 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2306 /* if increment 16 bits in register */
2307 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2314 /* If the next instruction is a goto and the goto target
2315 * is < 10 instructions previous to this, we can generate
2316 * jumps straight to that target.
2318 if (ic->next && ic->next->op == GOTO
2319 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2320 && labelRange <= 10 )
2322 emitcode(";", "tail increment optimized");
2323 tlbl = IC_LABEL(ic->next);
2328 tlbl = newiTempLabel(NULL);
2331 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2332 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2333 IS_AOP_PREG(IC_RESULT(ic)))
2334 emitcode("cjne","%s,#0x00,%05d$"
2335 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2338 emitcode("clr","a");
2339 emitcode("cjne","a,%s,%05d$"
2340 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2344 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2347 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2348 IS_AOP_PREG(IC_RESULT(ic)))
2349 emitcode("cjne","%s,#0x00,%05d$"
2350 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2353 emitcode("cjne","a,%s,%05d$"
2354 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2357 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2361 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2362 IS_AOP_PREG(IC_RESULT(ic)))
2363 emitcode("cjne","%s,#0x00,%05d$"
2364 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2367 emitcode("cjne","a,%s,%05d$"
2368 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2371 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2376 emitcode("","%05d$:",tlbl->key+100);
2381 /* if the sizes are greater than 1 then we cannot */
2382 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2383 AOP_SIZE(IC_LEFT(ic)) > 1 )
2386 /* we can if the aops of the left & result match or
2387 if they are in registers and the registers are the
2389 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2392 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2393 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2394 aopPut(AOP(IC_RESULT(ic)),"a",0);
2398 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2407 /*-----------------------------------------------------------------*/
2408 /* outBitAcc - output a bit in acc */
2409 /*-----------------------------------------------------------------*/
2410 static void outBitAcc(operand *result)
2412 symbol *tlbl = newiTempLabel(NULL);
2413 /* if the result is a bit */
2414 if (AOP_TYPE(result) == AOP_CRY){
2415 aopPut(AOP(result),"a",0);
2418 emitcode("jz","%05d$",tlbl->key+100);
2419 emitcode("mov","a,%s",one);
2420 emitcode("","%05d$:",tlbl->key+100);
2425 /*-----------------------------------------------------------------*/
2426 /* genPlusBits - generates code for addition of two bits */
2427 /*-----------------------------------------------------------------*/
2428 static void genPlusBits (iCode *ic)
2430 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2431 symbol *lbl = newiTempLabel(NULL);
2432 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2433 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2434 emitcode("cpl","c");
2435 emitcode("","%05d$:",(lbl->key+100));
2436 outBitC(IC_RESULT(ic));
2439 emitcode("clr","a");
2440 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2441 emitcode("rlc","a");
2442 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2443 emitcode("addc","a,#0x00");
2444 outAcc(IC_RESULT(ic));
2449 /* This is the original version of this code.
2451 * This is being kept around for reference,
2452 * because I am not entirely sure I got it right...
2454 static void adjustArithmeticResult(iCode *ic)
2456 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2457 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2458 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2459 aopPut(AOP(IC_RESULT(ic)),
2460 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2463 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2464 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
2465 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2466 aopPut(AOP(IC_RESULT(ic)),
2467 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2470 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2471 AOP_SIZE(IC_LEFT(ic)) < 3 &&
2472 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
2473 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2474 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2476 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2477 aopPut(AOP(IC_RESULT(ic)),buffer,2);
2481 /* This is the pure and virtuous version of this code.
2482 * I'm pretty certain it's right, but not enough to toss the old
2485 static void adjustArithmeticResult(iCode *ic)
2487 if (opIsGptr(IC_RESULT(ic)) &&
2488 opIsGptr(IC_LEFT(ic)) &&
2489 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2491 aopPut(AOP(IC_RESULT(ic)),
2492 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
2496 if (opIsGptr(IC_RESULT(ic)) &&
2497 opIsGptr(IC_RIGHT(ic)) &&
2498 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2500 aopPut(AOP(IC_RESULT(ic)),
2501 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
2505 if (opIsGptr(IC_RESULT(ic)) &&
2506 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2507 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2508 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2509 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2511 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2512 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2517 /*-----------------------------------------------------------------*/
2518 /* genPlus - generates code for addition */
2519 /*-----------------------------------------------------------------*/
2520 static void genPlus (iCode *ic)
2522 int size, offset = 0;
2524 /* special cases :- */
2526 aopOp (IC_LEFT(ic),ic,FALSE);
2527 aopOp (IC_RIGHT(ic),ic,FALSE);
2528 aopOp (IC_RESULT(ic),ic,TRUE);
2530 /* if literal, literal on the right or
2531 if left requires ACC or right is already
2533 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2534 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2535 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2536 operand *t = IC_RIGHT(ic);
2537 IC_RIGHT(ic) = IC_LEFT(ic);
2541 /* if both left & right are in bit
2543 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2544 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2549 /* if left in bit space & right literal */
2550 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2551 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2552 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2553 /* if result in bit space */
2554 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2555 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
2556 emitcode("cpl","c");
2557 outBitC(IC_RESULT(ic));
2559 size = getDataSize(IC_RESULT(ic));
2561 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2562 emitcode("addc","a,#00");
2563 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2569 /* if I can do an increment instead
2570 of add then GOOD for ME */
2571 if (genPlusIncr (ic) == TRUE)
2574 size = getDataSize(IC_RESULT(ic));
2577 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2578 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2580 emitcode("add","a,%s",
2581 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2583 emitcode("addc","a,%s",
2584 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2586 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2588 emitcode("add","a,%s",
2589 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2591 emitcode("addc","a,%s",
2592 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2594 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2597 adjustArithmeticResult(ic);
2600 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2601 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2602 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2605 /*-----------------------------------------------------------------*/
2606 /* genMinusDec :- does subtraction with deccrement if possible */
2607 /*-----------------------------------------------------------------*/
2608 static bool genMinusDec (iCode *ic)
2610 unsigned int icount ;
2611 unsigned int size = getDataSize(IC_RESULT(ic));
2613 /* will try to generate an increment */
2614 /* if the right side is not a literal
2616 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2619 /* if the literal value of the right hand side
2620 is greater than 4 then it is not worth it */
2621 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2624 /* if decrement 16 bits in register */
2625 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2632 /* If the next instruction is a goto and the goto target
2633 * is <= 10 instructions previous to this, we can generate
2634 * jumps straight to that target.
2636 if (ic->next && ic->next->op == GOTO
2637 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2638 && labelRange <= 10 )
2640 emitcode(";", "tail decrement optimized");
2641 tlbl = IC_LABEL(ic->next);
2646 tlbl = newiTempLabel(NULL);
2650 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2651 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2652 IS_AOP_PREG(IC_RESULT(ic)))
2653 emitcode("cjne","%s,#0xff,%05d$"
2654 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2657 emitcode("mov","a,#0xff");
2658 emitcode("cjne","a,%s,%05d$"
2659 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2662 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2665 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2666 IS_AOP_PREG(IC_RESULT(ic)))
2667 emitcode("cjne","%s,#0xff,%05d$"
2668 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2671 emitcode("cjne","a,%s,%05d$"
2672 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2675 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2679 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2680 IS_AOP_PREG(IC_RESULT(ic)))
2681 emitcode("cjne","%s,#0xff,%05d$"
2682 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2685 emitcode("cjne","a,%s,%05d$"
2686 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2689 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2693 emitcode("","%05d$:",tlbl->key+100);
2698 /* if the sizes are greater than 1 then we cannot */
2699 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2700 AOP_SIZE(IC_LEFT(ic)) > 1 )
2703 /* we can if the aops of the left & result match or
2704 if they are in registers and the registers are the
2706 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2709 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2717 /*-----------------------------------------------------------------*/
2718 /* addSign - complete with sign */
2719 /*-----------------------------------------------------------------*/
2720 static void addSign(operand *result, int offset, int sign)
2722 int size = (getDataSize(result) - offset);
2725 emitcode("rlc","a");
2726 emitcode("subb","a,acc");
2728 aopPut(AOP(result),"a",offset++);
2731 aopPut(AOP(result),zero,offset++);
2735 /*-----------------------------------------------------------------*/
2736 /* genMinusBits - generates code for subtraction of two bits */
2737 /*-----------------------------------------------------------------*/
2738 static void genMinusBits (iCode *ic)
2740 symbol *lbl = newiTempLabel(NULL);
2741 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2742 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2743 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2744 emitcode("cpl","c");
2745 emitcode("","%05d$:",(lbl->key+100));
2746 outBitC(IC_RESULT(ic));
2749 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2750 emitcode("subb","a,acc");
2751 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
2752 emitcode("inc","a");
2753 emitcode("","%05d$:",(lbl->key+100));
2754 aopPut(AOP(IC_RESULT(ic)),"a",0);
2755 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
2759 /*-----------------------------------------------------------------*/
2760 /* genMinus - generates code for subtraction */
2761 /*-----------------------------------------------------------------*/
2762 static void genMinus (iCode *ic)
2764 int size, offset = 0;
2765 unsigned long lit = 0L;
2767 aopOp (IC_LEFT(ic),ic,FALSE);
2768 aopOp (IC_RIGHT(ic),ic,FALSE);
2769 aopOp (IC_RESULT(ic),ic,TRUE);
2771 /* special cases :- */
2772 /* if both left & right are in bit space */
2773 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2774 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2779 /* if I can do an decrement instead
2780 of subtract then GOOD for ME */
2781 if (genMinusDec (ic) == TRUE)
2784 size = getDataSize(IC_RESULT(ic));
2786 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
2790 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2794 /* if literal, add a,#-lit, else normal subb */
2796 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2797 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2798 emitcode("subb","a,%s",
2799 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2801 /* first add without previous c */
2803 emitcode("add","a,#0x%02x",
2804 (unsigned int)(lit & 0x0FFL));
2806 emitcode("addc","a,#0x%02x",
2807 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
2809 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2812 adjustArithmeticResult(ic);
2815 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2816 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2817 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2821 /*-----------------------------------------------------------------*/
2822 /* genMultbits :- multiplication of bits */
2823 /*-----------------------------------------------------------------*/
2824 static void genMultbits (operand *left,
2828 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2829 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
2834 /*-----------------------------------------------------------------*/
2835 /* genMultOneByte : 8 bit multiplication & division */
2836 /*-----------------------------------------------------------------*/
2837 static void genMultOneByte (operand *left,
2841 link *opetype = operandType(result);
2846 /* (if two literals, the value is computed before) */
2847 /* if one literal, literal on the right */
2848 if (AOP_TYPE(left) == AOP_LIT){
2854 size = AOP_SIZE(result);
2855 /* signed or unsigned */
2856 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2857 l = aopGet(AOP(left),0,FALSE,FALSE);
2859 emitcode("mul","ab");
2860 /* if result size = 1, mul signed = mul unsigned */
2861 aopPut(AOP(result),"a",0);
2863 if (SPEC_USIGN(opetype)){
2864 aopPut(AOP(result),"b",1);
2866 /* for filling the MSBs */
2867 emitcode("clr","a");
2870 emitcode("mov","a,b");
2872 /* adjust the MSB if left or right neg */
2874 /* if one literal */
2875 if (AOP_TYPE(right) == AOP_LIT){
2876 /* AND literal negative */
2877 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
2878 /* adjust MSB (c==0 after mul) */
2879 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2883 lbl = newiTempLabel(NULL);
2884 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2885 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
2886 emitcode("","%05d$:",(lbl->key+100));
2887 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2888 lbl = newiTempLabel(NULL);
2889 emitcode("jc","%05d$",(lbl->key+100));
2890 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2891 emitcode("","%05d$:",(lbl->key+100));
2894 lbl = newiTempLabel(NULL);
2895 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
2896 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
2897 emitcode("","%05d$:",(lbl->key+100));
2898 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
2899 lbl = newiTempLabel(NULL);
2900 emitcode("jc","%05d$",(lbl->key+100));
2901 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
2902 emitcode("","%05d$:",(lbl->key+100));
2904 aopPut(AOP(result),"a",1);
2907 emitcode("rlc","a");
2908 emitcode("subb","a,acc");
2915 aopPut(AOP(result),"a",offset++);
2919 /*-----------------------------------------------------------------*/
2920 /* genMult - generates code for multiplication */
2921 /*-----------------------------------------------------------------*/
2922 static void genMult (iCode *ic)
2924 operand *left = IC_LEFT(ic);
2925 operand *right = IC_RIGHT(ic);
2926 operand *result= IC_RESULT(ic);
2928 /* assign the amsops */
2929 aopOp (left,ic,FALSE);
2930 aopOp (right,ic,FALSE);
2931 aopOp (result,ic,TRUE);
2933 /* special cases first */
2935 if (AOP_TYPE(left) == AOP_CRY &&
2936 AOP_TYPE(right)== AOP_CRY) {
2937 genMultbits(left,right,result);
2941 /* if both are of size == 1 */
2942 if (AOP_SIZE(left) == 1 &&
2943 AOP_SIZE(right) == 1 ) {
2944 genMultOneByte(left,right,result);
2948 /* should have been converted to function call */
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 /* genDivbits :- division of bits */
2959 /*-----------------------------------------------------------------*/
2960 static void genDivbits (operand *left,
2967 /* the result must be bit */
2968 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
2969 l = aopGet(AOP(left),0,FALSE,FALSE);
2973 emitcode("div","ab");
2974 emitcode("rrc","a");
2975 aopPut(AOP(result),"c",0);
2978 /*-----------------------------------------------------------------*/
2979 /* genDivOneByte : 8 bit division */
2980 /*-----------------------------------------------------------------*/
2981 static void genDivOneByte (operand *left,
2985 link *opetype = operandType(result);
2990 size = AOP_SIZE(result) - 1;
2992 /* signed or unsigned */
2993 if (SPEC_USIGN(opetype)) {
2994 /* unsigned is easy */
2995 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2996 l = aopGet(AOP(left),0,FALSE,FALSE);
2998 emitcode("div","ab");
2999 aopPut(AOP(result),"a",0);
3001 aopPut(AOP(result),zero,offset++);
3005 /* signed is a little bit more difficult */
3007 /* save the signs of the operands */
3008 l = aopGet(AOP(left),0,FALSE,FALSE);
3010 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3011 emitcode("push","acc"); /* save it on the stack */
3013 /* now sign adjust for both left & right */
3014 l = aopGet(AOP(right),0,FALSE,FALSE);
3016 lbl = newiTempLabel(NULL);
3017 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3018 emitcode("cpl","a");
3019 emitcode("inc","a");
3020 emitcode("","%05d$:",(lbl->key+100));
3021 emitcode("mov","b,a");
3023 /* sign adjust left side */
3024 l = aopGet(AOP(left),0,FALSE,FALSE);
3027 lbl = newiTempLabel(NULL);
3028 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3029 emitcode("cpl","a");
3030 emitcode("inc","a");
3031 emitcode("","%05d$:",(lbl->key+100));
3033 /* now the division */
3034 emitcode("div","ab");
3035 /* we are interested in the lower order
3037 emitcode("mov","b,a");
3038 lbl = newiTempLabel(NULL);
3039 emitcode("pop","acc");
3040 /* if there was an over flow we don't
3041 adjust the sign of the result */
3042 emitcode("jb","ov,%05d$",(lbl->key+100));
3043 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3045 emitcode("clr","a");
3046 emitcode("subb","a,b");
3047 emitcode("mov","b,a");
3048 emitcode("","%05d$:",(lbl->key+100));
3050 /* now we are done */
3051 aopPut(AOP(result),"b",0);
3053 emitcode("mov","c,b.7");
3054 emitcode("subb","a,acc");
3057 aopPut(AOP(result),"a",offset++);
3061 /*-----------------------------------------------------------------*/
3062 /* genDiv - generates code for division */
3063 /*-----------------------------------------------------------------*/
3064 static void genDiv (iCode *ic)
3066 operand *left = IC_LEFT(ic);
3067 operand *right = IC_RIGHT(ic);
3068 operand *result= IC_RESULT(ic);
3070 /* assign the amsops */
3071 aopOp (left,ic,FALSE);
3072 aopOp (right,ic,FALSE);
3073 aopOp (result,ic,TRUE);
3075 /* special cases first */
3077 if (AOP_TYPE(left) == AOP_CRY &&
3078 AOP_TYPE(right)== AOP_CRY) {
3079 genDivbits(left,right,result);
3083 /* if both are of size == 1 */
3084 if (AOP_SIZE(left) == 1 &&
3085 AOP_SIZE(right) == 1 ) {
3086 genDivOneByte(left,right,result);
3090 /* should have been converted to function call */
3093 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3094 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3095 freeAsmop(result,NULL,ic,TRUE);
3098 /*-----------------------------------------------------------------*/
3099 /* genModbits :- modulus of bits */
3100 /*-----------------------------------------------------------------*/
3101 static void genModbits (operand *left,
3108 /* the result must be bit */
3109 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3110 l = aopGet(AOP(left),0,FALSE,FALSE);
3114 emitcode("div","ab");
3115 emitcode("mov","a,b");
3116 emitcode("rrc","a");
3117 aopPut(AOP(result),"c",0);
3120 /*-----------------------------------------------------------------*/
3121 /* genModOneByte : 8 bit modulus */
3122 /*-----------------------------------------------------------------*/
3123 static void genModOneByte (operand *left,
3127 link *opetype = operandType(result);
3131 /* signed or unsigned */
3132 if (SPEC_USIGN(opetype)) {
3133 /* unsigned is easy */
3134 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3135 l = aopGet(AOP(left),0,FALSE,FALSE);
3137 emitcode("div","ab");
3138 aopPut(AOP(result),"b",0);
3142 /* signed is a little bit more difficult */
3144 /* save the signs of the operands */
3145 l = aopGet(AOP(left),0,FALSE,FALSE);
3148 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3149 emitcode("push","acc"); /* save it on the stack */
3151 /* now sign adjust for both left & right */
3152 l = aopGet(AOP(right),0,FALSE,FALSE);
3155 lbl = newiTempLabel(NULL);
3156 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3157 emitcode("cpl","a");
3158 emitcode("inc","a");
3159 emitcode("","%05d$:",(lbl->key+100));
3160 emitcode("mov","b,a");
3162 /* sign adjust left side */
3163 l = aopGet(AOP(left),0,FALSE,FALSE);
3166 lbl = newiTempLabel(NULL);
3167 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3168 emitcode("cpl","a");
3169 emitcode("inc","a");
3170 emitcode("","%05d$:",(lbl->key+100));
3172 /* now the multiplication */
3173 emitcode("div","ab");
3174 /* we are interested in the lower order
3176 lbl = newiTempLabel(NULL);
3177 emitcode("pop","acc");
3178 /* if there was an over flow we don't
3179 adjust the sign of the result */
3180 emitcode("jb","ov,%05d$",(lbl->key+100));
3181 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3183 emitcode("clr","a");
3184 emitcode("subb","a,b");
3185 emitcode("mov","b,a");
3186 emitcode("","%05d$:",(lbl->key+100));
3188 /* now we are done */
3189 aopPut(AOP(result),"b",0);
3193 /*-----------------------------------------------------------------*/
3194 /* genMod - generates code for division */
3195 /*-----------------------------------------------------------------*/
3196 static void genMod (iCode *ic)
3198 operand *left = IC_LEFT(ic);
3199 operand *right = IC_RIGHT(ic);
3200 operand *result= IC_RESULT(ic);
3202 /* assign the amsops */
3203 aopOp (left,ic,FALSE);
3204 aopOp (right,ic,FALSE);
3205 aopOp (result,ic,TRUE);
3207 /* special cases first */
3209 if (AOP_TYPE(left) == AOP_CRY &&
3210 AOP_TYPE(right)== AOP_CRY) {
3211 genModbits(left,right,result);
3215 /* if both are of size == 1 */
3216 if (AOP_SIZE(left) == 1 &&
3217 AOP_SIZE(right) == 1 ) {
3218 genModOneByte(left,right,result);
3222 /* should have been converted to function call */
3226 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3227 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3228 freeAsmop(result,NULL,ic,TRUE);
3231 /*-----------------------------------------------------------------*/
3232 /* genIfxJump :- will create a jump depending on the ifx */
3233 /*-----------------------------------------------------------------*/
3234 static void genIfxJump (iCode *ic, char *jval)
3237 symbol *tlbl = newiTempLabel(NULL);
3240 /* if true label then we jump if condition
3242 if ( IC_TRUE(ic) ) {
3244 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3245 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3248 /* false label is present */
3249 jlbl = IC_FALSE(ic) ;
3250 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3251 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3253 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3254 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3256 emitcode(inst,"%05d$",tlbl->key+100);
3257 emitcode("ljmp","%05d$",jlbl->key+100);
3258 emitcode("","%05d$:",tlbl->key+100);
3260 /* mark the icode as generated */
3264 /*-----------------------------------------------------------------*/
3265 /* genCmp :- greater or less than comparison */
3266 /*-----------------------------------------------------------------*/
3267 static void genCmp (operand *left,operand *right,
3268 operand *result, iCode *ifx, int sign)
3270 int size, offset = 0 ;
3271 unsigned long lit = 0L;
3273 /* if left & right are bit variables */
3274 if (AOP_TYPE(left) == AOP_CRY &&
3275 AOP_TYPE(right) == AOP_CRY ) {
3276 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3277 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3279 /* subtract right from left if at the
3280 end the carry flag is set then we know that
3281 left is greater than right */
3282 size = max(AOP_SIZE(left),AOP_SIZE(right));
3284 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3285 if((size == 1) && !sign &&
3286 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3287 symbol *lbl = newiTempLabel(NULL);
3288 emitcode("cjne","%s,%s,%05d$",
3289 aopGet(AOP(left),offset,FALSE,FALSE),
3290 aopGet(AOP(right),offset,FALSE,FALSE),
3292 emitcode("","%05d$:",lbl->key+100);
3294 if(AOP_TYPE(right) == AOP_LIT){
3295 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3296 /* optimize if(x < 0) or if(x >= 0) */
3302 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE));
3303 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3304 genIfxJump (ifx,"acc.7");
3308 emitcode("rlc","a");
3315 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3316 if (sign && size == 0) {
3317 emitcode("xrl","a,#0x80");
3318 if (AOP_TYPE(right) == AOP_LIT){
3319 unsigned long lit = (unsigned long)
3320 floatFromVal(AOP(right)->aopu.aop_lit);
3321 emitcode("subb","a,#0x%02x",
3322 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3324 emitcode("mov","b,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3325 emitcode("xrl","b,#0x80");
3326 emitcode("subb","a,b");
3329 emitcode("subb","a,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3335 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3338 /* if the result is used in the next
3339 ifx conditional branch then generate
3340 code a little differently */
3342 genIfxJump (ifx,"c");
3345 /* leave the result in acc */
3349 /*-----------------------------------------------------------------*/
3350 /* genCmpGt :- greater than comparison */
3351 /*-----------------------------------------------------------------*/
3352 static void genCmpGt (iCode *ic, iCode *ifx)
3354 operand *left, *right, *result;
3355 link *letype , *retype;
3359 right= IC_RIGHT(ic);
3360 result = IC_RESULT(ic);
3362 letype = getSpec(operandType(left));
3363 retype =getSpec(operandType(right));
3364 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3365 /* assign the amsops */
3366 aopOp (left,ic,FALSE);
3367 aopOp (right,ic,FALSE);
3368 aopOp (result,ic,TRUE);
3370 genCmp(right, left, result, ifx, sign);
3372 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3373 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3374 freeAsmop(result,NULL,ic,TRUE);
3377 /*-----------------------------------------------------------------*/
3378 /* genCmpLt - less than comparisons */
3379 /*-----------------------------------------------------------------*/
3380 static void genCmpLt (iCode *ic, iCode *ifx)
3382 operand *left, *right, *result;
3383 link *letype , *retype;
3387 right= IC_RIGHT(ic);
3388 result = IC_RESULT(ic);
3390 letype = getSpec(operandType(left));
3391 retype =getSpec(operandType(right));
3392 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3394 /* assign the amsops */
3395 aopOp (left,ic,FALSE);
3396 aopOp (right,ic,FALSE);
3397 aopOp (result,ic,TRUE);
3399 genCmp(left, right, result, ifx, sign);
3401 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3402 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3403 freeAsmop(result,NULL,ic,TRUE);
3406 /*-----------------------------------------------------------------*/
3407 /* gencjneshort - compare and jump if not equal */
3408 /*-----------------------------------------------------------------*/
3409 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3411 int size = max(AOP_SIZE(left),AOP_SIZE(right));
3413 unsigned long lit = 0L;
3415 /* if the left side is a literal or
3416 if the right is in a pointer register and left
3418 if ((AOP_TYPE(left) == AOP_LIT) ||
3419 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3424 if(AOP_TYPE(right) == AOP_LIT)
3425 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3427 /* if the right side is a literal then anything goes */
3428 if (AOP_TYPE(right) == AOP_LIT &&
3429 AOP_TYPE(left) != AOP_DIR ) {
3431 emitcode("cjne","%s,%s,%05d$",
3432 aopGet(AOP(left),offset,FALSE,FALSE),
3433 aopGet(AOP(right),offset,FALSE,FALSE),
3439 /* if the right side is in a register or in direct space or
3440 if the left is a pointer register & right is not */
3441 else if (AOP_TYPE(right) == AOP_REG ||
3442 AOP_TYPE(right) == AOP_DIR ||
3443 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3444 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3446 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3447 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3448 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
3449 emitcode("jnz","%05d$",lbl->key+100);
3451 emitcode("cjne","a,%s,%05d$",
3452 aopGet(AOP(right),offset,FALSE,TRUE),
3457 /* right is a pointer reg need both a & b */
3459 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
3461 emitcode("mov","b,%s",l);
3462 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3463 emitcode("cjne","a,b,%05d$",lbl->key+100);
3469 /*-----------------------------------------------------------------*/
3470 /* gencjne - compare and jump if not equal */
3471 /*-----------------------------------------------------------------*/
3472 static void gencjne(operand *left, operand *right, symbol *lbl)
3474 symbol *tlbl = newiTempLabel(NULL);
3476 gencjneshort(left, right, lbl);
3478 emitcode("mov","a,%s",one);
3479 emitcode("sjmp","%05d$",tlbl->key+100);
3480 emitcode("","%05d$:",lbl->key+100);
3481 emitcode("clr","a");
3482 emitcode("","%05d$:",tlbl->key+100);
3485 /*-----------------------------------------------------------------*/
3486 /* genCmpEq - generates code for equal to */
3487 /*-----------------------------------------------------------------*/
3488 static void genCmpEq (iCode *ic, iCode *ifx)
3490 operand *left, *right, *result;
3492 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3493 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3494 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3496 /* if literal, literal on the right or
3497 if the right is in a pointer register and left
3499 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
3500 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3501 operand *t = IC_RIGHT(ic);
3502 IC_RIGHT(ic) = IC_LEFT(ic);
3506 if(ifx && !AOP_SIZE(result)){
3508 /* if they are both bit variables */
3509 if (AOP_TYPE(left) == AOP_CRY &&
3510 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3511 if(AOP_TYPE(right) == AOP_LIT){
3512 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3514 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3515 emitcode("cpl","c");
3516 } else if(lit == 1L) {
3517 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3519 emitcode("clr","c");
3521 /* AOP_TYPE(right) == AOP_CRY */
3523 symbol *lbl = newiTempLabel(NULL);
3524 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3525 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3526 emitcode("cpl","c");
3527 emitcode("","%05d$:",(lbl->key+100));
3529 /* if true label then we jump if condition
3531 tlbl = newiTempLabel(NULL);
3532 if ( IC_TRUE(ifx) ) {
3533 emitcode("jnc","%05d$",tlbl->key+100);
3534 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3536 emitcode("jc","%05d$",tlbl->key+100);
3537 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3539 emitcode("","%05d$:",tlbl->key+100);
3541 tlbl = newiTempLabel(NULL);
3542 gencjneshort(left, right, tlbl);
3543 if ( IC_TRUE(ifx) ) {
3544 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3545 emitcode("","%05d$:",tlbl->key+100);
3547 symbol *lbl = newiTempLabel(NULL);
3548 emitcode("sjmp","%05d$",lbl->key+100);
3549 emitcode("","%05d$:",tlbl->key+100);
3550 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3551 emitcode("","%05d$:",lbl->key+100);
3554 /* mark the icode as generated */
3559 /* if they are both bit variables */
3560 if (AOP_TYPE(left) == AOP_CRY &&
3561 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3562 if(AOP_TYPE(right) == AOP_LIT){
3563 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3565 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3566 emitcode("cpl","c");
3567 } else if(lit == 1L) {
3568 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3570 emitcode("clr","c");
3572 /* AOP_TYPE(right) == AOP_CRY */
3574 symbol *lbl = newiTempLabel(NULL);
3575 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3576 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3577 emitcode("cpl","c");
3578 emitcode("","%05d$:",(lbl->key+100));
3581 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
3586 genIfxJump (ifx,"c");
3589 /* if the result is used in an arithmetic operation
3590 then put the result in place */
3593 gencjne(left,right,newiTempLabel(NULL));
3594 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3595 aopPut(AOP(result),"a",0);
3599 genIfxJump (ifx,"a");
3602 /* if the result is used in an arithmetic operation
3603 then put the result in place */
3604 if (AOP_TYPE(result) != AOP_CRY)
3606 /* leave the result in acc */
3610 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3611 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3612 freeAsmop(result,NULL,ic,TRUE);
3615 /*-----------------------------------------------------------------*/
3616 /* ifxForOp - returns the icode containing the ifx for operand */
3617 /*-----------------------------------------------------------------*/
3618 static iCode *ifxForOp ( operand *op, iCode *ic )
3620 /* if true symbol then needs to be assigned */
3621 if (IS_TRUE_SYMOP(op))
3624 /* if this has register type condition and
3625 the next instruction is ifx with the same operand
3626 and live to of the operand is upto the ifx only then */
3628 ic->next->op == IFX &&
3629 IC_COND(ic->next)->key == op->key &&
3630 OP_SYMBOL(op)->liveTo <= ic->next->seq )
3635 /*-----------------------------------------------------------------*/
3636 /* genAndOp - for && operation */
3637 /*-----------------------------------------------------------------*/
3638 static void genAndOp (iCode *ic)
3640 operand *left,*right, *result;
3643 /* note here that && operations that are in an
3644 if statement are taken away by backPatchLabels
3645 only those used in arthmetic operations remain */
3646 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3647 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3648 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3650 /* if both are bit variables */
3651 if (AOP_TYPE(left) == AOP_CRY &&
3652 AOP_TYPE(right) == AOP_CRY ) {
3653 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3654 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3657 tlbl = newiTempLabel(NULL);
3659 emitcode("jz","%05d$",tlbl->key+100);
3661 emitcode("","%05d$:",tlbl->key+100);
3665 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3666 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3667 freeAsmop(result,NULL,ic,TRUE);
3671 /*-----------------------------------------------------------------*/
3672 /* genOrOp - for || operation */
3673 /*-----------------------------------------------------------------*/
3674 static void genOrOp (iCode *ic)
3676 operand *left,*right, *result;
3679 /* note here that || operations that are in an
3680 if statement are taken away by backPatchLabels
3681 only those used in arthmetic operations remain */
3682 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3683 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3684 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3686 /* if both are bit variables */
3687 if (AOP_TYPE(left) == AOP_CRY &&
3688 AOP_TYPE(right) == AOP_CRY ) {
3689 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3690 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
3693 tlbl = newiTempLabel(NULL);
3695 emitcode("jnz","%05d$",tlbl->key+100);
3697 emitcode("","%05d$:",tlbl->key+100);
3701 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3702 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3703 freeAsmop(result,NULL,ic,TRUE);
3706 /*-----------------------------------------------------------------*/
3707 /* isLiteralBit - test if lit == 2^n */
3708 /*-----------------------------------------------------------------*/
3709 static int isLiteralBit(unsigned long lit)
3711 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
3712 0x100L,0x200L,0x400L,0x800L,
3713 0x1000L,0x2000L,0x4000L,0x8000L,
3714 0x10000L,0x20000L,0x40000L,0x80000L,
3715 0x100000L,0x200000L,0x400000L,0x800000L,
3716 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
3717 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
3720 for(idx = 0; idx < 32; idx++)
3726 /*-----------------------------------------------------------------*/
3727 /* continueIfTrue - */
3728 /*-----------------------------------------------------------------*/
3729 static void continueIfTrue (iCode *ic)
3732 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3736 /*-----------------------------------------------------------------*/
3738 /*-----------------------------------------------------------------*/
3739 static void jumpIfTrue (iCode *ic)
3742 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3746 /*-----------------------------------------------------------------*/
3747 /* jmpTrueOrFalse - */
3748 /*-----------------------------------------------------------------*/
3749 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
3751 // ugly but optimized by peephole
3753 symbol *nlbl = newiTempLabel(NULL);
3754 emitcode("sjmp","%05d$",nlbl->key+100);
3755 emitcode("","%05d$:",tlbl->key+100);
3756 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3757 emitcode("","%05d$:",nlbl->key+100);
3760 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3761 emitcode("","%05d$:",tlbl->key+100);
3766 /*-----------------------------------------------------------------*/
3767 /* genAnd - code for and */
3768 /*-----------------------------------------------------------------*/
3769 static void genAnd (iCode *ic, iCode *ifx)
3771 operand *left, *right, *result;
3773 unsigned long lit = 0L;
3777 aopOp((left = IC_LEFT(ic)),ic,FALSE);
3778 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3779 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3782 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3784 AOP_TYPE(left), AOP_TYPE(right));
3785 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3787 AOP_SIZE(left), AOP_SIZE(right));
3790 /* if left is a literal & right is not then exchange them */
3791 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3792 AOP_NEEDSACC(left)) {
3793 operand *tmp = right ;
3798 /* if result = right then exchange them */
3799 if(sameRegs(AOP(result),AOP(right))){
3800 operand *tmp = right ;
3805 /* if right is bit then exchange them */
3806 if (AOP_TYPE(right) == AOP_CRY &&
3807 AOP_TYPE(left) != AOP_CRY){
3808 operand *tmp = right ;
3812 if(AOP_TYPE(right) == AOP_LIT)
3813 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3815 size = AOP_SIZE(result);
3818 // result = bit & yy;
3819 if (AOP_TYPE(left) == AOP_CRY){
3820 // c = bit & literal;
3821 if(AOP_TYPE(right) == AOP_LIT){
3823 if(size && sameRegs(AOP(result),AOP(left)))
3826 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3829 if(size && (AOP_TYPE(result) == AOP_CRY)){
3830 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
3833 if((AOP_TYPE(result) == AOP_CRY) && ifx){
3837 emitcode("clr","c");
3840 if (AOP_TYPE(right) == AOP_CRY){
3842 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3843 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3846 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
3848 emitcode("rrc","a");
3849 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3857 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
3858 genIfxJump(ifx, "c");
3862 // if(val & 0xZZ) - size = 0, ifx != FALSE -
3863 // bit = val & 0xZZ - size = 1, ifx = FALSE -
3864 if((AOP_TYPE(right) == AOP_LIT) &&
3865 (AOP_TYPE(result) == AOP_CRY) &&
3866 (AOP_TYPE(left) != AOP_CRY)){
3867 int posbit = isLiteralBit(lit);
3871 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
3874 emitcode("mov","c,acc.%d",posbit&0x07);
3878 sprintf(buffer,"acc.%d",posbit&0x07);
3879 genIfxJump(ifx, buffer);
3884 symbol *tlbl = newiTempLabel(NULL);
3885 int sizel = AOP_SIZE(left);
3887 emitcode("setb","c");
3889 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
3890 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
3892 if((posbit = isLiteralBit(bytelit)) != 0)
3893 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
3895 if(bytelit != 0x0FFL)
3896 emitcode("anl","a,%s",
3897 aopGet(AOP(right),offset,FALSE,TRUE));
3898 emitcode("jnz","%05d$",tlbl->key+100);
3903 // bit = left & literal
3905 emitcode("clr","c");
3906 emitcode("","%05d$:",tlbl->key+100);
3908 // if(left & literal)
3911 jmpTrueOrFalse(ifx, tlbl);
3919 /* if left is same as result */
3920 if(sameRegs(AOP(result),AOP(left))){
3921 for(;size--; offset++) {
3922 if(AOP_TYPE(right) == AOP_LIT){
3923 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
3927 aopPut(AOP(result),zero,offset);
3929 if (IS_AOP_PREG(result)) {
3930 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3931 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
3932 aopPut(AOP(result),"a",offset);
3934 emitcode("anl","%s,%s",
3935 aopGet(AOP(left),offset,FALSE,TRUE),
3936 aopGet(AOP(right),offset,FALSE,FALSE));
3938 if (AOP_TYPE(left) == AOP_ACC)
3939 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
3941 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3942 if (IS_AOP_PREG(result)) {
3943 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
3944 aopPut(AOP(result),"a",offset);
3947 emitcode("anl","%s,a",
3948 aopGet(AOP(left),offset,FALSE,TRUE));
3953 // left & result in different registers
3954 if(AOP_TYPE(result) == AOP_CRY){
3956 // if(size), result in bit
3957 // if(!size && ifx), conditional oper: if(left & right)
3958 symbol *tlbl = newiTempLabel(NULL);
3959 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
3961 emitcode("setb","c");
3963 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3964 emitcode("anl","a,%s",
3965 aopGet(AOP(left),offset,FALSE,FALSE));
3966 emitcode("jnz","%05d$",tlbl->key+100);
3971 emitcode("","%05d$:",tlbl->key+100);
3974 jmpTrueOrFalse(ifx, tlbl);
3976 for(;(size--);offset++) {
3978 // result = left & right
3979 if(AOP_TYPE(right) == AOP_LIT){
3980 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
3982 aopGet(AOP(left),offset,FALSE,FALSE),
3985 } else if(bytelit == 0){
3986 aopPut(AOP(result),zero,offset);
3990 // faster than result <- left, anl result,right
3991 // and better if result is SFR
3992 if (AOP_TYPE(left) == AOP_ACC)
3993 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
3995 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3996 emitcode("anl","a,%s",
3997 aopGet(AOP(left),offset,FALSE,FALSE));
3999 aopPut(AOP(result),"a",offset);
4005 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4006 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4007 freeAsmop(result,NULL,ic,TRUE);
4010 /*-----------------------------------------------------------------*/
4011 /* genOr - code for or */
4012 /*-----------------------------------------------------------------*/
4013 static void genOr (iCode *ic, iCode *ifx)
4015 operand *left, *right, *result;
4017 unsigned long lit = 0L;
4019 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4020 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4021 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4024 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4026 AOP_TYPE(left), AOP_TYPE(right));
4027 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4029 AOP_SIZE(left), AOP_SIZE(right));
4032 /* if left is a literal & right is not then exchange them */
4033 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4034 AOP_NEEDSACC(left)) {
4035 operand *tmp = right ;
4040 /* if result = right then exchange them */
4041 if(sameRegs(AOP(result),AOP(right))){
4042 operand *tmp = right ;
4047 /* if right is bit then exchange them */
4048 if (AOP_TYPE(right) == AOP_CRY &&
4049 AOP_TYPE(left) != AOP_CRY){
4050 operand *tmp = right ;
4054 if(AOP_TYPE(right) == AOP_LIT)
4055 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4057 size = AOP_SIZE(result);
4061 if (AOP_TYPE(left) == AOP_CRY){
4062 if(AOP_TYPE(right) == AOP_LIT){
4063 // c = bit & literal;
4065 // lit != 0 => result = 1
4066 if(AOP_TYPE(result) == AOP_CRY){
4068 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4070 continueIfTrue(ifx);
4073 emitcode("setb","c");
4075 // lit == 0 => result = left
4076 if(size && sameRegs(AOP(result),AOP(left)))
4078 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4081 if (AOP_TYPE(right) == AOP_CRY){
4083 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4084 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4088 symbol *tlbl = newiTempLabel(NULL);
4089 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4090 emitcode("setb","c");
4091 emitcode("jb","%s,%05d$",
4092 AOP(left)->aopu.aop_dir,tlbl->key+100);
4094 emitcode("jnz","%05d$",tlbl->key+100);
4095 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4096 jmpTrueOrFalse(ifx, tlbl);
4100 emitcode("","%05d$:",tlbl->key+100);
4109 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4110 genIfxJump(ifx, "c");
4114 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4115 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4116 if((AOP_TYPE(right) == AOP_LIT) &&
4117 (AOP_TYPE(result) == AOP_CRY) &&
4118 (AOP_TYPE(left) != AOP_CRY)){
4122 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4124 continueIfTrue(ifx);
4127 // lit = 0, result = boolean(left)
4129 emitcode("setb","c");
4132 symbol *tlbl = newiTempLabel(NULL);
4133 emitcode("jnz","%05d$",tlbl->key+100);
4135 emitcode("","%05d$:",tlbl->key+100);
4137 genIfxJump (ifx,"a");
4145 /* if left is same as result */
4146 if(sameRegs(AOP(result),AOP(left))){
4147 for(;size--; offset++) {
4148 if(AOP_TYPE(right) == AOP_LIT){
4149 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4152 if (IS_AOP_PREG(left)) {
4153 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4154 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4155 aopPut(AOP(result),"a",offset);
4157 emitcode("orl","%s,%s",
4158 aopGet(AOP(left),offset,FALSE,TRUE),
4159 aopGet(AOP(right),offset,FALSE,FALSE));
4161 if (AOP_TYPE(left) == AOP_ACC)
4162 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4164 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4165 if (IS_AOP_PREG(left)) {
4166 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4167 aopPut(AOP(result),"a",offset);
4169 emitcode("orl","%s,a",
4170 aopGet(AOP(left),offset,FALSE,TRUE));
4175 // left & result in different registers
4176 if(AOP_TYPE(result) == AOP_CRY){
4178 // if(size), result in bit
4179 // if(!size && ifx), conditional oper: if(left | right)
4180 symbol *tlbl = newiTempLabel(NULL);
4181 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4183 emitcode("setb","c");
4185 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4186 emitcode("orl","a,%s",
4187 aopGet(AOP(left),offset,FALSE,FALSE));
4188 emitcode("jnz","%05d$",tlbl->key+100);
4193 emitcode("","%05d$:",tlbl->key+100);
4196 jmpTrueOrFalse(ifx, tlbl);
4197 } else for(;(size--);offset++){
4199 // result = left & right
4200 if(AOP_TYPE(right) == AOP_LIT){
4201 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4203 aopGet(AOP(left),offset,FALSE,FALSE),
4208 // faster than result <- left, anl result,right
4209 // and better if result is SFR
4210 if (AOP_TYPE(left) == AOP_ACC)
4211 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4213 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4214 emitcode("orl","a,%s",
4215 aopGet(AOP(left),offset,FALSE,FALSE));
4217 aopPut(AOP(result),"a",offset);
4222 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4223 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4224 freeAsmop(result,NULL,ic,TRUE);
4227 /*-----------------------------------------------------------------*/
4228 /* genXor - code for xclusive or */
4229 /*-----------------------------------------------------------------*/
4230 static void genXor (iCode *ic, iCode *ifx)
4232 operand *left, *right, *result;
4234 unsigned long lit = 0L;
4236 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4237 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4238 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4241 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4243 AOP_TYPE(left), AOP_TYPE(right));
4244 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4246 AOP_SIZE(left), AOP_SIZE(right));
4249 /* if left is a literal & right is not ||
4250 if left needs acc & right does not */
4251 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4252 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4253 operand *tmp = right ;
4258 /* if result = right then exchange them */
4259 if(sameRegs(AOP(result),AOP(right))){
4260 operand *tmp = right ;
4265 /* if right is bit then exchange them */
4266 if (AOP_TYPE(right) == AOP_CRY &&
4267 AOP_TYPE(left) != AOP_CRY){
4268 operand *tmp = right ;
4272 if(AOP_TYPE(right) == AOP_LIT)
4273 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4275 size = AOP_SIZE(result);
4279 if (AOP_TYPE(left) == AOP_CRY){
4280 if(AOP_TYPE(right) == AOP_LIT){
4281 // c = bit & literal;
4283 // lit>>1 != 0 => result = 1
4284 if(AOP_TYPE(result) == AOP_CRY){
4286 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4288 continueIfTrue(ifx);
4291 emitcode("setb","c");
4295 // lit == 0, result = left
4296 if(size && sameRegs(AOP(result),AOP(left)))
4298 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4300 // lit == 1, result = not(left)
4301 if(size && sameRegs(AOP(result),AOP(left))){
4302 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4305 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4306 emitcode("cpl","c");
4313 symbol *tlbl = newiTempLabel(NULL);
4314 if (AOP_TYPE(right) == AOP_CRY){
4316 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4319 int sizer = AOP_SIZE(right);
4321 // if val>>1 != 0, result = 1
4322 emitcode("setb","c");
4324 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
4326 // test the msb of the lsb
4327 emitcode("anl","a,#0xfe");
4328 emitcode("jnz","%05d$",tlbl->key+100);
4332 emitcode("rrc","a");
4334 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4335 emitcode("cpl","c");
4336 emitcode("","%05d$:",(tlbl->key+100));
4343 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4344 genIfxJump(ifx, "c");
4348 if(sameRegs(AOP(result),AOP(left))){
4349 /* if left is same as result */
4350 for(;size--; offset++) {
4351 if(AOP_TYPE(right) == AOP_LIT){
4352 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4355 if (IS_AOP_PREG(left)) {
4356 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4357 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4358 aopPut(AOP(result),"a",offset);
4360 emitcode("xrl","%s,%s",
4361 aopGet(AOP(left),offset,FALSE,TRUE),
4362 aopGet(AOP(right),offset,FALSE,FALSE));
4364 if (AOP_TYPE(left) == AOP_ACC)
4365 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4367 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4368 if (IS_AOP_PREG(left)) {
4369 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4370 aopPut(AOP(result),"a",offset);
4372 emitcode("xrl","%s,a",
4373 aopGet(AOP(left),offset,FALSE,TRUE));
4378 // left & result in different registers
4379 if(AOP_TYPE(result) == AOP_CRY){
4381 // if(size), result in bit
4382 // if(!size && ifx), conditional oper: if(left ^ right)
4383 symbol *tlbl = newiTempLabel(NULL);
4384 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4386 emitcode("setb","c");
4388 if((AOP_TYPE(right) == AOP_LIT) &&
4389 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4390 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4392 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4393 emitcode("xrl","a,%s",
4394 aopGet(AOP(left),offset,FALSE,FALSE));
4396 emitcode("jnz","%05d$",tlbl->key+100);
4401 emitcode("","%05d$:",tlbl->key+100);
4404 jmpTrueOrFalse(ifx, tlbl);
4405 } else for(;(size--);offset++){
4407 // result = left & right
4408 if(AOP_TYPE(right) == AOP_LIT){
4409 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4411 aopGet(AOP(left),offset,FALSE,FALSE),
4416 // faster than result <- left, anl result,right
4417 // and better if result is SFR
4418 if (AOP_TYPE(left) == AOP_ACC)
4419 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4421 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4422 emitcode("xrl","a,%s",
4423 aopGet(AOP(left),offset,FALSE,TRUE));
4425 aopPut(AOP(result),"a",offset);
4430 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4431 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4432 freeAsmop(result,NULL,ic,TRUE);
4435 /*-----------------------------------------------------------------*/
4436 /* genInline - write the inline code out */
4437 /*-----------------------------------------------------------------*/
4438 static void genInline (iCode *ic)
4440 char buffer[MAX_INLINEASM];
4444 _G.inLine += (!options.asmpeep);
4445 strcpy(buffer,IC_INLINE(ic));
4447 /* emit each line as a code */
4466 /* emitcode("",buffer); */
4467 _G.inLine -= (!options.asmpeep);
4470 /*-----------------------------------------------------------------*/
4471 /* genRRC - rotate right with carry */
4472 /*-----------------------------------------------------------------*/
4473 static void genRRC (iCode *ic)
4475 operand *left , *result ;
4476 int size, offset = 0;
4479 /* rotate right with carry */
4481 result=IC_RESULT(ic);
4482 aopOp (left,ic,FALSE);
4483 aopOp (result,ic,FALSE);
4485 /* move it to the result */
4486 size = AOP_SIZE(result);
4490 l = aopGet(AOP(left),offset,FALSE,FALSE);
4492 emitcode("rrc","a");
4493 if (AOP_SIZE(result) > 1)
4494 aopPut(AOP(result),"a",offset--);
4496 /* now we need to put the carry into the
4497 highest order byte of the result */
4498 if (AOP_SIZE(result) > 1) {
4499 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
4502 emitcode("mov","acc.7,c");
4503 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
4504 freeAsmop(left,NULL,ic,TRUE);
4505 freeAsmop(result,NULL,ic,TRUE);
4508 /*-----------------------------------------------------------------*/
4509 /* genRLC - generate code for rotate left with carry */
4510 /*-----------------------------------------------------------------*/
4511 static void genRLC (iCode *ic)
4513 operand *left , *result ;
4514 int size, offset = 0;
4517 /* rotate right with carry */
4519 result=IC_RESULT(ic);
4520 aopOp (left,ic,FALSE);
4521 aopOp (result,ic,FALSE);
4523 /* move it to the result */
4524 size = AOP_SIZE(result);
4527 l = aopGet(AOP(left),offset,FALSE,FALSE);
4529 emitcode("add","a,acc");
4530 if (AOP_SIZE(result) > 1)
4531 aopPut(AOP(result),"a",offset++);
4533 l = aopGet(AOP(left),offset,FALSE,FALSE);
4535 emitcode("rlc","a");
4536 if (AOP_SIZE(result) > 1)
4537 aopPut(AOP(result),"a",offset++);
4540 /* now we need to put the carry into the
4541 highest order byte of the result */
4542 if (AOP_SIZE(result) > 1) {
4543 l = aopGet(AOP(result),0,FALSE,FALSE);
4546 emitcode("mov","acc.0,c");
4547 aopPut(AOP(result),"a",0);
4548 freeAsmop(left,NULL,ic,TRUE);
4549 freeAsmop(result,NULL,ic,TRUE);
4552 /*-----------------------------------------------------------------*/
4553 /* genGetHbit - generates code get highest order bit */
4554 /*-----------------------------------------------------------------*/
4555 static void genGetHbit (iCode *ic)
4557 operand *left, *result;
4559 result=IC_RESULT(ic);
4560 aopOp (left,ic,FALSE);
4561 aopOp (result,ic,FALSE);
4563 /* get the highest order byte into a */
4564 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
4565 if(AOP_TYPE(result) == AOP_CRY){
4566 emitcode("rlc","a");
4571 emitcode("anl","a,#0x01");
4576 freeAsmop(left,NULL,ic,TRUE);
4577 freeAsmop(result,NULL,ic,TRUE);
4580 /*-----------------------------------------------------------------*/
4581 /* AccRol - rotate left accumulator by known count */
4582 /*-----------------------------------------------------------------*/
4583 static void AccRol (int shCount)
4585 shCount &= 0x0007; // shCount : 0..7
4597 emitcode("swap","a");
4601 emitcode("swap","a");
4604 emitcode("swap","a");
4617 /*-----------------------------------------------------------------*/
4618 /* AccLsh - left shift accumulator by known count */
4619 /*-----------------------------------------------------------------*/
4620 static void AccLsh (int shCount)
4624 emitcode("add","a,acc");
4627 emitcode("add","a,acc");
4628 emitcode("add","a,acc");
4630 /* rotate left accumulator */
4632 /* and kill the lower order bits */
4633 emitcode("anl","a,#0x%02x", SLMask[shCount]);
4638 /*-----------------------------------------------------------------*/
4639 /* AccRsh - right shift accumulator by known count */
4640 /*-----------------------------------------------------------------*/
4641 static void AccRsh (int shCount)
4646 emitcode("rrc","a");
4648 /* rotate right accumulator */
4649 AccRol(8 - shCount);
4650 /* and kill the higher order bits */
4651 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4656 /*-----------------------------------------------------------------*/
4657 /* AccSRsh - signed right shift accumulator by known count */
4658 /*-----------------------------------------------------------------*/
4659 static void AccSRsh (int shCount)
4664 emitcode("mov","c,acc.7");
4665 emitcode("rrc","a");
4666 } else if(shCount == 2){
4667 emitcode("mov","c,acc.7");
4668 emitcode("rrc","a");
4669 emitcode("mov","c,acc.7");
4670 emitcode("rrc","a");
4672 tlbl = newiTempLabel(NULL);
4673 /* rotate right accumulator */
4674 AccRol(8 - shCount);
4675 /* and kill the higher order bits */
4676 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4677 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4678 emitcode("orl","a,#0x%02x",
4679 (unsigned char)~SRMask[shCount]);
4680 emitcode("","%05d$:",tlbl->key+100);
4685 /*-----------------------------------------------------------------*/
4686 /* shiftR1Left2Result - shift right one byte from left to result */
4687 /*-----------------------------------------------------------------*/
4688 static void shiftR1Left2Result (operand *left, int offl,
4689 operand *result, int offr,
4690 int shCount, int sign)
4692 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4693 /* shift right accumulator */
4698 aopPut(AOP(result),"a",offr);
4701 /*-----------------------------------------------------------------*/
4702 /* shiftL1Left2Result - shift left one byte from left to result */
4703 /*-----------------------------------------------------------------*/
4704 static void shiftL1Left2Result (operand *left, int offl,
4705 operand *result, int offr, int shCount)
4708 l = aopGet(AOP(left),offl,FALSE,FALSE);
4710 /* shift left accumulator */
4712 aopPut(AOP(result),"a",offr);
4715 /*-----------------------------------------------------------------*/
4716 /* movLeft2Result - move byte from left to result */
4717 /*-----------------------------------------------------------------*/
4718 static void movLeft2Result (operand *left, int offl,
4719 operand *result, int offr, int sign)
4722 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
4723 l = aopGet(AOP(left),offl,FALSE,FALSE);
4725 if (*l == '@' && (IS_AOP_PREG(result))) {
4726 emitcode("mov","a,%s",l);
4727 aopPut(AOP(result),"a",offr);
4730 aopPut(AOP(result),l,offr);
4732 /* MSB sign in acc.7 ! */
4733 if(getDataSize(left) == offl+1){
4734 emitcode("mov","a,%s",l);
4735 aopPut(AOP(result),"a",offr);
4742 /*-----------------------------------------------------------------*/
4743 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
4744 /*-----------------------------------------------------------------*/
4745 static void AccAXRrl1 (char *x)
4747 emitcode("rrc","a");
4748 emitcode("xch","a,%s", x);
4749 emitcode("rrc","a");
4750 emitcode("xch","a,%s", x);
4753 /*-----------------------------------------------------------------*/
4754 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
4755 /*-----------------------------------------------------------------*/
4756 static void AccAXLrl1 (char *x)
4758 emitcode("xch","a,%s",x);
4759 emitcode("rlc","a");
4760 emitcode("xch","a,%s",x);
4761 emitcode("rlc","a");
4764 /*-----------------------------------------------------------------*/
4765 /* AccAXLsh1 - left shift a:x<-0 by 1 */
4766 /*-----------------------------------------------------------------*/
4767 static void AccAXLsh1 (char *x)
4769 emitcode("xch","a,%s",x);
4770 emitcode("add","a,acc");
4771 emitcode("xch","a,%s",x);
4772 emitcode("rlc","a");
4775 /*-----------------------------------------------------------------*/
4776 /* AccAXLsh - left shift a:x by known count (0..7) */
4777 /*-----------------------------------------------------------------*/
4778 static void AccAXLsh (char *x, int shCount)
4792 case 5 : // AAAAABBB:CCCCCDDD
4793 AccRol(shCount); // BBBAAAAA:CCCCCDDD
4794 emitcode("anl","a,#0x%02x",
4795 SLMask[shCount]); // BBB00000:CCCCCDDD
4796 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
4797 AccRol(shCount); // DDDCCCCC:BBB00000
4798 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
4799 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
4800 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
4801 emitcode("anl","a,#0x%02x",
4802 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
4803 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
4804 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
4806 case 6 : // AAAAAABB:CCCCCCDD
4807 emitcode("anl","a,#0x%02x",
4808 SRMask[shCount]); // 000000BB:CCCCCCDD
4809 emitcode("mov","c,acc.0"); // c = B
4810 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
4811 AccAXRrl1(x); // BCCCCCCD:D000000B
4812 AccAXRrl1(x); // BBCCCCCC:DD000000
4814 case 7 : // a:x <<= 7
4815 emitcode("anl","a,#0x%02x",
4816 SRMask[shCount]); // 0000000B:CCCCCCCD
4817 emitcode("mov","c,acc.0"); // c = B
4818 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
4819 AccAXRrl1(x); // BCCCCCCC:D0000000
4826 /*-----------------------------------------------------------------*/
4827 /* AccAXRsh - right shift a:x known count (0..7) */
4828 /*-----------------------------------------------------------------*/
4829 static void AccAXRsh (char *x, int shCount)
4836 AccAXRrl1(x); // 0->a:x
4840 AccAXRrl1(x); // 0->a:x
4842 AccAXRrl1(x); // 0->a:x
4846 case 5 : // AAAAABBB:CCCCCDDD = a:x
4847 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
4848 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
4849 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
4850 emitcode("anl","a,#0x%02x",
4851 SRMask[shCount]); // 000CCCCC:BBBAAAAA
4852 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
4853 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
4854 emitcode("anl","a,#0x%02x",
4855 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
4856 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
4857 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
4858 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
4860 case 6 : // AABBBBBB:CCDDDDDD
4861 emitcode("mov","c,acc.7");
4862 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
4863 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
4864 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
4865 emitcode("anl","a,#0x%02x",
4866 SRMask[shCount]); // 000000AA:BBBBBBCC
4868 case 7 : // ABBBBBBB:CDDDDDDD
4869 emitcode("mov","c,acc.7"); // c = A
4870 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
4871 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
4872 emitcode("anl","a,#0x%02x",
4873 SRMask[shCount]); // 0000000A:BBBBBBBC
4880 /*-----------------------------------------------------------------*/
4881 /* AccAXRshS - right shift signed a:x known count (0..7) */
4882 /*-----------------------------------------------------------------*/
4883 static void AccAXRshS (char *x, int shCount)
4890 emitcode("mov","c,acc.7");
4891 AccAXRrl1(x); // s->a:x
4894 emitcode("mov","c,acc.7");
4895 AccAXRrl1(x); // s->a:x
4896 emitcode("mov","c,acc.7");
4897 AccAXRrl1(x); // s->a:x
4901 case 5 : // AAAAABBB:CCCCCDDD = a:x
4902 tlbl = newiTempLabel(NULL);
4903 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
4904 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
4905 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
4906 emitcode("anl","a,#0x%02x",
4907 SRMask[shCount]); // 000CCCCC:BBBAAAAA
4908 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
4909 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
4910 emitcode("anl","a,#0x%02x",
4911 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
4912 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
4913 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
4914 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
4915 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4916 emitcode("orl","a,#0x%02x",
4917 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
4918 emitcode("","%05d$:",tlbl->key+100);
4919 break; // SSSSAAAA:BBBCCCCC
4920 case 6 : // AABBBBBB:CCDDDDDD
4921 tlbl = newiTempLabel(NULL);
4922 emitcode("mov","c,acc.7");
4923 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
4924 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
4925 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
4926 emitcode("anl","a,#0x%02x",
4927 SRMask[shCount]); // 000000AA:BBBBBBCC
4928 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4929 emitcode("orl","a,#0x%02x",
4930 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
4931 emitcode("","%05d$:",tlbl->key+100);
4933 case 7 : // ABBBBBBB:CDDDDDDD
4934 tlbl = newiTempLabel(NULL);
4935 emitcode("mov","c,acc.7"); // c = A
4936 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
4937 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
4938 emitcode("anl","a,#0x%02x",
4939 SRMask[shCount]); // 0000000A:BBBBBBBC
4940 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4941 emitcode("orl","a,#0x%02x",
4942 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
4943 emitcode("","%05d$:",tlbl->key+100);
4950 /*-----------------------------------------------------------------*/
4951 /* shiftL2Left2Result - shift left two bytes from left to result */
4952 /*-----------------------------------------------------------------*/
4953 static void shiftL2Left2Result (operand *left, int offl,
4954 operand *result, int offr, int shCount)
4956 if(sameRegs(AOP(result), AOP(left)) &&
4957 ((offl + MSB16) == offr)){
4958 /* don't crash result[offr] */
4959 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4960 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4962 movLeft2Result(left,offl, result, offr, 0);
4963 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4965 /* ax << shCount (x = lsb(result))*/
4966 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
4967 aopPut(AOP(result),"a",offr+MSB16);
4971 /*-----------------------------------------------------------------*/
4972 /* shiftR2Left2Result - shift right two bytes from left to result */
4973 /*-----------------------------------------------------------------*/
4974 static void shiftR2Left2Result (operand *left, int offl,
4975 operand *result, int offr,
4976 int shCount, int sign)
4978 if(sameRegs(AOP(result), AOP(left)) &&
4979 ((offl + MSB16) == offr)){
4980 /* don't crash result[offr] */
4981 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4982 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4984 movLeft2Result(left,offl, result, offr, 0);
4985 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4987 /* a:x >> shCount (x = lsb(result))*/
4989 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
4991 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
4992 if(getDataSize(result) > 1)
4993 aopPut(AOP(result),"a",offr+MSB16);
4996 /*-----------------------------------------------------------------*/
4997 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
4998 /*-----------------------------------------------------------------*/
4999 static void shiftLLeftOrResult (operand *left, int offl,
5000 operand *result, int offr, int shCount)
5002 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5003 /* shift left accumulator */
5005 /* or with result */
5006 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5007 /* back to result */
5008 aopPut(AOP(result),"a",offr);
5011 /*-----------------------------------------------------------------*/
5012 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5013 /*-----------------------------------------------------------------*/
5014 static void shiftRLeftOrResult (operand *left, int offl,
5015 operand *result, int offr, int shCount)
5017 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5018 /* shift right accumulator */
5020 /* or with result */
5021 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5022 /* back to result */
5023 aopPut(AOP(result),"a",offr);
5026 /*-----------------------------------------------------------------*/
5027 /* genlshOne - left shift a one byte quantity by known count */
5028 /*-----------------------------------------------------------------*/
5029 static void genlshOne (operand *result, operand *left, int shCount)
5031 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5034 /*-----------------------------------------------------------------*/
5035 /* genlshTwo - left shift two bytes by known amount != 0 */
5036 /*-----------------------------------------------------------------*/
5037 static void genlshTwo (operand *result,operand *left, int shCount)
5041 size = getDataSize(result);
5043 /* if shCount >= 8 */
5049 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5051 movLeft2Result(left, LSB, result, MSB16, 0);
5053 aopPut(AOP(result),zero,LSB);
5056 /* 1 <= shCount <= 7 */
5059 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5061 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5065 /*-----------------------------------------------------------------*/
5066 /* shiftLLong - shift left one long from left to result */
5067 /* offl = LSB or MSB16 */
5068 /*-----------------------------------------------------------------*/
5069 static void shiftLLong (operand *left, operand *result, int offr )
5072 int size = AOP_SIZE(result);
5074 if(size >= LSB+offr){
5075 l = aopGet(AOP(left),LSB,FALSE,FALSE);
5077 emitcode("add","a,acc");
5078 if (sameRegs(AOP(left),AOP(result)) &&
5079 size >= MSB16+offr && offr != LSB )
5080 emitcode("xch","a,%s",
5081 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
5083 aopPut(AOP(result),"a",LSB+offr);
5086 if(size >= MSB16+offr){
5087 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5088 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
5091 emitcode("rlc","a");
5092 if (sameRegs(AOP(left),AOP(result)) &&
5093 size >= MSB24+offr && offr != LSB)
5094 emitcode("xch","a,%s",
5095 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
5097 aopPut(AOP(result),"a",MSB16+offr);
5100 if(size >= MSB24+offr){
5101 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5102 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
5105 emitcode("rlc","a");
5106 if (sameRegs(AOP(left),AOP(result)) &&
5107 size >= MSB32+offr && offr != LSB )
5108 emitcode("xch","a,%s",
5109 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
5111 aopPut(AOP(result),"a",MSB24+offr);
5114 if(size > MSB32+offr){
5115 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5116 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
5119 emitcode("rlc","a");
5120 aopPut(AOP(result),"a",MSB32+offr);
5123 aopPut(AOP(result),zero,LSB);
5126 /*-----------------------------------------------------------------*/
5127 /* genlshFour - shift four byte by a known amount != 0 */
5128 /*-----------------------------------------------------------------*/
5129 static void genlshFour (operand *result, operand *left, int shCount)
5133 size = AOP_SIZE(result);
5135 /* if shifting more that 3 bytes */
5136 if (shCount >= 24 ) {
5139 /* lowest order of left goes to the highest
5140 order of the destination */
5141 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5143 movLeft2Result(left, LSB, result, MSB32, 0);
5144 aopPut(AOP(result),zero,LSB);
5145 aopPut(AOP(result),zero,MSB16);
5146 aopPut(AOP(result),zero,MSB32);
5150 /* more than two bytes */
5151 else if ( shCount >= 16 ) {
5152 /* lower order two bytes goes to higher order two bytes */
5154 /* if some more remaining */
5156 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5158 movLeft2Result(left, MSB16, result, MSB32, 0);
5159 movLeft2Result(left, LSB, result, MSB24, 0);
5161 aopPut(AOP(result),zero,MSB16);
5162 aopPut(AOP(result),zero,LSB);
5166 /* if more than 1 byte */
5167 else if ( shCount >= 8 ) {
5168 /* lower order three bytes goes to higher order three bytes */
5172 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5174 movLeft2Result(left, LSB, result, MSB16, 0);
5176 else{ /* size = 4 */
5178 movLeft2Result(left, MSB24, result, MSB32, 0);
5179 movLeft2Result(left, MSB16, result, MSB24, 0);
5180 movLeft2Result(left, LSB, result, MSB16, 0);
5181 aopPut(AOP(result),zero,LSB);
5183 else if(shCount == 1)
5184 shiftLLong(left, result, MSB16);
5186 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5187 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5188 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5189 aopPut(AOP(result),zero,LSB);
5194 /* 1 <= shCount <= 7 */
5195 else if(shCount <= 2){
5196 shiftLLong(left, result, LSB);
5198 shiftLLong(result, result, LSB);
5200 /* 3 <= shCount <= 7, optimize */
5202 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5203 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5204 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5208 /*-----------------------------------------------------------------*/
5209 /* genLeftShiftLiteral - left shifting by known count */
5210 /*-----------------------------------------------------------------*/
5211 static void genLeftShiftLiteral (operand *left,
5216 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5219 freeAsmop(right,NULL,ic,TRUE);
5221 aopOp(left,ic,FALSE);
5222 aopOp(result,ic,FALSE);
5224 size = getSize(operandType(result));
5227 emitcode("; shift left ","result %d, left %d",size,
5231 /* I suppose that the left size >= result size */
5234 movLeft2Result(left, size, result, size, 0);
5238 else if(shCount >= (size * 8))
5240 aopPut(AOP(result),zero,size);
5244 genlshOne (result,left,shCount);
5249 genlshTwo (result,left,shCount);
5253 genlshFour (result,left,shCount);
5257 freeAsmop(left,NULL,ic,TRUE);
5258 freeAsmop(result,NULL,ic,TRUE);
5261 /*-----------------------------------------------------------------*/
5262 /* genLeftShift - generates code for left shifting */
5263 /*-----------------------------------------------------------------*/
5264 static void genLeftShift (iCode *ic)
5266 operand *left,*right, *result;
5269 symbol *tlbl , *tlbl1;
5271 right = IC_RIGHT(ic);
5273 result = IC_RESULT(ic);
5275 aopOp(right,ic,FALSE);
5277 /* if the shift count is known then do it
5278 as efficiently as possible */
5279 if (AOP_TYPE(right) == AOP_LIT) {
5280 genLeftShiftLiteral (left,right,result,ic);
5284 /* shift count is unknown then we have to form
5285 a loop get the loop count in B : Note: we take
5286 only the lower order byte since shifting
5287 more that 32 bits make no sense anyway, ( the
5288 largest size of an object can be only 32 bits ) */
5290 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5291 emitcode("inc","b");
5292 freeAsmop (right,NULL,ic,TRUE);
5293 aopOp(left,ic,FALSE);
5294 aopOp(result,ic,FALSE);
5296 /* now move the left to the result if they are not the
5298 if (!sameRegs(AOP(left),AOP(result)) &&
5299 AOP_SIZE(result) > 1) {
5301 size = AOP_SIZE(result);
5304 l = aopGet(AOP(left),offset,FALSE,TRUE);
5305 if (*l == '@' && (IS_AOP_PREG(result))) {
5307 emitcode("mov","a,%s",l);
5308 aopPut(AOP(result),"a",offset);
5310 aopPut(AOP(result),l,offset);
5315 tlbl = newiTempLabel(NULL);
5316 size = AOP_SIZE(result);
5318 tlbl1 = newiTempLabel(NULL);
5320 /* if it is only one byte then */
5322 symbol *tlbl1 = newiTempLabel(NULL);
5324 l = aopGet(AOP(left),0,FALSE,FALSE);
5326 emitcode("sjmp","%05d$",tlbl1->key+100);
5327 emitcode("","%05d$:",tlbl->key+100);
5328 emitcode("add","a,acc");
5329 emitcode("","%05d$:",tlbl1->key+100);
5330 emitcode("djnz","b,%05d$",tlbl->key+100);
5331 aopPut(AOP(result),"a",0);
5335 reAdjustPreg(AOP(result));
5337 emitcode("sjmp","%05d$",tlbl1->key+100);
5338 emitcode("","%05d$:",tlbl->key+100);
5339 l = aopGet(AOP(result),offset,FALSE,FALSE);
5341 emitcode("add","a,acc");
5342 aopPut(AOP(result),"a",offset++);
5344 l = aopGet(AOP(result),offset,FALSE,FALSE);
5346 emitcode("rlc","a");
5347 aopPut(AOP(result),"a",offset++);
5349 reAdjustPreg(AOP(result));
5351 emitcode("","%05d$:",tlbl1->key+100);
5352 emitcode("djnz","b,%05d$",tlbl->key+100);
5354 freeAsmop(left,NULL,ic,TRUE);
5355 freeAsmop(result,NULL,ic,TRUE);
5358 /*-----------------------------------------------------------------*/
5359 /* genrshOne - right shift a one byte quantity by known count */
5360 /*-----------------------------------------------------------------*/
5361 static void genrshOne (operand *result, operand *left,
5362 int shCount, int sign)
5364 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
5367 /*-----------------------------------------------------------------*/
5368 /* genrshTwo - right shift two bytes by known amount != 0 */
5369 /*-----------------------------------------------------------------*/
5370 static void genrshTwo (operand *result,operand *left,
5371 int shCount, int sign)
5373 /* if shCount >= 8 */
5377 shiftR1Left2Result(left, MSB16, result, LSB,
5380 movLeft2Result(left, MSB16, result, LSB, sign);
5381 addSign(result, MSB16, sign);
5384 /* 1 <= shCount <= 7 */
5386 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
5389 /*-----------------------------------------------------------------*/
5390 /* shiftRLong - shift right one long from left to result */
5391 /* offl = LSB or MSB16 */
5392 /*-----------------------------------------------------------------*/
5393 static void shiftRLong (operand *left, int offl,
5394 operand *result, int sign)
5397 emitcode("clr","c");
5398 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
5400 emitcode("mov","c,acc.7");
5401 emitcode("rrc","a");
5402 aopPut(AOP(result),"a",MSB32-offl);
5404 /* add sign of "a" */
5405 addSign(result, MSB32, sign);
5407 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
5408 emitcode("rrc","a");
5409 aopPut(AOP(result),"a",MSB24-offl);
5411 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
5412 emitcode("rrc","a");
5413 aopPut(AOP(result),"a",MSB16-offl);
5416 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
5417 emitcode("rrc","a");
5418 aopPut(AOP(result),"a",LSB);
5422 /*-----------------------------------------------------------------*/
5423 /* genrshFour - shift four byte by a known amount != 0 */
5424 /*-----------------------------------------------------------------*/
5425 static void genrshFour (operand *result, operand *left,
5426 int shCount, int sign)
5428 /* if shifting more that 3 bytes */
5429 if(shCount >= 24 ) {
5432 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
5434 movLeft2Result(left, MSB32, result, LSB, sign);
5435 addSign(result, MSB16, sign);
5437 else if(shCount >= 16){
5440 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
5442 movLeft2Result(left, MSB24, result, LSB, 0);
5443 movLeft2Result(left, MSB32, result, MSB16, sign);
5445 addSign(result, MSB24, sign);
5447 else if(shCount >= 8){
5450 shiftRLong(left, MSB16, result, sign);
5451 else if(shCount == 0){
5452 movLeft2Result(left, MSB16, result, LSB, 0);
5453 movLeft2Result(left, MSB24, result, MSB16, 0);
5454 movLeft2Result(left, MSB32, result, MSB24, sign);
5455 addSign(result, MSB32, sign);
5458 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
5459 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
5460 /* the last shift is signed */
5461 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
5462 addSign(result, MSB32, sign);
5465 else{ /* 1 <= shCount <= 7 */
5467 shiftRLong(left, LSB, result, sign);
5469 shiftRLong(result, LSB, result, sign);
5472 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
5473 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
5474 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
5479 /*-----------------------------------------------------------------*/
5480 /* genRightShiftLiteral - right shifting by known count */
5481 /*-----------------------------------------------------------------*/
5482 static void genRightShiftLiteral (operand *left,
5488 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5491 freeAsmop(right,NULL,ic,TRUE);
5493 aopOp(left,ic,FALSE);
5494 aopOp(result,ic,FALSE);
5497 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
5501 size = getDataSize(left);
5502 /* test the LEFT size !!! */
5504 /* I suppose that the left size >= result size */
5506 size = getDataSize(result);
5508 movLeft2Result(left, size, result, size, 0);
5511 else if(shCount >= (size * 8)){
5513 /* get sign in acc.7 */
5514 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
5515 addSign(result, LSB, sign);
5519 genrshOne (result,left,shCount,sign);
5523 genrshTwo (result,left,shCount,sign);
5527 genrshFour (result,left,shCount,sign);
5533 freeAsmop(left,NULL,ic,TRUE);
5534 freeAsmop(result,NULL,ic,TRUE);
5538 /*-----------------------------------------------------------------*/
5539 /* genSignedRightShift - right shift of signed number */
5540 /*-----------------------------------------------------------------*/
5541 static void genSignedRightShift (iCode *ic)
5543 operand *right, *left, *result;
5546 symbol *tlbl, *tlbl1 ;
5548 /* we do it the hard way put the shift count in b
5549 and loop thru preserving the sign */
5551 right = IC_RIGHT(ic);
5553 result = IC_RESULT(ic);
5555 aopOp(right,ic,FALSE);
5558 if ( AOP_TYPE(right) == AOP_LIT) {
5559 genRightShiftLiteral (left,right,result,ic,1);
5562 /* shift count is unknown then we have to form
5563 a loop get the loop count in B : Note: we take
5564 only the lower order byte since shifting
5565 more that 32 bits make no sense anyway, ( the
5566 largest size of an object can be only 32 bits ) */
5568 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5569 emitcode("inc","b");
5570 freeAsmop (right,NULL,ic,TRUE);
5571 aopOp(left,ic,FALSE);
5572 aopOp(result,ic,FALSE);
5574 /* now move the left to the result if they are not the
5576 if (!sameRegs(AOP(left),AOP(result)) &&
5577 AOP_SIZE(result) > 1) {
5579 size = AOP_SIZE(result);
5582 l = aopGet(AOP(left),offset,FALSE,TRUE);
5583 if (*l == '@' && IS_AOP_PREG(result)) {
5585 emitcode("mov","a,%s",l);
5586 aopPut(AOP(result),"a",offset);
5588 aopPut(AOP(result),l,offset);
5593 /* mov the highest order bit to OVR */
5594 tlbl = newiTempLabel(NULL);
5595 tlbl1= newiTempLabel(NULL);
5597 size = AOP_SIZE(result);
5599 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
5600 emitcode("rlc","a");
5601 emitcode("mov","ov,c");
5602 /* if it is only one byte then */
5604 l = aopGet(AOP(left),0,FALSE,FALSE);
5606 emitcode("sjmp","%05d$",tlbl1->key+100);
5607 emitcode("","%05d$:",tlbl->key+100);
5608 emitcode("mov","c,ov");
5609 emitcode("rrc","a");
5610 emitcode("","%05d$:",tlbl1->key+100);
5611 emitcode("djnz","b,%05d$",tlbl->key+100);
5612 aopPut(AOP(result),"a",0);
5616 reAdjustPreg(AOP(result));
5617 emitcode("sjmp","%05d$",tlbl1->key+100);
5618 emitcode("","%05d$:",tlbl->key+100);
5619 emitcode("mov","c,ov");
5621 l = aopGet(AOP(result),offset,FALSE,FALSE);
5623 emitcode("rrc","a");
5624 aopPut(AOP(result),"a",offset--);
5626 reAdjustPreg(AOP(result));
5627 emitcode("","%05d$:",tlbl1->key+100);
5628 emitcode("djnz","b,%05d$",tlbl->key+100);
5631 freeAsmop(left,NULL,ic,TRUE);
5632 freeAsmop(result,NULL,ic,TRUE);
5635 /*-----------------------------------------------------------------*/
5636 /* genRightShift - generate code for right shifting */
5637 /*-----------------------------------------------------------------*/
5638 static void genRightShift (iCode *ic)
5640 operand *right, *left, *result;
5644 symbol *tlbl, *tlbl1 ;
5646 /* if signed then we do it the hard way preserve the
5647 sign bit moving it inwards */
5648 retype = getSpec(operandType(IC_RESULT(ic)));
5650 if (!SPEC_USIGN(retype)) {
5651 genSignedRightShift (ic);
5655 /* signed & unsigned types are treated the same : i.e. the
5656 signed is NOT propagated inwards : quoting from the
5657 ANSI - standard : "for E1 >> E2, is equivalent to division
5658 by 2**E2 if unsigned or if it has a non-negative value,
5659 otherwise the result is implementation defined ", MY definition
5660 is that the sign does not get propagated */
5662 right = IC_RIGHT(ic);
5664 result = IC_RESULT(ic);
5666 aopOp(right,ic,FALSE);
5668 /* if the shift count is known then do it
5669 as efficiently as possible */
5670 if (AOP_TYPE(right) == AOP_LIT) {
5671 genRightShiftLiteral (left,right,result,ic, 0);
5675 /* shift count is unknown then we have to form
5676 a loop get the loop count in B : Note: we take
5677 only the lower order byte since shifting
5678 more that 32 bits make no sense anyway, ( the
5679 largest size of an object can be only 32 bits ) */
5681 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5682 emitcode("inc","b");
5683 freeAsmop (right,NULL,ic,TRUE);
5684 aopOp(left,ic,FALSE);
5685 aopOp(result,ic,FALSE);
5687 /* now move the left to the result if they are not the
5689 if (!sameRegs(AOP(left),AOP(result)) &&
5690 AOP_SIZE(result) > 1) {
5692 size = AOP_SIZE(result);
5695 l = aopGet(AOP(left),offset,FALSE,TRUE);
5696 if (*l == '@' && IS_AOP_PREG(result)) {
5698 emitcode("mov","a,%s",l);
5699 aopPut(AOP(result),"a",offset);
5701 aopPut(AOP(result),l,offset);
5706 tlbl = newiTempLabel(NULL);
5707 tlbl1= newiTempLabel(NULL);
5708 size = AOP_SIZE(result);
5711 /* if it is only one byte then */
5713 l = aopGet(AOP(left),0,FALSE,FALSE);
5715 emitcode("sjmp","%05d$",tlbl1->key+100);
5716 emitcode("","%05d$:",tlbl->key+100);
5718 emitcode("rrc","a");
5719 emitcode("","%05d$:",tlbl1->key+100);
5720 emitcode("djnz","b,%05d$",tlbl->key+100);
5721 aopPut(AOP(result),"a",0);
5725 reAdjustPreg(AOP(result));
5726 emitcode("sjmp","%05d$",tlbl1->key+100);
5727 emitcode("","%05d$:",tlbl->key+100);
5730 l = aopGet(AOP(result),offset,FALSE,FALSE);
5732 emitcode("rrc","a");
5733 aopPut(AOP(result),"a",offset--);
5735 reAdjustPreg(AOP(result));
5737 emitcode("","%05d$:",tlbl1->key+100);
5738 emitcode("djnz","b,%05d$",tlbl->key+100);
5741 freeAsmop(left,NULL,ic,TRUE);
5742 freeAsmop(result,NULL,ic,TRUE);
5745 /*-----------------------------------------------------------------*/
5746 /* genUnpackBits - generates code for unpacking bits */
5747 /*-----------------------------------------------------------------*/
5748 static void genUnpackBits (operand *result, char *rname, int ptype)
5755 etype = getSpec(operandType(result));
5757 /* read the first byte */
5762 emitcode("mov","a,@%s",rname);
5766 emitcode("movx","a,@%s",rname);
5770 emitcode("movx","a,@dptr");
5774 emitcode("clr","a");
5775 emitcode("movc","a","@a+dptr");
5779 emitcode("lcall","__gptrget");
5783 /* if we have bitdisplacement then it fits */
5784 /* into this byte completely or if length is */
5785 /* less than a byte */
5786 if ((shCnt = SPEC_BSTR(etype)) ||
5787 (SPEC_BLEN(etype) <= 8)) {
5789 /* shift right acc */
5792 emitcode("anl","a,#0x%02x",
5793 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
5794 aopPut(AOP(result),"a",offset);
5798 /* bit field did not fit in a byte */
5799 rlen = SPEC_BLEN(etype) - 8;
5800 aopPut(AOP(result),"a",offset++);
5807 emitcode("inc","%s",rname);
5808 emitcode("mov","a,@%s",rname);
5812 emitcode("inc","%s",rname);
5813 emitcode("movx","a,@%s",rname);
5817 emitcode("inc","dptr");
5818 emitcode("movx","a,@dptr");
5822 emitcode("clr","a");
5823 emitcode("inc","dptr");
5824 emitcode("movc","a","@a+dptr");
5828 emitcode("inc","dptr");
5829 emitcode("lcall","__gptrget");
5834 /* if we are done */
5838 aopPut(AOP(result),"a",offset++);
5843 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
5844 aopPut(AOP(result),"a",offset);
5851 /*-----------------------------------------------------------------*/
5852 /* genDataPointerGet - generates code when ptr offset is known */
5853 /*-----------------------------------------------------------------*/
5854 static void genDataPointerGet (operand *left,
5860 int size , offset = 0;
5861 aopOp(result,ic,TRUE);
5863 /* get the string representation of the name */
5864 l = aopGet(AOP(left),0,FALSE,TRUE);
5865 size = AOP_SIZE(result);
5868 sprintf(buffer,"(%s + %d)",l+1,offset);
5870 sprintf(buffer,"%s",l+1);
5871 aopPut(AOP(result),buffer,offset++);
5874 freeAsmop(left,NULL,ic,TRUE);
5875 freeAsmop(result,NULL,ic,TRUE);
5878 /*-----------------------------------------------------------------*/
5879 /* genNearPointerGet - emitcode for near pointer fetch */
5880 /*-----------------------------------------------------------------*/
5881 static void genNearPointerGet (operand *left,
5888 link *rtype, *retype;
5889 link *ltype = operandType(left);
5892 rtype = operandType(result);
5893 retype= getSpec(rtype);
5895 aopOp(left,ic,FALSE);
5897 /* if left is rematerialisable and
5898 result is not bit variable type and
5899 the left is pointer to data space i.e
5900 lower 128 bytes of space */
5901 if (AOP_TYPE(left) == AOP_IMMD &&
5902 !IS_BITVAR(retype) &&
5903 DCL_TYPE(ltype) == POINTER) {
5904 genDataPointerGet (left,result,ic);
5908 /* if the value is already in a pointer register
5909 then don't need anything more */
5910 if (!AOP_INPREG(AOP(left))) {
5911 /* otherwise get a free pointer register */
5913 preg = getFreePtr(ic,&aop,FALSE);
5914 emitcode("mov","%s,%s",
5916 aopGet(AOP(left),0,FALSE,TRUE));
5917 rname = preg->name ;
5919 rname = aopGet(AOP(left),0,FALSE,FALSE);
5921 freeAsmop(left,NULL,ic,TRUE);
5922 aopOp (result,ic,FALSE);
5924 /* if bitfield then unpack the bits */
5925 if (IS_BITVAR(retype))
5926 genUnpackBits (result,rname,POINTER);
5928 /* we have can just get the values */
5929 int size = AOP_SIZE(result);
5933 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
5935 emitcode("mov","a,@%s",rname);
5936 aopPut(AOP(result),"a",offset);
5938 sprintf(buffer,"@%s",rname);
5939 aopPut(AOP(result),buffer,offset);
5943 emitcode("inc","%s",rname);
5947 /* now some housekeeping stuff */
5949 /* we had to allocate for this iCode */
5950 freeAsmop(NULL,aop,ic,TRUE);
5952 /* we did not allocate which means left
5953 already in a pointer register, then
5954 if size > 0 && this could be used again
5955 we have to point it back to where it
5957 if (AOP_SIZE(result) > 1 &&
5958 !OP_SYMBOL(left)->remat &&
5959 ( OP_SYMBOL(left)->liveTo > ic->seq ||
5961 int size = AOP_SIZE(result) - 1;
5963 emitcode("dec","%s",rname);
5968 freeAsmop(result,NULL,ic,TRUE);
5972 /*-----------------------------------------------------------------*/
5973 /* genPagedPointerGet - emitcode for paged pointer fetch */
5974 /*-----------------------------------------------------------------*/
5975 static void genPagedPointerGet (operand *left,
5982 link *rtype, *retype;
5984 rtype = operandType(result);
5985 retype= getSpec(rtype);
5987 aopOp(left,ic,FALSE);
5989 /* if the value is already in a pointer register
5990 then don't need anything more */
5991 if (!AOP_INPREG(AOP(left))) {
5992 /* otherwise get a free pointer register */
5994 preg = getFreePtr(ic,&aop,FALSE);
5995 emitcode("mov","%s,%s",
5997 aopGet(AOP(left),0,FALSE,TRUE));
5998 rname = preg->name ;
6000 rname = aopGet(AOP(left),0,FALSE,FALSE);
6002 freeAsmop(left,NULL,ic,TRUE);
6003 aopOp (result,ic,FALSE);
6005 /* if bitfield then unpack the bits */
6006 if (IS_BITVAR(retype))
6007 genUnpackBits (result,rname,PPOINTER);
6009 /* we have can just get the values */
6010 int size = AOP_SIZE(result);
6015 emitcode("movx","a,@%s",rname);
6016 aopPut(AOP(result),"a",offset);
6021 emitcode("inc","%s",rname);
6025 /* now some housekeeping stuff */
6027 /* we had to allocate for this iCode */
6028 freeAsmop(NULL,aop,ic,TRUE);
6030 /* we did not allocate which means left
6031 already in a pointer register, then
6032 if size > 0 && this could be used again
6033 we have to point it back to where it
6035 if (AOP_SIZE(result) > 1 &&
6036 !OP_SYMBOL(left)->remat &&
6037 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6039 int size = AOP_SIZE(result) - 1;
6041 emitcode("dec","%s",rname);
6046 freeAsmop(result,NULL,ic,TRUE);
6051 /*-----------------------------------------------------------------*/
6052 /* genFarPointerGet - gget value from far space */
6053 /*-----------------------------------------------------------------*/
6054 static void genFarPointerGet (operand *left,
6055 operand *result, iCode *ic)
6058 link *retype = getSpec(operandType(result));
6060 aopOp(left,ic,FALSE);
6062 /* if the operand is already in dptr
6063 then we do nothing else we move the value to dptr */
6064 if (AOP_TYPE(left) != AOP_STR) {
6065 /* if this is remateriazable */
6066 if (AOP_TYPE(left) == AOP_IMMD)
6067 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6068 else { /* we need to get it byte by byte */
6069 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6070 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6071 if (options.model == MODEL_FLAT24)
6073 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6077 /* so dptr know contains the address */
6078 freeAsmop(left,NULL,ic,TRUE);
6079 aopOp(result,ic,FALSE);
6081 /* if bit then unpack */
6082 if (IS_BITVAR(retype))
6083 genUnpackBits(result,"dptr",FPOINTER);
6085 size = AOP_SIZE(result);
6089 emitcode("movx","a,@dptr");
6090 aopPut(AOP(result),"a",offset++);
6092 emitcode("inc","dptr");
6096 freeAsmop(result,NULL,ic,TRUE);
6099 /*-----------------------------------------------------------------*/
6100 /* emitcodePointerGet - gget value from code space */
6101 /*-----------------------------------------------------------------*/
6102 static void emitcodePointerGet (operand *left,
6103 operand *result, iCode *ic)
6106 link *retype = getSpec(operandType(result));
6108 aopOp(left,ic,FALSE);
6110 /* if the operand is already in dptr
6111 then we do nothing else we move the value to dptr */
6112 if (AOP_TYPE(left) != AOP_STR) {
6113 /* if this is remateriazable */
6114 if (AOP_TYPE(left) == AOP_IMMD)
6115 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6116 else { /* we need to get it byte by byte */
6117 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6118 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6119 if (options.model == MODEL_FLAT24)
6121 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6125 /* so dptr know contains the address */
6126 freeAsmop(left,NULL,ic,TRUE);
6127 aopOp(result,ic,FALSE);
6129 /* if bit then unpack */
6130 if (IS_BITVAR(retype))
6131 genUnpackBits(result,"dptr",CPOINTER);
6133 size = AOP_SIZE(result);
6137 emitcode("clr","a");
6138 emitcode("movc","a,@a+dptr");
6139 aopPut(AOP(result),"a",offset++);
6141 emitcode("inc","dptr");
6145 freeAsmop(result,NULL,ic,TRUE);
6148 /*-----------------------------------------------------------------*/
6149 /* genGenPointerGet - gget value from generic pointer space */
6150 /*-----------------------------------------------------------------*/
6151 static void genGenPointerGet (operand *left,
6152 operand *result, iCode *ic)
6155 link *retype = getSpec(operandType(result));
6157 aopOp(left,ic,FALSE);
6159 /* if the operand is already in dptr
6160 then we do nothing else we move the value to dptr */
6161 if (AOP_TYPE(left) != AOP_STR) {
6162 /* if this is remateriazable */
6163 if (AOP_TYPE(left) == AOP_IMMD) {
6164 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6165 emitcode("mov","b,#%d",pointerCode(retype));
6167 else { /* we need to get it byte by byte */
6168 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6169 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6170 if (options.model == MODEL_FLAT24)
6172 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6173 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
6177 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
6181 /* so dptr know contains the address */
6182 freeAsmop(left,NULL,ic,TRUE);
6183 aopOp(result,ic,FALSE);
6185 /* if bit then unpack */
6186 if (IS_BITVAR(retype))
6187 genUnpackBits(result,"dptr",GPOINTER);
6189 size = AOP_SIZE(result);
6193 emitcode("lcall","__gptrget");
6194 aopPut(AOP(result),"a",offset++);
6196 emitcode("inc","dptr");
6200 freeAsmop(result,NULL,ic,TRUE);
6203 /*-----------------------------------------------------------------*/
6204 /* genPointerGet - generate code for pointer get */
6205 /*-----------------------------------------------------------------*/
6206 static void genPointerGet (iCode *ic)
6208 operand *left, *result ;
6213 result = IC_RESULT(ic) ;
6215 /* depending on the type of pointer we need to
6216 move it to the correct pointer register */
6217 type = operandType(left);
6218 etype = getSpec(type);
6219 /* if left is of type of pointer then it is simple */
6220 if (IS_PTR(type) && !IS_FUNC(type->next))
6221 p_type = DCL_TYPE(type);
6223 /* we have to go by the storage class */
6224 p_type = PTR_TYPE(SPEC_OCLS(etype));
6226 /* if (SPEC_OCLS(etype)->codesp ) { */
6227 /* p_type = CPOINTER ; */
6230 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6231 /* p_type = FPOINTER ; */
6233 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6234 /* p_type = PPOINTER; */
6236 /* if (SPEC_OCLS(etype) == idata ) */
6237 /* p_type = IPOINTER; */
6239 /* p_type = POINTER ; */
6242 /* now that we have the pointer type we assign
6243 the pointer values */
6248 genNearPointerGet (left,result,ic);
6252 genPagedPointerGet(left,result,ic);
6256 genFarPointerGet (left,result,ic);
6260 emitcodePointerGet (left,result,ic);
6264 genGenPointerGet (left,result,ic);
6270 /*-----------------------------------------------------------------*/
6271 /* genPackBits - generates code for packed bit storage */
6272 /*-----------------------------------------------------------------*/
6273 static void genPackBits (link *etype ,
6275 char *rname, int p_type)
6283 blen = SPEC_BLEN(etype);
6284 bstr = SPEC_BSTR(etype);
6286 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6289 /* if the bit lenth is less than or */
6290 /* it exactly fits a byte then */
6291 if (SPEC_BLEN(etype) <= 8 ) {
6292 shCount = SPEC_BSTR(etype) ;
6294 /* shift left acc */
6297 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6302 emitcode ("mov","b,a");
6303 emitcode("mov","a,@%s",rname);
6307 emitcode ("mov","b,a");
6308 emitcode("movx","a,@dptr");
6312 emitcode ("push","b");
6313 emitcode ("push","acc");
6314 emitcode ("lcall","__gptrget");
6315 emitcode ("pop","b");
6319 emitcode ("anl","a,#0x%02x",(unsigned char)
6320 ((unsigned char)(0xFF << (blen+bstr)) |
6321 (unsigned char)(0xFF >> (8-bstr)) ) );
6322 emitcode ("orl","a,b");
6323 if (p_type == GPOINTER)
6324 emitcode("pop","b");
6330 emitcode("mov","@%s,a",rname);
6334 emitcode("movx","@dptr,a");
6338 emitcode("lcall","__gptrput");
6343 if ( SPEC_BLEN(etype) <= 8 )
6346 emitcode("inc","%s",rname);
6347 rLen = SPEC_BLEN(etype) ;
6349 /* now generate for lengths greater than one byte */
6352 l = aopGet(AOP(right),offset++,FALSE,TRUE);
6362 emitcode("mov","@%s,a",rname);
6364 emitcode("mov","@%s,%s",rname,l);
6369 emitcode("movx","@dptr,a");
6374 emitcode("lcall","__gptrput");
6377 emitcode ("inc","%s",rname);
6382 /* last last was not complete */
6384 /* save the byte & read byte */
6387 emitcode ("mov","b,a");
6388 emitcode("mov","a,@%s",rname);
6392 emitcode ("mov","b,a");
6393 emitcode("movx","a,@dptr");
6397 emitcode ("push","b");
6398 emitcode ("push","acc");
6399 emitcode ("lcall","__gptrget");
6400 emitcode ("pop","b");
6404 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
6405 emitcode ("orl","a,b");
6408 if (p_type == GPOINTER)
6409 emitcode("pop","b");
6414 emitcode("mov","@%s,a",rname);
6418 emitcode("movx","@dptr,a");
6422 emitcode("lcall","__gptrput");
6426 /*-----------------------------------------------------------------*/
6427 /* genDataPointerSet - remat pointer to data space */
6428 /*-----------------------------------------------------------------*/
6429 static void genDataPointerSet(operand *right,
6433 int size, offset = 0 ;
6434 char *l, buffer[256];
6436 aopOp(right,ic,FALSE);
6438 l = aopGet(AOP(result),0,FALSE,TRUE);
6439 size = AOP_SIZE(right);
6442 sprintf(buffer,"(%s + %d)",l+1,offset);
6444 sprintf(buffer,"%s",l+1);
6445 emitcode("mov","%s,%s",buffer,
6446 aopGet(AOP(right),offset++,FALSE,FALSE));
6449 freeAsmop(right,NULL,ic,TRUE);
6450 freeAsmop(result,NULL,ic,TRUE);
6453 /*-----------------------------------------------------------------*/
6454 /* genNearPointerSet - emitcode for near pointer put */
6455 /*-----------------------------------------------------------------*/
6456 static void genNearPointerSet (operand *right,
6464 link *ptype = operandType(result);
6466 retype= getSpec(operandType(right));
6468 aopOp(result,ic,FALSE);
6470 /* if the result is rematerializable &
6471 in data space & not a bit variable */
6472 if (AOP_TYPE(result) == AOP_IMMD &&
6473 DCL_TYPE(ptype) == POINTER &&
6474 !IS_BITVAR(retype)) {
6475 genDataPointerSet (right,result,ic);
6479 /* if the value is already in a pointer register
6480 then don't need anything more */
6481 if (!AOP_INPREG(AOP(result))) {
6482 /* otherwise get a free pointer register */
6484 preg = getFreePtr(ic,&aop,FALSE);
6485 emitcode("mov","%s,%s",
6487 aopGet(AOP(result),0,FALSE,TRUE));
6488 rname = preg->name ;
6490 rname = aopGet(AOP(result),0,FALSE,FALSE);
6492 freeAsmop(result,NULL,ic,TRUE);
6493 aopOp (right,ic,FALSE);
6495 /* if bitfield then unpack the bits */
6496 if (IS_BITVAR(retype))
6497 genPackBits (retype,right,rname,POINTER);
6499 /* we have can just get the values */
6500 int size = AOP_SIZE(right);
6504 l = aopGet(AOP(right),offset,FALSE,TRUE);
6507 emitcode("mov","@%s,a",rname);
6509 emitcode("mov","@%s,%s",rname,l);
6511 emitcode("inc","%s",rname);
6516 /* now some housekeeping stuff */
6518 /* we had to allocate for this iCode */
6519 freeAsmop(NULL,aop,ic,TRUE);
6521 /* we did not allocate which means left
6522 already in a pointer register, then
6523 if size > 0 && this could be used again
6524 we have to point it back to where it
6526 if (AOP_SIZE(right) > 1 &&
6527 !OP_SYMBOL(result)->remat &&
6528 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6530 int size = AOP_SIZE(right) - 1;
6532 emitcode("dec","%s",rname);
6537 freeAsmop(right,NULL,ic,TRUE);
6542 /*-----------------------------------------------------------------*/
6543 /* genPagedPointerSet - emitcode for Paged pointer put */
6544 /*-----------------------------------------------------------------*/
6545 static void genPagedPointerSet (operand *right,
6554 retype= getSpec(operandType(right));
6556 aopOp(result,ic,FALSE);
6558 /* if the value is already in a pointer register
6559 then don't need anything more */
6560 if (!AOP_INPREG(AOP(result))) {
6561 /* otherwise get a free pointer register */
6563 preg = getFreePtr(ic,&aop,FALSE);
6564 emitcode("mov","%s,%s",
6566 aopGet(AOP(result),0,FALSE,TRUE));
6567 rname = preg->name ;
6569 rname = aopGet(AOP(result),0,FALSE,FALSE);
6571 freeAsmop(result,NULL,ic,TRUE);
6572 aopOp (right,ic,FALSE);
6574 /* if bitfield then unpack the bits */
6575 if (IS_BITVAR(retype))
6576 genPackBits (retype,right,rname,PPOINTER);
6578 /* we have can just get the values */
6579 int size = AOP_SIZE(right);
6583 l = aopGet(AOP(right),offset,FALSE,TRUE);
6586 emitcode("movx","@%s,a",rname);
6589 emitcode("inc","%s",rname);
6595 /* now some housekeeping stuff */
6597 /* we had to allocate for this iCode */
6598 freeAsmop(NULL,aop,ic,TRUE);
6600 /* we did not allocate which means left
6601 already in a pointer register, then
6602 if size > 0 && this could be used again
6603 we have to point it back to where it
6605 if (AOP_SIZE(right) > 1 &&
6606 !OP_SYMBOL(result)->remat &&
6607 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6609 int size = AOP_SIZE(right) - 1;
6611 emitcode("dec","%s",rname);
6616 freeAsmop(right,NULL,ic,TRUE);
6621 /*-----------------------------------------------------------------*/
6622 /* genFarPointerSet - set value from far space */
6623 /*-----------------------------------------------------------------*/
6624 static void genFarPointerSet (operand *right,
6625 operand *result, iCode *ic)
6628 link *retype = getSpec(operandType(right));
6630 aopOp(result,ic,FALSE);
6632 /* if the operand is already in dptr
6633 then we do nothing else we move the value to dptr */
6634 if (AOP_TYPE(result) != AOP_STR) {
6635 /* if this is remateriazable */
6636 if (AOP_TYPE(result) == AOP_IMMD)
6637 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6638 else { /* we need to get it byte by byte */
6639 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6640 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6641 if (options.model == MODEL_FLAT24)
6643 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6647 /* so dptr know contains the address */
6648 freeAsmop(result,NULL,ic,TRUE);
6649 aopOp(right,ic,FALSE);
6651 /* if bit then unpack */
6652 if (IS_BITVAR(retype))
6653 genPackBits(retype,right,"dptr",FPOINTER);
6655 size = AOP_SIZE(right);
6659 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6661 emitcode("movx","@dptr,a");
6663 emitcode("inc","dptr");
6667 freeAsmop(right,NULL,ic,TRUE);
6670 /*-----------------------------------------------------------------*/
6671 /* genGenPointerSet - set value from generic pointer space */
6672 /*-----------------------------------------------------------------*/
6673 static void genGenPointerSet (operand *right,
6674 operand *result, iCode *ic)
6677 link *retype = getSpec(operandType(right));
6679 aopOp(result,ic,FALSE);
6681 /* if the operand is already in dptr
6682 then we do nothing else we move the value to dptr */
6683 if (AOP_TYPE(result) != AOP_STR) {
6684 /* if this is remateriazable */
6685 if (AOP_TYPE(result) == AOP_IMMD) {
6686 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6687 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
6689 else { /* we need to get it byte by byte */
6690 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6691 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6692 if (options.model == MODEL_FLAT24)
6694 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6695 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
6699 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
6703 /* so dptr know contains the address */
6704 freeAsmop(result,NULL,ic,TRUE);
6705 aopOp(right,ic,FALSE);
6707 /* if bit then unpack */
6708 if (IS_BITVAR(retype))
6709 genPackBits(retype,right,"dptr",GPOINTER);
6711 size = AOP_SIZE(right);
6715 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6717 emitcode("lcall","__gptrput");
6719 emitcode("inc","dptr");
6723 freeAsmop(right,NULL,ic,TRUE);
6726 /*-----------------------------------------------------------------*/
6727 /* genPointerSet - stores the value into a pointer location */
6728 /*-----------------------------------------------------------------*/
6729 static void genPointerSet (iCode *ic)
6731 operand *right, *result ;
6735 right = IC_RIGHT(ic);
6736 result = IC_RESULT(ic) ;
6738 /* depending on the type of pointer we need to
6739 move it to the correct pointer register */
6740 type = operandType(result);
6741 etype = getSpec(type);
6742 /* if left is of type of pointer then it is simple */
6743 if (IS_PTR(type) && !IS_FUNC(type->next)) {
6744 p_type = DCL_TYPE(type);
6747 /* we have to go by the storage class */
6748 p_type = PTR_TYPE(SPEC_OCLS(etype));
6750 /* if (SPEC_OCLS(etype)->codesp ) { */
6751 /* p_type = CPOINTER ; */
6754 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6755 /* p_type = FPOINTER ; */
6757 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6758 /* p_type = PPOINTER ; */
6760 /* if (SPEC_OCLS(etype) == idata ) */
6761 /* p_type = IPOINTER ; */
6763 /* p_type = POINTER ; */
6766 /* now that we have the pointer type we assign
6767 the pointer values */
6772 genNearPointerSet (right,result,ic);
6776 genPagedPointerSet (right,result,ic);
6780 genFarPointerSet (right,result,ic);
6784 genGenPointerSet (right,result,ic);
6790 /*-----------------------------------------------------------------*/
6791 /* genIfx - generate code for Ifx statement */
6792 /*-----------------------------------------------------------------*/
6793 static void genIfx (iCode *ic, iCode *popIc)
6795 operand *cond = IC_COND(ic);
6798 aopOp(cond,ic,FALSE);
6800 /* get the value into acc */
6801 if (AOP_TYPE(cond) != AOP_CRY)
6805 /* the result is now in the accumulator */
6806 freeAsmop(cond,NULL,ic,TRUE);
6808 /* if there was something to be popped then do it */
6812 /* if the condition is a bit variable */
6813 if (isbit && IS_ITEMP(cond) &&
6815 genIfxJump(ic,SPIL_LOC(cond)->rname);
6817 if (isbit && !IS_ITEMP(cond))
6818 genIfxJump(ic,OP_SYMBOL(cond)->rname);
6825 /*-----------------------------------------------------------------*/
6826 /* genAddrOf - generates code for address of */
6827 /*-----------------------------------------------------------------*/
6828 static void genAddrOf (iCode *ic)
6830 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
6833 aopOp(IC_RESULT(ic),ic,FALSE);
6835 /* if the operand is on the stack then we
6836 need to get the stack offset of this
6839 /* if it has an offset then we need to compute
6842 emitcode("mov","a,_bp");
6843 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
6844 aopPut(AOP(IC_RESULT(ic)),"a",0);
6846 /* we can just move _bp */
6847 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
6848 /* fill the result with zero */
6849 size = AOP_SIZE(IC_RESULT(ic)) - 1;
6852 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
6857 /* object not on stack then we need the name */
6858 size = AOP_SIZE(IC_RESULT(ic));
6862 char s[SDCC_NAME_MAX];
6864 sprintf(s,"#(%s >> %d)",
6868 sprintf(s,"#%s",sym->rname);
6869 aopPut(AOP(IC_RESULT(ic)),s,offset++);
6873 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
6877 /*-----------------------------------------------------------------*/
6878 /* genFarFarAssign - assignment when both are in far space */
6879 /*-----------------------------------------------------------------*/
6880 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
6882 int size = AOP_SIZE(right);
6885 /* first push the right side on to the stack */
6887 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6889 emitcode ("push","acc");
6892 freeAsmop(right,NULL,ic,FALSE);
6893 /* now assign DPTR to result */
6894 aopOp(result,ic,FALSE);
6895 size = AOP_SIZE(result);
6897 emitcode ("pop","acc");
6898 aopPut(AOP(result),"a",--offset);
6900 freeAsmop(result,NULL,ic,FALSE);
6904 /*-----------------------------------------------------------------*/
6905 /* genAssign - generate code for assignment */
6906 /*-----------------------------------------------------------------*/
6907 static void genAssign (iCode *ic)
6909 operand *result, *right;
6911 unsigned long lit = 0L;
6913 result = IC_RESULT(ic);
6914 right = IC_RIGHT(ic) ;
6916 /* if they are the same */
6917 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
6920 aopOp(right,ic,FALSE);
6922 /* special case both in far space */
6923 if (AOP_TYPE(right) == AOP_DPTR &&
6924 IS_TRUE_SYMOP(result) &&
6925 isOperandInFarSpace(result)) {
6927 genFarFarAssign (result,right,ic);
6931 aopOp(result,ic,TRUE);
6933 /* if they are the same registers */
6934 if (sameRegs(AOP(right),AOP(result)))
6937 /* if the result is a bit */
6938 if (AOP_TYPE(result) == AOP_CRY) {
6940 /* if the right size is a literal then
6941 we know what the value is */
6942 if (AOP_TYPE(right) == AOP_LIT) {
6943 if (((int) operandLitValue(right)))
6944 aopPut(AOP(result),one,0);
6946 aopPut(AOP(result),zero,0);
6950 /* the right is also a bit variable */
6951 if (AOP_TYPE(right) == AOP_CRY) {
6952 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6953 aopPut(AOP(result),"c",0);
6959 aopPut(AOP(result),"a",0);
6963 /* bit variables done */
6965 size = AOP_SIZE(result);
6967 if(AOP_TYPE(right) == AOP_LIT)
6968 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6970 (AOP_TYPE(result) != AOP_REG) &&
6971 (AOP_TYPE(right) == AOP_LIT) &&
6972 !IS_FLOAT(operandType(right)) &&
6974 emitcode("clr","a");
6976 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
6977 aopPut(AOP(result),"a",size);
6980 aopGet(AOP(right),size,FALSE,FALSE),
6986 aopGet(AOP(right),offset,FALSE,FALSE),
6993 freeAsmop (right,NULL,ic,FALSE);
6994 freeAsmop (result,NULL,ic,TRUE);
6997 /*-----------------------------------------------------------------*/
6998 /* genJumpTab - genrates code for jump table */
6999 /*-----------------------------------------------------------------*/
7000 static void genJumpTab (iCode *ic)
7005 aopOp(IC_JTCOND(ic),ic,FALSE);
7006 /* get the condition into accumulator */
7007 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
7009 /* multiply by three */
7010 emitcode("add","a,acc");
7011 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
7012 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7014 jtab = newiTempLabel(NULL);
7015 emitcode("mov","dptr,#%05d$",jtab->key+100);
7016 emitcode("jmp","@a+dptr");
7017 emitcode("","%05d$:",jtab->key+100);
7018 /* now generate the jump labels */
7019 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
7020 jtab = setNextItem(IC_JTLABELS(ic)))
7021 emitcode("ljmp","%05d$",jtab->key+100);
7025 /*-----------------------------------------------------------------*/
7026 /* genCast - gen code for casting */
7027 /*-----------------------------------------------------------------*/
7028 static void genCast (iCode *ic)
7030 operand *result = IC_RESULT(ic);
7031 link *ctype = operandType(IC_LEFT(ic));
7032 operand *right = IC_RIGHT(ic);
7035 /* if they are equivalent then do nothing */
7036 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
7039 aopOp(right,ic,FALSE) ;
7040 aopOp(result,ic,FALSE);
7042 /* if the result is a bit */
7043 if (AOP_TYPE(result) == AOP_CRY) {
7044 /* if the right size is a literal then
7045 we know what the value is */
7046 if (AOP_TYPE(right) == AOP_LIT) {
7047 if (((int) operandLitValue(right)))
7048 aopPut(AOP(result),one,0);
7050 aopPut(AOP(result),zero,0);
7055 /* the right is also a bit variable */
7056 if (AOP_TYPE(right) == AOP_CRY) {
7057 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7058 aopPut(AOP(result),"c",0);
7064 aopPut(AOP(result),"a",0);
7068 /* if they are the same size : or less */
7069 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
7071 /* if they are in the same place */
7072 if (sameRegs(AOP(right),AOP(result)))
7075 /* if they in different places then copy */
7076 size = AOP_SIZE(result);
7080 aopGet(AOP(right),offset,FALSE,FALSE),
7088 /* if the result is of type pointer */
7089 if (IS_PTR(ctype)) {
7092 link *type = operandType(right);
7093 link *etype = getSpec(type);
7095 /* pointer to generic pointer */
7096 if (IS_GENPTR(ctype)) {
7100 p_type = DCL_TYPE(type);
7102 /* we have to go by the storage class */
7103 p_type = PTR_TYPE(SPEC_OCLS(etype));
7105 /* if (SPEC_OCLS(etype)->codesp ) */
7106 /* p_type = CPOINTER ; */
7108 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7109 /* p_type = FPOINTER ; */
7111 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7112 /* p_type = PPOINTER; */
7114 /* if (SPEC_OCLS(etype) == idata ) */
7115 /* p_type = IPOINTER ; */
7117 /* p_type = POINTER ; */
7120 /* the first two bytes are known */
7121 size = GPTRSIZE - 1;
7125 aopGet(AOP(right),offset,FALSE,FALSE),
7129 /* the last byte depending on type */
7146 /* this should never happen */
7147 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7148 "got unknown pointer type");
7151 aopPut(AOP(result),l, GPTRSIZE - 1);
7155 /* just copy the pointers */
7156 size = AOP_SIZE(result);
7160 aopGet(AOP(right),offset,FALSE,FALSE),
7167 /* so we now know that the size of destination is greater
7168 than the size of the source */
7169 /* we move to result for the size of source */
7170 size = AOP_SIZE(right);
7174 aopGet(AOP(right),offset,FALSE,FALSE),
7179 /* now depending on the sign of the destination */
7180 size = AOP_SIZE(result) - AOP_SIZE(right);
7181 /* if unsigned or not an integral type */
7182 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
7184 aopPut(AOP(result),zero,offset++);
7186 /* we need to extend the sign :{ */
7187 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
7190 emitcode("rlc","a");
7191 emitcode("subb","a,acc");
7193 aopPut(AOP(result),"a",offset++);
7196 /* we are done hurray !!!! */
7199 freeAsmop(right,NULL,ic,TRUE);
7200 freeAsmop(result,NULL,ic,TRUE);
7204 /*-----------------------------------------------------------------*/
7205 /* genDjnz - generate decrement & jump if not zero instrucion */
7206 /*-----------------------------------------------------------------*/
7207 static int genDjnz (iCode *ic, iCode *ifx)
7213 /* if the if condition has a false label
7214 then we cannot save */
7218 /* if the minus is not of the form
7220 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
7221 !IS_OP_LITERAL(IC_RIGHT(ic)))
7224 if (operandLitValue(IC_RIGHT(ic)) != 1)
7227 /* if the size of this greater than one then no
7229 if (getSize(operandType(IC_RESULT(ic))) > 1)
7232 /* otherwise we can save BIG */
7233 lbl = newiTempLabel(NULL);
7234 lbl1= newiTempLabel(NULL);
7236 aopOp(IC_RESULT(ic),ic,FALSE);
7238 if (IS_AOP_PREG(IC_RESULT(ic))) {
7239 emitcode("dec","%s",
7240 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7241 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7242 emitcode("jnz","%05d$",lbl->key+100);
7244 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
7247 emitcode ("sjmp","%05d$",lbl1->key+100);
7248 emitcode ("","%05d$:",lbl->key+100);
7249 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
7250 emitcode ("","%05d$:",lbl1->key+100);
7252 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7257 /*-----------------------------------------------------------------*/
7258 /* genReceive - generate code for a receive iCode */
7259 /*-----------------------------------------------------------------*/
7260 static void genReceive (iCode *ic)
7262 if (isOperandInFarSpace(IC_RESULT(ic)) &&
7263 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
7264 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
7266 int size = getSize(operandType(IC_RESULT(ic)));
7267 int offset = fReturnSize - size;
7269 emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
7270 fReturn[fReturnSize - offset - 1] : "acc"));
7273 aopOp(IC_RESULT(ic),ic,FALSE);
7274 size = AOP_SIZE(IC_RESULT(ic));
7277 emitcode ("pop","acc");
7278 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
7283 aopOp(IC_RESULT(ic),ic,FALSE);
7285 assignResultValue(IC_RESULT(ic));
7288 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7291 /*-----------------------------------------------------------------*/
7292 /* gen51Code - generate code for 8051 based controllers */
7293 /*-----------------------------------------------------------------*/
7294 void gen51Code (iCode *lic)
7299 lineHead = lineCurr = NULL;
7301 /* if debug information required */
7302 /* if (options.debug && currFunc) { */
7304 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
7306 if (IS_STATIC(currFunc->etype))
7307 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
7309 emitcode("","G$%s$0$0 ==.",currFunc->name);
7312 /* stack pointer name */
7313 if (options.useXstack)
7319 for (ic = lic ; ic ; ic = ic->next ) {
7321 if ( cln != ic->lineno ) {
7322 if ( options.debug ) {
7324 emitcode("","C$%s$%d$%d$%d ==.",
7325 ic->filename,ic->lineno,
7326 ic->level,ic->block);
7329 emitcode(";","%s %d",ic->filename,ic->lineno);
7332 /* if the result is marked as
7333 spilt and rematerializable or code for
7334 this has already been generated then
7336 if (resultRemat(ic) || ic->generated )
7339 /* depending on the operation */
7358 /* IPOP happens only when trying to restore a
7359 spilt live range, if there is an ifx statement
7360 following this pop then the if statement might
7361 be using some of the registers being popped which
7362 would destory the contents of the register so
7363 we need to check for this condition and handle it */
7365 ic->next->op == IFX &&
7366 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
7367 genIfx (ic->next,ic);
7385 genEndFunction (ic);
7405 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
7422 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
7426 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
7433 /* note these two are xlated by algebraic equivalence
7434 during parsing SDCC.y */
7435 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7436 "got '>=' or '<=' shouldn't have come here");
7440 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
7452 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
7456 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
7460 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
7487 case GET_VALUE_AT_ADDRESS:
7492 if (POINTER_SET(ic))
7519 addSet(&_G.sendSet,ic);
7524 /* piCode(ic,stdout); */
7530 /* now we are ready to call the
7531 peep hole optimizer */
7532 if (!options.nopeep)
7533 peepHole (&lineHead);
7535 /* now do the actual printing */
7536 printLine (lineHead,codeOutFile);