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 && !options.stack10bit) || 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) {
287 emitcode("push","acc");
289 emitcode("mov","a,_bp");
290 emitcode("add","a,#0x%02x",
292 ((char)(sym->stack - _G.nRegsSaved )) :
293 ((char)sym->stack)) & 0xff);
294 emitcode("mov","%s,a",
295 aop->aopu.aop_ptr->name);
298 emitcode("pop","acc");
300 emitcode("mov","%s,#%s",
301 aop->aopu.aop_ptr->name,
303 aop->paged = space->paged;
305 aop->aopu.aop_stk = sym->stack;
309 if (sym->onStack && options.stack10bit)
311 /* It's on the 10 bit stack, which is located in
318 "*** Internal error: 10 bit stack var used as result.\n");
319 emitcode(";", "look at me!");
324 emitcode("push","acc");
326 emitcode("mov","a,_bp");
327 emitcode("add","a,#0x%02x",
329 ((char)(sym->stack - _G.nRegsSaved )) :
330 ((char)sym->stack)) & 0xff);
334 emitcode (";", "#switchDPTR(2)");
336 emitcode ("mov","dpx,#0x40");
337 emitcode ("mov","dph,#0x00");
338 emitcode ("mov", "dpl, a");
341 emitcode (";", "#switchDPTR(1)");
345 emitcode("pop","acc");
349 sym->aop = aop = newAsmop(AOP_DPTR);
353 sym->aop = aop = newAsmop(AOP_DPTR2);
355 aop->size = getSize(sym->type);
359 /* if in bit space */
360 if (IN_BITSPACE(space)) {
361 sym->aop = aop = newAsmop (AOP_CRY);
362 aop->aopu.aop_dir = sym->rname ;
363 aop->size = getSize(sym->type);
366 /* if it is in direct space */
367 if (IN_DIRSPACE(space)) {
368 sym->aop = aop = newAsmop (AOP_DIR);
369 aop->aopu.aop_dir = sym->rname ;
370 aop->size = getSize(sym->type);
374 /* special case for a function */
375 if (IS_FUNC(sym->type)) {
376 sym->aop = aop = newAsmop(AOP_IMMD);
377 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
378 strcpy(aop->aopu.aop_immd,sym->rname);
379 aop->size = FPTRSIZE;
383 /* only remaining is far space */
384 /* in which case DPTR gets the address */
385 sym->aop = aop = newAsmop(AOP_DPTR);
386 emitcode ("mov","dptr,#%s", sym->rname);
387 aop->size = getSize(sym->type);
389 /* if it is in code space */
390 if (IN_CODESPACE(space))
396 /*-----------------------------------------------------------------*/
397 /* aopForRemat - rematerialzes an object */
398 /*-----------------------------------------------------------------*/
399 static asmop *aopForRemat (symbol *sym)
402 iCode *ic = sym->rematiCode;
403 asmop *aop = newAsmop(AOP_IMMD);
407 /* if plus or minus print the right hand side */
408 if (ic->op == '+' || ic->op == '-') {
409 sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
412 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
416 /* we reached the end */
417 sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
421 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
422 strcpy(aop->aopu.aop_immd,buffer);
426 /*-----------------------------------------------------------------*/
427 /* regsInCommon - two operands have some registers in common */
428 /*-----------------------------------------------------------------*/
429 static bool regsInCommon (operand *op1, operand *op2)
434 /* if they have registers in common */
435 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
438 sym1 = OP_SYMBOL(op1);
439 sym2 = OP_SYMBOL(op2);
441 if (sym1->nRegs == 0 || sym2->nRegs == 0)
444 for (i = 0 ; i < sym1->nRegs ; i++) {
449 for (j = 0 ; j < sym2->nRegs ;j++ ) {
453 if (sym2->regs[j] == sym1->regs[i])
461 /*-----------------------------------------------------------------*/
462 /* operandsEqu - equivalent */
463 /*-----------------------------------------------------------------*/
464 static bool operandsEqu ( operand *op1, operand *op2)
468 /* if they not symbols */
469 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
472 sym1 = OP_SYMBOL(op1);
473 sym2 = OP_SYMBOL(op2);
475 /* if both are itemps & one is spilt
476 and the other is not then false */
477 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
478 sym1->isspilt != sym2->isspilt )
481 /* if they are the same */
485 if (strcmp(sym1->rname,sym2->rname) == 0)
489 /* if left is a tmp & right is not */
493 (sym1->usl.spillLoc == sym2))
500 (sym2->usl.spillLoc == sym1))
506 /*-----------------------------------------------------------------*/
507 /* sameRegs - two asmops have the same registers */
508 /*-----------------------------------------------------------------*/
509 static bool sameRegs (asmop *aop1, asmop *aop2 )
516 if (aop1->type != AOP_REG ||
517 aop2->type != AOP_REG )
520 if (aop1->size != aop2->size )
523 for (i = 0 ; i < aop1->size ; i++ )
524 if (aop1->aopu.aop_reg[i] !=
525 aop2->aopu.aop_reg[i] )
531 /*-----------------------------------------------------------------*/
532 /* aopOp - allocates an asmop for an operand : */
533 /*-----------------------------------------------------------------*/
534 static void aopOp (operand *op, iCode *ic, bool result)
543 /* if this a literal */
544 if (IS_OP_LITERAL(op)) {
545 op->aop = aop = newAsmop(AOP_LIT);
546 aop->aopu.aop_lit = op->operand.valOperand;
547 aop->size = getSize(operandType(op));
551 /* if already has a asmop then continue */
555 /* if the underlying symbol has a aop */
556 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
557 op->aop = OP_SYMBOL(op)->aop;
561 /* if this is a true symbol */
562 if (IS_TRUE_SYMOP(op)) {
563 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
567 /* this is a temporary : this has
573 e) can be a return use only */
578 /* if the type is a conditional */
579 if (sym->regType == REG_CND) {
580 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
585 /* if it is spilt then two situations
587 b) has a spill location */
588 if (sym->isspilt || sym->nRegs == 0) {
590 /* rematerialize it NOW */
592 sym->aop = op->aop = aop =
594 aop->size = getSize(sym->type);
600 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
601 aop->size = getSize(sym->type);
602 for ( i = 0 ; i < 2 ; i++ )
603 aop->aopu.aop_str[i] = accUse[i];
609 aop = op->aop = sym->aop = newAsmop(AOP_STR);
610 aop->size = getSize(sym->type);
611 for ( i = 0 ; i < fReturnSize ; i++ )
612 aop->aopu.aop_str[i] = fReturn[i];
616 /* else spill location */
617 sym->aop = op->aop = aop =
618 aopForSym(ic,sym->usl.spillLoc,result);
619 aop->size = getSize(sym->type);
623 /* must be in a register */
624 sym->aop = op->aop = aop = newAsmop(AOP_REG);
625 aop->size = sym->nRegs;
626 for ( i = 0 ; i < sym->nRegs ;i++)
627 aop->aopu.aop_reg[i] = sym->regs[i];
630 /*-----------------------------------------------------------------*/
631 /* freeAsmop - free up the asmop given to an operand */
632 /*----------------------------------------------------------------*/
633 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
650 /* depending on the asmop type only three cases need work AOP_RO
651 , AOP_R1 && AOP_STK */
656 emitcode ("pop","ar0");
660 bitVectUnSetBit(ic->rUsed,R0_IDX);
666 emitcode ("pop","ar1");
670 bitVectUnSetBit(ic->rUsed,R1_IDX);
676 int stk = aop->aopu.aop_stk + aop->size;
677 bitVectUnSetBit(ic->rUsed,R0_IDX);
678 bitVectUnSetBit(ic->rUsed,R1_IDX);
680 getFreePtr(ic,&aop,FALSE);
682 if (options.stack10bit)
684 /* I'm not sure what to do here yet... */
687 "*** Warning: probably generating bad code for "
688 "10 bit stack mode.\n");
692 emitcode ("mov","a,_bp");
693 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
694 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
696 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
700 emitcode("pop","acc");
701 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
703 emitcode("dec","%s",aop->aopu.aop_ptr->name);
706 freeAsmop(op,NULL,ic,TRUE);
708 emitcode("pop","ar0");
713 emitcode("pop","ar1");
720 /* all other cases just dealloc */
724 OP_SYMBOL(op)->aop = NULL;
725 /* if the symbol has a spill */
727 SPIL_LOC(op)->aop = NULL;
732 /*-----------------------------------------------------------------*/
733 /* aopGet - for fetching value of the aop */
734 /*-----------------------------------------------------------------*/
735 static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
740 /* offset is greater than
742 if (offset > (aop->size - 1) &&
743 aop->type != AOP_LIT)
746 /* depending on type */
751 /* if we need to increment it */
752 while (offset > aop->coff) {
753 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
757 while (offset < aop->coff) {
758 emitcode("dec","%s",aop->aopu.aop_ptr->name);
764 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
765 return (dname ? "acc" : "a");
767 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
768 ALLOC_ATOMIC(rs,strlen(s)+1);
775 if (aop->type == AOP_DPTR2)
777 emitcode (";", "#switchDPTR(2)");
780 while (offset > aop->coff) {
781 emitcode ("inc","dptr");
785 while (offset < aop->coff) {
786 emitcode("lcall","__decdptr");
793 emitcode("movc","a,@a+dptr");
796 emitcode("movx","a,@dptr");
798 if (aop->type == AOP_DPTR2)
800 emitcode (";", "#switchDPTR(1)");
803 return (dname ? "acc" : "a");
808 sprintf (s,"#(%s)",aop->aopu.aop_immd);
811 sprintf(s,"#(%s >> %d)",
817 ALLOC_ATOMIC(rs,strlen(s)+1);
823 sprintf(s,"(%s + %d)",
827 sprintf(s,"%s",aop->aopu.aop_dir);
828 ALLOC_ATOMIC(rs,strlen(s)+1);
834 return aop->aopu.aop_reg[offset]->dname;
836 return aop->aopu.aop_reg[offset]->name;
840 emitcode("mov","c,%s",aop->aopu.aop_dir);
841 emitcode("rlc","a") ;
842 return (dname ? "acc" : "a");
845 if (!offset && dname)
847 return aop->aopu.aop_str[offset];
850 return aopLiteral (aop->aopu.aop_lit,offset);
854 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
858 return aop->aopu.aop_str[offset];
862 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
863 "aopget got unsupported aop->type");
866 /*-----------------------------------------------------------------*/
867 /* aopPut - puts a string for a aop */
868 /*-----------------------------------------------------------------*/
869 static void aopPut (asmop *aop, char *s, int offset)
874 if (aop->size && offset > ( aop->size - 1)) {
875 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
876 "aopPut got offset > aop->size");
880 /* will assign value to value */
881 /* depending on where it is ofcourse */
885 sprintf(d,"(%s + %d)",
886 aop->aopu.aop_dir,offset);
888 sprintf(d,"%s",aop->aopu.aop_dir);
891 emitcode("mov","%s,%s",d,s);
896 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
897 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
899 strcmp(s,"r0") == 0 ||
900 strcmp(s,"r1") == 0 ||
901 strcmp(s,"r2") == 0 ||
902 strcmp(s,"r3") == 0 ||
903 strcmp(s,"r4") == 0 ||
904 strcmp(s,"r5") == 0 ||
905 strcmp(s,"r6") == 0 ||
906 strcmp(s,"r7") == 0 )
907 emitcode("mov","%s,%s",
908 aop->aopu.aop_reg[offset]->dname,s);
910 emitcode("mov","%s,%s",
911 aop->aopu.aop_reg[offset]->name,s);
918 if (aop->type == AOP_DPTR2)
920 emitcode (";", "#switchDPTR(2)");
924 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
925 "aopPut writting to code space");
929 while (offset > aop->coff) {
931 emitcode ("inc","dptr");
934 while (offset < aop->coff) {
936 emitcode("lcall","__decdptr");
941 /* if not in accumulater */
944 emitcode ("movx","@dptr,a");
946 if (aop->type == AOP_DPTR2)
948 emitcode (";", "#switchDPTR(1)");
954 while (offset > aop->coff) {
956 emitcode("inc","%s",aop->aopu.aop_ptr->name);
958 while (offset < aop->coff) {
960 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
966 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
971 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
973 if (strcmp(s,"r0") == 0 ||
974 strcmp(s,"r1") == 0 ||
975 strcmp(s,"r2") == 0 ||
976 strcmp(s,"r3") == 0 ||
977 strcmp(s,"r4") == 0 ||
978 strcmp(s,"r5") == 0 ||
979 strcmp(s,"r6") == 0 ||
980 strcmp(s,"r7") == 0 ) {
982 sprintf(buffer,"a%s",s);
983 emitcode("mov","@%s,%s",
984 aop->aopu.aop_ptr->name,buffer);
986 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
991 if (strcmp(s,"a") == 0)
992 emitcode("push","acc");
994 emitcode("push","%s",s);
999 /* if bit variable */
1000 if (!aop->aopu.aop_dir) {
1001 emitcode("clr","a");
1002 emitcode("rlc","a");
1005 emitcode("clr","%s",aop->aopu.aop_dir);
1008 emitcode("setb","%s",aop->aopu.aop_dir);
1011 emitcode("mov","%s,c",aop->aopu.aop_dir);
1013 lbl = newiTempLabel(NULL);
1015 if (strcmp(s,"a")) {
1018 emitcode("clr","c");
1019 emitcode("jz","%05d$",lbl->key+100);
1020 emitcode("cpl","c");
1021 emitcode("","%05d$:",lbl->key+100);
1022 emitcode("mov","%s,c",aop->aopu.aop_dir);
1029 if (strcmp(aop->aopu.aop_str[offset],s))
1030 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1035 if (!offset && (strcmp(s,"acc") == 0))
1038 if (strcmp(aop->aopu.aop_str[offset],s))
1039 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1043 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1044 "aopPut got unsupported aop->type");
1052 /*-----------------------------------------------------------------*/
1053 /* pointToEnd :- points to the last byte of the operand */
1054 /*-----------------------------------------------------------------*/
1055 static void pointToEnd (asmop *aop)
1061 aop->coff = count = (aop->size - 1);
1062 switch (aop->type) {
1066 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1070 emitcode("inc","dptr");
1077 /*-----------------------------------------------------------------*/
1078 /* reAdjustPreg - points a register back to where it should */
1079 /*-----------------------------------------------------------------*/
1080 static void reAdjustPreg (asmop *aop)
1085 if ((size = aop->size) <= 1)
1088 switch (aop->type) {
1092 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1096 if (aop->type == AOP_DPTR2)
1098 emitcode (";", "#switchDPTR(2)");
1101 emitcode("lcall","__decdptr");
1103 if (aop->type == AOP_DPTR2)
1105 emitcode (";", "#switchDPTR(1)");
1113 #define AOP(op) op->aop
1114 #define AOP_TYPE(op) AOP(op)->type
1115 #define AOP_SIZE(op) AOP(op)->size
1116 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1117 AOP_TYPE(x) == AOP_R0))
1119 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1120 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1123 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1124 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1125 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1127 /*-----------------------------------------------------------------*/
1128 /* genNotFloat - generates not for float operations */
1129 /*-----------------------------------------------------------------*/
1130 static void genNotFloat (operand *op, operand *res)
1136 /* we will put 127 in the first byte of
1138 aopPut(AOP(res),"#127",0);
1139 size = AOP_SIZE(op) - 1;
1142 l = aopGet(op->aop,offset++,FALSE,FALSE);
1146 emitcode("orl","a,%s",
1148 offset++,FALSE,FALSE));
1150 tlbl = newiTempLabel(NULL);
1152 tlbl = newiTempLabel(NULL);
1153 aopPut(res->aop,one,1);
1154 emitcode("jz","%05d$",(tlbl->key+100));
1155 aopPut(res->aop,zero,1);
1156 emitcode("","%05d$:",(tlbl->key+100));
1158 size = res->aop->size - 2;
1160 /* put zeros in the rest */
1162 aopPut(res->aop,zero,offset++);
1165 /*-----------------------------------------------------------------*/
1166 /* opIsGptr: returns non-zero if the passed operand is */
1167 /* a generic pointer type. */
1168 /*-----------------------------------------------------------------*/
1169 static int opIsGptr(operand *op)
1171 link *type = operandType(op);
1173 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1180 /*-----------------------------------------------------------------*/
1181 /* getDataSize - get the operand data size */
1182 /*-----------------------------------------------------------------*/
1183 static int getDataSize(operand *op)
1186 size = AOP_SIZE(op);
1187 if (size == GPTRSIZE)
1189 link *type = operandType(op);
1190 if (IS_GENPTR(type))
1192 /* generic pointer; arithmetic operations
1193 * should ignore the high byte (pointer type).
1201 /*-----------------------------------------------------------------*/
1202 /* outAcc - output Acc */
1203 /*-----------------------------------------------------------------*/
1204 static void outAcc(operand *result)
1207 size = getDataSize(result);
1209 aopPut(AOP(result),"a",0);
1212 /* unsigned or positive */
1214 aopPut(AOP(result),zero,offset++);
1219 /*-----------------------------------------------------------------*/
1220 /* outBitC - output a bit C */
1221 /*-----------------------------------------------------------------*/
1222 static void outBitC(operand *result)
1224 /* if the result is bit */
1225 if (AOP_TYPE(result) == AOP_CRY)
1226 aopPut(AOP(result),"c",0);
1228 emitcode("clr","a");
1229 emitcode("rlc","a");
1234 /*-----------------------------------------------------------------*/
1235 /* toBoolean - emit code for orl a,operator(sizeop) */
1236 /*-----------------------------------------------------------------*/
1237 static void toBoolean(operand *oper)
1239 int size = AOP_SIZE(oper) - 1;
1241 MOVA(aopGet(AOP(oper),0,FALSE,FALSE));
1243 emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE));
1247 /*-----------------------------------------------------------------*/
1248 /* genNot - generate code for ! operation */
1249 /*-----------------------------------------------------------------*/
1250 static void genNot (iCode *ic)
1253 link *optype = operandType(IC_LEFT(ic));
1255 /* assign asmOps to operand & result */
1256 aopOp (IC_LEFT(ic),ic,FALSE);
1257 aopOp (IC_RESULT(ic),ic,TRUE);
1259 /* if in bit space then a special case */
1260 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1261 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1262 emitcode("cpl","c");
1263 outBitC(IC_RESULT(ic));
1267 /* if type float then do float */
1268 if (IS_FLOAT(optype)) {
1269 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1273 toBoolean(IC_LEFT(ic));
1275 tlbl = newiTempLabel(NULL);
1276 emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1277 emitcode("","%05d$:",tlbl->key+100);
1278 outBitC(IC_RESULT(ic));
1281 /* release the aops */
1282 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1283 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1287 /*-----------------------------------------------------------------*/
1288 /* genCpl - generate code for complement */
1289 /*-----------------------------------------------------------------*/
1290 static void genCpl (iCode *ic)
1296 /* assign asmOps to operand & result */
1297 aopOp (IC_LEFT(ic),ic,FALSE);
1298 aopOp (IC_RESULT(ic),ic,TRUE);
1300 /* if both are in bit space then
1302 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1303 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1305 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1306 emitcode("cpl","c");
1307 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1311 size = AOP_SIZE(IC_RESULT(ic));
1313 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1315 emitcode("cpl","a");
1316 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1321 /* release the aops */
1322 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1323 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1326 /*-----------------------------------------------------------------*/
1327 /* genUminusFloat - unary minus for floating points */
1328 /*-----------------------------------------------------------------*/
1329 static void genUminusFloat(operand *op,operand *result)
1331 int size ,offset =0 ;
1333 /* for this we just need to flip the
1334 first it then copy the rest in place */
1335 size = AOP_SIZE(op) - 1;
1336 l = aopGet(AOP(op),3,FALSE,FALSE);
1340 emitcode("cpl","acc.7");
1341 aopPut(AOP(result),"a",3);
1345 aopGet(AOP(op),offset,FALSE,FALSE),
1351 /*-----------------------------------------------------------------*/
1352 /* genUminus - unary minus code generation */
1353 /*-----------------------------------------------------------------*/
1354 static void genUminus (iCode *ic)
1357 link *optype, *rtype;
1361 aopOp(IC_LEFT(ic),ic,FALSE);
1362 aopOp(IC_RESULT(ic),ic,TRUE);
1364 /* if both in bit space then special
1366 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1367 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1369 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1370 emitcode("cpl","c");
1371 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1375 optype = operandType(IC_LEFT(ic));
1376 rtype = operandType(IC_RESULT(ic));
1378 /* if float then do float stuff */
1379 if (IS_FLOAT(optype)) {
1380 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1384 /* otherwise subtract from zero */
1385 size = AOP_SIZE(IC_LEFT(ic));
1389 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1390 if (!strcmp(l,"a")) {
1391 emitcode("cpl","a");
1392 emitcode("inc","a");
1394 emitcode("clr","a");
1395 emitcode("subb","a,%s",l);
1397 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1400 /* if any remaining bytes in the result */
1401 /* we just need to propagate the sign */
1402 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1403 emitcode("rlc","a");
1404 emitcode("subb","a,acc");
1406 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1410 /* release the aops */
1411 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1412 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1415 /*-----------------------------------------------------------------*/
1416 /* saveRegisters - will look for a call and save the registers */
1417 /*-----------------------------------------------------------------*/
1418 static void saveRegisters(iCode *lic)
1426 for (ic = lic ; ic ; ic = ic->next)
1427 if (ic->op == CALL || ic->op == PCALL)
1431 fprintf(stderr,"found parameter push with no function call\n");
1435 /* if the registers have been saved already then
1437 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1440 /* find the registers in use at this time
1441 and push them away to safety */
1442 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1446 if (options.useXstack) {
1447 if (bitVectBitValue(rsave,R0_IDX))
1448 emitcode("mov","b,r0");
1449 emitcode("mov","r0,%s",spname);
1450 for (i = 0 ; i < mcs51_nRegs ; i++) {
1451 if (bitVectBitValue(rsave,i)) {
1453 emitcode("mov","a,b");
1455 emitcode("mov","a,%s",mcs51_regWithIdx(i)->name);
1456 emitcode("movx","@r0,a");
1457 emitcode("inc","r0");
1460 emitcode("mov","%s,r0",spname);
1461 if (bitVectBitValue(rsave,R0_IDX))
1462 emitcode("mov","r0,b");
1464 for (i = 0 ; i < mcs51_nRegs ; i++) {
1465 if (bitVectBitValue(rsave,i))
1466 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
1469 detype = getSpec(operandType(IC_LEFT(ic)));
1471 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1472 IS_ISR(currFunc->etype) &&
1475 saverbank(SPEC_BANK(detype),ic,TRUE);
1478 /*-----------------------------------------------------------------*/
1479 /* unsaveRegisters - pop the pushed registers */
1480 /*-----------------------------------------------------------------*/
1481 static void unsaveRegisters (iCode *ic)
1485 /* find the registers in use at this time
1486 and push them away to safety */
1487 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1490 if (options.useXstack) {
1491 emitcode("mov","r0,%s",spname);
1492 for (i = mcs51_nRegs ; i >= 0 ; i--) {
1493 if (bitVectBitValue(rsave,i)) {
1494 emitcode("dec","r0");
1495 emitcode("movx","a,@r0");
1497 emitcode("mov","b,a");
1499 emitcode("mov","%s,a",mcs51_regWithIdx(i)->name);
1503 emitcode("mov","%s,r0",spname);
1504 if (bitVectBitValue(rsave,R0_IDX))
1505 emitcode("mov","r0,b");
1507 for (i = mcs51_nRegs ; i >= 0 ; i--) {
1508 if (bitVectBitValue(rsave,i))
1509 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
1515 /*-----------------------------------------------------------------*/
1517 /*-----------------------------------------------------------------*/
1518 static void pushSide(operand * oper, int size)
1522 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1523 if (AOP_TYPE(oper) != AOP_REG &&
1524 AOP_TYPE(oper) != AOP_DIR &&
1526 emitcode("mov","a,%s",l);
1527 emitcode("push","acc");
1529 emitcode("push","%s",l);
1533 /*-----------------------------------------------------------------*/
1534 /* assignResultValue - */
1535 /*-----------------------------------------------------------------*/
1536 static void assignResultValue(operand * oper)
1539 int size = AOP_SIZE(oper);
1541 aopPut(AOP(oper),fReturn[offset],offset);
1547 /*-----------------------------------------------------------------*/
1548 /* genXpush - pushes onto the external stack */
1549 /*-----------------------------------------------------------------*/
1550 static void genXpush (iCode *ic)
1552 asmop *aop = newAsmop(0);
1554 int size,offset = 0;
1556 aopOp(IC_LEFT(ic),ic,FALSE);
1557 r = getFreePtr(ic,&aop,FALSE);
1560 emitcode("mov","%s,_spx",r->name);
1562 size = AOP_SIZE(IC_LEFT(ic));
1565 char *l = aopGet(AOP(IC_LEFT(ic)),
1566 offset++,FALSE,FALSE);
1568 emitcode("movx","@%s,a",r->name);
1569 emitcode("inc","%s",r->name);
1574 emitcode("mov","_spx,%s",r->name);
1576 freeAsmop(NULL,aop,ic,TRUE);
1577 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1580 /*-----------------------------------------------------------------*/
1581 /* genIpush - genrate code for pushing this gets a little complex */
1582 /*-----------------------------------------------------------------*/
1583 static void genIpush (iCode *ic)
1585 int size, offset = 0 ;
1589 /* if this is not a parm push : ie. it is spill push
1590 and spill push is always done on the local stack */
1591 if (!ic->parmPush) {
1593 /* and the item is spilt then do nothing */
1594 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1597 aopOp(IC_LEFT(ic),ic,FALSE);
1598 size = AOP_SIZE(IC_LEFT(ic));
1599 /* push it on the stack */
1601 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1606 emitcode("push","%s",l);
1611 /* this is a paramter push: in this case we call
1612 the routine to find the call and save those
1613 registers that need to be saved */
1616 /* if use external stack then call the external
1617 stack pushing routine */
1618 if (options.useXstack) {
1623 /* then do the push */
1624 aopOp(IC_LEFT(ic),ic,FALSE);
1627 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1628 size = AOP_SIZE(IC_LEFT(ic));
1631 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1632 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1633 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1635 emitcode("mov","a,%s",l);
1636 emitcode("push","acc");
1638 emitcode("push","%s",l);
1641 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1644 /*-----------------------------------------------------------------*/
1645 /* genIpop - recover the registers: can happen only for spilling */
1646 /*-----------------------------------------------------------------*/
1647 static void genIpop (iCode *ic)
1652 /* if the temp was not pushed then */
1653 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1656 aopOp(IC_LEFT(ic),ic,FALSE);
1657 size = AOP_SIZE(IC_LEFT(ic));
1660 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1663 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1666 /*-----------------------------------------------------------------*/
1667 /* unsaverbank - restores the resgister bank from stack */
1668 /*-----------------------------------------------------------------*/
1669 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1676 if (options.useXstack) {
1678 r = getFreePtr(ic,&aop,FALSE);
1681 emitcode("mov","%s,_spx",r->name);
1682 emitcode("movx","a,@%s",r->name);
1683 emitcode("mov","psw,a");
1684 emitcode("dec","%s",r->name);
1687 emitcode ("pop","psw");
1690 for (i = (mcs51_nRegs - 1) ; i >= 0 ;i--) {
1691 if (options.useXstack) {
1692 emitcode("movx","a,@%s",r->name);
1693 emitcode("mov","(%s+%d),a",
1694 regs8051[i].base,8*bank+regs8051[i].offset);
1695 emitcode("dec","%s",r->name);
1698 emitcode("pop","(%s+%d)",
1699 regs8051[i].base,8*bank+regs8051[i].offset);
1702 if (options.useXstack) {
1704 emitcode("mov","_spx,%s",r->name);
1705 freeAsmop(NULL,aop,ic,TRUE);
1710 /*-----------------------------------------------------------------*/
1711 /* saverbank - saves an entire register bank on the stack */
1712 /*-----------------------------------------------------------------*/
1713 static void saverbank (int bank, iCode *ic, bool pushPsw)
1719 if (options.useXstack) {
1722 r = getFreePtr(ic,&aop,FALSE);
1723 emitcode("mov","%s,_spx",r->name);
1727 for (i = 0 ; i < mcs51_nRegs ;i++) {
1728 if (options.useXstack) {
1729 emitcode("inc","%s",r->name);
1730 emitcode("mov","a,(%s+%d)",
1731 regs8051[i].base,8*bank+regs8051[i].offset);
1732 emitcode("movx","@%s,a",r->name);
1734 emitcode("push","(%s+%d)",
1735 regs8051[i].base,8*bank+regs8051[i].offset);
1739 if (options.useXstack) {
1740 emitcode("mov","a,psw");
1741 emitcode("movx","@%s,a",r->name);
1742 emitcode("inc","%s",r->name);
1743 emitcode("mov","_spx,%s",r->name);
1744 freeAsmop (NULL,aop,ic,TRUE);
1747 emitcode("push","psw");
1749 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1755 /*-----------------------------------------------------------------*/
1756 /* genCall - generates a call statement */
1757 /*-----------------------------------------------------------------*/
1758 static void genCall (iCode *ic)
1762 /* if caller saves & we have not saved then */
1766 /* if we are calling a function that is not using
1767 the same register bank then we need to save the
1768 destination registers on the stack */
1769 detype = getSpec(operandType(IC_LEFT(ic)));
1771 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1772 IS_ISR(currFunc->etype) &&
1775 saverbank(SPEC_BANK(detype),ic,TRUE);
1777 /* if send set is not empty the assign */
1781 for (sic = setFirstItem(_G.sendSet) ; sic ;
1782 sic = setNextItem(_G.sendSet)) {
1783 int size, offset = 0;
1784 aopOp(IC_LEFT(sic),sic,FALSE);
1785 size = AOP_SIZE(IC_LEFT(sic));
1787 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1789 if (strcmp(l,fReturn[offset]))
1790 emitcode("mov","%s,%s",
1795 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1800 emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1801 OP_SYMBOL(IC_LEFT(ic))->rname :
1802 OP_SYMBOL(IC_LEFT(ic))->name));
1804 /* if we need assign a result value */
1805 if ((IS_ITEMP(IC_RESULT(ic)) &&
1806 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1807 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1808 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1811 aopOp(IC_RESULT(ic),ic,FALSE);
1814 assignResultValue(IC_RESULT(ic));
1816 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1819 /* adjust the stack for parameters if
1821 if (IC_LEFT(ic)->parmBytes) {
1823 if (IC_LEFT(ic)->parmBytes > 3) {
1824 emitcode("mov","a,%s",spname);
1825 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1826 emitcode("mov","%s,a",spname);
1828 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1829 emitcode("dec","%s",spname);
1833 /* if register bank was saved then pop them */
1835 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1837 /* if we hade saved some registers then unsave them */
1838 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1839 unsaveRegisters (ic);
1844 /*-----------------------------------------------------------------*/
1845 /* genPcall - generates a call by pointer statement */
1846 /*-----------------------------------------------------------------*/
1847 static void genPcall (iCode *ic)
1850 symbol *rlbl = newiTempLabel(NULL);
1853 /* if caller saves & we have not saved then */
1857 /* if we are calling a function that is not using
1858 the same register bank then we need to save the
1859 destination registers on the stack */
1860 detype = getSpec(operandType(IC_LEFT(ic)));
1862 IS_ISR(currFunc->etype) &&
1863 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
1864 saverbank(SPEC_BANK(detype),ic,TRUE);
1867 /* push the return address on to the stack */
1868 emitcode("mov","a,#%05d$",(rlbl->key+100));
1869 emitcode("push","acc");
1870 emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
1871 emitcode("push","acc");
1873 if (options.model == MODEL_FLAT24)
1875 emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
1876 emitcode("push","acc");
1879 /* now push the calling address */
1880 aopOp(IC_LEFT(ic),ic,FALSE);
1882 pushSide(IC_LEFT(ic), FPTRSIZE);
1884 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1886 /* if send set is not empty the assign */
1890 for (sic = setFirstItem(_G.sendSet) ; sic ;
1891 sic = setNextItem(_G.sendSet)) {
1892 int size, offset = 0;
1893 aopOp(IC_LEFT(sic),sic,FALSE);
1894 size = AOP_SIZE(IC_LEFT(sic));
1896 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1898 if (strcmp(l,fReturn[offset]))
1899 emitcode("mov","%s,%s",
1904 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1910 emitcode("","%05d$:",(rlbl->key+100));
1913 /* if we need assign a result value */
1914 if ((IS_ITEMP(IC_RESULT(ic)) &&
1915 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1916 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
1917 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1920 aopOp(IC_RESULT(ic),ic,FALSE);
1923 assignResultValue(IC_RESULT(ic));
1925 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1928 /* adjust the stack for parameters if
1930 if (IC_LEFT(ic)->parmBytes) {
1932 if (IC_LEFT(ic)->parmBytes > 3) {
1933 emitcode("mov","a,%s",spname);
1934 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1935 emitcode("mov","%s,a",spname);
1937 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1938 emitcode("dec","%s",spname);
1942 /* if register bank was saved then unsave them */
1944 (SPEC_BANK(currFunc->etype) !=
1946 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1948 /* if we hade saved some registers then
1951 unsaveRegisters (ic);
1955 /*-----------------------------------------------------------------*/
1956 /* resultRemat - result is rematerializable */
1957 /*-----------------------------------------------------------------*/
1958 static int resultRemat (iCode *ic)
1960 if (SKIP_IC(ic) || ic->op == IFX)
1963 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1964 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1965 if (sym->remat && !POINTER_SET(ic))
1973 #define STRCASECMP stricmp
1975 #define STRCASECMP strcasecmp
1978 /*-----------------------------------------------------------------*/
1979 /* inExcludeList - return 1 if the string is in exclude Reg list */
1980 /*-----------------------------------------------------------------*/
1981 static bool inExcludeList(char *s)
1985 if (options.excludeRegs[i] &&
1986 STRCASECMP(options.excludeRegs[i],"none") == 0)
1989 for ( i = 0 ; options.excludeRegs[i]; i++) {
1990 if (options.excludeRegs[i] &&
1991 STRCASECMP(s,options.excludeRegs[i]) == 0)
1997 /*-----------------------------------------------------------------*/
1998 /* genFunction - generated code for function entry */
1999 /*-----------------------------------------------------------------*/
2000 static void genFunction (iCode *ic)
2006 /* create the function header */
2007 emitcode(";","-----------------------------------------");
2008 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2009 emitcode(";","-----------------------------------------");
2011 emitcode("","%s:",sym->rname);
2012 fetype = getSpec(operandType(IC_LEFT(ic)));
2014 /* if critical function then turn interrupts off */
2015 if (SPEC_CRTCL(fetype))
2016 emitcode("clr","ea");
2018 /* here we need to generate the equates for the
2019 register bank if required */
2020 if (SPEC_BANK(fetype) != rbank) {
2023 rbank = SPEC_BANK(fetype);
2024 for ( i = 0 ; i < mcs51_nRegs ; i++ ) {
2025 if (strcmp(regs8051[i].base,"0") == 0)
2026 emitcode("","%s = 0x%02x",
2028 8*rbank+regs8051[i].offset);
2030 emitcode ("","%s = %s + 0x%02x",
2033 8*rbank+regs8051[i].offset);
2037 /* if this is an interrupt service routine then
2038 save acc, b, dpl, dph */
2039 if (IS_ISR(sym->etype)) {
2041 if (!inExcludeList("acc"))
2042 emitcode ("push","acc");
2043 if (!inExcludeList("b"))
2044 emitcode ("push","b");
2045 if (!inExcludeList("dpl"))
2046 emitcode ("push","dpl");
2047 if (!inExcludeList("dph"))
2048 emitcode ("push","dph");
2049 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2050 emitcode ("push", "dpx");
2051 /* if this isr has no bank i.e. is going to
2052 run with bank 0 , then we need to save more
2054 if (!SPEC_BANK(sym->etype)) {
2056 /* if this function does not call any other
2057 function then we can be economical and
2058 save only those registers that are used */
2059 if (! sym->hasFcall) {
2062 /* if any registers used */
2063 if (sym->regsUsed) {
2064 /* save the registers used */
2065 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2066 if (bitVectBitValue(sym->regsUsed,i) ||
2067 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2068 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
2073 /* this function has a function call cannot
2074 determines register usage so we will have the
2076 saverbank(0,ic,FALSE);
2080 /* if callee-save to be used for this function
2081 then save the registers being used in this function */
2082 if (sym->calleeSave) {
2085 /* if any registers used */
2086 if (sym->regsUsed) {
2087 /* save the registers used */
2088 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2089 if (bitVectBitValue(sym->regsUsed,i) ||
2090 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2091 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
2099 /* set the register bank to the desired value */
2100 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2101 emitcode("push","psw");
2102 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2105 if (IS_RENT(sym->etype) || options.stackAuto) {
2107 if (options.useXstack) {
2108 emitcode("mov","r0,%s",spname);
2109 emitcode("mov","a,_bp");
2110 emitcode("movx","@r0,a");
2111 emitcode("inc","%s",spname);
2115 /* set up the stack */
2116 emitcode ("push","_bp"); /* save the callers stack */
2118 emitcode ("mov","_bp,%s",spname);
2121 /* adjust the stack for the function */
2126 werror(W_STACK_OVERFLOW,sym->name);
2128 if (i > 3 && sym->recvSize < 4) {
2130 emitcode ("mov","a,sp");
2131 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2132 emitcode ("mov","sp,a");
2137 emitcode("inc","sp");
2142 emitcode ("mov","a,_spx");
2143 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2144 emitcode ("mov","_spx,a");
2149 /*-----------------------------------------------------------------*/
2150 /* genEndFunction - generates epilogue for functions */
2151 /*-----------------------------------------------------------------*/
2152 static void genEndFunction (iCode *ic)
2154 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2156 if (IS_RENT(sym->etype) || options.stackAuto)
2158 emitcode ("mov","%s,_bp",spname);
2161 /* if use external stack but some variables were
2162 added to the local stack then decrement the
2164 if (options.useXstack && sym->stack) {
2165 emitcode("mov","a,sp");
2166 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2167 emitcode("mov","sp,a");
2171 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2172 if (options.useXstack) {
2173 emitcode("mov","r0,%s",spname);
2174 emitcode("movx","a,@r0");
2175 emitcode("mov","_bp,a");
2176 emitcode("dec","%s",spname);
2180 emitcode ("pop","_bp");
2184 /* restore the register bank */
2185 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2186 emitcode ("pop","psw");
2188 if (IS_ISR(sym->etype)) {
2190 /* now we need to restore the registers */
2191 /* if this isr has no bank i.e. is going to
2192 run with bank 0 , then we need to save more
2194 if (!SPEC_BANK(sym->etype)) {
2196 /* if this function does not call any other
2197 function then we can be economical and
2198 save only those registers that are used */
2199 if (! sym->hasFcall) {
2202 /* if any registers used */
2203 if (sym->regsUsed) {
2204 /* save the registers used */
2205 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2206 if (bitVectBitValue(sym->regsUsed,i) ||
2207 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2208 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
2213 /* this function has a function call cannot
2214 determines register usage so we will have the
2216 unsaverbank(0,ic,FALSE);
2220 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2221 emitcode ("pop", "dpx");
2222 if (!inExcludeList("dph"))
2223 emitcode ("pop","dph");
2224 if (!inExcludeList("dpl"))
2225 emitcode ("pop","dpl");
2226 if (!inExcludeList("b"))
2227 emitcode ("pop","b");
2228 if (!inExcludeList("acc"))
2229 emitcode ("pop","acc");
2231 if (SPEC_CRTCL(sym->etype))
2232 emitcode("setb","ea");
2234 /* if debug then send end of function */
2235 /* if (options.debug && currFunc) { */
2238 emitcode("","C$%s$%d$%d$%d ==.",
2239 ic->filename,currFunc->lastLine,
2240 ic->level,ic->block);
2241 if (IS_STATIC(currFunc->etype))
2242 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2244 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2248 emitcode ("reti","");
2251 if (SPEC_CRTCL(sym->etype))
2252 emitcode("setb","ea");
2254 if (sym->calleeSave) {
2257 /* if any registers used */
2258 if (sym->regsUsed) {
2259 /* save the registers used */
2260 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2261 if (bitVectBitValue(sym->regsUsed,i) ||
2262 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2263 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
2269 /* if debug then send end of function */
2270 /* if (options.debug && currFunc) { */
2273 emitcode("","C$%s$%d$%d$%d ==.",
2274 ic->filename,currFunc->lastLine,
2275 ic->level,ic->block);
2276 if (IS_STATIC(currFunc->etype))
2277 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2279 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2283 emitcode ("ret","");
2288 /*-----------------------------------------------------------------*/
2289 /* genRet - generate code for return statement */
2290 /*-----------------------------------------------------------------*/
2291 static void genRet (iCode *ic)
2293 int size,offset = 0 , pushed = 0;
2295 /* if we have no return value then
2296 just generate the "ret" */
2300 /* we have something to return then
2301 move the return value into place */
2302 aopOp(IC_LEFT(ic),ic,FALSE);
2303 size = AOP_SIZE(IC_LEFT(ic));
2307 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2309 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2311 emitcode("push","%s",l);
2314 l = aopGet(AOP(IC_LEFT(ic)),offset,
2316 if (strcmp(fReturn[offset],l))
2317 emitcode("mov","%s,%s",fReturn[offset++],l);
2324 if (strcmp(fReturn[pushed],"a"))
2325 emitcode("pop",fReturn[pushed]);
2327 emitcode("pop","acc");
2330 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2333 /* generate a jump to the return label
2334 if the next is not the return statement */
2335 if (!(ic->next && ic->next->op == LABEL &&
2336 IC_LABEL(ic->next) == returnLabel))
2338 emitcode("ljmp","%05d$",(returnLabel->key+100));
2342 /*-----------------------------------------------------------------*/
2343 /* genLabel - generates a label */
2344 /*-----------------------------------------------------------------*/
2345 static void genLabel (iCode *ic)
2347 /* special case never generate */
2348 if (IC_LABEL(ic) == entryLabel)
2351 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2354 /*-----------------------------------------------------------------*/
2355 /* genGoto - generates a ljmp */
2356 /*-----------------------------------------------------------------*/
2357 static void genGoto (iCode *ic)
2359 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2362 /*-----------------------------------------------------------------*/
2363 /* findLabelBackwards: walks back through the iCode chain looking */
2364 /* for the given label. Returns number of iCode instructions */
2365 /* between that label and given ic. */
2366 /* Returns zero if label not found. */
2367 /*-----------------------------------------------------------------*/
2368 static int findLabelBackwards(iCode *ic, int key)
2377 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2379 /* printf("findLabelBackwards = %d\n", count); */
2384 /* printf("findLabelBackwards: not found.\n"); */
2389 /*-----------------------------------------------------------------*/
2390 /* genPlusIncr :- does addition with increment if possible */
2391 /*-----------------------------------------------------------------*/
2392 static bool genPlusIncr (iCode *ic)
2394 unsigned int icount ;
2395 unsigned int size = getDataSize(IC_RESULT(ic));
2397 /* will try to generate an increment */
2398 /* if the right side is not a literal
2400 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2403 /* if the literal value of the right hand side
2404 is greater than 4 then it is not worth it */
2405 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2408 /* if increment 16 bits in register */
2409 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2416 /* If the next instruction is a goto and the goto target
2417 * is < 10 instructions previous to this, we can generate
2418 * jumps straight to that target.
2420 if (ic->next && ic->next->op == GOTO
2421 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2422 && labelRange <= 10 )
2424 emitcode(";", "tail increment optimized");
2425 tlbl = IC_LABEL(ic->next);
2430 tlbl = newiTempLabel(NULL);
2433 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2434 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2435 IS_AOP_PREG(IC_RESULT(ic)))
2436 emitcode("cjne","%s,#0x00,%05d$"
2437 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2440 emitcode("clr","a");
2441 emitcode("cjne","a,%s,%05d$"
2442 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2446 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2449 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2450 IS_AOP_PREG(IC_RESULT(ic)))
2451 emitcode("cjne","%s,#0x00,%05d$"
2452 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2455 emitcode("cjne","a,%s,%05d$"
2456 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2459 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2463 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2464 IS_AOP_PREG(IC_RESULT(ic)))
2465 emitcode("cjne","%s,#0x00,%05d$"
2466 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2469 emitcode("cjne","a,%s,%05d$"
2470 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2473 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2478 emitcode("","%05d$:",tlbl->key+100);
2483 /* if the sizes are greater than 1 then we cannot */
2484 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2485 AOP_SIZE(IC_LEFT(ic)) > 1 )
2488 /* we can if the aops of the left & result match or
2489 if they are in registers and the registers are the
2491 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2494 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2495 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2496 aopPut(AOP(IC_RESULT(ic)),"a",0);
2500 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2509 /*-----------------------------------------------------------------*/
2510 /* outBitAcc - output a bit in acc */
2511 /*-----------------------------------------------------------------*/
2512 static void outBitAcc(operand *result)
2514 symbol *tlbl = newiTempLabel(NULL);
2515 /* if the result is a bit */
2516 if (AOP_TYPE(result) == AOP_CRY){
2517 aopPut(AOP(result),"a",0);
2520 emitcode("jz","%05d$",tlbl->key+100);
2521 emitcode("mov","a,%s",one);
2522 emitcode("","%05d$:",tlbl->key+100);
2527 /*-----------------------------------------------------------------*/
2528 /* genPlusBits - generates code for addition of two bits */
2529 /*-----------------------------------------------------------------*/
2530 static void genPlusBits (iCode *ic)
2532 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2533 symbol *lbl = newiTempLabel(NULL);
2534 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2535 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2536 emitcode("cpl","c");
2537 emitcode("","%05d$:",(lbl->key+100));
2538 outBitC(IC_RESULT(ic));
2541 emitcode("clr","a");
2542 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2543 emitcode("rlc","a");
2544 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2545 emitcode("addc","a,#0x00");
2546 outAcc(IC_RESULT(ic));
2551 /* This is the original version of this code.
2553 * This is being kept around for reference,
2554 * because I am not entirely sure I got it right...
2556 static void adjustArithmeticResult(iCode *ic)
2558 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2559 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2560 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2561 aopPut(AOP(IC_RESULT(ic)),
2562 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2565 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2566 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
2567 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2568 aopPut(AOP(IC_RESULT(ic)),
2569 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2572 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2573 AOP_SIZE(IC_LEFT(ic)) < 3 &&
2574 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
2575 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2576 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2578 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2579 aopPut(AOP(IC_RESULT(ic)),buffer,2);
2583 /* This is the pure and virtuous version of this code.
2584 * I'm pretty certain it's right, but not enough to toss the old
2587 static void adjustArithmeticResult(iCode *ic)
2589 if (opIsGptr(IC_RESULT(ic)) &&
2590 opIsGptr(IC_LEFT(ic)) &&
2591 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2593 aopPut(AOP(IC_RESULT(ic)),
2594 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
2598 if (opIsGptr(IC_RESULT(ic)) &&
2599 opIsGptr(IC_RIGHT(ic)) &&
2600 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2602 aopPut(AOP(IC_RESULT(ic)),
2603 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
2607 if (opIsGptr(IC_RESULT(ic)) &&
2608 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2609 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2610 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2611 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2613 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2614 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2619 /*-----------------------------------------------------------------*/
2620 /* genPlus - generates code for addition */
2621 /*-----------------------------------------------------------------*/
2622 static void genPlus (iCode *ic)
2624 int size, offset = 0;
2626 /* special cases :- */
2628 aopOp (IC_LEFT(ic),ic,FALSE);
2629 aopOp (IC_RIGHT(ic),ic,FALSE);
2630 aopOp (IC_RESULT(ic),ic,TRUE);
2632 /* if literal, literal on the right or
2633 if left requires ACC or right is already
2635 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2636 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2637 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2638 operand *t = IC_RIGHT(ic);
2639 IC_RIGHT(ic) = IC_LEFT(ic);
2643 /* if both left & right are in bit
2645 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2646 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2651 /* if left in bit space & right literal */
2652 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2653 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2654 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2655 /* if result in bit space */
2656 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2657 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
2658 emitcode("cpl","c");
2659 outBitC(IC_RESULT(ic));
2661 size = getDataSize(IC_RESULT(ic));
2663 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2664 emitcode("addc","a,#00");
2665 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2671 /* if I can do an increment instead
2672 of add then GOOD for ME */
2673 if (genPlusIncr (ic) == TRUE)
2676 size = getDataSize(IC_RESULT(ic));
2679 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2680 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2682 emitcode("add","a,%s",
2683 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2685 emitcode("addc","a,%s",
2686 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2688 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2690 emitcode("add","a,%s",
2691 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2693 emitcode("addc","a,%s",
2694 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2696 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2699 adjustArithmeticResult(ic);
2702 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2703 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2704 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2707 /*-----------------------------------------------------------------*/
2708 /* genMinusDec :- does subtraction with deccrement if possible */
2709 /*-----------------------------------------------------------------*/
2710 static bool genMinusDec (iCode *ic)
2712 unsigned int icount ;
2713 unsigned int size = getDataSize(IC_RESULT(ic));
2715 /* will try to generate an increment */
2716 /* if the right side is not a literal
2718 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2721 /* if the literal value of the right hand side
2722 is greater than 4 then it is not worth it */
2723 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2726 /* if decrement 16 bits in register */
2727 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2734 /* If the next instruction is a goto and the goto target
2735 * is <= 10 instructions previous to this, we can generate
2736 * jumps straight to that target.
2738 if (ic->next && ic->next->op == GOTO
2739 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2740 && labelRange <= 10 )
2742 emitcode(";", "tail decrement optimized");
2743 tlbl = IC_LABEL(ic->next);
2748 tlbl = newiTempLabel(NULL);
2752 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2753 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2754 IS_AOP_PREG(IC_RESULT(ic)))
2755 emitcode("cjne","%s,#0xff,%05d$"
2756 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2759 emitcode("mov","a,#0xff");
2760 emitcode("cjne","a,%s,%05d$"
2761 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2764 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2767 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2768 IS_AOP_PREG(IC_RESULT(ic)))
2769 emitcode("cjne","%s,#0xff,%05d$"
2770 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2773 emitcode("cjne","a,%s,%05d$"
2774 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2777 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2781 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2782 IS_AOP_PREG(IC_RESULT(ic)))
2783 emitcode("cjne","%s,#0xff,%05d$"
2784 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2787 emitcode("cjne","a,%s,%05d$"
2788 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2791 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2795 emitcode("","%05d$:",tlbl->key+100);
2800 /* if the sizes are greater than 1 then we cannot */
2801 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2802 AOP_SIZE(IC_LEFT(ic)) > 1 )
2805 /* we can if the aops of the left & result match or
2806 if they are in registers and the registers are the
2808 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2811 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2819 /*-----------------------------------------------------------------*/
2820 /* addSign - complete with sign */
2821 /*-----------------------------------------------------------------*/
2822 static void addSign(operand *result, int offset, int sign)
2824 int size = (getDataSize(result) - offset);
2827 emitcode("rlc","a");
2828 emitcode("subb","a,acc");
2830 aopPut(AOP(result),"a",offset++);
2833 aopPut(AOP(result),zero,offset++);
2837 /*-----------------------------------------------------------------*/
2838 /* genMinusBits - generates code for subtraction of two bits */
2839 /*-----------------------------------------------------------------*/
2840 static void genMinusBits (iCode *ic)
2842 symbol *lbl = newiTempLabel(NULL);
2843 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2844 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2845 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2846 emitcode("cpl","c");
2847 emitcode("","%05d$:",(lbl->key+100));
2848 outBitC(IC_RESULT(ic));
2851 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2852 emitcode("subb","a,acc");
2853 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
2854 emitcode("inc","a");
2855 emitcode("","%05d$:",(lbl->key+100));
2856 aopPut(AOP(IC_RESULT(ic)),"a",0);
2857 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
2861 /*-----------------------------------------------------------------*/
2862 /* genMinus - generates code for subtraction */
2863 /*-----------------------------------------------------------------*/
2864 static void genMinus (iCode *ic)
2866 int size, offset = 0;
2867 unsigned long lit = 0L;
2869 aopOp (IC_LEFT(ic),ic,FALSE);
2870 aopOp (IC_RIGHT(ic),ic,FALSE);
2871 aopOp (IC_RESULT(ic),ic,TRUE);
2873 /* special cases :- */
2874 /* if both left & right are in bit space */
2875 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2876 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2881 /* if I can do an decrement instead
2882 of subtract then GOOD for ME */
2883 if (genMinusDec (ic) == TRUE)
2886 size = getDataSize(IC_RESULT(ic));
2888 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
2892 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2896 /* if literal, add a,#-lit, else normal subb */
2898 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2899 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2900 emitcode("subb","a,%s",
2901 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2903 /* first add without previous c */
2905 emitcode("add","a,#0x%02x",
2906 (unsigned int)(lit & 0x0FFL));
2908 emitcode("addc","a,#0x%02x",
2909 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
2911 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2914 adjustArithmeticResult(ic);
2917 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2918 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2919 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2923 /*-----------------------------------------------------------------*/
2924 /* genMultbits :- multiplication of bits */
2925 /*-----------------------------------------------------------------*/
2926 static void genMultbits (operand *left,
2930 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2931 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
2936 /*-----------------------------------------------------------------*/
2937 /* genMultOneByte : 8 bit multiplication & division */
2938 /*-----------------------------------------------------------------*/
2939 static void genMultOneByte (operand *left,
2943 link *opetype = operandType(result);
2948 /* (if two literals, the value is computed before) */
2949 /* if one literal, literal on the right */
2950 if (AOP_TYPE(left) == AOP_LIT){
2956 size = AOP_SIZE(result);
2957 /* signed or unsigned */
2958 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2959 l = aopGet(AOP(left),0,FALSE,FALSE);
2961 emitcode("mul","ab");
2962 /* if result size = 1, mul signed = mul unsigned */
2963 aopPut(AOP(result),"a",0);
2965 if (SPEC_USIGN(opetype)){
2966 aopPut(AOP(result),"b",1);
2968 /* for filling the MSBs */
2969 emitcode("clr","a");
2972 emitcode("mov","a,b");
2974 /* adjust the MSB if left or right neg */
2976 /* if one literal */
2977 if (AOP_TYPE(right) == AOP_LIT){
2978 /* AND literal negative */
2979 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
2980 /* adjust MSB (c==0 after mul) */
2981 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2985 lbl = newiTempLabel(NULL);
2986 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2987 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
2988 emitcode("","%05d$:",(lbl->key+100));
2989 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2990 lbl = newiTempLabel(NULL);
2991 emitcode("jc","%05d$",(lbl->key+100));
2992 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2993 emitcode("","%05d$:",(lbl->key+100));
2996 lbl = newiTempLabel(NULL);
2997 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
2998 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
2999 emitcode("","%05d$:",(lbl->key+100));
3000 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3001 lbl = newiTempLabel(NULL);
3002 emitcode("jc","%05d$",(lbl->key+100));
3003 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
3004 emitcode("","%05d$:",(lbl->key+100));
3006 aopPut(AOP(result),"a",1);
3009 emitcode("rlc","a");
3010 emitcode("subb","a,acc");
3017 aopPut(AOP(result),"a",offset++);
3021 /*-----------------------------------------------------------------*/
3022 /* genMult - generates code for multiplication */
3023 /*-----------------------------------------------------------------*/
3024 static void genMult (iCode *ic)
3026 operand *left = IC_LEFT(ic);
3027 operand *right = IC_RIGHT(ic);
3028 operand *result= IC_RESULT(ic);
3030 /* assign the amsops */
3031 aopOp (left,ic,FALSE);
3032 aopOp (right,ic,FALSE);
3033 aopOp (result,ic,TRUE);
3035 /* special cases first */
3037 if (AOP_TYPE(left) == AOP_CRY &&
3038 AOP_TYPE(right)== AOP_CRY) {
3039 genMultbits(left,right,result);
3043 /* if both are of size == 1 */
3044 if (AOP_SIZE(left) == 1 &&
3045 AOP_SIZE(right) == 1 ) {
3046 genMultOneByte(left,right,result);
3050 /* should have been converted to function call */
3054 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3055 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3056 freeAsmop(result,NULL,ic,TRUE);
3059 /*-----------------------------------------------------------------*/
3060 /* genDivbits :- division of bits */
3061 /*-----------------------------------------------------------------*/
3062 static void genDivbits (operand *left,
3069 /* the result must be bit */
3070 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3071 l = aopGet(AOP(left),0,FALSE,FALSE);
3075 emitcode("div","ab");
3076 emitcode("rrc","a");
3077 aopPut(AOP(result),"c",0);
3080 /*-----------------------------------------------------------------*/
3081 /* genDivOneByte : 8 bit division */
3082 /*-----------------------------------------------------------------*/
3083 static void genDivOneByte (operand *left,
3087 link *opetype = operandType(result);
3092 size = AOP_SIZE(result) - 1;
3094 /* signed or unsigned */
3095 if (SPEC_USIGN(opetype)) {
3096 /* unsigned is easy */
3097 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3098 l = aopGet(AOP(left),0,FALSE,FALSE);
3100 emitcode("div","ab");
3101 aopPut(AOP(result),"a",0);
3103 aopPut(AOP(result),zero,offset++);
3107 /* signed is a little bit more difficult */
3109 /* save the signs of the operands */
3110 l = aopGet(AOP(left),0,FALSE,FALSE);
3112 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3113 emitcode("push","acc"); /* save it on the stack */
3115 /* now sign adjust for both left & right */
3116 l = aopGet(AOP(right),0,FALSE,FALSE);
3118 lbl = newiTempLabel(NULL);
3119 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3120 emitcode("cpl","a");
3121 emitcode("inc","a");
3122 emitcode("","%05d$:",(lbl->key+100));
3123 emitcode("mov","b,a");
3125 /* sign adjust left side */
3126 l = aopGet(AOP(left),0,FALSE,FALSE);
3129 lbl = newiTempLabel(NULL);
3130 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3131 emitcode("cpl","a");
3132 emitcode("inc","a");
3133 emitcode("","%05d$:",(lbl->key+100));
3135 /* now the division */
3136 emitcode("div","ab");
3137 /* we are interested in the lower order
3139 emitcode("mov","b,a");
3140 lbl = newiTempLabel(NULL);
3141 emitcode("pop","acc");
3142 /* if there was an over flow we don't
3143 adjust the sign of the result */
3144 emitcode("jb","ov,%05d$",(lbl->key+100));
3145 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3147 emitcode("clr","a");
3148 emitcode("subb","a,b");
3149 emitcode("mov","b,a");
3150 emitcode("","%05d$:",(lbl->key+100));
3152 /* now we are done */
3153 aopPut(AOP(result),"b",0);
3155 emitcode("mov","c,b.7");
3156 emitcode("subb","a,acc");
3159 aopPut(AOP(result),"a",offset++);
3163 /*-----------------------------------------------------------------*/
3164 /* genDiv - generates code for division */
3165 /*-----------------------------------------------------------------*/
3166 static void genDiv (iCode *ic)
3168 operand *left = IC_LEFT(ic);
3169 operand *right = IC_RIGHT(ic);
3170 operand *result= IC_RESULT(ic);
3172 /* assign the amsops */
3173 aopOp (left,ic,FALSE);
3174 aopOp (right,ic,FALSE);
3175 aopOp (result,ic,TRUE);
3177 /* special cases first */
3179 if (AOP_TYPE(left) == AOP_CRY &&
3180 AOP_TYPE(right)== AOP_CRY) {
3181 genDivbits(left,right,result);
3185 /* if both are of size == 1 */
3186 if (AOP_SIZE(left) == 1 &&
3187 AOP_SIZE(right) == 1 ) {
3188 genDivOneByte(left,right,result);
3192 /* should have been converted to function call */
3195 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3196 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3197 freeAsmop(result,NULL,ic,TRUE);
3200 /*-----------------------------------------------------------------*/
3201 /* genModbits :- modulus of bits */
3202 /*-----------------------------------------------------------------*/
3203 static void genModbits (operand *left,
3210 /* the result must be bit */
3211 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3212 l = aopGet(AOP(left),0,FALSE,FALSE);
3216 emitcode("div","ab");
3217 emitcode("mov","a,b");
3218 emitcode("rrc","a");
3219 aopPut(AOP(result),"c",0);
3222 /*-----------------------------------------------------------------*/
3223 /* genModOneByte : 8 bit modulus */
3224 /*-----------------------------------------------------------------*/
3225 static void genModOneByte (operand *left,
3229 link *opetype = operandType(result);
3233 /* signed or unsigned */
3234 if (SPEC_USIGN(opetype)) {
3235 /* unsigned is easy */
3236 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3237 l = aopGet(AOP(left),0,FALSE,FALSE);
3239 emitcode("div","ab");
3240 aopPut(AOP(result),"b",0);
3244 /* signed is a little bit more difficult */
3246 /* save the signs of the operands */
3247 l = aopGet(AOP(left),0,FALSE,FALSE);
3250 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3251 emitcode("push","acc"); /* save it on the stack */
3253 /* now sign adjust for both left & right */
3254 l = aopGet(AOP(right),0,FALSE,FALSE);
3257 lbl = newiTempLabel(NULL);
3258 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3259 emitcode("cpl","a");
3260 emitcode("inc","a");
3261 emitcode("","%05d$:",(lbl->key+100));
3262 emitcode("mov","b,a");
3264 /* sign adjust left side */
3265 l = aopGet(AOP(left),0,FALSE,FALSE);
3268 lbl = newiTempLabel(NULL);
3269 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3270 emitcode("cpl","a");
3271 emitcode("inc","a");
3272 emitcode("","%05d$:",(lbl->key+100));
3274 /* now the multiplication */
3275 emitcode("div","ab");
3276 /* we are interested in the lower order
3278 lbl = newiTempLabel(NULL);
3279 emitcode("pop","acc");
3280 /* if there was an over flow we don't
3281 adjust the sign of the result */
3282 emitcode("jb","ov,%05d$",(lbl->key+100));
3283 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3285 emitcode("clr","a");
3286 emitcode("subb","a,b");
3287 emitcode("mov","b,a");
3288 emitcode("","%05d$:",(lbl->key+100));
3290 /* now we are done */
3291 aopPut(AOP(result),"b",0);
3295 /*-----------------------------------------------------------------*/
3296 /* genMod - generates code for division */
3297 /*-----------------------------------------------------------------*/
3298 static void genMod (iCode *ic)
3300 operand *left = IC_LEFT(ic);
3301 operand *right = IC_RIGHT(ic);
3302 operand *result= IC_RESULT(ic);
3304 /* assign the amsops */
3305 aopOp (left,ic,FALSE);
3306 aopOp (right,ic,FALSE);
3307 aopOp (result,ic,TRUE);
3309 /* special cases first */
3311 if (AOP_TYPE(left) == AOP_CRY &&
3312 AOP_TYPE(right)== AOP_CRY) {
3313 genModbits(left,right,result);
3317 /* if both are of size == 1 */
3318 if (AOP_SIZE(left) == 1 &&
3319 AOP_SIZE(right) == 1 ) {
3320 genModOneByte(left,right,result);
3324 /* should have been converted to function call */
3328 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3329 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3330 freeAsmop(result,NULL,ic,TRUE);
3333 /*-----------------------------------------------------------------*/
3334 /* genIfxJump :- will create a jump depending on the ifx */
3335 /*-----------------------------------------------------------------*/
3336 static void genIfxJump (iCode *ic, char *jval)
3339 symbol *tlbl = newiTempLabel(NULL);
3342 /* if true label then we jump if condition
3344 if ( IC_TRUE(ic) ) {
3346 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3347 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3350 /* false label is present */
3351 jlbl = IC_FALSE(ic) ;
3352 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3353 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3355 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3356 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3358 emitcode(inst,"%05d$",tlbl->key+100);
3359 emitcode("ljmp","%05d$",jlbl->key+100);
3360 emitcode("","%05d$:",tlbl->key+100);
3362 /* mark the icode as generated */
3366 /*-----------------------------------------------------------------*/
3367 /* genCmp :- greater or less than comparison */
3368 /*-----------------------------------------------------------------*/
3369 static void genCmp (operand *left,operand *right,
3370 operand *result, iCode *ifx, int sign)
3372 int size, offset = 0 ;
3373 unsigned long lit = 0L;
3375 /* if left & right are bit variables */
3376 if (AOP_TYPE(left) == AOP_CRY &&
3377 AOP_TYPE(right) == AOP_CRY ) {
3378 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3379 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3381 /* subtract right from left if at the
3382 end the carry flag is set then we know that
3383 left is greater than right */
3384 size = max(AOP_SIZE(left),AOP_SIZE(right));
3386 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3387 if((size == 1) && !sign &&
3388 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3389 symbol *lbl = newiTempLabel(NULL);
3390 emitcode("cjne","%s,%s,%05d$",
3391 aopGet(AOP(left),offset,FALSE,FALSE),
3392 aopGet(AOP(right),offset,FALSE,FALSE),
3394 emitcode("","%05d$:",lbl->key+100);
3396 if(AOP_TYPE(right) == AOP_LIT){
3397 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3398 /* optimize if(x < 0) or if(x >= 0) */
3404 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE));
3405 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3406 genIfxJump (ifx,"acc.7");
3410 emitcode("rlc","a");
3417 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3418 if (sign && size == 0) {
3419 emitcode("xrl","a,#0x80");
3420 if (AOP_TYPE(right) == AOP_LIT){
3421 unsigned long lit = (unsigned long)
3422 floatFromVal(AOP(right)->aopu.aop_lit);
3423 emitcode("subb","a,#0x%02x",
3424 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3426 emitcode("mov","b,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3427 emitcode("xrl","b,#0x80");
3428 emitcode("subb","a,b");
3431 emitcode("subb","a,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3437 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3440 /* if the result is used in the next
3441 ifx conditional branch then generate
3442 code a little differently */
3444 genIfxJump (ifx,"c");
3447 /* leave the result in acc */
3451 /*-----------------------------------------------------------------*/
3452 /* genCmpGt :- greater than comparison */
3453 /*-----------------------------------------------------------------*/
3454 static void genCmpGt (iCode *ic, iCode *ifx)
3456 operand *left, *right, *result;
3457 link *letype , *retype;
3461 right= IC_RIGHT(ic);
3462 result = IC_RESULT(ic);
3464 letype = getSpec(operandType(left));
3465 retype =getSpec(operandType(right));
3466 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3467 /* assign the amsops */
3468 aopOp (left,ic,FALSE);
3469 aopOp (right,ic,FALSE);
3470 aopOp (result,ic,TRUE);
3472 genCmp(right, left, result, ifx, sign);
3474 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3475 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3476 freeAsmop(result,NULL,ic,TRUE);
3479 /*-----------------------------------------------------------------*/
3480 /* genCmpLt - less than comparisons */
3481 /*-----------------------------------------------------------------*/
3482 static void genCmpLt (iCode *ic, iCode *ifx)
3484 operand *left, *right, *result;
3485 link *letype , *retype;
3489 right= IC_RIGHT(ic);
3490 result = IC_RESULT(ic);
3492 letype = getSpec(operandType(left));
3493 retype =getSpec(operandType(right));
3494 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3496 /* assign the amsops */
3497 aopOp (left,ic,FALSE);
3498 aopOp (right,ic,FALSE);
3499 aopOp (result,ic,TRUE);
3501 genCmp(left, right, result, ifx, sign);
3503 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3504 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3505 freeAsmop(result,NULL,ic,TRUE);
3508 /*-----------------------------------------------------------------*/
3509 /* gencjneshort - compare and jump if not equal */
3510 /*-----------------------------------------------------------------*/
3511 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3513 int size = max(AOP_SIZE(left),AOP_SIZE(right));
3515 unsigned long lit = 0L;
3517 /* if the left side is a literal or
3518 if the right is in a pointer register and left
3520 if ((AOP_TYPE(left) == AOP_LIT) ||
3521 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3526 if(AOP_TYPE(right) == AOP_LIT)
3527 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3529 /* if the right side is a literal then anything goes */
3530 if (AOP_TYPE(right) == AOP_LIT &&
3531 AOP_TYPE(left) != AOP_DIR ) {
3533 emitcode("cjne","%s,%s,%05d$",
3534 aopGet(AOP(left),offset,FALSE,FALSE),
3535 aopGet(AOP(right),offset,FALSE,FALSE),
3541 /* if the right side is in a register or in direct space or
3542 if the left is a pointer register & right is not */
3543 else if (AOP_TYPE(right) == AOP_REG ||
3544 AOP_TYPE(right) == AOP_DIR ||
3545 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3546 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3548 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3549 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3550 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
3551 emitcode("jnz","%05d$",lbl->key+100);
3553 emitcode("cjne","a,%s,%05d$",
3554 aopGet(AOP(right),offset,FALSE,TRUE),
3559 /* right is a pointer reg need both a & b */
3561 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
3563 emitcode("mov","b,%s",l);
3564 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3565 emitcode("cjne","a,b,%05d$",lbl->key+100);
3571 /*-----------------------------------------------------------------*/
3572 /* gencjne - compare and jump if not equal */
3573 /*-----------------------------------------------------------------*/
3574 static void gencjne(operand *left, operand *right, symbol *lbl)
3576 symbol *tlbl = newiTempLabel(NULL);
3578 gencjneshort(left, right, lbl);
3580 emitcode("mov","a,%s",one);
3581 emitcode("sjmp","%05d$",tlbl->key+100);
3582 emitcode("","%05d$:",lbl->key+100);
3583 emitcode("clr","a");
3584 emitcode("","%05d$:",tlbl->key+100);
3587 /*-----------------------------------------------------------------*/
3588 /* genCmpEq - generates code for equal to */
3589 /*-----------------------------------------------------------------*/
3590 static void genCmpEq (iCode *ic, iCode *ifx)
3592 operand *left, *right, *result;
3594 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3595 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3596 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3598 /* if literal, literal on the right or
3599 if the right is in a pointer register and left
3601 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
3602 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3603 operand *t = IC_RIGHT(ic);
3604 IC_RIGHT(ic) = IC_LEFT(ic);
3608 if(ifx && !AOP_SIZE(result)){
3610 /* if they are both bit variables */
3611 if (AOP_TYPE(left) == AOP_CRY &&
3612 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3613 if(AOP_TYPE(right) == AOP_LIT){
3614 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3616 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3617 emitcode("cpl","c");
3618 } else if(lit == 1L) {
3619 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3621 emitcode("clr","c");
3623 /* AOP_TYPE(right) == AOP_CRY */
3625 symbol *lbl = newiTempLabel(NULL);
3626 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3627 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3628 emitcode("cpl","c");
3629 emitcode("","%05d$:",(lbl->key+100));
3631 /* if true label then we jump if condition
3633 tlbl = newiTempLabel(NULL);
3634 if ( IC_TRUE(ifx) ) {
3635 emitcode("jnc","%05d$",tlbl->key+100);
3636 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3638 emitcode("jc","%05d$",tlbl->key+100);
3639 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3641 emitcode("","%05d$:",tlbl->key+100);
3643 tlbl = newiTempLabel(NULL);
3644 gencjneshort(left, right, tlbl);
3645 if ( IC_TRUE(ifx) ) {
3646 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3647 emitcode("","%05d$:",tlbl->key+100);
3649 symbol *lbl = newiTempLabel(NULL);
3650 emitcode("sjmp","%05d$",lbl->key+100);
3651 emitcode("","%05d$:",tlbl->key+100);
3652 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3653 emitcode("","%05d$:",lbl->key+100);
3656 /* mark the icode as generated */
3661 /* if they are both bit variables */
3662 if (AOP_TYPE(left) == AOP_CRY &&
3663 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3664 if(AOP_TYPE(right) == AOP_LIT){
3665 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3667 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3668 emitcode("cpl","c");
3669 } else if(lit == 1L) {
3670 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3672 emitcode("clr","c");
3674 /* AOP_TYPE(right) == AOP_CRY */
3676 symbol *lbl = newiTempLabel(NULL);
3677 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3678 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3679 emitcode("cpl","c");
3680 emitcode("","%05d$:",(lbl->key+100));
3683 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
3688 genIfxJump (ifx,"c");
3691 /* if the result is used in an arithmetic operation
3692 then put the result in place */
3695 gencjne(left,right,newiTempLabel(NULL));
3696 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3697 aopPut(AOP(result),"a",0);
3701 genIfxJump (ifx,"a");
3704 /* if the result is used in an arithmetic operation
3705 then put the result in place */
3706 if (AOP_TYPE(result) != AOP_CRY)
3708 /* leave the result in acc */
3712 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3713 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3714 freeAsmop(result,NULL,ic,TRUE);
3717 /*-----------------------------------------------------------------*/
3718 /* ifxForOp - returns the icode containing the ifx for operand */
3719 /*-----------------------------------------------------------------*/
3720 static iCode *ifxForOp ( operand *op, iCode *ic )
3722 /* if true symbol then needs to be assigned */
3723 if (IS_TRUE_SYMOP(op))
3726 /* if this has register type condition and
3727 the next instruction is ifx with the same operand
3728 and live to of the operand is upto the ifx only then */
3730 ic->next->op == IFX &&
3731 IC_COND(ic->next)->key == op->key &&
3732 OP_SYMBOL(op)->liveTo <= ic->next->seq )
3737 /*-----------------------------------------------------------------*/
3738 /* genAndOp - for && operation */
3739 /*-----------------------------------------------------------------*/
3740 static void genAndOp (iCode *ic)
3742 operand *left,*right, *result;
3745 /* note here that && operations that are in an
3746 if statement are taken away by backPatchLabels
3747 only those used in arthmetic operations remain */
3748 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3749 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3750 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3752 /* if both are bit variables */
3753 if (AOP_TYPE(left) == AOP_CRY &&
3754 AOP_TYPE(right) == AOP_CRY ) {
3755 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3756 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3759 tlbl = newiTempLabel(NULL);
3761 emitcode("jz","%05d$",tlbl->key+100);
3763 emitcode("","%05d$:",tlbl->key+100);
3767 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3768 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3769 freeAsmop(result,NULL,ic,TRUE);
3773 /*-----------------------------------------------------------------*/
3774 /* genOrOp - for || operation */
3775 /*-----------------------------------------------------------------*/
3776 static void genOrOp (iCode *ic)
3778 operand *left,*right, *result;
3781 /* note here that || operations that are in an
3782 if statement are taken away by backPatchLabels
3783 only those used in arthmetic operations remain */
3784 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3785 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3786 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3788 /* if both are bit variables */
3789 if (AOP_TYPE(left) == AOP_CRY &&
3790 AOP_TYPE(right) == AOP_CRY ) {
3791 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3792 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
3795 tlbl = newiTempLabel(NULL);
3797 emitcode("jnz","%05d$",tlbl->key+100);
3799 emitcode("","%05d$:",tlbl->key+100);
3803 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3804 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3805 freeAsmop(result,NULL,ic,TRUE);
3808 /*-----------------------------------------------------------------*/
3809 /* isLiteralBit - test if lit == 2^n */
3810 /*-----------------------------------------------------------------*/
3811 static int isLiteralBit(unsigned long lit)
3813 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
3814 0x100L,0x200L,0x400L,0x800L,
3815 0x1000L,0x2000L,0x4000L,0x8000L,
3816 0x10000L,0x20000L,0x40000L,0x80000L,
3817 0x100000L,0x200000L,0x400000L,0x800000L,
3818 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
3819 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
3822 for(idx = 0; idx < 32; idx++)
3828 /*-----------------------------------------------------------------*/
3829 /* continueIfTrue - */
3830 /*-----------------------------------------------------------------*/
3831 static void continueIfTrue (iCode *ic)
3834 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3838 /*-----------------------------------------------------------------*/
3840 /*-----------------------------------------------------------------*/
3841 static void jumpIfTrue (iCode *ic)
3844 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3848 /*-----------------------------------------------------------------*/
3849 /* jmpTrueOrFalse - */
3850 /*-----------------------------------------------------------------*/
3851 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
3853 // ugly but optimized by peephole
3855 symbol *nlbl = newiTempLabel(NULL);
3856 emitcode("sjmp","%05d$",nlbl->key+100);
3857 emitcode("","%05d$:",tlbl->key+100);
3858 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3859 emitcode("","%05d$:",nlbl->key+100);
3862 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3863 emitcode("","%05d$:",tlbl->key+100);
3868 /*-----------------------------------------------------------------*/
3869 /* genAnd - code for and */
3870 /*-----------------------------------------------------------------*/
3871 static void genAnd (iCode *ic, iCode *ifx)
3873 operand *left, *right, *result;
3875 unsigned long lit = 0L;
3879 aopOp((left = IC_LEFT(ic)),ic,FALSE);
3880 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3881 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3884 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3886 AOP_TYPE(left), AOP_TYPE(right));
3887 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3889 AOP_SIZE(left), AOP_SIZE(right));
3892 /* if left is a literal & right is not then exchange them */
3893 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3894 AOP_NEEDSACC(left)) {
3895 operand *tmp = right ;
3900 /* if result = right then exchange them */
3901 if(sameRegs(AOP(result),AOP(right))){
3902 operand *tmp = right ;
3907 /* if right is bit then exchange them */
3908 if (AOP_TYPE(right) == AOP_CRY &&
3909 AOP_TYPE(left) != AOP_CRY){
3910 operand *tmp = right ;
3914 if(AOP_TYPE(right) == AOP_LIT)
3915 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3917 size = AOP_SIZE(result);
3920 // result = bit & yy;
3921 if (AOP_TYPE(left) == AOP_CRY){
3922 // c = bit & literal;
3923 if(AOP_TYPE(right) == AOP_LIT){
3925 if(size && sameRegs(AOP(result),AOP(left)))
3928 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3931 if(size && (AOP_TYPE(result) == AOP_CRY)){
3932 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
3935 if((AOP_TYPE(result) == AOP_CRY) && ifx){
3939 emitcode("clr","c");
3942 if (AOP_TYPE(right) == AOP_CRY){
3944 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3945 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3948 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
3950 emitcode("rrc","a");
3951 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3959 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
3960 genIfxJump(ifx, "c");
3964 // if(val & 0xZZ) - size = 0, ifx != FALSE -
3965 // bit = val & 0xZZ - size = 1, ifx = FALSE -
3966 if((AOP_TYPE(right) == AOP_LIT) &&
3967 (AOP_TYPE(result) == AOP_CRY) &&
3968 (AOP_TYPE(left) != AOP_CRY)){
3969 int posbit = isLiteralBit(lit);
3973 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
3976 emitcode("mov","c,acc.%d",posbit&0x07);
3980 sprintf(buffer,"acc.%d",posbit&0x07);
3981 genIfxJump(ifx, buffer);
3986 symbol *tlbl = newiTempLabel(NULL);
3987 int sizel = AOP_SIZE(left);
3989 emitcode("setb","c");
3991 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
3992 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
3994 if((posbit = isLiteralBit(bytelit)) != 0)
3995 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
3997 if(bytelit != 0x0FFL)
3998 emitcode("anl","a,%s",
3999 aopGet(AOP(right),offset,FALSE,TRUE));
4000 emitcode("jnz","%05d$",tlbl->key+100);
4005 // bit = left & literal
4007 emitcode("clr","c");
4008 emitcode("","%05d$:",tlbl->key+100);
4010 // if(left & literal)
4013 jmpTrueOrFalse(ifx, tlbl);
4021 /* if left is same as result */
4022 if(sameRegs(AOP(result),AOP(left))){
4023 for(;size--; offset++) {
4024 if(AOP_TYPE(right) == AOP_LIT){
4025 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4029 aopPut(AOP(result),zero,offset);
4031 if (IS_AOP_PREG(result)) {
4032 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4033 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4034 aopPut(AOP(result),"a",offset);
4036 emitcode("anl","%s,%s",
4037 aopGet(AOP(left),offset,FALSE,TRUE),
4038 aopGet(AOP(right),offset,FALSE,FALSE));
4040 if (AOP_TYPE(left) == AOP_ACC)
4041 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4043 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4044 if (IS_AOP_PREG(result)) {
4045 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4046 aopPut(AOP(result),"a",offset);
4049 emitcode("anl","%s,a",
4050 aopGet(AOP(left),offset,FALSE,TRUE));
4055 // left & result in different registers
4056 if(AOP_TYPE(result) == AOP_CRY){
4058 // if(size), result in bit
4059 // if(!size && ifx), conditional oper: if(left & right)
4060 symbol *tlbl = newiTempLabel(NULL);
4061 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4063 emitcode("setb","c");
4065 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4066 emitcode("anl","a,%s",
4067 aopGet(AOP(left),offset,FALSE,FALSE));
4068 emitcode("jnz","%05d$",tlbl->key+100);
4073 emitcode("","%05d$:",tlbl->key+100);
4076 jmpTrueOrFalse(ifx, tlbl);
4078 for(;(size--);offset++) {
4080 // result = left & right
4081 if(AOP_TYPE(right) == AOP_LIT){
4082 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
4084 aopGet(AOP(left),offset,FALSE,FALSE),
4087 } else if(bytelit == 0){
4088 aopPut(AOP(result),zero,offset);
4092 // faster than result <- left, anl result,right
4093 // and better if result is SFR
4094 if (AOP_TYPE(left) == AOP_ACC)
4095 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4097 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4098 emitcode("anl","a,%s",
4099 aopGet(AOP(left),offset,FALSE,FALSE));
4101 aopPut(AOP(result),"a",offset);
4107 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4108 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4109 freeAsmop(result,NULL,ic,TRUE);
4112 /*-----------------------------------------------------------------*/
4113 /* genOr - code for or */
4114 /*-----------------------------------------------------------------*/
4115 static void genOr (iCode *ic, iCode *ifx)
4117 operand *left, *right, *result;
4119 unsigned long lit = 0L;
4121 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4122 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4123 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4126 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4128 AOP_TYPE(left), AOP_TYPE(right));
4129 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4131 AOP_SIZE(left), AOP_SIZE(right));
4134 /* if left is a literal & right is not then exchange them */
4135 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4136 AOP_NEEDSACC(left)) {
4137 operand *tmp = right ;
4142 /* if result = right then exchange them */
4143 if(sameRegs(AOP(result),AOP(right))){
4144 operand *tmp = right ;
4149 /* if right is bit then exchange them */
4150 if (AOP_TYPE(right) == AOP_CRY &&
4151 AOP_TYPE(left) != AOP_CRY){
4152 operand *tmp = right ;
4156 if(AOP_TYPE(right) == AOP_LIT)
4157 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4159 size = AOP_SIZE(result);
4163 if (AOP_TYPE(left) == AOP_CRY){
4164 if(AOP_TYPE(right) == AOP_LIT){
4165 // c = bit & literal;
4167 // lit != 0 => result = 1
4168 if(AOP_TYPE(result) == AOP_CRY){
4170 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4172 continueIfTrue(ifx);
4175 emitcode("setb","c");
4177 // lit == 0 => result = left
4178 if(size && sameRegs(AOP(result),AOP(left)))
4180 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4183 if (AOP_TYPE(right) == AOP_CRY){
4185 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4186 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4190 symbol *tlbl = newiTempLabel(NULL);
4191 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4192 emitcode("setb","c");
4193 emitcode("jb","%s,%05d$",
4194 AOP(left)->aopu.aop_dir,tlbl->key+100);
4196 emitcode("jnz","%05d$",tlbl->key+100);
4197 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4198 jmpTrueOrFalse(ifx, tlbl);
4202 emitcode("","%05d$:",tlbl->key+100);
4211 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4212 genIfxJump(ifx, "c");
4216 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4217 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4218 if((AOP_TYPE(right) == AOP_LIT) &&
4219 (AOP_TYPE(result) == AOP_CRY) &&
4220 (AOP_TYPE(left) != AOP_CRY)){
4224 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4226 continueIfTrue(ifx);
4229 // lit = 0, result = boolean(left)
4231 emitcode("setb","c");
4234 symbol *tlbl = newiTempLabel(NULL);
4235 emitcode("jnz","%05d$",tlbl->key+100);
4237 emitcode("","%05d$:",tlbl->key+100);
4239 genIfxJump (ifx,"a");
4247 /* if left is same as result */
4248 if(sameRegs(AOP(result),AOP(left))){
4249 for(;size--; offset++) {
4250 if(AOP_TYPE(right) == AOP_LIT){
4251 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4254 if (IS_AOP_PREG(left)) {
4255 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4256 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4257 aopPut(AOP(result),"a",offset);
4259 emitcode("orl","%s,%s",
4260 aopGet(AOP(left),offset,FALSE,TRUE),
4261 aopGet(AOP(right),offset,FALSE,FALSE));
4263 if (AOP_TYPE(left) == AOP_ACC)
4264 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4266 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4267 if (IS_AOP_PREG(left)) {
4268 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4269 aopPut(AOP(result),"a",offset);
4271 emitcode("orl","%s,a",
4272 aopGet(AOP(left),offset,FALSE,TRUE));
4277 // left & result in different registers
4278 if(AOP_TYPE(result) == AOP_CRY){
4280 // if(size), result in bit
4281 // if(!size && ifx), conditional oper: if(left | right)
4282 symbol *tlbl = newiTempLabel(NULL);
4283 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4285 emitcode("setb","c");
4287 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4288 emitcode("orl","a,%s",
4289 aopGet(AOP(left),offset,FALSE,FALSE));
4290 emitcode("jnz","%05d$",tlbl->key+100);
4295 emitcode("","%05d$:",tlbl->key+100);
4298 jmpTrueOrFalse(ifx, tlbl);
4299 } else for(;(size--);offset++){
4301 // result = left & right
4302 if(AOP_TYPE(right) == AOP_LIT){
4303 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4305 aopGet(AOP(left),offset,FALSE,FALSE),
4310 // faster than result <- left, anl result,right
4311 // and better if result is SFR
4312 if (AOP_TYPE(left) == AOP_ACC)
4313 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4315 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4316 emitcode("orl","a,%s",
4317 aopGet(AOP(left),offset,FALSE,FALSE));
4319 aopPut(AOP(result),"a",offset);
4324 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4325 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4326 freeAsmop(result,NULL,ic,TRUE);
4329 /*-----------------------------------------------------------------*/
4330 /* genXor - code for xclusive or */
4331 /*-----------------------------------------------------------------*/
4332 static void genXor (iCode *ic, iCode *ifx)
4334 operand *left, *right, *result;
4336 unsigned long lit = 0L;
4338 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4339 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4340 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4343 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4345 AOP_TYPE(left), AOP_TYPE(right));
4346 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4348 AOP_SIZE(left), AOP_SIZE(right));
4351 /* if left is a literal & right is not ||
4352 if left needs acc & right does not */
4353 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4354 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4355 operand *tmp = right ;
4360 /* if result = right then exchange them */
4361 if(sameRegs(AOP(result),AOP(right))){
4362 operand *tmp = right ;
4367 /* if right is bit then exchange them */
4368 if (AOP_TYPE(right) == AOP_CRY &&
4369 AOP_TYPE(left) != AOP_CRY){
4370 operand *tmp = right ;
4374 if(AOP_TYPE(right) == AOP_LIT)
4375 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4377 size = AOP_SIZE(result);
4381 if (AOP_TYPE(left) == AOP_CRY){
4382 if(AOP_TYPE(right) == AOP_LIT){
4383 // c = bit & literal;
4385 // lit>>1 != 0 => result = 1
4386 if(AOP_TYPE(result) == AOP_CRY){
4388 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4390 continueIfTrue(ifx);
4393 emitcode("setb","c");
4397 // lit == 0, result = left
4398 if(size && sameRegs(AOP(result),AOP(left)))
4400 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4402 // lit == 1, result = not(left)
4403 if(size && sameRegs(AOP(result),AOP(left))){
4404 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4407 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4408 emitcode("cpl","c");
4415 symbol *tlbl = newiTempLabel(NULL);
4416 if (AOP_TYPE(right) == AOP_CRY){
4418 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4421 int sizer = AOP_SIZE(right);
4423 // if val>>1 != 0, result = 1
4424 emitcode("setb","c");
4426 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
4428 // test the msb of the lsb
4429 emitcode("anl","a,#0xfe");
4430 emitcode("jnz","%05d$",tlbl->key+100);
4434 emitcode("rrc","a");
4436 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4437 emitcode("cpl","c");
4438 emitcode("","%05d$:",(tlbl->key+100));
4445 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4446 genIfxJump(ifx, "c");
4450 if(sameRegs(AOP(result),AOP(left))){
4451 /* if left is same as result */
4452 for(;size--; offset++) {
4453 if(AOP_TYPE(right) == AOP_LIT){
4454 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4457 if (IS_AOP_PREG(left)) {
4458 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4459 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4460 aopPut(AOP(result),"a",offset);
4462 emitcode("xrl","%s,%s",
4463 aopGet(AOP(left),offset,FALSE,TRUE),
4464 aopGet(AOP(right),offset,FALSE,FALSE));
4466 if (AOP_TYPE(left) == AOP_ACC)
4467 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4469 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4470 if (IS_AOP_PREG(left)) {
4471 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4472 aopPut(AOP(result),"a",offset);
4474 emitcode("xrl","%s,a",
4475 aopGet(AOP(left),offset,FALSE,TRUE));
4480 // left & result in different registers
4481 if(AOP_TYPE(result) == AOP_CRY){
4483 // if(size), result in bit
4484 // if(!size && ifx), conditional oper: if(left ^ right)
4485 symbol *tlbl = newiTempLabel(NULL);
4486 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4488 emitcode("setb","c");
4490 if((AOP_TYPE(right) == AOP_LIT) &&
4491 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4492 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4494 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4495 emitcode("xrl","a,%s",
4496 aopGet(AOP(left),offset,FALSE,FALSE));
4498 emitcode("jnz","%05d$",tlbl->key+100);
4503 emitcode("","%05d$:",tlbl->key+100);
4506 jmpTrueOrFalse(ifx, tlbl);
4507 } else for(;(size--);offset++){
4509 // result = left & right
4510 if(AOP_TYPE(right) == AOP_LIT){
4511 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4513 aopGet(AOP(left),offset,FALSE,FALSE),
4518 // faster than result <- left, anl result,right
4519 // and better if result is SFR
4520 if (AOP_TYPE(left) == AOP_ACC)
4521 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4523 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4524 emitcode("xrl","a,%s",
4525 aopGet(AOP(left),offset,FALSE,TRUE));
4527 aopPut(AOP(result),"a",offset);
4532 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4533 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4534 freeAsmop(result,NULL,ic,TRUE);
4537 /*-----------------------------------------------------------------*/
4538 /* genInline - write the inline code out */
4539 /*-----------------------------------------------------------------*/
4540 static void genInline (iCode *ic)
4542 char buffer[MAX_INLINEASM];
4546 _G.inLine += (!options.asmpeep);
4547 strcpy(buffer,IC_INLINE(ic));
4549 /* emit each line as a code */
4568 /* emitcode("",buffer); */
4569 _G.inLine -= (!options.asmpeep);
4572 /*-----------------------------------------------------------------*/
4573 /* genRRC - rotate right with carry */
4574 /*-----------------------------------------------------------------*/
4575 static void genRRC (iCode *ic)
4577 operand *left , *result ;
4578 int size, offset = 0;
4581 /* rotate right with carry */
4583 result=IC_RESULT(ic);
4584 aopOp (left,ic,FALSE);
4585 aopOp (result,ic,FALSE);
4587 /* move it to the result */
4588 size = AOP_SIZE(result);
4592 l = aopGet(AOP(left),offset,FALSE,FALSE);
4594 emitcode("rrc","a");
4595 if (AOP_SIZE(result) > 1)
4596 aopPut(AOP(result),"a",offset--);
4598 /* now we need to put the carry into the
4599 highest order byte of the result */
4600 if (AOP_SIZE(result) > 1) {
4601 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
4604 emitcode("mov","acc.7,c");
4605 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
4606 freeAsmop(left,NULL,ic,TRUE);
4607 freeAsmop(result,NULL,ic,TRUE);
4610 /*-----------------------------------------------------------------*/
4611 /* genRLC - generate code for rotate left with carry */
4612 /*-----------------------------------------------------------------*/
4613 static void genRLC (iCode *ic)
4615 operand *left , *result ;
4616 int size, offset = 0;
4619 /* rotate right with carry */
4621 result=IC_RESULT(ic);
4622 aopOp (left,ic,FALSE);
4623 aopOp (result,ic,FALSE);
4625 /* move it to the result */
4626 size = AOP_SIZE(result);
4629 l = aopGet(AOP(left),offset,FALSE,FALSE);
4631 emitcode("add","a,acc");
4632 if (AOP_SIZE(result) > 1)
4633 aopPut(AOP(result),"a",offset++);
4635 l = aopGet(AOP(left),offset,FALSE,FALSE);
4637 emitcode("rlc","a");
4638 if (AOP_SIZE(result) > 1)
4639 aopPut(AOP(result),"a",offset++);
4642 /* now we need to put the carry into the
4643 highest order byte of the result */
4644 if (AOP_SIZE(result) > 1) {
4645 l = aopGet(AOP(result),0,FALSE,FALSE);
4648 emitcode("mov","acc.0,c");
4649 aopPut(AOP(result),"a",0);
4650 freeAsmop(left,NULL,ic,TRUE);
4651 freeAsmop(result,NULL,ic,TRUE);
4654 /*-----------------------------------------------------------------*/
4655 /* genGetHbit - generates code get highest order bit */
4656 /*-----------------------------------------------------------------*/
4657 static void genGetHbit (iCode *ic)
4659 operand *left, *result;
4661 result=IC_RESULT(ic);
4662 aopOp (left,ic,FALSE);
4663 aopOp (result,ic,FALSE);
4665 /* get the highest order byte into a */
4666 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
4667 if(AOP_TYPE(result) == AOP_CRY){
4668 emitcode("rlc","a");
4673 emitcode("anl","a,#0x01");
4678 freeAsmop(left,NULL,ic,TRUE);
4679 freeAsmop(result,NULL,ic,TRUE);
4682 /*-----------------------------------------------------------------*/
4683 /* AccRol - rotate left accumulator by known count */
4684 /*-----------------------------------------------------------------*/
4685 static void AccRol (int shCount)
4687 shCount &= 0x0007; // shCount : 0..7
4699 emitcode("swap","a");
4703 emitcode("swap","a");
4706 emitcode("swap","a");
4719 /*-----------------------------------------------------------------*/
4720 /* AccLsh - left shift accumulator by known count */
4721 /*-----------------------------------------------------------------*/
4722 static void AccLsh (int shCount)
4726 emitcode("add","a,acc");
4729 emitcode("add","a,acc");
4730 emitcode("add","a,acc");
4732 /* rotate left accumulator */
4734 /* and kill the lower order bits */
4735 emitcode("anl","a,#0x%02x", SLMask[shCount]);
4740 /*-----------------------------------------------------------------*/
4741 /* AccRsh - right shift accumulator by known count */
4742 /*-----------------------------------------------------------------*/
4743 static void AccRsh (int shCount)
4748 emitcode("rrc","a");
4750 /* rotate right accumulator */
4751 AccRol(8 - shCount);
4752 /* and kill the higher order bits */
4753 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4758 /*-----------------------------------------------------------------*/
4759 /* AccSRsh - signed right shift accumulator by known count */
4760 /*-----------------------------------------------------------------*/
4761 static void AccSRsh (int shCount)
4766 emitcode("mov","c,acc.7");
4767 emitcode("rrc","a");
4768 } else if(shCount == 2){
4769 emitcode("mov","c,acc.7");
4770 emitcode("rrc","a");
4771 emitcode("mov","c,acc.7");
4772 emitcode("rrc","a");
4774 tlbl = newiTempLabel(NULL);
4775 /* rotate right accumulator */
4776 AccRol(8 - shCount);
4777 /* and kill the higher order bits */
4778 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4779 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4780 emitcode("orl","a,#0x%02x",
4781 (unsigned char)~SRMask[shCount]);
4782 emitcode("","%05d$:",tlbl->key+100);
4787 /*-----------------------------------------------------------------*/
4788 /* shiftR1Left2Result - shift right one byte from left to result */
4789 /*-----------------------------------------------------------------*/
4790 static void shiftR1Left2Result (operand *left, int offl,
4791 operand *result, int offr,
4792 int shCount, int sign)
4794 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4795 /* shift right accumulator */
4800 aopPut(AOP(result),"a",offr);
4803 /*-----------------------------------------------------------------*/
4804 /* shiftL1Left2Result - shift left one byte from left to result */
4805 /*-----------------------------------------------------------------*/
4806 static void shiftL1Left2Result (operand *left, int offl,
4807 operand *result, int offr, int shCount)
4810 l = aopGet(AOP(left),offl,FALSE,FALSE);
4812 /* shift left accumulator */
4814 aopPut(AOP(result),"a",offr);
4817 /*-----------------------------------------------------------------*/
4818 /* movLeft2Result - move byte from left to result */
4819 /*-----------------------------------------------------------------*/
4820 static void movLeft2Result (operand *left, int offl,
4821 operand *result, int offr, int sign)
4824 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
4825 l = aopGet(AOP(left),offl,FALSE,FALSE);
4827 if (*l == '@' && (IS_AOP_PREG(result))) {
4828 emitcode("mov","a,%s",l);
4829 aopPut(AOP(result),"a",offr);
4832 aopPut(AOP(result),l,offr);
4834 /* MSB sign in acc.7 ! */
4835 if(getDataSize(left) == offl+1){
4836 emitcode("mov","a,%s",l);
4837 aopPut(AOP(result),"a",offr);
4844 /*-----------------------------------------------------------------*/
4845 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
4846 /*-----------------------------------------------------------------*/
4847 static void AccAXRrl1 (char *x)
4849 emitcode("rrc","a");
4850 emitcode("xch","a,%s", x);
4851 emitcode("rrc","a");
4852 emitcode("xch","a,%s", x);
4855 /*-----------------------------------------------------------------*/
4856 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
4857 /*-----------------------------------------------------------------*/
4858 static void AccAXLrl1 (char *x)
4860 emitcode("xch","a,%s",x);
4861 emitcode("rlc","a");
4862 emitcode("xch","a,%s",x);
4863 emitcode("rlc","a");
4866 /*-----------------------------------------------------------------*/
4867 /* AccAXLsh1 - left shift a:x<-0 by 1 */
4868 /*-----------------------------------------------------------------*/
4869 static void AccAXLsh1 (char *x)
4871 emitcode("xch","a,%s",x);
4872 emitcode("add","a,acc");
4873 emitcode("xch","a,%s",x);
4874 emitcode("rlc","a");
4877 /*-----------------------------------------------------------------*/
4878 /* AccAXLsh - left shift a:x by known count (0..7) */
4879 /*-----------------------------------------------------------------*/
4880 static void AccAXLsh (char *x, int shCount)
4894 case 5 : // AAAAABBB:CCCCCDDD
4895 AccRol(shCount); // BBBAAAAA:CCCCCDDD
4896 emitcode("anl","a,#0x%02x",
4897 SLMask[shCount]); // BBB00000:CCCCCDDD
4898 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
4899 AccRol(shCount); // DDDCCCCC:BBB00000
4900 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
4901 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
4902 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
4903 emitcode("anl","a,#0x%02x",
4904 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
4905 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
4906 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
4908 case 6 : // AAAAAABB:CCCCCCDD
4909 emitcode("anl","a,#0x%02x",
4910 SRMask[shCount]); // 000000BB:CCCCCCDD
4911 emitcode("mov","c,acc.0"); // c = B
4912 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
4913 AccAXRrl1(x); // BCCCCCCD:D000000B
4914 AccAXRrl1(x); // BBCCCCCC:DD000000
4916 case 7 : // a:x <<= 7
4917 emitcode("anl","a,#0x%02x",
4918 SRMask[shCount]); // 0000000B:CCCCCCCD
4919 emitcode("mov","c,acc.0"); // c = B
4920 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
4921 AccAXRrl1(x); // BCCCCCCC:D0000000
4928 /*-----------------------------------------------------------------*/
4929 /* AccAXRsh - right shift a:x known count (0..7) */
4930 /*-----------------------------------------------------------------*/
4931 static void AccAXRsh (char *x, int shCount)
4938 AccAXRrl1(x); // 0->a:x
4942 AccAXRrl1(x); // 0->a:x
4944 AccAXRrl1(x); // 0->a:x
4948 case 5 : // AAAAABBB:CCCCCDDD = a:x
4949 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
4950 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
4951 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
4952 emitcode("anl","a,#0x%02x",
4953 SRMask[shCount]); // 000CCCCC:BBBAAAAA
4954 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
4955 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
4956 emitcode("anl","a,#0x%02x",
4957 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
4958 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
4959 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
4960 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
4962 case 6 : // AABBBBBB:CCDDDDDD
4963 emitcode("mov","c,acc.7");
4964 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
4965 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
4966 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
4967 emitcode("anl","a,#0x%02x",
4968 SRMask[shCount]); // 000000AA:BBBBBBCC
4970 case 7 : // ABBBBBBB:CDDDDDDD
4971 emitcode("mov","c,acc.7"); // c = A
4972 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
4973 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
4974 emitcode("anl","a,#0x%02x",
4975 SRMask[shCount]); // 0000000A:BBBBBBBC
4982 /*-----------------------------------------------------------------*/
4983 /* AccAXRshS - right shift signed a:x known count (0..7) */
4984 /*-----------------------------------------------------------------*/
4985 static void AccAXRshS (char *x, int shCount)
4992 emitcode("mov","c,acc.7");
4993 AccAXRrl1(x); // s->a:x
4996 emitcode("mov","c,acc.7");
4997 AccAXRrl1(x); // s->a:x
4998 emitcode("mov","c,acc.7");
4999 AccAXRrl1(x); // s->a:x
5003 case 5 : // AAAAABBB:CCCCCDDD = a:x
5004 tlbl = newiTempLabel(NULL);
5005 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5006 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5007 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5008 emitcode("anl","a,#0x%02x",
5009 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5010 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5011 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5012 emitcode("anl","a,#0x%02x",
5013 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5014 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5015 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5016 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5017 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5018 emitcode("orl","a,#0x%02x",
5019 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5020 emitcode("","%05d$:",tlbl->key+100);
5021 break; // SSSSAAAA:BBBCCCCC
5022 case 6 : // AABBBBBB:CCDDDDDD
5023 tlbl = newiTempLabel(NULL);
5024 emitcode("mov","c,acc.7");
5025 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5026 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5027 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5028 emitcode("anl","a,#0x%02x",
5029 SRMask[shCount]); // 000000AA:BBBBBBCC
5030 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5031 emitcode("orl","a,#0x%02x",
5032 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5033 emitcode("","%05d$:",tlbl->key+100);
5035 case 7 : // ABBBBBBB:CDDDDDDD
5036 tlbl = newiTempLabel(NULL);
5037 emitcode("mov","c,acc.7"); // c = A
5038 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5039 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5040 emitcode("anl","a,#0x%02x",
5041 SRMask[shCount]); // 0000000A:BBBBBBBC
5042 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5043 emitcode("orl","a,#0x%02x",
5044 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5045 emitcode("","%05d$:",tlbl->key+100);
5052 /*-----------------------------------------------------------------*/
5053 /* shiftL2Left2Result - shift left two bytes from left to result */
5054 /*-----------------------------------------------------------------*/
5055 static void shiftL2Left2Result (operand *left, int offl,
5056 operand *result, int offr, int shCount)
5058 if(sameRegs(AOP(result), AOP(left)) &&
5059 ((offl + MSB16) == offr)){
5060 /* don't crash result[offr] */
5061 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5062 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5064 movLeft2Result(left,offl, result, offr, 0);
5065 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5067 /* ax << shCount (x = lsb(result))*/
5068 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5069 aopPut(AOP(result),"a",offr+MSB16);
5073 /*-----------------------------------------------------------------*/
5074 /* shiftR2Left2Result - shift right two bytes from left to result */
5075 /*-----------------------------------------------------------------*/
5076 static void shiftR2Left2Result (operand *left, int offl,
5077 operand *result, int offr,
5078 int shCount, int sign)
5080 if(sameRegs(AOP(result), AOP(left)) &&
5081 ((offl + MSB16) == offr)){
5082 /* don't crash result[offr] */
5083 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5084 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5086 movLeft2Result(left,offl, result, offr, 0);
5087 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5089 /* a:x >> shCount (x = lsb(result))*/
5091 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5093 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5094 if(getDataSize(result) > 1)
5095 aopPut(AOP(result),"a",offr+MSB16);
5098 /*-----------------------------------------------------------------*/
5099 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5100 /*-----------------------------------------------------------------*/
5101 static void shiftLLeftOrResult (operand *left, int offl,
5102 operand *result, int offr, int shCount)
5104 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5105 /* shift left accumulator */
5107 /* or with result */
5108 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5109 /* back to result */
5110 aopPut(AOP(result),"a",offr);
5113 /*-----------------------------------------------------------------*/
5114 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5115 /*-----------------------------------------------------------------*/
5116 static void shiftRLeftOrResult (operand *left, int offl,
5117 operand *result, int offr, int shCount)
5119 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5120 /* shift right accumulator */
5122 /* or with result */
5123 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5124 /* back to result */
5125 aopPut(AOP(result),"a",offr);
5128 /*-----------------------------------------------------------------*/
5129 /* genlshOne - left shift a one byte quantity by known count */
5130 /*-----------------------------------------------------------------*/
5131 static void genlshOne (operand *result, operand *left, int shCount)
5133 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5136 /*-----------------------------------------------------------------*/
5137 /* genlshTwo - left shift two bytes by known amount != 0 */
5138 /*-----------------------------------------------------------------*/
5139 static void genlshTwo (operand *result,operand *left, int shCount)
5143 size = getDataSize(result);
5145 /* if shCount >= 8 */
5151 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5153 movLeft2Result(left, LSB, result, MSB16, 0);
5155 aopPut(AOP(result),zero,LSB);
5158 /* 1 <= shCount <= 7 */
5161 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5163 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5167 /*-----------------------------------------------------------------*/
5168 /* shiftLLong - shift left one long from left to result */
5169 /* offl = LSB or MSB16 */
5170 /*-----------------------------------------------------------------*/
5171 static void shiftLLong (operand *left, operand *result, int offr )
5174 int size = AOP_SIZE(result);
5176 if(size >= LSB+offr){
5177 l = aopGet(AOP(left),LSB,FALSE,FALSE);
5179 emitcode("add","a,acc");
5180 if (sameRegs(AOP(left),AOP(result)) &&
5181 size >= MSB16+offr && offr != LSB )
5182 emitcode("xch","a,%s",
5183 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
5185 aopPut(AOP(result),"a",LSB+offr);
5188 if(size >= MSB16+offr){
5189 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5190 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
5193 emitcode("rlc","a");
5194 if (sameRegs(AOP(left),AOP(result)) &&
5195 size >= MSB24+offr && offr != LSB)
5196 emitcode("xch","a,%s",
5197 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
5199 aopPut(AOP(result),"a",MSB16+offr);
5202 if(size >= MSB24+offr){
5203 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5204 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
5207 emitcode("rlc","a");
5208 if (sameRegs(AOP(left),AOP(result)) &&
5209 size >= MSB32+offr && offr != LSB )
5210 emitcode("xch","a,%s",
5211 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
5213 aopPut(AOP(result),"a",MSB24+offr);
5216 if(size > MSB32+offr){
5217 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5218 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
5221 emitcode("rlc","a");
5222 aopPut(AOP(result),"a",MSB32+offr);
5225 aopPut(AOP(result),zero,LSB);
5228 /*-----------------------------------------------------------------*/
5229 /* genlshFour - shift four byte by a known amount != 0 */
5230 /*-----------------------------------------------------------------*/
5231 static void genlshFour (operand *result, operand *left, int shCount)
5235 size = AOP_SIZE(result);
5237 /* if shifting more that 3 bytes */
5238 if (shCount >= 24 ) {
5241 /* lowest order of left goes to the highest
5242 order of the destination */
5243 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5245 movLeft2Result(left, LSB, result, MSB32, 0);
5246 aopPut(AOP(result),zero,LSB);
5247 aopPut(AOP(result),zero,MSB16);
5248 aopPut(AOP(result),zero,MSB32);
5252 /* more than two bytes */
5253 else if ( shCount >= 16 ) {
5254 /* lower order two bytes goes to higher order two bytes */
5256 /* if some more remaining */
5258 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5260 movLeft2Result(left, MSB16, result, MSB32, 0);
5261 movLeft2Result(left, LSB, result, MSB24, 0);
5263 aopPut(AOP(result),zero,MSB16);
5264 aopPut(AOP(result),zero,LSB);
5268 /* if more than 1 byte */
5269 else if ( shCount >= 8 ) {
5270 /* lower order three bytes goes to higher order three bytes */
5274 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5276 movLeft2Result(left, LSB, result, MSB16, 0);
5278 else{ /* size = 4 */
5280 movLeft2Result(left, MSB24, result, MSB32, 0);
5281 movLeft2Result(left, MSB16, result, MSB24, 0);
5282 movLeft2Result(left, LSB, result, MSB16, 0);
5283 aopPut(AOP(result),zero,LSB);
5285 else if(shCount == 1)
5286 shiftLLong(left, result, MSB16);
5288 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5289 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5290 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5291 aopPut(AOP(result),zero,LSB);
5296 /* 1 <= shCount <= 7 */
5297 else if(shCount <= 2){
5298 shiftLLong(left, result, LSB);
5300 shiftLLong(result, result, LSB);
5302 /* 3 <= shCount <= 7, optimize */
5304 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5305 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5306 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5310 /*-----------------------------------------------------------------*/
5311 /* genLeftShiftLiteral - left shifting by known count */
5312 /*-----------------------------------------------------------------*/
5313 static void genLeftShiftLiteral (operand *left,
5318 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5321 freeAsmop(right,NULL,ic,TRUE);
5323 aopOp(left,ic,FALSE);
5324 aopOp(result,ic,FALSE);
5326 size = getSize(operandType(result));
5329 emitcode("; shift left ","result %d, left %d",size,
5333 /* I suppose that the left size >= result size */
5336 movLeft2Result(left, size, result, size, 0);
5340 else if(shCount >= (size * 8))
5342 aopPut(AOP(result),zero,size);
5346 genlshOne (result,left,shCount);
5351 genlshTwo (result,left,shCount);
5355 genlshFour (result,left,shCount);
5359 freeAsmop(left,NULL,ic,TRUE);
5360 freeAsmop(result,NULL,ic,TRUE);
5363 /*-----------------------------------------------------------------*/
5364 /* genLeftShift - generates code for left shifting */
5365 /*-----------------------------------------------------------------*/
5366 static void genLeftShift (iCode *ic)
5368 operand *left,*right, *result;
5371 symbol *tlbl , *tlbl1;
5373 right = IC_RIGHT(ic);
5375 result = IC_RESULT(ic);
5377 aopOp(right,ic,FALSE);
5379 /* if the shift count is known then do it
5380 as efficiently as possible */
5381 if (AOP_TYPE(right) == AOP_LIT) {
5382 genLeftShiftLiteral (left,right,result,ic);
5386 /* shift count is unknown then we have to form
5387 a loop get the loop count in B : Note: we take
5388 only the lower order byte since shifting
5389 more that 32 bits make no sense anyway, ( the
5390 largest size of an object can be only 32 bits ) */
5392 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5393 emitcode("inc","b");
5394 freeAsmop (right,NULL,ic,TRUE);
5395 aopOp(left,ic,FALSE);
5396 aopOp(result,ic,FALSE);
5398 /* now move the left to the result if they are not the
5400 if (!sameRegs(AOP(left),AOP(result)) &&
5401 AOP_SIZE(result) > 1) {
5403 size = AOP_SIZE(result);
5406 l = aopGet(AOP(left),offset,FALSE,TRUE);
5407 if (*l == '@' && (IS_AOP_PREG(result))) {
5409 emitcode("mov","a,%s",l);
5410 aopPut(AOP(result),"a",offset);
5412 aopPut(AOP(result),l,offset);
5417 tlbl = newiTempLabel(NULL);
5418 size = AOP_SIZE(result);
5420 tlbl1 = newiTempLabel(NULL);
5422 /* if it is only one byte then */
5424 symbol *tlbl1 = newiTempLabel(NULL);
5426 l = aopGet(AOP(left),0,FALSE,FALSE);
5428 emitcode("sjmp","%05d$",tlbl1->key+100);
5429 emitcode("","%05d$:",tlbl->key+100);
5430 emitcode("add","a,acc");
5431 emitcode("","%05d$:",tlbl1->key+100);
5432 emitcode("djnz","b,%05d$",tlbl->key+100);
5433 aopPut(AOP(result),"a",0);
5437 reAdjustPreg(AOP(result));
5439 emitcode("sjmp","%05d$",tlbl1->key+100);
5440 emitcode("","%05d$:",tlbl->key+100);
5441 l = aopGet(AOP(result),offset,FALSE,FALSE);
5443 emitcode("add","a,acc");
5444 aopPut(AOP(result),"a",offset++);
5446 l = aopGet(AOP(result),offset,FALSE,FALSE);
5448 emitcode("rlc","a");
5449 aopPut(AOP(result),"a",offset++);
5451 reAdjustPreg(AOP(result));
5453 emitcode("","%05d$:",tlbl1->key+100);
5454 emitcode("djnz","b,%05d$",tlbl->key+100);
5456 freeAsmop(left,NULL,ic,TRUE);
5457 freeAsmop(result,NULL,ic,TRUE);
5460 /*-----------------------------------------------------------------*/
5461 /* genrshOne - right shift a one byte quantity by known count */
5462 /*-----------------------------------------------------------------*/
5463 static void genrshOne (operand *result, operand *left,
5464 int shCount, int sign)
5466 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
5469 /*-----------------------------------------------------------------*/
5470 /* genrshTwo - right shift two bytes by known amount != 0 */
5471 /*-----------------------------------------------------------------*/
5472 static void genrshTwo (operand *result,operand *left,
5473 int shCount, int sign)
5475 /* if shCount >= 8 */
5479 shiftR1Left2Result(left, MSB16, result, LSB,
5482 movLeft2Result(left, MSB16, result, LSB, sign);
5483 addSign(result, MSB16, sign);
5486 /* 1 <= shCount <= 7 */
5488 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
5491 /*-----------------------------------------------------------------*/
5492 /* shiftRLong - shift right one long from left to result */
5493 /* offl = LSB or MSB16 */
5494 /*-----------------------------------------------------------------*/
5495 static void shiftRLong (operand *left, int offl,
5496 operand *result, int sign)
5499 emitcode("clr","c");
5500 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
5502 emitcode("mov","c,acc.7");
5503 emitcode("rrc","a");
5504 aopPut(AOP(result),"a",MSB32-offl);
5506 /* add sign of "a" */
5507 addSign(result, MSB32, sign);
5509 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
5510 emitcode("rrc","a");
5511 aopPut(AOP(result),"a",MSB24-offl);
5513 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
5514 emitcode("rrc","a");
5515 aopPut(AOP(result),"a",MSB16-offl);
5518 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
5519 emitcode("rrc","a");
5520 aopPut(AOP(result),"a",LSB);
5524 /*-----------------------------------------------------------------*/
5525 /* genrshFour - shift four byte by a known amount != 0 */
5526 /*-----------------------------------------------------------------*/
5527 static void genrshFour (operand *result, operand *left,
5528 int shCount, int sign)
5530 /* if shifting more that 3 bytes */
5531 if(shCount >= 24 ) {
5534 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
5536 movLeft2Result(left, MSB32, result, LSB, sign);
5537 addSign(result, MSB16, sign);
5539 else if(shCount >= 16){
5542 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
5544 movLeft2Result(left, MSB24, result, LSB, 0);
5545 movLeft2Result(left, MSB32, result, MSB16, sign);
5547 addSign(result, MSB24, sign);
5549 else if(shCount >= 8){
5552 shiftRLong(left, MSB16, result, sign);
5553 else if(shCount == 0){
5554 movLeft2Result(left, MSB16, result, LSB, 0);
5555 movLeft2Result(left, MSB24, result, MSB16, 0);
5556 movLeft2Result(left, MSB32, result, MSB24, sign);
5557 addSign(result, MSB32, sign);
5560 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
5561 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
5562 /* the last shift is signed */
5563 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
5564 addSign(result, MSB32, sign);
5567 else{ /* 1 <= shCount <= 7 */
5569 shiftRLong(left, LSB, result, sign);
5571 shiftRLong(result, LSB, result, sign);
5574 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
5575 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
5576 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
5581 /*-----------------------------------------------------------------*/
5582 /* genRightShiftLiteral - right shifting by known count */
5583 /*-----------------------------------------------------------------*/
5584 static void genRightShiftLiteral (operand *left,
5590 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5593 freeAsmop(right,NULL,ic,TRUE);
5595 aopOp(left,ic,FALSE);
5596 aopOp(result,ic,FALSE);
5599 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
5603 size = getDataSize(left);
5604 /* test the LEFT size !!! */
5606 /* I suppose that the left size >= result size */
5608 size = getDataSize(result);
5610 movLeft2Result(left, size, result, size, 0);
5613 else if(shCount >= (size * 8)){
5615 /* get sign in acc.7 */
5616 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
5617 addSign(result, LSB, sign);
5621 genrshOne (result,left,shCount,sign);
5625 genrshTwo (result,left,shCount,sign);
5629 genrshFour (result,left,shCount,sign);
5635 freeAsmop(left,NULL,ic,TRUE);
5636 freeAsmop(result,NULL,ic,TRUE);
5640 /*-----------------------------------------------------------------*/
5641 /* genSignedRightShift - right shift of signed number */
5642 /*-----------------------------------------------------------------*/
5643 static void genSignedRightShift (iCode *ic)
5645 operand *right, *left, *result;
5648 symbol *tlbl, *tlbl1 ;
5650 /* we do it the hard way put the shift count in b
5651 and loop thru preserving the sign */
5653 right = IC_RIGHT(ic);
5655 result = IC_RESULT(ic);
5657 aopOp(right,ic,FALSE);
5660 if ( AOP_TYPE(right) == AOP_LIT) {
5661 genRightShiftLiteral (left,right,result,ic,1);
5664 /* shift count is unknown then we have to form
5665 a loop get the loop count in B : Note: we take
5666 only the lower order byte since shifting
5667 more that 32 bits make no sense anyway, ( the
5668 largest size of an object can be only 32 bits ) */
5670 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5671 emitcode("inc","b");
5672 freeAsmop (right,NULL,ic,TRUE);
5673 aopOp(left,ic,FALSE);
5674 aopOp(result,ic,FALSE);
5676 /* now move the left to the result if they are not the
5678 if (!sameRegs(AOP(left),AOP(result)) &&
5679 AOP_SIZE(result) > 1) {
5681 size = AOP_SIZE(result);
5684 l = aopGet(AOP(left),offset,FALSE,TRUE);
5685 if (*l == '@' && IS_AOP_PREG(result)) {
5687 emitcode("mov","a,%s",l);
5688 aopPut(AOP(result),"a",offset);
5690 aopPut(AOP(result),l,offset);
5695 /* mov the highest order bit to OVR */
5696 tlbl = newiTempLabel(NULL);
5697 tlbl1= newiTempLabel(NULL);
5699 size = AOP_SIZE(result);
5701 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
5702 emitcode("rlc","a");
5703 emitcode("mov","ov,c");
5704 /* if it is only one byte then */
5706 l = aopGet(AOP(left),0,FALSE,FALSE);
5708 emitcode("sjmp","%05d$",tlbl1->key+100);
5709 emitcode("","%05d$:",tlbl->key+100);
5710 emitcode("mov","c,ov");
5711 emitcode("rrc","a");
5712 emitcode("","%05d$:",tlbl1->key+100);
5713 emitcode("djnz","b,%05d$",tlbl->key+100);
5714 aopPut(AOP(result),"a",0);
5718 reAdjustPreg(AOP(result));
5719 emitcode("sjmp","%05d$",tlbl1->key+100);
5720 emitcode("","%05d$:",tlbl->key+100);
5721 emitcode("mov","c,ov");
5723 l = aopGet(AOP(result),offset,FALSE,FALSE);
5725 emitcode("rrc","a");
5726 aopPut(AOP(result),"a",offset--);
5728 reAdjustPreg(AOP(result));
5729 emitcode("","%05d$:",tlbl1->key+100);
5730 emitcode("djnz","b,%05d$",tlbl->key+100);
5733 freeAsmop(left,NULL,ic,TRUE);
5734 freeAsmop(result,NULL,ic,TRUE);
5737 /*-----------------------------------------------------------------*/
5738 /* genRightShift - generate code for right shifting */
5739 /*-----------------------------------------------------------------*/
5740 static void genRightShift (iCode *ic)
5742 operand *right, *left, *result;
5746 symbol *tlbl, *tlbl1 ;
5748 /* if signed then we do it the hard way preserve the
5749 sign bit moving it inwards */
5750 retype = getSpec(operandType(IC_RESULT(ic)));
5752 if (!SPEC_USIGN(retype)) {
5753 genSignedRightShift (ic);
5757 /* signed & unsigned types are treated the same : i.e. the
5758 signed is NOT propagated inwards : quoting from the
5759 ANSI - standard : "for E1 >> E2, is equivalent to division
5760 by 2**E2 if unsigned or if it has a non-negative value,
5761 otherwise the result is implementation defined ", MY definition
5762 is that the sign does not get propagated */
5764 right = IC_RIGHT(ic);
5766 result = IC_RESULT(ic);
5768 aopOp(right,ic,FALSE);
5770 /* if the shift count is known then do it
5771 as efficiently as possible */
5772 if (AOP_TYPE(right) == AOP_LIT) {
5773 genRightShiftLiteral (left,right,result,ic, 0);
5777 /* shift count is unknown then we have to form
5778 a loop get the loop count in B : Note: we take
5779 only the lower order byte since shifting
5780 more that 32 bits make no sense anyway, ( the
5781 largest size of an object can be only 32 bits ) */
5783 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5784 emitcode("inc","b");
5785 freeAsmop (right,NULL,ic,TRUE);
5786 aopOp(left,ic,FALSE);
5787 aopOp(result,ic,FALSE);
5789 /* now move the left to the result if they are not the
5791 if (!sameRegs(AOP(left),AOP(result)) &&
5792 AOP_SIZE(result) > 1) {
5794 size = AOP_SIZE(result);
5797 l = aopGet(AOP(left),offset,FALSE,TRUE);
5798 if (*l == '@' && IS_AOP_PREG(result)) {
5800 emitcode("mov","a,%s",l);
5801 aopPut(AOP(result),"a",offset);
5803 aopPut(AOP(result),l,offset);
5808 tlbl = newiTempLabel(NULL);
5809 tlbl1= newiTempLabel(NULL);
5810 size = AOP_SIZE(result);
5813 /* if it is only one byte then */
5815 l = aopGet(AOP(left),0,FALSE,FALSE);
5817 emitcode("sjmp","%05d$",tlbl1->key+100);
5818 emitcode("","%05d$:",tlbl->key+100);
5820 emitcode("rrc","a");
5821 emitcode("","%05d$:",tlbl1->key+100);
5822 emitcode("djnz","b,%05d$",tlbl->key+100);
5823 aopPut(AOP(result),"a",0);
5827 reAdjustPreg(AOP(result));
5828 emitcode("sjmp","%05d$",tlbl1->key+100);
5829 emitcode("","%05d$:",tlbl->key+100);
5832 l = aopGet(AOP(result),offset,FALSE,FALSE);
5834 emitcode("rrc","a");
5835 aopPut(AOP(result),"a",offset--);
5837 reAdjustPreg(AOP(result));
5839 emitcode("","%05d$:",tlbl1->key+100);
5840 emitcode("djnz","b,%05d$",tlbl->key+100);
5843 freeAsmop(left,NULL,ic,TRUE);
5844 freeAsmop(result,NULL,ic,TRUE);
5847 /*-----------------------------------------------------------------*/
5848 /* genUnpackBits - generates code for unpacking bits */
5849 /*-----------------------------------------------------------------*/
5850 static void genUnpackBits (operand *result, char *rname, int ptype)
5857 etype = getSpec(operandType(result));
5859 /* read the first byte */
5864 emitcode("mov","a,@%s",rname);
5868 emitcode("movx","a,@%s",rname);
5872 emitcode("movx","a,@dptr");
5876 emitcode("clr","a");
5877 emitcode("movc","a","@a+dptr");
5881 emitcode("lcall","__gptrget");
5885 /* if we have bitdisplacement then it fits */
5886 /* into this byte completely or if length is */
5887 /* less than a byte */
5888 if ((shCnt = SPEC_BSTR(etype)) ||
5889 (SPEC_BLEN(etype) <= 8)) {
5891 /* shift right acc */
5894 emitcode("anl","a,#0x%02x",
5895 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
5896 aopPut(AOP(result),"a",offset);
5900 /* bit field did not fit in a byte */
5901 rlen = SPEC_BLEN(etype) - 8;
5902 aopPut(AOP(result),"a",offset++);
5909 emitcode("inc","%s",rname);
5910 emitcode("mov","a,@%s",rname);
5914 emitcode("inc","%s",rname);
5915 emitcode("movx","a,@%s",rname);
5919 emitcode("inc","dptr");
5920 emitcode("movx","a,@dptr");
5924 emitcode("clr","a");
5925 emitcode("inc","dptr");
5926 emitcode("movc","a","@a+dptr");
5930 emitcode("inc","dptr");
5931 emitcode("lcall","__gptrget");
5936 /* if we are done */
5940 aopPut(AOP(result),"a",offset++);
5945 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
5946 aopPut(AOP(result),"a",offset);
5953 /*-----------------------------------------------------------------*/
5954 /* genDataPointerGet - generates code when ptr offset is known */
5955 /*-----------------------------------------------------------------*/
5956 static void genDataPointerGet (operand *left,
5962 int size , offset = 0;
5963 aopOp(result,ic,TRUE);
5965 /* get the string representation of the name */
5966 l = aopGet(AOP(left),0,FALSE,TRUE);
5967 size = AOP_SIZE(result);
5970 sprintf(buffer,"(%s + %d)",l+1,offset);
5972 sprintf(buffer,"%s",l+1);
5973 aopPut(AOP(result),buffer,offset++);
5976 freeAsmop(left,NULL,ic,TRUE);
5977 freeAsmop(result,NULL,ic,TRUE);
5980 /*-----------------------------------------------------------------*/
5981 /* genNearPointerGet - emitcode for near pointer fetch */
5982 /*-----------------------------------------------------------------*/
5983 static void genNearPointerGet (operand *left,
5990 link *rtype, *retype;
5991 link *ltype = operandType(left);
5994 rtype = operandType(result);
5995 retype= getSpec(rtype);
5997 aopOp(left,ic,FALSE);
5999 /* if left is rematerialisable and
6000 result is not bit variable type and
6001 the left is pointer to data space i.e
6002 lower 128 bytes of space */
6003 if (AOP_TYPE(left) == AOP_IMMD &&
6004 !IS_BITVAR(retype) &&
6005 DCL_TYPE(ltype) == POINTER) {
6006 genDataPointerGet (left,result,ic);
6010 /* if the value is already in a pointer register
6011 then don't need anything more */
6012 if (!AOP_INPREG(AOP(left))) {
6013 /* otherwise get a free pointer register */
6015 preg = getFreePtr(ic,&aop,FALSE);
6016 emitcode("mov","%s,%s",
6018 aopGet(AOP(left),0,FALSE,TRUE));
6019 rname = preg->name ;
6021 rname = aopGet(AOP(left),0,FALSE,FALSE);
6023 freeAsmop(left,NULL,ic,TRUE);
6024 aopOp (result,ic,FALSE);
6026 /* if bitfield then unpack the bits */
6027 if (IS_BITVAR(retype))
6028 genUnpackBits (result,rname,POINTER);
6030 /* we have can just get the values */
6031 int size = AOP_SIZE(result);
6035 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6037 emitcode("mov","a,@%s",rname);
6038 aopPut(AOP(result),"a",offset);
6040 sprintf(buffer,"@%s",rname);
6041 aopPut(AOP(result),buffer,offset);
6045 emitcode("inc","%s",rname);
6049 /* now some housekeeping stuff */
6051 /* we had to allocate for this iCode */
6052 freeAsmop(NULL,aop,ic,TRUE);
6054 /* we did not allocate which means left
6055 already in a pointer register, then
6056 if size > 0 && this could be used again
6057 we have to point it back to where it
6059 if (AOP_SIZE(result) > 1 &&
6060 !OP_SYMBOL(left)->remat &&
6061 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6063 int size = AOP_SIZE(result) - 1;
6065 emitcode("dec","%s",rname);
6070 freeAsmop(result,NULL,ic,TRUE);
6074 /*-----------------------------------------------------------------*/
6075 /* genPagedPointerGet - emitcode for paged pointer fetch */
6076 /*-----------------------------------------------------------------*/
6077 static void genPagedPointerGet (operand *left,
6084 link *rtype, *retype;
6086 rtype = operandType(result);
6087 retype= getSpec(rtype);
6089 aopOp(left,ic,FALSE);
6091 /* if the value is already in a pointer register
6092 then don't need anything more */
6093 if (!AOP_INPREG(AOP(left))) {
6094 /* otherwise get a free pointer register */
6096 preg = getFreePtr(ic,&aop,FALSE);
6097 emitcode("mov","%s,%s",
6099 aopGet(AOP(left),0,FALSE,TRUE));
6100 rname = preg->name ;
6102 rname = aopGet(AOP(left),0,FALSE,FALSE);
6104 freeAsmop(left,NULL,ic,TRUE);
6105 aopOp (result,ic,FALSE);
6107 /* if bitfield then unpack the bits */
6108 if (IS_BITVAR(retype))
6109 genUnpackBits (result,rname,PPOINTER);
6111 /* we have can just get the values */
6112 int size = AOP_SIZE(result);
6117 emitcode("movx","a,@%s",rname);
6118 aopPut(AOP(result),"a",offset);
6123 emitcode("inc","%s",rname);
6127 /* now some housekeeping stuff */
6129 /* we had to allocate for this iCode */
6130 freeAsmop(NULL,aop,ic,TRUE);
6132 /* we did not allocate which means left
6133 already in a pointer register, then
6134 if size > 0 && this could be used again
6135 we have to point it back to where it
6137 if (AOP_SIZE(result) > 1 &&
6138 !OP_SYMBOL(left)->remat &&
6139 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6141 int size = AOP_SIZE(result) - 1;
6143 emitcode("dec","%s",rname);
6148 freeAsmop(result,NULL,ic,TRUE);
6153 /*-----------------------------------------------------------------*/
6154 /* genFarPointerGet - gget value from far space */
6155 /*-----------------------------------------------------------------*/
6156 static void genFarPointerGet (operand *left,
6157 operand *result, iCode *ic)
6160 link *retype = getSpec(operandType(result));
6162 aopOp(left,ic,FALSE);
6164 /* if the operand is already in dptr
6165 then we do nothing else we move the value to dptr */
6166 if (AOP_TYPE(left) != AOP_STR) {
6167 /* if this is remateriazable */
6168 if (AOP_TYPE(left) == AOP_IMMD)
6169 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6170 else { /* we need to get it byte by byte */
6171 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6172 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6173 if (options.model == MODEL_FLAT24)
6175 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6179 /* so dptr know contains the address */
6180 freeAsmop(left,NULL,ic,TRUE);
6181 aopOp(result,ic,FALSE);
6183 /* if bit then unpack */
6184 if (IS_BITVAR(retype))
6185 genUnpackBits(result,"dptr",FPOINTER);
6187 size = AOP_SIZE(result);
6191 emitcode("movx","a,@dptr");
6192 aopPut(AOP(result),"a",offset++);
6194 emitcode("inc","dptr");
6198 freeAsmop(result,NULL,ic,TRUE);
6201 /*-----------------------------------------------------------------*/
6202 /* emitcodePointerGet - gget value from code space */
6203 /*-----------------------------------------------------------------*/
6204 static void emitcodePointerGet (operand *left,
6205 operand *result, iCode *ic)
6208 link *retype = getSpec(operandType(result));
6210 aopOp(left,ic,FALSE);
6212 /* if the operand is already in dptr
6213 then we do nothing else we move the value to dptr */
6214 if (AOP_TYPE(left) != AOP_STR) {
6215 /* if this is remateriazable */
6216 if (AOP_TYPE(left) == AOP_IMMD)
6217 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6218 else { /* we need to get it byte by byte */
6219 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6220 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6221 if (options.model == MODEL_FLAT24)
6223 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6227 /* so dptr know contains the address */
6228 freeAsmop(left,NULL,ic,TRUE);
6229 aopOp(result,ic,FALSE);
6231 /* if bit then unpack */
6232 if (IS_BITVAR(retype))
6233 genUnpackBits(result,"dptr",CPOINTER);
6235 size = AOP_SIZE(result);
6239 emitcode("clr","a");
6240 emitcode("movc","a,@a+dptr");
6241 aopPut(AOP(result),"a",offset++);
6243 emitcode("inc","dptr");
6247 freeAsmop(result,NULL,ic,TRUE);
6250 /*-----------------------------------------------------------------*/
6251 /* genGenPointerGet - gget value from generic pointer space */
6252 /*-----------------------------------------------------------------*/
6253 static void genGenPointerGet (operand *left,
6254 operand *result, iCode *ic)
6257 link *retype = getSpec(operandType(result));
6259 aopOp(left,ic,FALSE);
6261 /* if the operand is already in dptr
6262 then we do nothing else we move the value to dptr */
6263 if (AOP_TYPE(left) != AOP_STR) {
6264 /* if this is remateriazable */
6265 if (AOP_TYPE(left) == AOP_IMMD) {
6266 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6267 emitcode("mov","b,#%d",pointerCode(retype));
6269 else { /* we need to get it byte by byte */
6270 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6271 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6272 if (options.model == MODEL_FLAT24)
6274 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6275 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
6279 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
6283 /* so dptr know contains the address */
6284 freeAsmop(left,NULL,ic,TRUE);
6285 aopOp(result,ic,FALSE);
6287 /* if bit then unpack */
6288 if (IS_BITVAR(retype))
6289 genUnpackBits(result,"dptr",GPOINTER);
6291 size = AOP_SIZE(result);
6295 emitcode("lcall","__gptrget");
6296 aopPut(AOP(result),"a",offset++);
6298 emitcode("inc","dptr");
6302 freeAsmop(result,NULL,ic,TRUE);
6305 /*-----------------------------------------------------------------*/
6306 /* genPointerGet - generate code for pointer get */
6307 /*-----------------------------------------------------------------*/
6308 static void genPointerGet (iCode *ic)
6310 operand *left, *result ;
6315 result = IC_RESULT(ic) ;
6317 /* depending on the type of pointer we need to
6318 move it to the correct pointer register */
6319 type = operandType(left);
6320 etype = getSpec(type);
6321 /* if left is of type of pointer then it is simple */
6322 if (IS_PTR(type) && !IS_FUNC(type->next))
6323 p_type = DCL_TYPE(type);
6325 /* we have to go by the storage class */
6326 p_type = PTR_TYPE(SPEC_OCLS(etype));
6328 /* if (SPEC_OCLS(etype)->codesp ) { */
6329 /* p_type = CPOINTER ; */
6332 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6333 /* p_type = FPOINTER ; */
6335 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6336 /* p_type = PPOINTER; */
6338 /* if (SPEC_OCLS(etype) == idata ) */
6339 /* p_type = IPOINTER; */
6341 /* p_type = POINTER ; */
6344 /* now that we have the pointer type we assign
6345 the pointer values */
6350 genNearPointerGet (left,result,ic);
6354 genPagedPointerGet(left,result,ic);
6358 genFarPointerGet (left,result,ic);
6362 emitcodePointerGet (left,result,ic);
6366 genGenPointerGet (left,result,ic);
6372 /*-----------------------------------------------------------------*/
6373 /* genPackBits - generates code for packed bit storage */
6374 /*-----------------------------------------------------------------*/
6375 static void genPackBits (link *etype ,
6377 char *rname, int p_type)
6385 blen = SPEC_BLEN(etype);
6386 bstr = SPEC_BSTR(etype);
6388 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6391 /* if the bit lenth is less than or */
6392 /* it exactly fits a byte then */
6393 if (SPEC_BLEN(etype) <= 8 ) {
6394 shCount = SPEC_BSTR(etype) ;
6396 /* shift left acc */
6399 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6404 emitcode ("mov","b,a");
6405 emitcode("mov","a,@%s",rname);
6409 emitcode ("mov","b,a");
6410 emitcode("movx","a,@dptr");
6414 emitcode ("push","b");
6415 emitcode ("push","acc");
6416 emitcode ("lcall","__gptrget");
6417 emitcode ("pop","b");
6421 emitcode ("anl","a,#0x%02x",(unsigned char)
6422 ((unsigned char)(0xFF << (blen+bstr)) |
6423 (unsigned char)(0xFF >> (8-bstr)) ) );
6424 emitcode ("orl","a,b");
6425 if (p_type == GPOINTER)
6426 emitcode("pop","b");
6432 emitcode("mov","@%s,a",rname);
6436 emitcode("movx","@dptr,a");
6440 emitcode("lcall","__gptrput");
6445 if ( SPEC_BLEN(etype) <= 8 )
6448 emitcode("inc","%s",rname);
6449 rLen = SPEC_BLEN(etype) ;
6451 /* now generate for lengths greater than one byte */
6454 l = aopGet(AOP(right),offset++,FALSE,TRUE);
6464 emitcode("mov","@%s,a",rname);
6466 emitcode("mov","@%s,%s",rname,l);
6471 emitcode("movx","@dptr,a");
6476 emitcode("lcall","__gptrput");
6479 emitcode ("inc","%s",rname);
6484 /* last last was not complete */
6486 /* save the byte & read byte */
6489 emitcode ("mov","b,a");
6490 emitcode("mov","a,@%s",rname);
6494 emitcode ("mov","b,a");
6495 emitcode("movx","a,@dptr");
6499 emitcode ("push","b");
6500 emitcode ("push","acc");
6501 emitcode ("lcall","__gptrget");
6502 emitcode ("pop","b");
6506 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
6507 emitcode ("orl","a,b");
6510 if (p_type == GPOINTER)
6511 emitcode("pop","b");
6516 emitcode("mov","@%s,a",rname);
6520 emitcode("movx","@dptr,a");
6524 emitcode("lcall","__gptrput");
6528 /*-----------------------------------------------------------------*/
6529 /* genDataPointerSet - remat pointer to data space */
6530 /*-----------------------------------------------------------------*/
6531 static void genDataPointerSet(operand *right,
6535 int size, offset = 0 ;
6536 char *l, buffer[256];
6538 aopOp(right,ic,FALSE);
6540 l = aopGet(AOP(result),0,FALSE,TRUE);
6541 size = AOP_SIZE(right);
6544 sprintf(buffer,"(%s + %d)",l+1,offset);
6546 sprintf(buffer,"%s",l+1);
6547 emitcode("mov","%s,%s",buffer,
6548 aopGet(AOP(right),offset++,FALSE,FALSE));
6551 freeAsmop(right,NULL,ic,TRUE);
6552 freeAsmop(result,NULL,ic,TRUE);
6555 /*-----------------------------------------------------------------*/
6556 /* genNearPointerSet - emitcode for near pointer put */
6557 /*-----------------------------------------------------------------*/
6558 static void genNearPointerSet (operand *right,
6566 link *ptype = operandType(result);
6568 retype= getSpec(operandType(right));
6570 aopOp(result,ic,FALSE);
6572 /* if the result is rematerializable &
6573 in data space & not a bit variable */
6574 if (AOP_TYPE(result) == AOP_IMMD &&
6575 DCL_TYPE(ptype) == POINTER &&
6576 !IS_BITVAR(retype)) {
6577 genDataPointerSet (right,result,ic);
6581 /* if the value is already in a pointer register
6582 then don't need anything more */
6583 if (!AOP_INPREG(AOP(result))) {
6584 /* otherwise get a free pointer register */
6586 preg = getFreePtr(ic,&aop,FALSE);
6587 emitcode("mov","%s,%s",
6589 aopGet(AOP(result),0,FALSE,TRUE));
6590 rname = preg->name ;
6592 rname = aopGet(AOP(result),0,FALSE,FALSE);
6594 freeAsmop(result,NULL,ic,TRUE);
6595 aopOp (right,ic,FALSE);
6597 /* if bitfield then unpack the bits */
6598 if (IS_BITVAR(retype))
6599 genPackBits (retype,right,rname,POINTER);
6601 /* we have can just get the values */
6602 int size = AOP_SIZE(right);
6606 l = aopGet(AOP(right),offset,FALSE,TRUE);
6609 emitcode("mov","@%s,a",rname);
6611 emitcode("mov","@%s,%s",rname,l);
6613 emitcode("inc","%s",rname);
6618 /* now some housekeeping stuff */
6620 /* we had to allocate for this iCode */
6621 freeAsmop(NULL,aop,ic,TRUE);
6623 /* we did not allocate which means left
6624 already in a pointer register, then
6625 if size > 0 && this could be used again
6626 we have to point it back to where it
6628 if (AOP_SIZE(right) > 1 &&
6629 !OP_SYMBOL(result)->remat &&
6630 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6632 int size = AOP_SIZE(right) - 1;
6634 emitcode("dec","%s",rname);
6639 freeAsmop(right,NULL,ic,TRUE);
6644 /*-----------------------------------------------------------------*/
6645 /* genPagedPointerSet - emitcode for Paged pointer put */
6646 /*-----------------------------------------------------------------*/
6647 static void genPagedPointerSet (operand *right,
6656 retype= getSpec(operandType(right));
6658 aopOp(result,ic,FALSE);
6660 /* if the value is already in a pointer register
6661 then don't need anything more */
6662 if (!AOP_INPREG(AOP(result))) {
6663 /* otherwise get a free pointer register */
6665 preg = getFreePtr(ic,&aop,FALSE);
6666 emitcode("mov","%s,%s",
6668 aopGet(AOP(result),0,FALSE,TRUE));
6669 rname = preg->name ;
6671 rname = aopGet(AOP(result),0,FALSE,FALSE);
6673 freeAsmop(result,NULL,ic,TRUE);
6674 aopOp (right,ic,FALSE);
6676 /* if bitfield then unpack the bits */
6677 if (IS_BITVAR(retype))
6678 genPackBits (retype,right,rname,PPOINTER);
6680 /* we have can just get the values */
6681 int size = AOP_SIZE(right);
6685 l = aopGet(AOP(right),offset,FALSE,TRUE);
6688 emitcode("movx","@%s,a",rname);
6691 emitcode("inc","%s",rname);
6697 /* now some housekeeping stuff */
6699 /* we had to allocate for this iCode */
6700 freeAsmop(NULL,aop,ic,TRUE);
6702 /* we did not allocate which means left
6703 already in a pointer register, then
6704 if size > 0 && this could be used again
6705 we have to point it back to where it
6707 if (AOP_SIZE(right) > 1 &&
6708 !OP_SYMBOL(result)->remat &&
6709 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6711 int size = AOP_SIZE(right) - 1;
6713 emitcode("dec","%s",rname);
6718 freeAsmop(right,NULL,ic,TRUE);
6723 /*-----------------------------------------------------------------*/
6724 /* genFarPointerSet - set value from far space */
6725 /*-----------------------------------------------------------------*/
6726 static void genFarPointerSet (operand *right,
6727 operand *result, iCode *ic)
6730 link *retype = getSpec(operandType(right));
6732 aopOp(result,ic,FALSE);
6734 /* if the operand is already in dptr
6735 then we do nothing else we move the value to dptr */
6736 if (AOP_TYPE(result) != AOP_STR) {
6737 /* if this is remateriazable */
6738 if (AOP_TYPE(result) == AOP_IMMD)
6739 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6740 else { /* we need to get it byte by byte */
6741 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6742 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6743 if (options.model == MODEL_FLAT24)
6745 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6749 /* so dptr know contains the address */
6750 freeAsmop(result,NULL,ic,TRUE);
6751 aopOp(right,ic,FALSE);
6753 /* if bit then unpack */
6754 if (IS_BITVAR(retype))
6755 genPackBits(retype,right,"dptr",FPOINTER);
6757 size = AOP_SIZE(right);
6761 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6763 emitcode("movx","@dptr,a");
6765 emitcode("inc","dptr");
6769 freeAsmop(right,NULL,ic,TRUE);
6772 /*-----------------------------------------------------------------*/
6773 /* genGenPointerSet - set value from generic pointer space */
6774 /*-----------------------------------------------------------------*/
6775 static void genGenPointerSet (operand *right,
6776 operand *result, iCode *ic)
6779 link *retype = getSpec(operandType(right));
6781 aopOp(result,ic,FALSE);
6783 /* if the operand is already in dptr
6784 then we do nothing else we move the value to dptr */
6785 if (AOP_TYPE(result) != AOP_STR) {
6786 /* if this is remateriazable */
6787 if (AOP_TYPE(result) == AOP_IMMD) {
6788 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6789 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
6791 else { /* we need to get it byte by byte */
6792 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6793 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6794 if (options.model == MODEL_FLAT24)
6796 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6797 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
6801 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
6805 /* so dptr know contains the address */
6806 freeAsmop(result,NULL,ic,TRUE);
6807 aopOp(right,ic,FALSE);
6809 /* if bit then unpack */
6810 if (IS_BITVAR(retype))
6811 genPackBits(retype,right,"dptr",GPOINTER);
6813 size = AOP_SIZE(right);
6817 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6819 emitcode("lcall","__gptrput");
6821 emitcode("inc","dptr");
6825 freeAsmop(right,NULL,ic,TRUE);
6828 /*-----------------------------------------------------------------*/
6829 /* genPointerSet - stores the value into a pointer location */
6830 /*-----------------------------------------------------------------*/
6831 static void genPointerSet (iCode *ic)
6833 operand *right, *result ;
6837 right = IC_RIGHT(ic);
6838 result = IC_RESULT(ic) ;
6840 /* depending on the type of pointer we need to
6841 move it to the correct pointer register */
6842 type = operandType(result);
6843 etype = getSpec(type);
6844 /* if left is of type of pointer then it is simple */
6845 if (IS_PTR(type) && !IS_FUNC(type->next)) {
6846 p_type = DCL_TYPE(type);
6849 /* we have to go by the storage class */
6850 p_type = PTR_TYPE(SPEC_OCLS(etype));
6852 /* if (SPEC_OCLS(etype)->codesp ) { */
6853 /* p_type = CPOINTER ; */
6856 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6857 /* p_type = FPOINTER ; */
6859 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6860 /* p_type = PPOINTER ; */
6862 /* if (SPEC_OCLS(etype) == idata ) */
6863 /* p_type = IPOINTER ; */
6865 /* p_type = POINTER ; */
6868 /* now that we have the pointer type we assign
6869 the pointer values */
6874 genNearPointerSet (right,result,ic);
6878 genPagedPointerSet (right,result,ic);
6882 genFarPointerSet (right,result,ic);
6886 genGenPointerSet (right,result,ic);
6892 /*-----------------------------------------------------------------*/
6893 /* genIfx - generate code for Ifx statement */
6894 /*-----------------------------------------------------------------*/
6895 static void genIfx (iCode *ic, iCode *popIc)
6897 operand *cond = IC_COND(ic);
6900 aopOp(cond,ic,FALSE);
6902 /* get the value into acc */
6903 if (AOP_TYPE(cond) != AOP_CRY)
6907 /* the result is now in the accumulator */
6908 freeAsmop(cond,NULL,ic,TRUE);
6910 /* if there was something to be popped then do it */
6914 /* if the condition is a bit variable */
6915 if (isbit && IS_ITEMP(cond) &&
6917 genIfxJump(ic,SPIL_LOC(cond)->rname);
6919 if (isbit && !IS_ITEMP(cond))
6920 genIfxJump(ic,OP_SYMBOL(cond)->rname);
6927 /*-----------------------------------------------------------------*/
6928 /* genAddrOf - generates code for address of */
6929 /*-----------------------------------------------------------------*/
6930 static void genAddrOf (iCode *ic)
6932 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
6935 aopOp(IC_RESULT(ic),ic,FALSE);
6937 /* if the operand is on the stack then we
6938 need to get the stack offset of this
6941 /* if it has an offset then we need to compute
6944 emitcode("mov","a,_bp");
6945 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
6946 aopPut(AOP(IC_RESULT(ic)),"a",0);
6948 /* we can just move _bp */
6949 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
6951 /* fill the result with zero */
6952 size = AOP_SIZE(IC_RESULT(ic)) - 1;
6955 if (options.stack10bit && size < (FPTRSIZE - 1))
6958 "*** warning: pointer to stack var truncated.\n");
6965 if (options.stack10bit && offset == 2)
6967 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
6971 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
6978 /* object not on stack then we need the name */
6979 size = AOP_SIZE(IC_RESULT(ic));
6983 char s[SDCC_NAME_MAX];
6985 sprintf(s,"#(%s >> %d)",
6989 sprintf(s,"#%s",sym->rname);
6990 aopPut(AOP(IC_RESULT(ic)),s,offset++);
6994 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
6998 /*-----------------------------------------------------------------*/
6999 /* genFarFarAssign - assignment when both are in far space */
7000 /*-----------------------------------------------------------------*/
7001 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7003 int size = AOP_SIZE(right);
7006 /* first push the right side on to the stack */
7008 l = aopGet(AOP(right),offset++,FALSE,FALSE);
7010 emitcode ("push","acc");
7013 freeAsmop(right,NULL,ic,FALSE);
7014 /* now assign DPTR to result */
7015 aopOp(result,ic,FALSE);
7016 size = AOP_SIZE(result);
7018 emitcode ("pop","acc");
7019 aopPut(AOP(result),"a",--offset);
7021 freeAsmop(result,NULL,ic,FALSE);
7025 /*-----------------------------------------------------------------*/
7026 /* genAssign - generate code for assignment */
7027 /*-----------------------------------------------------------------*/
7028 static void genAssign (iCode *ic)
7030 operand *result, *right;
7032 unsigned long lit = 0L;
7034 result = IC_RESULT(ic);
7035 right = IC_RIGHT(ic) ;
7037 /* if they are the same */
7038 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7041 aopOp(right,ic,FALSE);
7043 /* special case both in far space */
7044 /* However, if we are using 10 bit stack mode,
7045 * the result should be held in DPTR2,
7046 * so we can operate without the special case.
7050 if (AOP_TYPE(right) == AOP_DPTR &&
7051 IS_TRUE_SYMOP(result) &&
7052 isOperandInFarSpace(result)) {
7054 if (!options.stack10bit)
7056 genFarFarAssign (result,right,ic);
7061 fprintf(stderr, "*** 10bit stack opt 1\n");
7062 emitcode(";", "look at me: optimization possible?\n");
7066 aopOp(result,ic,TRUE);
7068 /* if they are the same registers */
7069 if (sameRegs(AOP(right),AOP(result)))
7072 /* if the result is a bit */
7073 if (AOP_TYPE(result) == AOP_CRY) {
7075 /* if the right size is a literal then
7076 we know what the value is */
7077 if (AOP_TYPE(right) == AOP_LIT) {
7078 if (((int) operandLitValue(right)))
7079 aopPut(AOP(result),one,0);
7081 aopPut(AOP(result),zero,0);
7085 /* the right is also a bit variable */
7086 if (AOP_TYPE(right) == AOP_CRY) {
7087 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7088 aopPut(AOP(result),"c",0);
7094 aopPut(AOP(result),"a",0);
7098 /* bit variables done */
7100 size = AOP_SIZE(result);
7102 if(AOP_TYPE(right) == AOP_LIT)
7103 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7105 (AOP_TYPE(result) != AOP_REG) &&
7106 (AOP_TYPE(right) == AOP_LIT) &&
7107 !IS_FLOAT(operandType(right)) &&
7109 emitcode("clr","a");
7111 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7112 aopPut(AOP(result),"a",size);
7115 aopGet(AOP(right),size,FALSE,FALSE),
7121 aopGet(AOP(right),offset,FALSE,FALSE),
7128 freeAsmop (right,NULL,ic,FALSE);
7129 freeAsmop (result,NULL,ic,TRUE);
7132 /*-----------------------------------------------------------------*/
7133 /* genJumpTab - genrates code for jump table */
7134 /*-----------------------------------------------------------------*/
7135 static void genJumpTab (iCode *ic)
7140 aopOp(IC_JTCOND(ic),ic,FALSE);
7141 /* get the condition into accumulator */
7142 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
7144 /* multiply by three */
7145 emitcode("add","a,acc");
7146 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
7147 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7149 jtab = newiTempLabel(NULL);
7150 emitcode("mov","dptr,#%05d$",jtab->key+100);
7151 emitcode("jmp","@a+dptr");
7152 emitcode("","%05d$:",jtab->key+100);
7153 /* now generate the jump labels */
7154 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
7155 jtab = setNextItem(IC_JTLABELS(ic)))
7156 emitcode("ljmp","%05d$",jtab->key+100);
7160 /*-----------------------------------------------------------------*/
7161 /* genCast - gen code for casting */
7162 /*-----------------------------------------------------------------*/
7163 static void genCast (iCode *ic)
7165 operand *result = IC_RESULT(ic);
7166 link *ctype = operandType(IC_LEFT(ic));
7167 operand *right = IC_RIGHT(ic);
7170 /* if they are equivalent then do nothing */
7171 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
7174 aopOp(right,ic,FALSE) ;
7175 aopOp(result,ic,FALSE);
7177 /* if the result is a bit */
7178 if (AOP_TYPE(result) == AOP_CRY) {
7179 /* if the right size is a literal then
7180 we know what the value is */
7181 if (AOP_TYPE(right) == AOP_LIT) {
7182 if (((int) operandLitValue(right)))
7183 aopPut(AOP(result),one,0);
7185 aopPut(AOP(result),zero,0);
7190 /* the right is also a bit variable */
7191 if (AOP_TYPE(right) == AOP_CRY) {
7192 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7193 aopPut(AOP(result),"c",0);
7199 aopPut(AOP(result),"a",0);
7203 /* if they are the same size : or less */
7204 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
7206 /* if they are in the same place */
7207 if (sameRegs(AOP(right),AOP(result)))
7210 /* if they in different places then copy */
7211 size = AOP_SIZE(result);
7215 aopGet(AOP(right),offset,FALSE,FALSE),
7223 /* if the result is of type pointer */
7224 if (IS_PTR(ctype)) {
7227 link *type = operandType(right);
7228 link *etype = getSpec(type);
7230 /* pointer to generic pointer */
7231 if (IS_GENPTR(ctype)) {
7235 p_type = DCL_TYPE(type);
7237 /* we have to go by the storage class */
7238 p_type = PTR_TYPE(SPEC_OCLS(etype));
7240 /* if (SPEC_OCLS(etype)->codesp ) */
7241 /* p_type = CPOINTER ; */
7243 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7244 /* p_type = FPOINTER ; */
7246 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7247 /* p_type = PPOINTER; */
7249 /* if (SPEC_OCLS(etype) == idata ) */
7250 /* p_type = IPOINTER ; */
7252 /* p_type = POINTER ; */
7255 /* the first two bytes are known */
7256 size = GPTRSIZE - 1;
7260 aopGet(AOP(right),offset,FALSE,FALSE),
7264 /* the last byte depending on type */
7281 /* this should never happen */
7282 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7283 "got unknown pointer type");
7286 aopPut(AOP(result),l, GPTRSIZE - 1);
7290 /* just copy the pointers */
7291 size = AOP_SIZE(result);
7295 aopGet(AOP(right),offset,FALSE,FALSE),
7302 /* so we now know that the size of destination is greater
7303 than the size of the source */
7304 /* we move to result for the size of source */
7305 size = AOP_SIZE(right);
7309 aopGet(AOP(right),offset,FALSE,FALSE),
7314 /* now depending on the sign of the destination */
7315 size = AOP_SIZE(result) - AOP_SIZE(right);
7316 /* if unsigned or not an integral type */
7317 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
7319 aopPut(AOP(result),zero,offset++);
7321 /* we need to extend the sign :{ */
7322 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
7325 emitcode("rlc","a");
7326 emitcode("subb","a,acc");
7328 aopPut(AOP(result),"a",offset++);
7331 /* we are done hurray !!!! */
7334 freeAsmop(right,NULL,ic,TRUE);
7335 freeAsmop(result,NULL,ic,TRUE);
7339 /*-----------------------------------------------------------------*/
7340 /* genDjnz - generate decrement & jump if not zero instrucion */
7341 /*-----------------------------------------------------------------*/
7342 static int genDjnz (iCode *ic, iCode *ifx)
7348 /* if the if condition has a false label
7349 then we cannot save */
7353 /* if the minus is not of the form
7355 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
7356 !IS_OP_LITERAL(IC_RIGHT(ic)))
7359 if (operandLitValue(IC_RIGHT(ic)) != 1)
7362 /* if the size of this greater than one then no
7364 if (getSize(operandType(IC_RESULT(ic))) > 1)
7367 /* otherwise we can save BIG */
7368 lbl = newiTempLabel(NULL);
7369 lbl1= newiTempLabel(NULL);
7371 aopOp(IC_RESULT(ic),ic,FALSE);
7373 if (IS_AOP_PREG(IC_RESULT(ic))) {
7374 emitcode("dec","%s",
7375 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7376 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7377 emitcode("jnz","%05d$",lbl->key+100);
7379 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
7382 emitcode ("sjmp","%05d$",lbl1->key+100);
7383 emitcode ("","%05d$:",lbl->key+100);
7384 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
7385 emitcode ("","%05d$:",lbl1->key+100);
7387 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7392 /*-----------------------------------------------------------------*/
7393 /* genReceive - generate code for a receive iCode */
7394 /*-----------------------------------------------------------------*/
7395 static void genReceive (iCode *ic)
7397 if (isOperandInFarSpace(IC_RESULT(ic)) &&
7398 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
7399 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
7401 int size = getSize(operandType(IC_RESULT(ic)));
7402 int offset = fReturnSize - size;
7404 emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
7405 fReturn[fReturnSize - offset - 1] : "acc"));
7408 aopOp(IC_RESULT(ic),ic,FALSE);
7409 size = AOP_SIZE(IC_RESULT(ic));
7412 emitcode ("pop","acc");
7413 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
7418 aopOp(IC_RESULT(ic),ic,FALSE);
7420 assignResultValue(IC_RESULT(ic));
7423 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7426 /*-----------------------------------------------------------------*/
7427 /* gen51Code - generate code for 8051 based controllers */
7428 /*-----------------------------------------------------------------*/
7429 void gen51Code (iCode *lic)
7434 lineHead = lineCurr = NULL;
7436 /* if debug information required */
7437 /* if (options.debug && currFunc) { */
7439 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
7441 if (IS_STATIC(currFunc->etype))
7442 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
7444 emitcode("","G$%s$0$0 ==.",currFunc->name);
7447 /* stack pointer name */
7448 if (options.useXstack)
7454 for (ic = lic ; ic ; ic = ic->next ) {
7456 if ( cln != ic->lineno ) {
7457 if ( options.debug ) {
7459 emitcode("","C$%s$%d$%d$%d ==.",
7460 ic->filename,ic->lineno,
7461 ic->level,ic->block);
7464 emitcode(";","%s %d",ic->filename,ic->lineno);
7467 /* if the result is marked as
7468 spilt and rematerializable or code for
7469 this has already been generated then
7471 if (resultRemat(ic) || ic->generated )
7474 /* depending on the operation */
7493 /* IPOP happens only when trying to restore a
7494 spilt live range, if there is an ifx statement
7495 following this pop then the if statement might
7496 be using some of the registers being popped which
7497 would destory the contents of the register so
7498 we need to check for this condition and handle it */
7500 ic->next->op == IFX &&
7501 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
7502 genIfx (ic->next,ic);
7520 genEndFunction (ic);
7540 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
7557 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
7561 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
7568 /* note these two are xlated by algebraic equivalence
7569 during parsing SDCC.y */
7570 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7571 "got '>=' or '<=' shouldn't have come here");
7575 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
7587 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
7591 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
7595 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
7622 case GET_VALUE_AT_ADDRESS:
7627 if (POINTER_SET(ic))
7654 addSet(&_G.sendSet,ic);
7659 /* piCode(ic,stdout); */
7665 /* now we are ready to call the
7666 peep hole optimizer */
7667 if (!options.nopeep)
7668 peepHole (&lineHead);
7670 /* now do the actual printing */
7671 printLine (lineHead,codeOutFile);