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);
58 /* this is the down and dirty file with all kinds of
59 kludgy & hacky stuff. This is what it is all about
60 CODE GENERATION for a specific MCU . some of the
61 routines may be reusable, will have to see */
63 static char *zero = "#0x00";
64 static char *one = "#0x01";
67 char *fReturn8051[] = {"dpl","dph","b","a" };
68 char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
69 unsigned fReturnSize = 4; /* shared with ralloc.c */
70 char **fReturn = fReturn8051;
71 static char *accUse[] = {"a","b"};
73 static short rbank = -1;
85 extern int mcs51_ptrRegReq ;
86 extern int mcs51_nRegs;
87 extern FILE *codeOutFile;
88 static void saverbank (int, iCode *,bool);
89 #define RESULTONSTACK(x) \
90 (IC_RESULT(x) && IC_RESULT(x)->aop && \
91 IC_RESULT(x)->aop->type == AOP_STK )
93 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x);
94 #define CLRC emitcode("clr","c")
95 #define SETC emitcode("setb","c")
97 static lineNode *lineHead = NULL;
98 static lineNode *lineCurr = NULL;
100 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
101 0xE0, 0xC0, 0x80, 0x00};
102 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
103 0x07, 0x03, 0x01, 0x00};
110 /*-----------------------------------------------------------------*/
111 /* emitcode - writes the code into a file : for now it is simple */
112 /*-----------------------------------------------------------------*/
113 static void emitcode (char *inst,char *fmt, ...)
116 char lb[MAX_INLINEASM];
123 sprintf(lb,"%s\t",inst);
125 sprintf(lb,"%s",inst);
126 vsprintf(lb+(strlen(lb)),fmt,ap);
130 while (isspace(*lbp)) lbp++;
133 lineCurr = (lineCurr ?
134 connectLine(lineCurr,newLineNode(lb)) :
135 (lineHead = newLineNode(lb)));
136 lineCurr->isInline = _G.inLine;
137 lineCurr->isDebug = _G.debugLine;
141 /*-----------------------------------------------------------------*/
142 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
143 /*-----------------------------------------------------------------*/
144 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
146 bool r0iu = FALSE , r1iu = FALSE;
147 bool r0ou = FALSE , r1ou = FALSE;
149 /* the logic: if r0 & r1 used in the instruction
150 then we are in trouble otherwise */
152 /* first check if r0 & r1 are used by this
153 instruction, in which case we are in trouble */
154 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
155 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
160 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
161 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
163 /* if no usage of r0 then return it */
164 if (!r0iu && !r0ou) {
165 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
166 (*aopp)->type = AOP_R0;
168 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R0_IDX);
171 /* if no usage of r1 then return it */
172 if (!r1iu && !r1ou) {
173 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
174 (*aopp)->type = AOP_R1;
176 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R1_IDX);
179 /* now we know they both have usage */
180 /* if r0 not used in this instruction */
182 /* push it if not already pushed */
184 emitcode ("push","%s",
185 mcs51_regWithIdx(R0_IDX)->dname);
189 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
190 (*aopp)->type = AOP_R0;
192 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R0_IDX);
195 /* if r1 not used then */
198 /* push it if not already pushed */
200 emitcode ("push","%s",
201 mcs51_regWithIdx(R1_IDX)->dname);
205 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
206 (*aopp)->type = AOP_R1;
207 return mcs51_regWithIdx(R1_IDX);
211 /* I said end of world but not quite end of world yet */
212 /* if this is a result then we can push it on the stack*/
214 (*aopp)->type = AOP_STK;
219 /* other wise this is true end of the world */
220 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
221 "getFreePtr should never reach here");
225 /*-----------------------------------------------------------------*/
226 /* newAsmop - creates a new asmOp */
227 /*-----------------------------------------------------------------*/
228 static asmop *newAsmop (short type)
232 ALLOC(aop,sizeof(asmop));
237 static void genSetDPTR(int n)
241 emitcode(";", "Select standard DPTR");
242 emitcode("mov", "dps, #0x00");
246 emitcode(";", "Select alternate DPTR");
247 emitcode("mov", "dps, #0x01");
251 /*-----------------------------------------------------------------*/
252 /* pointerCode - returns the code for a pointer type */
253 /*-----------------------------------------------------------------*/
254 static int pointerCode (link *etype)
257 return PTR_TYPE(SPEC_OCLS(etype));
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
316 emitcode("push","acc");
318 emitcode("mov","a,_bp");
319 emitcode("add","a,#0x%02x",
321 ((char)(sym->stack - _G.nRegsSaved )) :
322 ((char)sym->stack)) & 0xff);
325 emitcode ("mov","dpx1,#0x40");
326 emitcode ("mov","dph1,#0x00");
327 emitcode ("mov","dpl1, a");
331 emitcode("pop","acc");
333 sym->aop = aop = newAsmop(AOP_DPTR2);
334 aop->size = getSize(sym->type);
338 /* if in bit space */
339 if (IN_BITSPACE(space)) {
340 sym->aop = aop = newAsmop (AOP_CRY);
341 aop->aopu.aop_dir = sym->rname ;
342 aop->size = getSize(sym->type);
345 /* if it is in direct space */
346 if (IN_DIRSPACE(space)) {
347 sym->aop = aop = newAsmop (AOP_DIR);
348 aop->aopu.aop_dir = sym->rname ;
349 aop->size = getSize(sym->type);
353 /* special case for a function */
354 if (IS_FUNC(sym->type)) {
355 sym->aop = aop = newAsmop(AOP_IMMD);
356 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
357 strcpy(aop->aopu.aop_immd,sym->rname);
358 aop->size = FPTRSIZE;
362 /* only remaining is far space */
363 /* in which case DPTR gets the address */
364 sym->aop = aop = newAsmop(AOP_DPTR);
365 emitcode ("mov","dptr,#%s", sym->rname);
366 aop->size = getSize(sym->type);
368 /* if it is in code space */
369 if (IN_CODESPACE(space))
375 /*-----------------------------------------------------------------*/
376 /* aopForRemat - rematerialzes an object */
377 /*-----------------------------------------------------------------*/
378 static asmop *aopForRemat (symbol *sym)
380 iCode *ic = sym->rematiCode;
381 asmop *aop = newAsmop(AOP_IMMD);
386 val += operandLitValue(IC_RIGHT(ic));
387 else if (ic->op == '-')
388 val -= operandLitValue(IC_RIGHT(ic));
392 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
396 sprintf(buffer,"(%s %c 0x%04x)",
397 OP_SYMBOL(IC_LEFT(ic))->rname,
398 val >= 0 ? '+' : '-',
401 strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
403 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
404 strcpy(aop->aopu.aop_immd,buffer);
408 /*-----------------------------------------------------------------*/
409 /* regsInCommon - two operands have some registers in common */
410 /*-----------------------------------------------------------------*/
411 static bool regsInCommon (operand *op1, operand *op2)
416 /* if they have registers in common */
417 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
420 sym1 = OP_SYMBOL(op1);
421 sym2 = OP_SYMBOL(op2);
423 if (sym1->nRegs == 0 || sym2->nRegs == 0)
426 for (i = 0 ; i < sym1->nRegs ; i++) {
431 for (j = 0 ; j < sym2->nRegs ;j++ ) {
435 if (sym2->regs[j] == sym1->regs[i])
443 /*-----------------------------------------------------------------*/
444 /* operandsEqu - equivalent */
445 /*-----------------------------------------------------------------*/
446 static bool operandsEqu ( operand *op1, operand *op2)
450 /* if they not symbols */
451 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
454 sym1 = OP_SYMBOL(op1);
455 sym2 = OP_SYMBOL(op2);
457 /* if both are itemps & one is spilt
458 and the other is not then false */
459 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
460 sym1->isspilt != sym2->isspilt )
463 /* if they are the same */
467 if (strcmp(sym1->rname,sym2->rname) == 0)
471 /* if left is a tmp & right is not */
475 (sym1->usl.spillLoc == sym2))
482 (sym2->usl.spillLoc == sym1))
488 /*-----------------------------------------------------------------*/
489 /* sameRegs - two asmops have the same registers */
490 /*-----------------------------------------------------------------*/
491 static bool sameRegs (asmop *aop1, asmop *aop2 )
498 if (aop1->type != AOP_REG ||
499 aop2->type != AOP_REG )
502 if (aop1->size != aop2->size )
505 for (i = 0 ; i < aop1->size ; i++ )
506 if (aop1->aopu.aop_reg[i] !=
507 aop2->aopu.aop_reg[i] )
513 /*-----------------------------------------------------------------*/
514 /* aopOp - allocates an asmop for an operand : */
515 /*-----------------------------------------------------------------*/
516 static void aopOp (operand *op, iCode *ic, bool result)
525 /* if this a literal */
526 if (IS_OP_LITERAL(op)) {
527 op->aop = aop = newAsmop(AOP_LIT);
528 aop->aopu.aop_lit = op->operand.valOperand;
529 aop->size = getSize(operandType(op));
533 /* if already has a asmop then continue */
537 /* if the underlying symbol has a aop */
538 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
539 op->aop = OP_SYMBOL(op)->aop;
543 /* if this is a true symbol */
544 if (IS_TRUE_SYMOP(op)) {
545 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
549 /* this is a temporary : this has
555 e) can be a return use only */
560 /* if the type is a conditional */
561 if (sym->regType == REG_CND) {
562 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
567 /* if it is spilt then two situations
569 b) has a spill location */
570 if (sym->isspilt || sym->nRegs == 0) {
572 /* rematerialize it NOW */
574 sym->aop = op->aop = aop =
576 aop->size = getSize(sym->type);
582 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
583 aop->size = getSize(sym->type);
584 for ( i = 0 ; i < 2 ; i++ )
585 aop->aopu.aop_str[i] = accUse[i];
591 aop = op->aop = sym->aop = newAsmop(AOP_STR);
592 aop->size = getSize(sym->type);
593 for ( i = 0 ; i < fReturnSize ; i++ )
594 aop->aopu.aop_str[i] = fReturn[i];
598 /* else spill location */
599 sym->aop = op->aop = aop =
600 aopForSym(ic,sym->usl.spillLoc,result);
601 aop->size = getSize(sym->type);
605 /* must be in a register */
606 sym->aop = op->aop = aop = newAsmop(AOP_REG);
607 aop->size = sym->nRegs;
608 for ( i = 0 ; i < sym->nRegs ;i++)
609 aop->aopu.aop_reg[i] = sym->regs[i];
612 /*-----------------------------------------------------------------*/
613 /* freeAsmop - free up the asmop given to an operand */
614 /*----------------------------------------------------------------*/
615 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
632 /* depending on the asmop type only three cases need work AOP_RO
633 , AOP_R1 && AOP_STK */
638 emitcode ("pop","ar0");
642 bitVectUnSetBit(ic->rUsed,R0_IDX);
648 emitcode ("pop","ar1");
652 bitVectUnSetBit(ic->rUsed,R1_IDX);
658 int stk = aop->aopu.aop_stk + aop->size;
659 bitVectUnSetBit(ic->rUsed,R0_IDX);
660 bitVectUnSetBit(ic->rUsed,R1_IDX);
662 getFreePtr(ic,&aop,FALSE);
664 if (options.stack10bit)
666 /* I'm not sure what to do here yet... */
669 "*** Warning: probably generating bad code for "
670 "10 bit stack mode.\n");
674 emitcode ("mov","a,_bp");
675 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
676 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
678 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
682 emitcode("pop","acc");
683 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
685 emitcode("dec","%s",aop->aopu.aop_ptr->name);
688 freeAsmop(op,NULL,ic,TRUE);
690 emitcode("pop","ar0");
695 emitcode("pop","ar1");
702 /* all other cases just dealloc */
706 OP_SYMBOL(op)->aop = NULL;
707 /* if the symbol has a spill */
709 SPIL_LOC(op)->aop = NULL;
714 /*-----------------------------------------------------------------*/
715 /* aopGet - for fetching value of the aop */
716 /*-----------------------------------------------------------------*/
717 static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
722 /* offset is greater than
724 if (offset > (aop->size - 1) &&
725 aop->type != AOP_LIT)
728 /* depending on type */
733 /* if we need to increment it */
734 while (offset > aop->coff) {
735 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
739 while (offset < aop->coff) {
740 emitcode("dec","%s",aop->aopu.aop_ptr->name);
746 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
747 return (dname ? "acc" : "a");
749 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
750 ALLOC_ATOMIC(rs,strlen(s)+1);
757 if (aop->type == AOP_DPTR2)
762 while (offset > aop->coff) {
763 emitcode ("inc","dptr");
767 while (offset < aop->coff) {
768 emitcode("lcall","__decdptr");
775 emitcode("movc","a,@a+dptr");
778 emitcode("movx","a,@dptr");
781 if (aop->type == AOP_DPTR2)
786 return (dname ? "acc" : "a");
791 sprintf (s,"#%s",aop->aopu.aop_immd);
794 sprintf(s,"#(%s >> %d)",
800 ALLOC_ATOMIC(rs,strlen(s)+1);
806 sprintf(s,"(%s + %d)",
810 sprintf(s,"%s",aop->aopu.aop_dir);
811 ALLOC_ATOMIC(rs,strlen(s)+1);
817 return aop->aopu.aop_reg[offset]->dname;
819 return aop->aopu.aop_reg[offset]->name;
823 emitcode("mov","c,%s",aop->aopu.aop_dir);
824 emitcode("rlc","a") ;
825 return (dname ? "acc" : "a");
828 if (!offset && dname)
830 return aop->aopu.aop_str[offset];
833 return aopLiteral (aop->aopu.aop_lit,offset);
837 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
841 return aop->aopu.aop_str[offset];
845 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
846 "aopget got unsupported aop->type");
849 /*-----------------------------------------------------------------*/
850 /* aopPut - puts a string for a aop */
851 /*-----------------------------------------------------------------*/
852 static void aopPut (asmop *aop, char *s, int offset)
857 if (aop->size && offset > ( aop->size - 1)) {
858 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
859 "aopPut got offset > aop->size");
863 /* will assign value to value */
864 /* depending on where it is ofcourse */
868 sprintf(d,"(%s + %d)",
869 aop->aopu.aop_dir,offset);
871 sprintf(d,"%s",aop->aopu.aop_dir);
874 emitcode("mov","%s,%s",d,s);
879 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
880 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
882 strcmp(s,"r0") == 0 ||
883 strcmp(s,"r1") == 0 ||
884 strcmp(s,"r2") == 0 ||
885 strcmp(s,"r3") == 0 ||
886 strcmp(s,"r4") == 0 ||
887 strcmp(s,"r5") == 0 ||
888 strcmp(s,"r6") == 0 ||
889 strcmp(s,"r7") == 0 )
890 emitcode("mov","%s,%s",
891 aop->aopu.aop_reg[offset]->dname,s);
893 emitcode("mov","%s,%s",
894 aop->aopu.aop_reg[offset]->name,s);
901 if (aop->type == AOP_DPTR2)
907 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
908 "aopPut writting to code space");
912 while (offset > aop->coff) {
914 emitcode ("inc","dptr");
917 while (offset < aop->coff) {
919 emitcode("lcall","__decdptr");
924 /* if not in accumulater */
927 emitcode ("movx","@dptr,a");
929 if (aop->type == AOP_DPTR2)
937 while (offset > aop->coff) {
939 emitcode("inc","%s",aop->aopu.aop_ptr->name);
941 while (offset < aop->coff) {
943 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
949 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
954 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
956 if (strcmp(s,"r0") == 0 ||
957 strcmp(s,"r1") == 0 ||
958 strcmp(s,"r2") == 0 ||
959 strcmp(s,"r3") == 0 ||
960 strcmp(s,"r4") == 0 ||
961 strcmp(s,"r5") == 0 ||
962 strcmp(s,"r6") == 0 ||
963 strcmp(s,"r7") == 0 ) {
965 sprintf(buffer,"a%s",s);
966 emitcode("mov","@%s,%s",
967 aop->aopu.aop_ptr->name,buffer);
969 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
974 if (strcmp(s,"a") == 0)
975 emitcode("push","acc");
977 emitcode("push","%s",s);
982 /* if bit variable */
983 if (!aop->aopu.aop_dir) {
988 emitcode("clr","%s",aop->aopu.aop_dir);
991 emitcode("setb","%s",aop->aopu.aop_dir);
994 emitcode("mov","%s,c",aop->aopu.aop_dir);
996 lbl = newiTempLabel(NULL);
1001 emitcode("clr","c");
1002 emitcode("jz","%05d$",lbl->key+100);
1003 emitcode("cpl","c");
1004 emitcode("","%05d$:",lbl->key+100);
1005 emitcode("mov","%s,c",aop->aopu.aop_dir);
1012 if (strcmp(aop->aopu.aop_str[offset],s))
1013 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1018 if (!offset && (strcmp(s,"acc") == 0))
1021 if (strcmp(aop->aopu.aop_str[offset],s))
1022 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1026 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1027 "aopPut got unsupported aop->type");
1035 /*-----------------------------------------------------------------*/
1036 /* pointToEnd :- points to the last byte of the operand */
1037 /*-----------------------------------------------------------------*/
1038 static void pointToEnd (asmop *aop)
1044 aop->coff = count = (aop->size - 1);
1045 switch (aop->type) {
1049 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1053 emitcode("inc","dptr");
1060 /*-----------------------------------------------------------------*/
1061 /* reAdjustPreg - points a register back to where it should */
1062 /*-----------------------------------------------------------------*/
1063 static void reAdjustPreg (asmop *aop)
1068 if ((size = aop->size) <= 1)
1071 switch (aop->type) {
1075 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1079 if (aop->type == AOP_DPTR2)
1085 emitcode("lcall","__decdptr");
1088 if (aop->type == AOP_DPTR2)
1098 #define AOP(op) op->aop
1099 #define AOP_TYPE(op) AOP(op)->type
1100 #define AOP_SIZE(op) AOP(op)->size
1101 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1102 AOP_TYPE(x) == AOP_R0))
1104 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1105 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1108 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1109 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1110 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1112 /*-----------------------------------------------------------------*/
1113 /* genNotFloat - generates not for float operations */
1114 /*-----------------------------------------------------------------*/
1115 static void genNotFloat (operand *op, operand *res)
1121 /* we will put 127 in the first byte of
1123 aopPut(AOP(res),"#127",0);
1124 size = AOP_SIZE(op) - 1;
1127 l = aopGet(op->aop,offset++,FALSE,FALSE);
1131 emitcode("orl","a,%s",
1133 offset++,FALSE,FALSE));
1135 tlbl = newiTempLabel(NULL);
1137 tlbl = newiTempLabel(NULL);
1138 aopPut(res->aop,one,1);
1139 emitcode("jz","%05d$",(tlbl->key+100));
1140 aopPut(res->aop,zero,1);
1141 emitcode("","%05d$:",(tlbl->key+100));
1143 size = res->aop->size - 2;
1145 /* put zeros in the rest */
1147 aopPut(res->aop,zero,offset++);
1150 /*-----------------------------------------------------------------*/
1151 /* opIsGptr: returns non-zero if the passed operand is */
1152 /* a generic pointer type. */
1153 /*-----------------------------------------------------------------*/
1154 static int opIsGptr(operand *op)
1156 link *type = operandType(op);
1158 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1165 /*-----------------------------------------------------------------*/
1166 /* getDataSize - get the operand data size */
1167 /*-----------------------------------------------------------------*/
1168 static int getDataSize(operand *op)
1171 size = AOP_SIZE(op);
1172 if (size == GPTRSIZE)
1174 link *type = operandType(op);
1175 if (IS_GENPTR(type))
1177 /* generic pointer; arithmetic operations
1178 * should ignore the high byte (pointer type).
1186 /*-----------------------------------------------------------------*/
1187 /* outAcc - output Acc */
1188 /*-----------------------------------------------------------------*/
1189 static void outAcc(operand *result)
1192 size = getDataSize(result);
1194 aopPut(AOP(result),"a",0);
1197 /* unsigned or positive */
1199 aopPut(AOP(result),zero,offset++);
1204 /*-----------------------------------------------------------------*/
1205 /* outBitC - output a bit C */
1206 /*-----------------------------------------------------------------*/
1207 static void outBitC(operand *result)
1209 /* if the result is bit */
1210 if (AOP_TYPE(result) == AOP_CRY)
1211 aopPut(AOP(result),"c",0);
1213 emitcode("clr","a");
1214 emitcode("rlc","a");
1219 /*-----------------------------------------------------------------*/
1220 /* toBoolean - emit code for orl a,operator(sizeop) */
1221 /*-----------------------------------------------------------------*/
1222 static void toBoolean(operand *oper)
1224 int size = AOP_SIZE(oper) - 1;
1226 MOVA(aopGet(AOP(oper),0,FALSE,FALSE));
1228 emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE));
1232 /*-----------------------------------------------------------------*/
1233 /* genNot - generate code for ! operation */
1234 /*-----------------------------------------------------------------*/
1235 static void genNot (iCode *ic)
1238 link *optype = operandType(IC_LEFT(ic));
1240 /* assign asmOps to operand & result */
1241 aopOp (IC_LEFT(ic),ic,FALSE);
1242 aopOp (IC_RESULT(ic),ic,TRUE);
1244 /* if in bit space then a special case */
1245 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1246 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1247 emitcode("cpl","c");
1248 outBitC(IC_RESULT(ic));
1252 /* if type float then do float */
1253 if (IS_FLOAT(optype)) {
1254 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1258 toBoolean(IC_LEFT(ic));
1260 tlbl = newiTempLabel(NULL);
1261 emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1262 emitcode("","%05d$:",tlbl->key+100);
1263 outBitC(IC_RESULT(ic));
1266 /* release the aops */
1267 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1268 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1272 /*-----------------------------------------------------------------*/
1273 /* genCpl - generate code for complement */
1274 /*-----------------------------------------------------------------*/
1275 static void genCpl (iCode *ic)
1281 /* assign asmOps to operand & result */
1282 aopOp (IC_LEFT(ic),ic,FALSE);
1283 aopOp (IC_RESULT(ic),ic,TRUE);
1285 /* if both are in bit space then
1287 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1288 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1290 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1291 emitcode("cpl","c");
1292 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1296 size = AOP_SIZE(IC_RESULT(ic));
1298 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1300 emitcode("cpl","a");
1301 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1306 /* release the aops */
1307 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1308 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1311 /*-----------------------------------------------------------------*/
1312 /* genUminusFloat - unary minus for floating points */
1313 /*-----------------------------------------------------------------*/
1314 static void genUminusFloat(operand *op,operand *result)
1316 int size ,offset =0 ;
1318 /* for this we just need to flip the
1319 first it then copy the rest in place */
1320 size = AOP_SIZE(op) - 1;
1321 l = aopGet(AOP(op),3,FALSE,FALSE);
1325 emitcode("cpl","acc.7");
1326 aopPut(AOP(result),"a",3);
1330 aopGet(AOP(op),offset,FALSE,FALSE),
1336 /*-----------------------------------------------------------------*/
1337 /* genUminus - unary minus code generation */
1338 /*-----------------------------------------------------------------*/
1339 static void genUminus (iCode *ic)
1342 link *optype, *rtype;
1346 aopOp(IC_LEFT(ic),ic,FALSE);
1347 aopOp(IC_RESULT(ic),ic,TRUE);
1349 /* if both in bit space then special
1351 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1352 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1354 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1355 emitcode("cpl","c");
1356 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1360 optype = operandType(IC_LEFT(ic));
1361 rtype = operandType(IC_RESULT(ic));
1363 /* if float then do float stuff */
1364 if (IS_FLOAT(optype)) {
1365 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1369 /* otherwise subtract from zero */
1370 size = AOP_SIZE(IC_LEFT(ic));
1374 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1375 if (!strcmp(l,"a")) {
1378 emitcode("cpl","a");
1379 emitcode("addc","a,#0");
1383 emitcode("clr","a");
1384 emitcode("subb","a,%s",l);
1386 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1389 /* if any remaining bytes in the result */
1390 /* we just need to propagate the sign */
1391 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1392 emitcode("rlc","a");
1393 emitcode("subb","a,acc");
1395 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1399 /* release the aops */
1400 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1401 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1404 /*-----------------------------------------------------------------*/
1405 /* saveRegisters - will look for a call and save the registers */
1406 /*-----------------------------------------------------------------*/
1407 static void saveRegisters(iCode *lic)
1415 for (ic = lic ; ic ; ic = ic->next)
1416 if (ic->op == CALL || ic->op == PCALL)
1420 fprintf(stderr,"found parameter push with no function call\n");
1424 /* if the registers have been saved already then
1426 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1429 /* find the registers in use at this time
1430 and push them away to safety */
1431 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1435 if (options.useXstack) {
1436 if (bitVectBitValue(rsave,R0_IDX))
1437 emitcode("mov","b,r0");
1438 emitcode("mov","r0,%s",spname);
1439 for (i = 0 ; i < mcs51_nRegs ; i++) {
1440 if (bitVectBitValue(rsave,i)) {
1442 emitcode("mov","a,b");
1444 emitcode("mov","a,%s",mcs51_regWithIdx(i)->name);
1445 emitcode("movx","@r0,a");
1446 emitcode("inc","r0");
1449 emitcode("mov","%s,r0",spname);
1450 if (bitVectBitValue(rsave,R0_IDX))
1451 emitcode("mov","r0,b");
1453 for (i = 0 ; i < mcs51_nRegs ; i++) {
1454 if (bitVectBitValue(rsave,i))
1455 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
1458 detype = getSpec(operandType(IC_LEFT(ic)));
1460 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1461 IS_ISR(currFunc->etype) &&
1464 saverbank(SPEC_BANK(detype),ic,TRUE);
1467 /*-----------------------------------------------------------------*/
1468 /* unsaveRegisters - pop the pushed registers */
1469 /*-----------------------------------------------------------------*/
1470 static void unsaveRegisters (iCode *ic)
1474 /* find the registers in use at this time
1475 and push them away to safety */
1476 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1479 if (options.useXstack) {
1480 emitcode("mov","r0,%s",spname);
1481 for (i = mcs51_nRegs ; i >= 0 ; i--) {
1482 if (bitVectBitValue(rsave,i)) {
1483 emitcode("dec","r0");
1484 emitcode("movx","a,@r0");
1486 emitcode("mov","b,a");
1488 emitcode("mov","%s,a",mcs51_regWithIdx(i)->name);
1492 emitcode("mov","%s,r0",spname);
1493 if (bitVectBitValue(rsave,R0_IDX))
1494 emitcode("mov","r0,b");
1496 for (i = mcs51_nRegs ; i >= 0 ; i--) {
1497 if (bitVectBitValue(rsave,i))
1498 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
1504 /*-----------------------------------------------------------------*/
1506 /*-----------------------------------------------------------------*/
1507 static void pushSide(operand * oper, int size)
1511 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1512 if (AOP_TYPE(oper) != AOP_REG &&
1513 AOP_TYPE(oper) != AOP_DIR &&
1515 emitcode("mov","a,%s",l);
1516 emitcode("push","acc");
1518 emitcode("push","%s",l);
1522 /*-----------------------------------------------------------------*/
1523 /* assignResultValue - */
1524 /*-----------------------------------------------------------------*/
1525 static void assignResultValue(operand * oper)
1528 int size = AOP_SIZE(oper);
1530 aopPut(AOP(oper),fReturn[offset],offset);
1536 /*-----------------------------------------------------------------*/
1537 /* genXpush - pushes onto the external stack */
1538 /*-----------------------------------------------------------------*/
1539 static void genXpush (iCode *ic)
1541 asmop *aop = newAsmop(0);
1543 int size,offset = 0;
1545 aopOp(IC_LEFT(ic),ic,FALSE);
1546 r = getFreePtr(ic,&aop,FALSE);
1549 emitcode("mov","%s,_spx",r->name);
1551 size = AOP_SIZE(IC_LEFT(ic));
1554 char *l = aopGet(AOP(IC_LEFT(ic)),
1555 offset++,FALSE,FALSE);
1557 emitcode("movx","@%s,a",r->name);
1558 emitcode("inc","%s",r->name);
1563 emitcode("mov","_spx,%s",r->name);
1565 freeAsmop(NULL,aop,ic,TRUE);
1566 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1569 /*-----------------------------------------------------------------*/
1570 /* genIpush - genrate code for pushing this gets a little complex */
1571 /*-----------------------------------------------------------------*/
1572 static void genIpush (iCode *ic)
1574 int size, offset = 0 ;
1578 /* if this is not a parm push : ie. it is spill push
1579 and spill push is always done on the local stack */
1580 if (!ic->parmPush) {
1582 /* and the item is spilt then do nothing */
1583 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1586 aopOp(IC_LEFT(ic),ic,FALSE);
1587 size = AOP_SIZE(IC_LEFT(ic));
1588 /* push it on the stack */
1590 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1595 emitcode("push","%s",l);
1600 /* this is a paramter push: in this case we call
1601 the routine to find the call and save those
1602 registers that need to be saved */
1605 /* if use external stack then call the external
1606 stack pushing routine */
1607 if (options.useXstack) {
1612 /* then do the push */
1613 aopOp(IC_LEFT(ic),ic,FALSE);
1616 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1617 size = AOP_SIZE(IC_LEFT(ic));
1620 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1621 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1622 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1624 emitcode("mov","a,%s",l);
1625 emitcode("push","acc");
1627 emitcode("push","%s",l);
1630 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1633 /*-----------------------------------------------------------------*/
1634 /* genIpop - recover the registers: can happen only for spilling */
1635 /*-----------------------------------------------------------------*/
1636 static void genIpop (iCode *ic)
1641 /* if the temp was not pushed then */
1642 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1645 aopOp(IC_LEFT(ic),ic,FALSE);
1646 size = AOP_SIZE(IC_LEFT(ic));
1649 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1652 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1655 /*-----------------------------------------------------------------*/
1656 /* unsaverbank - restores the resgister bank from stack */
1657 /*-----------------------------------------------------------------*/
1658 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1665 if (options.useXstack) {
1667 r = getFreePtr(ic,&aop,FALSE);
1670 emitcode("mov","%s,_spx",r->name);
1671 emitcode("movx","a,@%s",r->name);
1672 emitcode("mov","psw,a");
1673 emitcode("dec","%s",r->name);
1676 emitcode ("pop","psw");
1679 for (i = (mcs51_nRegs - 1) ; i >= 0 ;i--) {
1680 if (options.useXstack) {
1681 emitcode("movx","a,@%s",r->name);
1682 emitcode("mov","(%s+%d),a",
1683 regs8051[i].base,8*bank+regs8051[i].offset);
1684 emitcode("dec","%s",r->name);
1687 emitcode("pop","(%s+%d)",
1688 regs8051[i].base,8*bank+regs8051[i].offset);
1691 if (options.useXstack) {
1693 emitcode("mov","_spx,%s",r->name);
1694 freeAsmop(NULL,aop,ic,TRUE);
1699 /*-----------------------------------------------------------------*/
1700 /* saverbank - saves an entire register bank on the stack */
1701 /*-----------------------------------------------------------------*/
1702 static void saverbank (int bank, iCode *ic, bool pushPsw)
1708 if (options.useXstack) {
1711 r = getFreePtr(ic,&aop,FALSE);
1712 emitcode("mov","%s,_spx",r->name);
1716 for (i = 0 ; i < mcs51_nRegs ;i++) {
1717 if (options.useXstack) {
1718 emitcode("inc","%s",r->name);
1719 emitcode("mov","a,(%s+%d)",
1720 regs8051[i].base,8*bank+regs8051[i].offset);
1721 emitcode("movx","@%s,a",r->name);
1723 emitcode("push","(%s+%d)",
1724 regs8051[i].base,8*bank+regs8051[i].offset);
1728 if (options.useXstack) {
1729 emitcode("mov","a,psw");
1730 emitcode("movx","@%s,a",r->name);
1731 emitcode("inc","%s",r->name);
1732 emitcode("mov","_spx,%s",r->name);
1733 freeAsmop (NULL,aop,ic,TRUE);
1736 emitcode("push","psw");
1738 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1744 /*-----------------------------------------------------------------*/
1745 /* genCall - generates a call statement */
1746 /*-----------------------------------------------------------------*/
1747 static void genCall (iCode *ic)
1751 /* if caller saves & we have not saved then */
1755 /* if we are calling a function that is not using
1756 the same register bank then we need to save the
1757 destination registers on the stack */
1758 detype = getSpec(operandType(IC_LEFT(ic)));
1760 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1761 IS_ISR(currFunc->etype) &&
1764 saverbank(SPEC_BANK(detype),ic,TRUE);
1766 /* if send set is not empty the assign */
1770 for (sic = setFirstItem(_G.sendSet) ; sic ;
1771 sic = setNextItem(_G.sendSet)) {
1772 int size, offset = 0;
1773 aopOp(IC_LEFT(sic),sic,FALSE);
1774 size = AOP_SIZE(IC_LEFT(sic));
1776 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1778 if (strcmp(l,fReturn[offset]))
1779 emitcode("mov","%s,%s",
1784 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1789 emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1790 OP_SYMBOL(IC_LEFT(ic))->rname :
1791 OP_SYMBOL(IC_LEFT(ic))->name));
1793 /* if we need assign a result value */
1794 if ((IS_ITEMP(IC_RESULT(ic)) &&
1795 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1796 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1797 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1800 aopOp(IC_RESULT(ic),ic,FALSE);
1803 assignResultValue(IC_RESULT(ic));
1805 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1808 /* adjust the stack for parameters if
1810 if (IC_LEFT(ic)->parmBytes) {
1812 if (IC_LEFT(ic)->parmBytes > 3) {
1813 emitcode("mov","a,%s",spname);
1814 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1815 emitcode("mov","%s,a",spname);
1817 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1818 emitcode("dec","%s",spname);
1822 /* if register bank was saved then pop them */
1824 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1826 /* if we hade saved some registers then unsave them */
1827 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1828 unsaveRegisters (ic);
1833 /*-----------------------------------------------------------------*/
1834 /* genPcall - generates a call by pointer statement */
1835 /*-----------------------------------------------------------------*/
1836 static void genPcall (iCode *ic)
1839 symbol *rlbl = newiTempLabel(NULL);
1842 /* if caller saves & we have not saved then */
1846 /* if we are calling a function that is not using
1847 the same register bank then we need to save the
1848 destination registers on the stack */
1849 detype = getSpec(operandType(IC_LEFT(ic)));
1851 IS_ISR(currFunc->etype) &&
1852 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
1853 saverbank(SPEC_BANK(detype),ic,TRUE);
1856 /* push the return address on to the stack */
1857 emitcode("mov","a,#%05d$",(rlbl->key+100));
1858 emitcode("push","acc");
1859 emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
1860 emitcode("push","acc");
1862 if (options.model == MODEL_FLAT24)
1864 emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
1865 emitcode("push","acc");
1868 /* now push the calling address */
1869 aopOp(IC_LEFT(ic),ic,FALSE);
1871 pushSide(IC_LEFT(ic), FPTRSIZE);
1873 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1875 /* if send set is not empty the assign */
1879 for (sic = setFirstItem(_G.sendSet) ; sic ;
1880 sic = setNextItem(_G.sendSet)) {
1881 int size, offset = 0;
1882 aopOp(IC_LEFT(sic),sic,FALSE);
1883 size = AOP_SIZE(IC_LEFT(sic));
1885 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1887 if (strcmp(l,fReturn[offset]))
1888 emitcode("mov","%s,%s",
1893 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1899 emitcode("","%05d$:",(rlbl->key+100));
1902 /* if we need assign a result value */
1903 if ((IS_ITEMP(IC_RESULT(ic)) &&
1904 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1905 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
1906 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1909 aopOp(IC_RESULT(ic),ic,FALSE);
1912 assignResultValue(IC_RESULT(ic));
1914 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1917 /* adjust the stack for parameters if
1919 if (IC_LEFT(ic)->parmBytes) {
1921 if (IC_LEFT(ic)->parmBytes > 3) {
1922 emitcode("mov","a,%s",spname);
1923 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1924 emitcode("mov","%s,a",spname);
1926 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1927 emitcode("dec","%s",spname);
1931 /* if register bank was saved then unsave them */
1933 (SPEC_BANK(currFunc->etype) !=
1935 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1937 /* if we hade saved some registers then
1940 unsaveRegisters (ic);
1944 /*-----------------------------------------------------------------*/
1945 /* resultRemat - result is rematerializable */
1946 /*-----------------------------------------------------------------*/
1947 static int resultRemat (iCode *ic)
1949 if (SKIP_IC(ic) || ic->op == IFX)
1952 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1953 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1954 if (sym->remat && !POINTER_SET(ic))
1962 #define STRCASECMP stricmp
1964 #define STRCASECMP strcasecmp
1967 /*-----------------------------------------------------------------*/
1968 /* inExcludeList - return 1 if the string is in exclude Reg list */
1969 /*-----------------------------------------------------------------*/
1970 static bool inExcludeList(char *s)
1974 if (options.excludeRegs[i] &&
1975 STRCASECMP(options.excludeRegs[i],"none") == 0)
1978 for ( i = 0 ; options.excludeRegs[i]; i++) {
1979 if (options.excludeRegs[i] &&
1980 STRCASECMP(s,options.excludeRegs[i]) == 0)
1986 /*-----------------------------------------------------------------*/
1987 /* genFunction - generated code for function entry */
1988 /*-----------------------------------------------------------------*/
1989 static void genFunction (iCode *ic)
1995 /* create the function header */
1996 emitcode(";","-----------------------------------------");
1997 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1998 emitcode(";","-----------------------------------------");
2000 emitcode("","%s:",sym->rname);
2001 fetype = getSpec(operandType(IC_LEFT(ic)));
2003 /* if critical function then turn interrupts off */
2004 if (SPEC_CRTCL(fetype))
2005 emitcode("clr","ea");
2007 /* here we need to generate the equates for the
2008 register bank if required */
2009 if (SPEC_BANK(fetype) != rbank) {
2012 rbank = SPEC_BANK(fetype);
2013 for ( i = 0 ; i < mcs51_nRegs ; i++ ) {
2014 if (strcmp(regs8051[i].base,"0") == 0)
2015 emitcode("","%s = 0x%02x",
2017 8*rbank+regs8051[i].offset);
2019 emitcode ("","%s = %s + 0x%02x",
2022 8*rbank+regs8051[i].offset);
2026 /* if this is an interrupt service routine then
2027 save acc, b, dpl, dph */
2028 if (IS_ISR(sym->etype)) {
2030 if (!inExcludeList("acc"))
2031 emitcode ("push","acc");
2032 if (!inExcludeList("b"))
2033 emitcode ("push","b");
2034 if (!inExcludeList("dpl"))
2035 emitcode ("push","dpl");
2036 if (!inExcludeList("dph"))
2037 emitcode ("push","dph");
2038 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2040 emitcode ("push", "dpx");
2041 /* Make sure we're using standard DPTR */
2042 emitcode ("push", "dps");
2043 emitcode ("mov", "dps, #0x00");
2044 if (options.stack10bit)
2046 /* This ISR could conceivably use DPTR2. Better save it. */
2047 emitcode ("push", "dpl1");
2048 emitcode ("push", "dph1");
2049 emitcode ("push", "dpx1");
2052 /* if this isr has no bank i.e. is going to
2053 run with bank 0 , then we need to save more
2055 if (!SPEC_BANK(sym->etype)) {
2057 /* if this function does not call any other
2058 function then we can be economical and
2059 save only those registers that are used */
2060 if (! sym->hasFcall) {
2063 /* if any registers used */
2064 if (sym->regsUsed) {
2065 /* save the registers used */
2066 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2067 if (bitVectBitValue(sym->regsUsed,i) ||
2068 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2069 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
2074 /* this function has a function call cannot
2075 determines register usage so we will have the
2077 saverbank(0,ic,FALSE);
2081 /* if callee-save to be used for this function
2082 then save the registers being used in this function */
2083 if (sym->calleeSave) {
2086 /* if any registers used */
2087 if (sym->regsUsed) {
2088 /* save the registers used */
2089 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2090 if (bitVectBitValue(sym->regsUsed,i) ||
2091 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2092 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
2100 /* set the register bank to the desired value */
2101 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2102 emitcode("push","psw");
2103 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2106 if (IS_RENT(sym->etype) || options.stackAuto) {
2108 if (options.useXstack) {
2109 /* set up the PAGE for the xternal stack */
2111 emitcode("push","dph");
2112 emitcode("push","acc");
2114 emitcode("mov","dph,__page_no__");
2115 emitcode("movx","a,@dptr");
2117 emitcode("pop","acc");
2118 emitcode("pop","dph");
2120 emitcode("mov","r0,%s",spname);
2121 emitcode("mov","a,_bp");
2122 emitcode("movx","@r0,a");
2123 emitcode("inc","%s",spname);
2127 /* set up the stack */
2128 emitcode ("push","_bp"); /* save the callers stack */
2130 emitcode ("mov","_bp,%s",spname);
2133 /* adjust the stack for the function */
2138 werror(W_STACK_OVERFLOW,sym->name);
2140 if (i > 3 && sym->recvSize < 4) {
2142 emitcode ("mov","a,sp");
2143 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2144 emitcode ("mov","sp,a");
2149 emitcode("inc","sp");
2154 emitcode ("mov","a,_spx");
2155 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2156 emitcode ("mov","_spx,a");
2161 /*-----------------------------------------------------------------*/
2162 /* genEndFunction - generates epilogue for functions */
2163 /*-----------------------------------------------------------------*/
2164 static void genEndFunction (iCode *ic)
2166 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2168 if (IS_RENT(sym->etype) || options.stackAuto)
2170 emitcode ("mov","%s,_bp",spname);
2173 /* if use external stack but some variables were
2174 added to the local stack then decrement the
2176 if (options.useXstack && sym->stack) {
2177 emitcode("mov","a,sp");
2178 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2179 emitcode("mov","sp,a");
2183 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2184 if (options.useXstack) {
2185 emitcode("mov","r0,%s",spname);
2186 emitcode("movx","a,@r0");
2187 emitcode("mov","_bp,a");
2188 emitcode("dec","%s",spname);
2192 emitcode ("pop","_bp");
2196 /* restore the register bank */
2197 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2198 emitcode ("pop","psw");
2200 if (IS_ISR(sym->etype)) {
2202 /* now we need to restore the registers */
2203 /* if this isr has no bank i.e. is going to
2204 run with bank 0 , then we need to save more
2206 if (!SPEC_BANK(sym->etype)) {
2208 /* if this function does not call any other
2209 function then we can be economical and
2210 save only those registers that are used */
2211 if (! sym->hasFcall) {
2214 /* if any registers used */
2215 if (sym->regsUsed) {
2216 /* save the registers used */
2217 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2218 if (bitVectBitValue(sym->regsUsed,i) ||
2219 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2220 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
2225 /* this function has a function call cannot
2226 determines register usage so we will have the
2228 unsaverbank(0,ic,FALSE);
2232 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2234 if (options.stack10bit)
2236 emitcode ("pop", "dpx1");
2237 emitcode ("pop", "dph1");
2238 emitcode ("pop", "dpl1");
2240 emitcode ("pop", "dps");
2241 emitcode ("pop", "dpx");
2243 if (!inExcludeList("dph"))
2244 emitcode ("pop","dph");
2245 if (!inExcludeList("dpl"))
2246 emitcode ("pop","dpl");
2247 if (!inExcludeList("b"))
2248 emitcode ("pop","b");
2249 if (!inExcludeList("acc"))
2250 emitcode ("pop","acc");
2252 if (SPEC_CRTCL(sym->etype))
2253 emitcode("setb","ea");
2255 /* if debug then send end of function */
2256 /* if (options.debug && currFunc) { */
2259 emitcode("","C$%s$%d$%d$%d ==.",
2260 ic->filename,currFunc->lastLine,
2261 ic->level,ic->block);
2262 if (IS_STATIC(currFunc->etype))
2263 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2265 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2269 emitcode ("reti","");
2272 if (SPEC_CRTCL(sym->etype))
2273 emitcode("setb","ea");
2275 if (sym->calleeSave) {
2278 /* if any registers used */
2279 if (sym->regsUsed) {
2280 /* save the registers used */
2281 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2282 if (bitVectBitValue(sym->regsUsed,i) ||
2283 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2284 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
2290 /* if debug then send end of function */
2293 emitcode("","C$%s$%d$%d$%d ==.",
2294 ic->filename,currFunc->lastLine,
2295 ic->level,ic->block);
2296 if (IS_STATIC(currFunc->etype))
2297 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2299 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2303 emitcode ("ret","");
2308 /*-----------------------------------------------------------------*/
2309 /* genRet - generate code for return statement */
2310 /*-----------------------------------------------------------------*/
2311 static void genRet (iCode *ic)
2313 int size,offset = 0 , pushed = 0;
2315 /* if we have no return value then
2316 just generate the "ret" */
2320 /* we have something to return then
2321 move the return value into place */
2322 aopOp(IC_LEFT(ic),ic,FALSE);
2323 size = AOP_SIZE(IC_LEFT(ic));
2327 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2329 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2331 emitcode("push","%s",l);
2334 l = aopGet(AOP(IC_LEFT(ic)),offset,
2336 if (strcmp(fReturn[offset],l))
2337 emitcode("mov","%s,%s",fReturn[offset++],l);
2344 if (strcmp(fReturn[pushed],"a"))
2345 emitcode("pop",fReturn[pushed]);
2347 emitcode("pop","acc");
2350 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2353 /* generate a jump to the return label
2354 if the next is not the return statement */
2355 if (!(ic->next && ic->next->op == LABEL &&
2356 IC_LABEL(ic->next) == returnLabel))
2358 emitcode("ljmp","%05d$",(returnLabel->key+100));
2362 /*-----------------------------------------------------------------*/
2363 /* genLabel - generates a label */
2364 /*-----------------------------------------------------------------*/
2365 static void genLabel (iCode *ic)
2367 /* special case never generate */
2368 if (IC_LABEL(ic) == entryLabel)
2371 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2374 /*-----------------------------------------------------------------*/
2375 /* genGoto - generates a ljmp */
2376 /*-----------------------------------------------------------------*/
2377 static void genGoto (iCode *ic)
2379 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2382 /*-----------------------------------------------------------------*/
2383 /* findLabelBackwards: walks back through the iCode chain looking */
2384 /* for the given label. Returns number of iCode instructions */
2385 /* between that label and given ic. */
2386 /* Returns zero if label not found. */
2387 /*-----------------------------------------------------------------*/
2388 static int findLabelBackwards(iCode *ic, int key)
2397 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2399 /* printf("findLabelBackwards = %d\n", count); */
2407 /*-----------------------------------------------------------------*/
2408 /* genPlusIncr :- does addition with increment if possible */
2409 /*-----------------------------------------------------------------*/
2410 static bool genPlusIncr (iCode *ic)
2412 unsigned int icount ;
2413 unsigned int size = getDataSize(IC_RESULT(ic));
2415 /* will try to generate an increment */
2416 /* if the right side is not a literal
2418 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2421 /* if the literal value of the right hand side
2422 is greater than 4 then it is not worth it */
2423 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2426 /* if increment 16 bits in register */
2427 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2434 /* If the next instruction is a goto and the goto target
2435 * is < 10 instructions previous to this, we can generate
2436 * jumps straight to that target.
2438 if (ic->next && ic->next->op == GOTO
2439 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2440 && labelRange <= 10 )
2442 emitcode(";", "tail increment optimized");
2443 tlbl = IC_LABEL(ic->next);
2448 tlbl = newiTempLabel(NULL);
2451 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2452 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2453 IS_AOP_PREG(IC_RESULT(ic)))
2454 emitcode("cjne","%s,#0x00,%05d$"
2455 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2458 emitcode("clr","a");
2459 emitcode("cjne","a,%s,%05d$"
2460 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2464 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2467 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2468 IS_AOP_PREG(IC_RESULT(ic)))
2469 emitcode("cjne","%s,#0x00,%05d$"
2470 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2473 emitcode("cjne","a,%s,%05d$"
2474 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2477 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2481 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2482 IS_AOP_PREG(IC_RESULT(ic)))
2483 emitcode("cjne","%s,#0x00,%05d$"
2484 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2487 emitcode("cjne","a,%s,%05d$"
2488 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2491 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2496 emitcode("","%05d$:",tlbl->key+100);
2501 /* if the sizes are greater than 1 then we cannot */
2502 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2503 AOP_SIZE(IC_LEFT(ic)) > 1 )
2506 /* we can if the aops of the left & result match or
2507 if they are in registers and the registers are the
2509 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2512 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2513 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2514 aopPut(AOP(IC_RESULT(ic)),"a",0);
2518 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2527 /*-----------------------------------------------------------------*/
2528 /* outBitAcc - output a bit in acc */
2529 /*-----------------------------------------------------------------*/
2530 static void outBitAcc(operand *result)
2532 symbol *tlbl = newiTempLabel(NULL);
2533 /* if the result is a bit */
2534 if (AOP_TYPE(result) == AOP_CRY){
2535 aopPut(AOP(result),"a",0);
2538 emitcode("jz","%05d$",tlbl->key+100);
2539 emitcode("mov","a,%s",one);
2540 emitcode("","%05d$:",tlbl->key+100);
2545 /*-----------------------------------------------------------------*/
2546 /* genPlusBits - generates code for addition of two bits */
2547 /*-----------------------------------------------------------------*/
2548 static void genPlusBits (iCode *ic)
2550 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2551 symbol *lbl = newiTempLabel(NULL);
2552 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2553 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2554 emitcode("cpl","c");
2555 emitcode("","%05d$:",(lbl->key+100));
2556 outBitC(IC_RESULT(ic));
2559 emitcode("clr","a");
2560 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2561 emitcode("rlc","a");
2562 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2563 emitcode("addc","a,#0x00");
2564 outAcc(IC_RESULT(ic));
2569 /* This is the original version of this code.
2571 * This is being kept around for reference,
2572 * because I am not entirely sure I got it right...
2574 static void adjustArithmeticResult(iCode *ic)
2576 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2577 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2578 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2579 aopPut(AOP(IC_RESULT(ic)),
2580 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2583 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2584 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
2585 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2586 aopPut(AOP(IC_RESULT(ic)),
2587 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2590 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2591 AOP_SIZE(IC_LEFT(ic)) < 3 &&
2592 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
2593 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2594 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2596 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2597 aopPut(AOP(IC_RESULT(ic)),buffer,2);
2601 /* This is the pure and virtuous version of this code.
2602 * I'm pretty certain it's right, but not enough to toss the old
2605 static void adjustArithmeticResult(iCode *ic)
2607 if (opIsGptr(IC_RESULT(ic)) &&
2608 opIsGptr(IC_LEFT(ic)) &&
2609 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2611 aopPut(AOP(IC_RESULT(ic)),
2612 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
2616 if (opIsGptr(IC_RESULT(ic)) &&
2617 opIsGptr(IC_RIGHT(ic)) &&
2618 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2620 aopPut(AOP(IC_RESULT(ic)),
2621 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
2625 if (opIsGptr(IC_RESULT(ic)) &&
2626 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2627 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2628 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2629 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2631 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2632 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2637 /*-----------------------------------------------------------------*/
2638 /* genPlus - generates code for addition */
2639 /*-----------------------------------------------------------------*/
2640 static void genPlus (iCode *ic)
2642 int size, offset = 0;
2644 /* special cases :- */
2646 aopOp (IC_LEFT(ic),ic,FALSE);
2647 aopOp (IC_RIGHT(ic),ic,FALSE);
2648 aopOp (IC_RESULT(ic),ic,TRUE);
2650 /* if literal, literal on the right or
2651 if left requires ACC or right is already
2653 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2654 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2655 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2656 operand *t = IC_RIGHT(ic);
2657 IC_RIGHT(ic) = IC_LEFT(ic);
2661 /* if both left & right are in bit
2663 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2664 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2669 /* if left in bit space & right literal */
2670 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2671 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2672 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2673 /* if result in bit space */
2674 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2675 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
2676 emitcode("cpl","c");
2677 outBitC(IC_RESULT(ic));
2679 size = getDataSize(IC_RESULT(ic));
2681 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2682 emitcode("addc","a,#00");
2683 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2689 /* if I can do an increment instead
2690 of add then GOOD for ME */
2691 if (genPlusIncr (ic) == TRUE)
2694 size = getDataSize(IC_RESULT(ic));
2697 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2698 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2700 emitcode("add","a,%s",
2701 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2703 emitcode("addc","a,%s",
2704 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2706 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2708 emitcode("add","a,%s",
2709 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2711 emitcode("addc","a,%s",
2712 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2714 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2717 adjustArithmeticResult(ic);
2720 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2721 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2722 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2725 /*-----------------------------------------------------------------*/
2726 /* genMinusDec :- does subtraction with deccrement if possible */
2727 /*-----------------------------------------------------------------*/
2728 static bool genMinusDec (iCode *ic)
2730 unsigned int icount ;
2731 unsigned int size = getDataSize(IC_RESULT(ic));
2733 /* will try to generate an increment */
2734 /* if the right side is not a literal
2736 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2739 /* if the literal value of the right hand side
2740 is greater than 4 then it is not worth it */
2741 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2744 /* if decrement 16 bits in register */
2745 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2752 /* If the next instruction is a goto and the goto target
2753 * is <= 10 instructions previous to this, we can generate
2754 * jumps straight to that target.
2756 if (ic->next && ic->next->op == GOTO
2757 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2758 && labelRange <= 10 )
2760 emitcode(";", "tail decrement optimized");
2761 tlbl = IC_LABEL(ic->next);
2766 tlbl = newiTempLabel(NULL);
2770 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2771 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2772 IS_AOP_PREG(IC_RESULT(ic)))
2773 emitcode("cjne","%s,#0xff,%05d$"
2774 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2777 emitcode("mov","a,#0xff");
2778 emitcode("cjne","a,%s,%05d$"
2779 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2782 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2785 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2786 IS_AOP_PREG(IC_RESULT(ic)))
2787 emitcode("cjne","%s,#0xff,%05d$"
2788 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2791 emitcode("cjne","a,%s,%05d$"
2792 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2795 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2799 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2800 IS_AOP_PREG(IC_RESULT(ic)))
2801 emitcode("cjne","%s,#0xff,%05d$"
2802 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2805 emitcode("cjne","a,%s,%05d$"
2806 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2809 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2813 emitcode("","%05d$:",tlbl->key+100);
2818 /* if the sizes are greater than 1 then we cannot */
2819 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2820 AOP_SIZE(IC_LEFT(ic)) > 1 )
2823 /* we can if the aops of the left & result match or
2824 if they are in registers and the registers are the
2826 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2829 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2837 /*-----------------------------------------------------------------*/
2838 /* addSign - complete with sign */
2839 /*-----------------------------------------------------------------*/
2840 static void addSign(operand *result, int offset, int sign)
2842 int size = (getDataSize(result) - offset);
2845 emitcode("rlc","a");
2846 emitcode("subb","a,acc");
2848 aopPut(AOP(result),"a",offset++);
2851 aopPut(AOP(result),zero,offset++);
2855 /*-----------------------------------------------------------------*/
2856 /* genMinusBits - generates code for subtraction of two bits */
2857 /*-----------------------------------------------------------------*/
2858 static void genMinusBits (iCode *ic)
2860 symbol *lbl = newiTempLabel(NULL);
2861 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2862 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2863 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2864 emitcode("cpl","c");
2865 emitcode("","%05d$:",(lbl->key+100));
2866 outBitC(IC_RESULT(ic));
2869 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2870 emitcode("subb","a,acc");
2871 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
2872 emitcode("inc","a");
2873 emitcode("","%05d$:",(lbl->key+100));
2874 aopPut(AOP(IC_RESULT(ic)),"a",0);
2875 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
2879 /*-----------------------------------------------------------------*/
2880 /* genMinus - generates code for subtraction */
2881 /*-----------------------------------------------------------------*/
2882 static void genMinus (iCode *ic)
2884 int size, offset = 0;
2885 unsigned long lit = 0L;
2887 aopOp (IC_LEFT(ic),ic,FALSE);
2888 aopOp (IC_RIGHT(ic),ic,FALSE);
2889 aopOp (IC_RESULT(ic),ic,TRUE);
2891 /* special cases :- */
2892 /* if both left & right are in bit space */
2893 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2894 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2899 /* if I can do an decrement instead
2900 of subtract then GOOD for ME */
2901 if (genMinusDec (ic) == TRUE)
2904 size = getDataSize(IC_RESULT(ic));
2906 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
2910 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2914 /* if literal, add a,#-lit, else normal subb */
2916 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2917 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2918 emitcode("subb","a,%s",
2919 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2921 /* first add without previous c */
2923 emitcode("add","a,#0x%02x",
2924 (unsigned int)(lit & 0x0FFL));
2926 emitcode("addc","a,#0x%02x",
2927 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
2929 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2932 adjustArithmeticResult(ic);
2935 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2936 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2937 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2941 /*-----------------------------------------------------------------*/
2942 /* genMultbits :- multiplication of bits */
2943 /*-----------------------------------------------------------------*/
2944 static void genMultbits (operand *left,
2948 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2949 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
2954 /*-----------------------------------------------------------------*/
2955 /* genMultOneByte : 8 bit multiplication & division */
2956 /*-----------------------------------------------------------------*/
2957 static void genMultOneByte (operand *left,
2961 link *opetype = operandType(result);
2966 /* (if two literals, the value is computed before) */
2967 /* if one literal, literal on the right */
2968 if (AOP_TYPE(left) == AOP_LIT){
2974 size = AOP_SIZE(result);
2975 /* signed or unsigned */
2976 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2977 l = aopGet(AOP(left),0,FALSE,FALSE);
2979 emitcode("mul","ab");
2980 /* if result size = 1, mul signed = mul unsigned */
2981 aopPut(AOP(result),"a",0);
2983 if (SPEC_USIGN(opetype)){
2984 aopPut(AOP(result),"b",1);
2986 /* for filling the MSBs */
2987 emitcode("clr","a");
2990 emitcode("mov","a,b");
2992 /* adjust the MSB if left or right neg */
2994 /* if one literal */
2995 if (AOP_TYPE(right) == AOP_LIT){
2996 /* AND literal negative */
2997 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
2998 /* adjust MSB (c==0 after mul) */
2999 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3003 lbl = newiTempLabel(NULL);
3004 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3005 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3006 emitcode("","%05d$:",(lbl->key+100));
3007 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3008 lbl = newiTempLabel(NULL);
3009 emitcode("jc","%05d$",(lbl->key+100));
3010 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3011 emitcode("","%05d$:",(lbl->key+100));
3014 lbl = newiTempLabel(NULL);
3015 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3016 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3017 emitcode("","%05d$:",(lbl->key+100));
3018 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3019 lbl = newiTempLabel(NULL);
3020 emitcode("jc","%05d$",(lbl->key+100));
3021 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
3022 emitcode("","%05d$:",(lbl->key+100));
3024 aopPut(AOP(result),"a",1);
3027 emitcode("rlc","a");
3028 emitcode("subb","a,acc");
3035 aopPut(AOP(result),"a",offset++);
3039 /*-----------------------------------------------------------------*/
3040 /* genMult - generates code for multiplication */
3041 /*-----------------------------------------------------------------*/
3042 static void genMult (iCode *ic)
3044 operand *left = IC_LEFT(ic);
3045 operand *right = IC_RIGHT(ic);
3046 operand *result= IC_RESULT(ic);
3048 /* assign the amsops */
3049 aopOp (left,ic,FALSE);
3050 aopOp (right,ic,FALSE);
3051 aopOp (result,ic,TRUE);
3053 /* special cases first */
3055 if (AOP_TYPE(left) == AOP_CRY &&
3056 AOP_TYPE(right)== AOP_CRY) {
3057 genMultbits(left,right,result);
3061 /* if both are of size == 1 */
3062 if (AOP_SIZE(left) == 1 &&
3063 AOP_SIZE(right) == 1 ) {
3064 genMultOneByte(left,right,result);
3068 /* should have been converted to function call */
3072 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3073 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3074 freeAsmop(result,NULL,ic,TRUE);
3077 /*-----------------------------------------------------------------*/
3078 /* genDivbits :- division of bits */
3079 /*-----------------------------------------------------------------*/
3080 static void genDivbits (operand *left,
3087 /* the result must be bit */
3088 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3089 l = aopGet(AOP(left),0,FALSE,FALSE);
3093 emitcode("div","ab");
3094 emitcode("rrc","a");
3095 aopPut(AOP(result),"c",0);
3098 /*-----------------------------------------------------------------*/
3099 /* genDivOneByte : 8 bit division */
3100 /*-----------------------------------------------------------------*/
3101 static void genDivOneByte (operand *left,
3105 link *opetype = operandType(result);
3110 size = AOP_SIZE(result) - 1;
3112 /* signed or unsigned */
3113 if (SPEC_USIGN(opetype)) {
3114 /* unsigned is easy */
3115 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3116 l = aopGet(AOP(left),0,FALSE,FALSE);
3118 emitcode("div","ab");
3119 aopPut(AOP(result),"a",0);
3121 aopPut(AOP(result),zero,offset++);
3125 /* signed is a little bit more difficult */
3127 /* save the signs of the operands */
3128 l = aopGet(AOP(left),0,FALSE,FALSE);
3130 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3131 emitcode("push","acc"); /* save it on the stack */
3133 /* now sign adjust for both left & right */
3134 l = aopGet(AOP(right),0,FALSE,FALSE);
3136 lbl = newiTempLabel(NULL);
3137 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3138 emitcode("cpl","a");
3139 emitcode("inc","a");
3140 emitcode("","%05d$:",(lbl->key+100));
3141 emitcode("mov","b,a");
3143 /* sign adjust left side */
3144 l = aopGet(AOP(left),0,FALSE,FALSE);
3147 lbl = newiTempLabel(NULL);
3148 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3149 emitcode("cpl","a");
3150 emitcode("inc","a");
3151 emitcode("","%05d$:",(lbl->key+100));
3153 /* now the division */
3154 emitcode("div","ab");
3155 /* we are interested in the lower order
3157 emitcode("mov","b,a");
3158 lbl = newiTempLabel(NULL);
3159 emitcode("pop","acc");
3160 /* if there was an over flow we don't
3161 adjust the sign of the result */
3162 emitcode("jb","ov,%05d$",(lbl->key+100));
3163 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3165 emitcode("clr","a");
3166 emitcode("subb","a,b");
3167 emitcode("mov","b,a");
3168 emitcode("","%05d$:",(lbl->key+100));
3170 /* now we are done */
3171 aopPut(AOP(result),"b",0);
3173 emitcode("mov","c,b.7");
3174 emitcode("subb","a,acc");
3177 aopPut(AOP(result),"a",offset++);
3181 /*-----------------------------------------------------------------*/
3182 /* genDiv - generates code for division */
3183 /*-----------------------------------------------------------------*/
3184 static void genDiv (iCode *ic)
3186 operand *left = IC_LEFT(ic);
3187 operand *right = IC_RIGHT(ic);
3188 operand *result= IC_RESULT(ic);
3190 /* assign the amsops */
3191 aopOp (left,ic,FALSE);
3192 aopOp (right,ic,FALSE);
3193 aopOp (result,ic,TRUE);
3195 /* special cases first */
3197 if (AOP_TYPE(left) == AOP_CRY &&
3198 AOP_TYPE(right)== AOP_CRY) {
3199 genDivbits(left,right,result);
3203 /* if both are of size == 1 */
3204 if (AOP_SIZE(left) == 1 &&
3205 AOP_SIZE(right) == 1 ) {
3206 genDivOneByte(left,right,result);
3210 /* should have been converted to function call */
3213 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3214 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3215 freeAsmop(result,NULL,ic,TRUE);
3218 /*-----------------------------------------------------------------*/
3219 /* genModbits :- modulus of bits */
3220 /*-----------------------------------------------------------------*/
3221 static void genModbits (operand *left,
3228 /* the result must be bit */
3229 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3230 l = aopGet(AOP(left),0,FALSE,FALSE);
3234 emitcode("div","ab");
3235 emitcode("mov","a,b");
3236 emitcode("rrc","a");
3237 aopPut(AOP(result),"c",0);
3240 /*-----------------------------------------------------------------*/
3241 /* genModOneByte : 8 bit modulus */
3242 /*-----------------------------------------------------------------*/
3243 static void genModOneByte (operand *left,
3247 link *opetype = operandType(result);
3251 /* signed or unsigned */
3252 if (SPEC_USIGN(opetype)) {
3253 /* unsigned is easy */
3254 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3255 l = aopGet(AOP(left),0,FALSE,FALSE);
3257 emitcode("div","ab");
3258 aopPut(AOP(result),"b",0);
3262 /* signed is a little bit more difficult */
3264 /* save the signs of the operands */
3265 l = aopGet(AOP(left),0,FALSE,FALSE);
3268 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3269 emitcode("push","acc"); /* save it on the stack */
3271 /* now sign adjust for both left & right */
3272 l = aopGet(AOP(right),0,FALSE,FALSE);
3275 lbl = newiTempLabel(NULL);
3276 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3277 emitcode("cpl","a");
3278 emitcode("inc","a");
3279 emitcode("","%05d$:",(lbl->key+100));
3280 emitcode("mov","b,a");
3282 /* sign adjust left side */
3283 l = aopGet(AOP(left),0,FALSE,FALSE);
3286 lbl = newiTempLabel(NULL);
3287 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3288 emitcode("cpl","a");
3289 emitcode("inc","a");
3290 emitcode("","%05d$:",(lbl->key+100));
3292 /* now the multiplication */
3293 emitcode("div","ab");
3294 /* we are interested in the lower order
3296 lbl = newiTempLabel(NULL);
3297 emitcode("pop","acc");
3298 /* if there was an over flow we don't
3299 adjust the sign of the result */
3300 emitcode("jb","ov,%05d$",(lbl->key+100));
3301 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3303 emitcode("clr","a");
3304 emitcode("subb","a,b");
3305 emitcode("mov","b,a");
3306 emitcode("","%05d$:",(lbl->key+100));
3308 /* now we are done */
3309 aopPut(AOP(result),"b",0);
3313 /*-----------------------------------------------------------------*/
3314 /* genMod - generates code for division */
3315 /*-----------------------------------------------------------------*/
3316 static void genMod (iCode *ic)
3318 operand *left = IC_LEFT(ic);
3319 operand *right = IC_RIGHT(ic);
3320 operand *result= IC_RESULT(ic);
3322 /* assign the amsops */
3323 aopOp (left,ic,FALSE);
3324 aopOp (right,ic,FALSE);
3325 aopOp (result,ic,TRUE);
3327 /* special cases first */
3329 if (AOP_TYPE(left) == AOP_CRY &&
3330 AOP_TYPE(right)== AOP_CRY) {
3331 genModbits(left,right,result);
3335 /* if both are of size == 1 */
3336 if (AOP_SIZE(left) == 1 &&
3337 AOP_SIZE(right) == 1 ) {
3338 genModOneByte(left,right,result);
3342 /* should have been converted to function call */
3346 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3347 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3348 freeAsmop(result,NULL,ic,TRUE);
3351 /*-----------------------------------------------------------------*/
3352 /* genIfxJump :- will create a jump depending on the ifx */
3353 /*-----------------------------------------------------------------*/
3354 static void genIfxJump (iCode *ic, char *jval)
3357 symbol *tlbl = newiTempLabel(NULL);
3360 /* if true label then we jump if condition
3362 if ( IC_TRUE(ic) ) {
3364 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3365 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3368 /* false label is present */
3369 jlbl = IC_FALSE(ic) ;
3370 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3371 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3373 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3374 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3376 emitcode(inst,"%05d$",tlbl->key+100);
3377 emitcode("ljmp","%05d$",jlbl->key+100);
3378 emitcode("","%05d$:",tlbl->key+100);
3380 /* mark the icode as generated */
3384 /*-----------------------------------------------------------------*/
3385 /* genCmp :- greater or less than comparison */
3386 /*-----------------------------------------------------------------*/
3387 static void genCmp (operand *left,operand *right,
3388 operand *result, iCode *ifx, int sign)
3390 int size, offset = 0 ;
3391 unsigned long lit = 0L;
3393 /* if left & right are bit variables */
3394 if (AOP_TYPE(left) == AOP_CRY &&
3395 AOP_TYPE(right) == AOP_CRY ) {
3396 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3397 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3399 /* subtract right from left if at the
3400 end the carry flag is set then we know that
3401 left is greater than right */
3402 size = max(AOP_SIZE(left),AOP_SIZE(right));
3404 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3405 if((size == 1) && !sign &&
3406 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3407 symbol *lbl = newiTempLabel(NULL);
3408 emitcode("cjne","%s,%s,%05d$",
3409 aopGet(AOP(left),offset,FALSE,FALSE),
3410 aopGet(AOP(right),offset,FALSE,FALSE),
3412 emitcode("","%05d$:",lbl->key+100);
3414 if(AOP_TYPE(right) == AOP_LIT){
3415 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3416 /* optimize if(x < 0) or if(x >= 0) */
3422 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE));
3423 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3424 genIfxJump (ifx,"acc.7");
3428 emitcode("rlc","a");
3435 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3436 if (sign && size == 0) {
3437 emitcode("xrl","a,#0x80");
3438 if (AOP_TYPE(right) == AOP_LIT){
3439 unsigned long lit = (unsigned long)
3440 floatFromVal(AOP(right)->aopu.aop_lit);
3441 emitcode("subb","a,#0x%02x",
3442 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3444 emitcode("mov","b,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3445 emitcode("xrl","b,#0x80");
3446 emitcode("subb","a,b");
3449 emitcode("subb","a,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3455 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3458 /* if the result is used in the next
3459 ifx conditional branch then generate
3460 code a little differently */
3462 genIfxJump (ifx,"c");
3465 /* leave the result in acc */
3469 /*-----------------------------------------------------------------*/
3470 /* genCmpGt :- greater than comparison */
3471 /*-----------------------------------------------------------------*/
3472 static void genCmpGt (iCode *ic, iCode *ifx)
3474 operand *left, *right, *result;
3475 link *letype , *retype;
3479 right= IC_RIGHT(ic);
3480 result = IC_RESULT(ic);
3482 letype = getSpec(operandType(left));
3483 retype =getSpec(operandType(right));
3484 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3485 /* assign the amsops */
3486 aopOp (left,ic,FALSE);
3487 aopOp (right,ic,FALSE);
3488 aopOp (result,ic,TRUE);
3490 genCmp(right, left, result, ifx, sign);
3492 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3493 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3494 freeAsmop(result,NULL,ic,TRUE);
3497 /*-----------------------------------------------------------------*/
3498 /* genCmpLt - less than comparisons */
3499 /*-----------------------------------------------------------------*/
3500 static void genCmpLt (iCode *ic, iCode *ifx)
3502 operand *left, *right, *result;
3503 link *letype , *retype;
3507 right= IC_RIGHT(ic);
3508 result = IC_RESULT(ic);
3510 letype = getSpec(operandType(left));
3511 retype =getSpec(operandType(right));
3512 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3514 /* assign the amsops */
3515 aopOp (left,ic,FALSE);
3516 aopOp (right,ic,FALSE);
3517 aopOp (result,ic,TRUE);
3519 genCmp(left, right, result, ifx, sign);
3521 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3522 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3523 freeAsmop(result,NULL,ic,TRUE);
3526 /*-----------------------------------------------------------------*/
3527 /* gencjneshort - compare and jump if not equal */
3528 /*-----------------------------------------------------------------*/
3529 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3531 int size = max(AOP_SIZE(left),AOP_SIZE(right));
3533 unsigned long lit = 0L;
3535 /* if the left side is a literal or
3536 if the right is in a pointer register and left
3538 if ((AOP_TYPE(left) == AOP_LIT) ||
3539 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3544 if(AOP_TYPE(right) == AOP_LIT)
3545 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3547 /* if the right side is a literal then anything goes */
3548 if (AOP_TYPE(right) == AOP_LIT &&
3549 AOP_TYPE(left) != AOP_DIR ) {
3551 emitcode("cjne","%s,%s,%05d$",
3552 aopGet(AOP(left),offset,FALSE,FALSE),
3553 aopGet(AOP(right),offset,FALSE,FALSE),
3559 /* if the right side is in a register or in direct space or
3560 if the left is a pointer register & right is not */
3561 else if (AOP_TYPE(right) == AOP_REG ||
3562 AOP_TYPE(right) == AOP_DIR ||
3563 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3564 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3566 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3567 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3568 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
3569 emitcode("jnz","%05d$",lbl->key+100);
3571 emitcode("cjne","a,%s,%05d$",
3572 aopGet(AOP(right),offset,FALSE,TRUE),
3577 /* right is a pointer reg need both a & b */
3579 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
3581 emitcode("mov","b,%s",l);
3582 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3583 emitcode("cjne","a,b,%05d$",lbl->key+100);
3589 /*-----------------------------------------------------------------*/
3590 /* gencjne - compare and jump if not equal */
3591 /*-----------------------------------------------------------------*/
3592 static void gencjne(operand *left, operand *right, symbol *lbl)
3594 symbol *tlbl = newiTempLabel(NULL);
3596 gencjneshort(left, right, lbl);
3598 emitcode("mov","a,%s",one);
3599 emitcode("sjmp","%05d$",tlbl->key+100);
3600 emitcode("","%05d$:",lbl->key+100);
3601 emitcode("clr","a");
3602 emitcode("","%05d$:",tlbl->key+100);
3605 /*-----------------------------------------------------------------*/
3606 /* genCmpEq - generates code for equal to */
3607 /*-----------------------------------------------------------------*/
3608 static void genCmpEq (iCode *ic, iCode *ifx)
3610 operand *left, *right, *result;
3612 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3613 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3614 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3616 /* if literal, literal on the right or
3617 if the right is in a pointer register and left
3619 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
3620 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3621 operand *t = IC_RIGHT(ic);
3622 IC_RIGHT(ic) = IC_LEFT(ic);
3626 if(ifx && !AOP_SIZE(result)){
3628 /* if they are both bit variables */
3629 if (AOP_TYPE(left) == AOP_CRY &&
3630 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3631 if(AOP_TYPE(right) == AOP_LIT){
3632 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3634 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3635 emitcode("cpl","c");
3636 } else if(lit == 1L) {
3637 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3639 emitcode("clr","c");
3641 /* AOP_TYPE(right) == AOP_CRY */
3643 symbol *lbl = newiTempLabel(NULL);
3644 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3645 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3646 emitcode("cpl","c");
3647 emitcode("","%05d$:",(lbl->key+100));
3649 /* if true label then we jump if condition
3651 tlbl = newiTempLabel(NULL);
3652 if ( IC_TRUE(ifx) ) {
3653 emitcode("jnc","%05d$",tlbl->key+100);
3654 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3656 emitcode("jc","%05d$",tlbl->key+100);
3657 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3659 emitcode("","%05d$:",tlbl->key+100);
3661 tlbl = newiTempLabel(NULL);
3662 gencjneshort(left, right, tlbl);
3663 if ( IC_TRUE(ifx) ) {
3664 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3665 emitcode("","%05d$:",tlbl->key+100);
3667 symbol *lbl = newiTempLabel(NULL);
3668 emitcode("sjmp","%05d$",lbl->key+100);
3669 emitcode("","%05d$:",tlbl->key+100);
3670 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3671 emitcode("","%05d$:",lbl->key+100);
3674 /* mark the icode as generated */
3679 /* if they are both bit variables */
3680 if (AOP_TYPE(left) == AOP_CRY &&
3681 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3682 if(AOP_TYPE(right) == AOP_LIT){
3683 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3685 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3686 emitcode("cpl","c");
3687 } else if(lit == 1L) {
3688 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3690 emitcode("clr","c");
3692 /* AOP_TYPE(right) == AOP_CRY */
3694 symbol *lbl = newiTempLabel(NULL);
3695 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3696 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3697 emitcode("cpl","c");
3698 emitcode("","%05d$:",(lbl->key+100));
3701 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
3706 genIfxJump (ifx,"c");
3709 /* if the result is used in an arithmetic operation
3710 then put the result in place */
3713 gencjne(left,right,newiTempLabel(NULL));
3714 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3715 aopPut(AOP(result),"a",0);
3719 genIfxJump (ifx,"a");
3722 /* if the result is used in an arithmetic operation
3723 then put the result in place */
3724 if (AOP_TYPE(result) != AOP_CRY)
3726 /* leave the result in acc */
3730 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3731 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3732 freeAsmop(result,NULL,ic,TRUE);
3735 /*-----------------------------------------------------------------*/
3736 /* ifxForOp - returns the icode containing the ifx for operand */
3737 /*-----------------------------------------------------------------*/
3738 static iCode *ifxForOp ( operand *op, iCode *ic )
3740 /* if true symbol then needs to be assigned */
3741 if (IS_TRUE_SYMOP(op))
3744 /* if this has register type condition and
3745 the next instruction is ifx with the same operand
3746 and live to of the operand is upto the ifx only then */
3748 ic->next->op == IFX &&
3749 IC_COND(ic->next)->key == op->key &&
3750 OP_SYMBOL(op)->liveTo <= ic->next->seq )
3755 /*-----------------------------------------------------------------*/
3756 /* genAndOp - for && operation */
3757 /*-----------------------------------------------------------------*/
3758 static void genAndOp (iCode *ic)
3760 operand *left,*right, *result;
3763 /* note here that && operations that are in an
3764 if statement are taken away by backPatchLabels
3765 only those used in arthmetic operations remain */
3766 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3767 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3768 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3770 /* if both are bit variables */
3771 if (AOP_TYPE(left) == AOP_CRY &&
3772 AOP_TYPE(right) == AOP_CRY ) {
3773 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3774 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3777 tlbl = newiTempLabel(NULL);
3779 emitcode("jz","%05d$",tlbl->key+100);
3781 emitcode("","%05d$:",tlbl->key+100);
3785 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3786 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3787 freeAsmop(result,NULL,ic,TRUE);
3791 /*-----------------------------------------------------------------*/
3792 /* genOrOp - for || operation */
3793 /*-----------------------------------------------------------------*/
3794 static void genOrOp (iCode *ic)
3796 operand *left,*right, *result;
3799 /* note here that || operations that are in an
3800 if statement are taken away by backPatchLabels
3801 only those used in arthmetic operations remain */
3802 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3803 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3804 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3806 /* if both are bit variables */
3807 if (AOP_TYPE(left) == AOP_CRY &&
3808 AOP_TYPE(right) == AOP_CRY ) {
3809 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3810 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
3813 tlbl = newiTempLabel(NULL);
3815 emitcode("jnz","%05d$",tlbl->key+100);
3817 emitcode("","%05d$:",tlbl->key+100);
3821 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3822 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3823 freeAsmop(result,NULL,ic,TRUE);
3826 /*-----------------------------------------------------------------*/
3827 /* isLiteralBit - test if lit == 2^n */
3828 /*-----------------------------------------------------------------*/
3829 static int isLiteralBit(unsigned long lit)
3831 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
3832 0x100L,0x200L,0x400L,0x800L,
3833 0x1000L,0x2000L,0x4000L,0x8000L,
3834 0x10000L,0x20000L,0x40000L,0x80000L,
3835 0x100000L,0x200000L,0x400000L,0x800000L,
3836 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
3837 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
3840 for(idx = 0; idx < 32; idx++)
3846 /*-----------------------------------------------------------------*/
3847 /* continueIfTrue - */
3848 /*-----------------------------------------------------------------*/
3849 static void continueIfTrue (iCode *ic)
3852 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3856 /*-----------------------------------------------------------------*/
3858 /*-----------------------------------------------------------------*/
3859 static void jumpIfTrue (iCode *ic)
3862 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3866 /*-----------------------------------------------------------------*/
3867 /* jmpTrueOrFalse - */
3868 /*-----------------------------------------------------------------*/
3869 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
3871 // ugly but optimized by peephole
3873 symbol *nlbl = newiTempLabel(NULL);
3874 emitcode("sjmp","%05d$",nlbl->key+100);
3875 emitcode("","%05d$:",tlbl->key+100);
3876 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3877 emitcode("","%05d$:",nlbl->key+100);
3880 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3881 emitcode("","%05d$:",tlbl->key+100);
3886 /*-----------------------------------------------------------------*/
3887 /* genAnd - code for and */
3888 /*-----------------------------------------------------------------*/
3889 static void genAnd (iCode *ic, iCode *ifx)
3891 operand *left, *right, *result;
3893 unsigned long lit = 0L;
3897 aopOp((left = IC_LEFT(ic)),ic,FALSE);
3898 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3899 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3902 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3904 AOP_TYPE(left), AOP_TYPE(right));
3905 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3907 AOP_SIZE(left), AOP_SIZE(right));
3910 /* if left is a literal & right is not then exchange them */
3911 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3912 AOP_NEEDSACC(left)) {
3913 operand *tmp = right ;
3918 /* if result = right then exchange them */
3919 if(sameRegs(AOP(result),AOP(right))){
3920 operand *tmp = right ;
3925 /* if right is bit then exchange them */
3926 if (AOP_TYPE(right) == AOP_CRY &&
3927 AOP_TYPE(left) != AOP_CRY){
3928 operand *tmp = right ;
3932 if(AOP_TYPE(right) == AOP_LIT)
3933 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3935 size = AOP_SIZE(result);
3938 // result = bit & yy;
3939 if (AOP_TYPE(left) == AOP_CRY){
3940 // c = bit & literal;
3941 if(AOP_TYPE(right) == AOP_LIT){
3943 if(size && sameRegs(AOP(result),AOP(left)))
3946 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3949 if(size && (AOP_TYPE(result) == AOP_CRY)){
3950 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
3953 if((AOP_TYPE(result) == AOP_CRY) && ifx){
3957 emitcode("clr","c");
3960 if (AOP_TYPE(right) == AOP_CRY){
3962 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3963 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3966 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
3968 emitcode("rrc","a");
3969 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3977 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
3978 genIfxJump(ifx, "c");
3982 // if(val & 0xZZ) - size = 0, ifx != FALSE -
3983 // bit = val & 0xZZ - size = 1, ifx = FALSE -
3984 if((AOP_TYPE(right) == AOP_LIT) &&
3985 (AOP_TYPE(result) == AOP_CRY) &&
3986 (AOP_TYPE(left) != AOP_CRY)){
3987 int posbit = isLiteralBit(lit);
3991 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
3994 emitcode("mov","c,acc.%d",posbit&0x07);
3998 sprintf(buffer,"acc.%d",posbit&0x07);
3999 genIfxJump(ifx, buffer);
4004 symbol *tlbl = newiTempLabel(NULL);
4005 int sizel = AOP_SIZE(left);
4007 emitcode("setb","c");
4009 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4010 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
4012 if((posbit = isLiteralBit(bytelit)) != 0)
4013 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
4015 if(bytelit != 0x0FFL)
4016 emitcode("anl","a,%s",
4017 aopGet(AOP(right),offset,FALSE,TRUE));
4018 emitcode("jnz","%05d$",tlbl->key+100);
4023 // bit = left & literal
4025 emitcode("clr","c");
4026 emitcode("","%05d$:",tlbl->key+100);
4028 // if(left & literal)
4031 jmpTrueOrFalse(ifx, tlbl);
4039 /* if left is same as result */
4040 if(sameRegs(AOP(result),AOP(left))){
4041 for(;size--; offset++) {
4042 if(AOP_TYPE(right) == AOP_LIT){
4043 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4047 aopPut(AOP(result),zero,offset);
4049 if (IS_AOP_PREG(result)) {
4050 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4051 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4052 aopPut(AOP(result),"a",offset);
4054 emitcode("anl","%s,%s",
4055 aopGet(AOP(left),offset,FALSE,TRUE),
4056 aopGet(AOP(right),offset,FALSE,FALSE));
4058 if (AOP_TYPE(left) == AOP_ACC)
4059 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4061 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4062 if (IS_AOP_PREG(result)) {
4063 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4064 aopPut(AOP(result),"a",offset);
4067 emitcode("anl","%s,a",
4068 aopGet(AOP(left),offset,FALSE,TRUE));
4073 // left & result in different registers
4074 if(AOP_TYPE(result) == AOP_CRY){
4076 // if(size), result in bit
4077 // if(!size && ifx), conditional oper: if(left & right)
4078 symbol *tlbl = newiTempLabel(NULL);
4079 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4081 emitcode("setb","c");
4083 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4084 emitcode("anl","a,%s",
4085 aopGet(AOP(left),offset,FALSE,FALSE));
4086 emitcode("jnz","%05d$",tlbl->key+100);
4091 emitcode("","%05d$:",tlbl->key+100);
4094 jmpTrueOrFalse(ifx, tlbl);
4096 for(;(size--);offset++) {
4098 // result = left & right
4099 if(AOP_TYPE(right) == AOP_LIT){
4100 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
4102 aopGet(AOP(left),offset,FALSE,FALSE),
4105 } else if(bytelit == 0){
4106 aopPut(AOP(result),zero,offset);
4110 // faster than result <- left, anl result,right
4111 // and better if result is SFR
4112 if (AOP_TYPE(left) == AOP_ACC)
4113 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4115 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4116 emitcode("anl","a,%s",
4117 aopGet(AOP(left),offset,FALSE,FALSE));
4119 aopPut(AOP(result),"a",offset);
4125 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4126 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4127 freeAsmop(result,NULL,ic,TRUE);
4130 /*-----------------------------------------------------------------*/
4131 /* genOr - code for or */
4132 /*-----------------------------------------------------------------*/
4133 static void genOr (iCode *ic, iCode *ifx)
4135 operand *left, *right, *result;
4137 unsigned long lit = 0L;
4139 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4140 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4141 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4144 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4146 AOP_TYPE(left), AOP_TYPE(right));
4147 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4149 AOP_SIZE(left), AOP_SIZE(right));
4152 /* if left is a literal & right is not then exchange them */
4153 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4154 AOP_NEEDSACC(left)) {
4155 operand *tmp = right ;
4160 /* if result = right then exchange them */
4161 if(sameRegs(AOP(result),AOP(right))){
4162 operand *tmp = right ;
4167 /* if right is bit then exchange them */
4168 if (AOP_TYPE(right) == AOP_CRY &&
4169 AOP_TYPE(left) != AOP_CRY){
4170 operand *tmp = right ;
4174 if(AOP_TYPE(right) == AOP_LIT)
4175 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4177 size = AOP_SIZE(result);
4181 if (AOP_TYPE(left) == AOP_CRY){
4182 if(AOP_TYPE(right) == AOP_LIT){
4183 // c = bit & literal;
4185 // lit != 0 => result = 1
4186 if(AOP_TYPE(result) == AOP_CRY){
4188 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4190 continueIfTrue(ifx);
4193 emitcode("setb","c");
4195 // lit == 0 => result = left
4196 if(size && sameRegs(AOP(result),AOP(left)))
4198 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4201 if (AOP_TYPE(right) == AOP_CRY){
4203 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4204 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4208 symbol *tlbl = newiTempLabel(NULL);
4209 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4210 emitcode("setb","c");
4211 emitcode("jb","%s,%05d$",
4212 AOP(left)->aopu.aop_dir,tlbl->key+100);
4214 emitcode("jnz","%05d$",tlbl->key+100);
4215 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4216 jmpTrueOrFalse(ifx, tlbl);
4220 emitcode("","%05d$:",tlbl->key+100);
4229 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4230 genIfxJump(ifx, "c");
4234 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4235 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4236 if((AOP_TYPE(right) == AOP_LIT) &&
4237 (AOP_TYPE(result) == AOP_CRY) &&
4238 (AOP_TYPE(left) != AOP_CRY)){
4242 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4244 continueIfTrue(ifx);
4247 // lit = 0, result = boolean(left)
4249 emitcode("setb","c");
4252 symbol *tlbl = newiTempLabel(NULL);
4253 emitcode("jnz","%05d$",tlbl->key+100);
4255 emitcode("","%05d$:",tlbl->key+100);
4257 genIfxJump (ifx,"a");
4265 /* if left is same as result */
4266 if(sameRegs(AOP(result),AOP(left))){
4267 for(;size--; offset++) {
4268 if(AOP_TYPE(right) == AOP_LIT){
4269 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4272 if (IS_AOP_PREG(left)) {
4273 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4274 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4275 aopPut(AOP(result),"a",offset);
4277 emitcode("orl","%s,%s",
4278 aopGet(AOP(left),offset,FALSE,TRUE),
4279 aopGet(AOP(right),offset,FALSE,FALSE));
4281 if (AOP_TYPE(left) == AOP_ACC)
4282 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4284 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4285 if (IS_AOP_PREG(left)) {
4286 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4287 aopPut(AOP(result),"a",offset);
4289 emitcode("orl","%s,a",
4290 aopGet(AOP(left),offset,FALSE,TRUE));
4295 // left & result in different registers
4296 if(AOP_TYPE(result) == AOP_CRY){
4298 // if(size), result in bit
4299 // if(!size && ifx), conditional oper: if(left | right)
4300 symbol *tlbl = newiTempLabel(NULL);
4301 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4303 emitcode("setb","c");
4305 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4306 emitcode("orl","a,%s",
4307 aopGet(AOP(left),offset,FALSE,FALSE));
4308 emitcode("jnz","%05d$",tlbl->key+100);
4313 emitcode("","%05d$:",tlbl->key+100);
4316 jmpTrueOrFalse(ifx, tlbl);
4317 } else for(;(size--);offset++){
4319 // result = left & right
4320 if(AOP_TYPE(right) == AOP_LIT){
4321 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4323 aopGet(AOP(left),offset,FALSE,FALSE),
4328 // faster than result <- left, anl result,right
4329 // and better if result is SFR
4330 if (AOP_TYPE(left) == AOP_ACC)
4331 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4333 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4334 emitcode("orl","a,%s",
4335 aopGet(AOP(left),offset,FALSE,FALSE));
4337 aopPut(AOP(result),"a",offset);
4342 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4343 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4344 freeAsmop(result,NULL,ic,TRUE);
4347 /*-----------------------------------------------------------------*/
4348 /* genXor - code for xclusive or */
4349 /*-----------------------------------------------------------------*/
4350 static void genXor (iCode *ic, iCode *ifx)
4352 operand *left, *right, *result;
4354 unsigned long lit = 0L;
4356 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4357 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4358 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4361 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4363 AOP_TYPE(left), AOP_TYPE(right));
4364 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4366 AOP_SIZE(left), AOP_SIZE(right));
4369 /* if left is a literal & right is not ||
4370 if left needs acc & right does not */
4371 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4372 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4373 operand *tmp = right ;
4378 /* if result = right then exchange them */
4379 if(sameRegs(AOP(result),AOP(right))){
4380 operand *tmp = right ;
4385 /* if right is bit then exchange them */
4386 if (AOP_TYPE(right) == AOP_CRY &&
4387 AOP_TYPE(left) != AOP_CRY){
4388 operand *tmp = right ;
4392 if(AOP_TYPE(right) == AOP_LIT)
4393 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4395 size = AOP_SIZE(result);
4399 if (AOP_TYPE(left) == AOP_CRY){
4400 if(AOP_TYPE(right) == AOP_LIT){
4401 // c = bit & literal;
4403 // lit>>1 != 0 => result = 1
4404 if(AOP_TYPE(result) == AOP_CRY){
4406 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4408 continueIfTrue(ifx);
4411 emitcode("setb","c");
4415 // lit == 0, result = left
4416 if(size && sameRegs(AOP(result),AOP(left)))
4418 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4420 // lit == 1, result = not(left)
4421 if(size && sameRegs(AOP(result),AOP(left))){
4422 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4425 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4426 emitcode("cpl","c");
4433 symbol *tlbl = newiTempLabel(NULL);
4434 if (AOP_TYPE(right) == AOP_CRY){
4436 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4439 int sizer = AOP_SIZE(right);
4441 // if val>>1 != 0, result = 1
4442 emitcode("setb","c");
4444 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
4446 // test the msb of the lsb
4447 emitcode("anl","a,#0xfe");
4448 emitcode("jnz","%05d$",tlbl->key+100);
4452 emitcode("rrc","a");
4454 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4455 emitcode("cpl","c");
4456 emitcode("","%05d$:",(tlbl->key+100));
4463 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4464 genIfxJump(ifx, "c");
4468 if(sameRegs(AOP(result),AOP(left))){
4469 /* if left is same as result */
4470 for(;size--; offset++) {
4471 if(AOP_TYPE(right) == AOP_LIT){
4472 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4475 if (IS_AOP_PREG(left)) {
4476 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4477 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4478 aopPut(AOP(result),"a",offset);
4480 emitcode("xrl","%s,%s",
4481 aopGet(AOP(left),offset,FALSE,TRUE),
4482 aopGet(AOP(right),offset,FALSE,FALSE));
4484 if (AOP_TYPE(left) == AOP_ACC)
4485 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4487 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4488 if (IS_AOP_PREG(left)) {
4489 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4490 aopPut(AOP(result),"a",offset);
4492 emitcode("xrl","%s,a",
4493 aopGet(AOP(left),offset,FALSE,TRUE));
4498 // left & result in different registers
4499 if(AOP_TYPE(result) == AOP_CRY){
4501 // if(size), result in bit
4502 // if(!size && ifx), conditional oper: if(left ^ right)
4503 symbol *tlbl = newiTempLabel(NULL);
4504 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4506 emitcode("setb","c");
4508 if((AOP_TYPE(right) == AOP_LIT) &&
4509 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4510 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4512 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4513 emitcode("xrl","a,%s",
4514 aopGet(AOP(left),offset,FALSE,FALSE));
4516 emitcode("jnz","%05d$",tlbl->key+100);
4521 emitcode("","%05d$:",tlbl->key+100);
4524 jmpTrueOrFalse(ifx, tlbl);
4525 } else for(;(size--);offset++){
4527 // result = left & right
4528 if(AOP_TYPE(right) == AOP_LIT){
4529 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4531 aopGet(AOP(left),offset,FALSE,FALSE),
4536 // faster than result <- left, anl result,right
4537 // and better if result is SFR
4538 if (AOP_TYPE(left) == AOP_ACC)
4539 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4541 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4542 emitcode("xrl","a,%s",
4543 aopGet(AOP(left),offset,FALSE,TRUE));
4545 aopPut(AOP(result),"a",offset);
4550 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4551 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4552 freeAsmop(result,NULL,ic,TRUE);
4555 /*-----------------------------------------------------------------*/
4556 /* genInline - write the inline code out */
4557 /*-----------------------------------------------------------------*/
4558 static void genInline (iCode *ic)
4560 char buffer[MAX_INLINEASM];
4564 _G.inLine += (!options.asmpeep);
4565 strcpy(buffer,IC_INLINE(ic));
4567 /* emit each line as a code */
4586 /* emitcode("",buffer); */
4587 _G.inLine -= (!options.asmpeep);
4590 /*-----------------------------------------------------------------*/
4591 /* genRRC - rotate right with carry */
4592 /*-----------------------------------------------------------------*/
4593 static void genRRC (iCode *ic)
4595 operand *left , *result ;
4596 int size, offset = 0;
4599 /* rotate right with carry */
4601 result=IC_RESULT(ic);
4602 aopOp (left,ic,FALSE);
4603 aopOp (result,ic,FALSE);
4605 /* move it to the result */
4606 size = AOP_SIZE(result);
4610 l = aopGet(AOP(left),offset,FALSE,FALSE);
4612 emitcode("rrc","a");
4613 if (AOP_SIZE(result) > 1)
4614 aopPut(AOP(result),"a",offset--);
4616 /* now we need to put the carry into the
4617 highest order byte of the result */
4618 if (AOP_SIZE(result) > 1) {
4619 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
4622 emitcode("mov","acc.7,c");
4623 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
4624 freeAsmop(left,NULL,ic,TRUE);
4625 freeAsmop(result,NULL,ic,TRUE);
4628 /*-----------------------------------------------------------------*/
4629 /* genRLC - generate code for rotate left with carry */
4630 /*-----------------------------------------------------------------*/
4631 static void genRLC (iCode *ic)
4633 operand *left , *result ;
4634 int size, offset = 0;
4637 /* rotate right with carry */
4639 result=IC_RESULT(ic);
4640 aopOp (left,ic,FALSE);
4641 aopOp (result,ic,FALSE);
4643 /* move it to the result */
4644 size = AOP_SIZE(result);
4647 l = aopGet(AOP(left),offset,FALSE,FALSE);
4649 emitcode("add","a,acc");
4650 if (AOP_SIZE(result) > 1)
4651 aopPut(AOP(result),"a",offset++);
4653 l = aopGet(AOP(left),offset,FALSE,FALSE);
4655 emitcode("rlc","a");
4656 if (AOP_SIZE(result) > 1)
4657 aopPut(AOP(result),"a",offset++);
4660 /* now we need to put the carry into the
4661 highest order byte of the result */
4662 if (AOP_SIZE(result) > 1) {
4663 l = aopGet(AOP(result),0,FALSE,FALSE);
4666 emitcode("mov","acc.0,c");
4667 aopPut(AOP(result),"a",0);
4668 freeAsmop(left,NULL,ic,TRUE);
4669 freeAsmop(result,NULL,ic,TRUE);
4672 /*-----------------------------------------------------------------*/
4673 /* genGetHbit - generates code get highest order bit */
4674 /*-----------------------------------------------------------------*/
4675 static void genGetHbit (iCode *ic)
4677 operand *left, *result;
4679 result=IC_RESULT(ic);
4680 aopOp (left,ic,FALSE);
4681 aopOp (result,ic,FALSE);
4683 /* get the highest order byte into a */
4684 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
4685 if(AOP_TYPE(result) == AOP_CRY){
4686 emitcode("rlc","a");
4691 emitcode("anl","a,#0x01");
4696 freeAsmop(left,NULL,ic,TRUE);
4697 freeAsmop(result,NULL,ic,TRUE);
4700 /*-----------------------------------------------------------------*/
4701 /* AccRol - rotate left accumulator by known count */
4702 /*-----------------------------------------------------------------*/
4703 static void AccRol (int shCount)
4705 shCount &= 0x0007; // shCount : 0..7
4717 emitcode("swap","a");
4721 emitcode("swap","a");
4724 emitcode("swap","a");
4737 /*-----------------------------------------------------------------*/
4738 /* AccLsh - left shift accumulator by known count */
4739 /*-----------------------------------------------------------------*/
4740 static void AccLsh (int shCount)
4744 emitcode("add","a,acc");
4747 emitcode("add","a,acc");
4748 emitcode("add","a,acc");
4750 /* rotate left accumulator */
4752 /* and kill the lower order bits */
4753 emitcode("anl","a,#0x%02x", SLMask[shCount]);
4758 /*-----------------------------------------------------------------*/
4759 /* AccRsh - right shift accumulator by known count */
4760 /*-----------------------------------------------------------------*/
4761 static void AccRsh (int shCount)
4766 emitcode("rrc","a");
4768 /* rotate right accumulator */
4769 AccRol(8 - shCount);
4770 /* and kill the higher order bits */
4771 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4776 /*-----------------------------------------------------------------*/
4777 /* AccSRsh - signed right shift accumulator by known count */
4778 /*-----------------------------------------------------------------*/
4779 static void AccSRsh (int shCount)
4784 emitcode("mov","c,acc.7");
4785 emitcode("rrc","a");
4786 } else if(shCount == 2){
4787 emitcode("mov","c,acc.7");
4788 emitcode("rrc","a");
4789 emitcode("mov","c,acc.7");
4790 emitcode("rrc","a");
4792 tlbl = newiTempLabel(NULL);
4793 /* rotate right accumulator */
4794 AccRol(8 - shCount);
4795 /* and kill the higher order bits */
4796 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4797 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4798 emitcode("orl","a,#0x%02x",
4799 (unsigned char)~SRMask[shCount]);
4800 emitcode("","%05d$:",tlbl->key+100);
4805 /*-----------------------------------------------------------------*/
4806 /* shiftR1Left2Result - shift right one byte from left to result */
4807 /*-----------------------------------------------------------------*/
4808 static void shiftR1Left2Result (operand *left, int offl,
4809 operand *result, int offr,
4810 int shCount, int sign)
4812 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4813 /* shift right accumulator */
4818 aopPut(AOP(result),"a",offr);
4821 /*-----------------------------------------------------------------*/
4822 /* shiftL1Left2Result - shift left one byte from left to result */
4823 /*-----------------------------------------------------------------*/
4824 static void shiftL1Left2Result (operand *left, int offl,
4825 operand *result, int offr, int shCount)
4828 l = aopGet(AOP(left),offl,FALSE,FALSE);
4830 /* shift left accumulator */
4832 aopPut(AOP(result),"a",offr);
4835 /*-----------------------------------------------------------------*/
4836 /* movLeft2Result - move byte from left to result */
4837 /*-----------------------------------------------------------------*/
4838 static void movLeft2Result (operand *left, int offl,
4839 operand *result, int offr, int sign)
4842 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
4843 l = aopGet(AOP(left),offl,FALSE,FALSE);
4845 if (*l == '@' && (IS_AOP_PREG(result))) {
4846 emitcode("mov","a,%s",l);
4847 aopPut(AOP(result),"a",offr);
4850 aopPut(AOP(result),l,offr);
4852 /* MSB sign in acc.7 ! */
4853 if(getDataSize(left) == offl+1){
4854 emitcode("mov","a,%s",l);
4855 aopPut(AOP(result),"a",offr);
4862 /*-----------------------------------------------------------------*/
4863 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
4864 /*-----------------------------------------------------------------*/
4865 static void AccAXRrl1 (char *x)
4867 emitcode("rrc","a");
4868 emitcode("xch","a,%s", x);
4869 emitcode("rrc","a");
4870 emitcode("xch","a,%s", x);
4873 /*-----------------------------------------------------------------*/
4874 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
4875 /*-----------------------------------------------------------------*/
4876 static void AccAXLrl1 (char *x)
4878 emitcode("xch","a,%s",x);
4879 emitcode("rlc","a");
4880 emitcode("xch","a,%s",x);
4881 emitcode("rlc","a");
4884 /*-----------------------------------------------------------------*/
4885 /* AccAXLsh1 - left shift a:x<-0 by 1 */
4886 /*-----------------------------------------------------------------*/
4887 static void AccAXLsh1 (char *x)
4889 emitcode("xch","a,%s",x);
4890 emitcode("add","a,acc");
4891 emitcode("xch","a,%s",x);
4892 emitcode("rlc","a");
4895 /*-----------------------------------------------------------------*/
4896 /* AccAXLsh - left shift a:x by known count (0..7) */
4897 /*-----------------------------------------------------------------*/
4898 static void AccAXLsh (char *x, int shCount)
4912 case 5 : // AAAAABBB:CCCCCDDD
4913 AccRol(shCount); // BBBAAAAA:CCCCCDDD
4914 emitcode("anl","a,#0x%02x",
4915 SLMask[shCount]); // BBB00000:CCCCCDDD
4916 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
4917 AccRol(shCount); // DDDCCCCC:BBB00000
4918 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
4919 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
4920 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
4921 emitcode("anl","a,#0x%02x",
4922 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
4923 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
4924 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
4926 case 6 : // AAAAAABB:CCCCCCDD
4927 emitcode("anl","a,#0x%02x",
4928 SRMask[shCount]); // 000000BB:CCCCCCDD
4929 emitcode("mov","c,acc.0"); // c = B
4930 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
4931 AccAXRrl1(x); // BCCCCCCD:D000000B
4932 AccAXRrl1(x); // BBCCCCCC:DD000000
4934 case 7 : // a:x <<= 7
4935 emitcode("anl","a,#0x%02x",
4936 SRMask[shCount]); // 0000000B:CCCCCCCD
4937 emitcode("mov","c,acc.0"); // c = B
4938 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
4939 AccAXRrl1(x); // BCCCCCCC:D0000000
4946 /*-----------------------------------------------------------------*/
4947 /* AccAXRsh - right shift a:x known count (0..7) */
4948 /*-----------------------------------------------------------------*/
4949 static void AccAXRsh (char *x, int shCount)
4956 AccAXRrl1(x); // 0->a:x
4960 AccAXRrl1(x); // 0->a:x
4962 AccAXRrl1(x); // 0->a:x
4966 case 5 : // AAAAABBB:CCCCCDDD = a:x
4967 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
4968 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
4969 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
4970 emitcode("anl","a,#0x%02x",
4971 SRMask[shCount]); // 000CCCCC:BBBAAAAA
4972 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
4973 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
4974 emitcode("anl","a,#0x%02x",
4975 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
4976 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
4977 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
4978 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
4980 case 6 : // AABBBBBB:CCDDDDDD
4981 emitcode("mov","c,acc.7");
4982 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
4983 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
4984 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
4985 emitcode("anl","a,#0x%02x",
4986 SRMask[shCount]); // 000000AA:BBBBBBCC
4988 case 7 : // ABBBBBBB:CDDDDDDD
4989 emitcode("mov","c,acc.7"); // c = A
4990 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
4991 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
4992 emitcode("anl","a,#0x%02x",
4993 SRMask[shCount]); // 0000000A:BBBBBBBC
5000 /*-----------------------------------------------------------------*/
5001 /* AccAXRshS - right shift signed a:x known count (0..7) */
5002 /*-----------------------------------------------------------------*/
5003 static void AccAXRshS (char *x, int shCount)
5010 emitcode("mov","c,acc.7");
5011 AccAXRrl1(x); // s->a:x
5014 emitcode("mov","c,acc.7");
5015 AccAXRrl1(x); // s->a:x
5016 emitcode("mov","c,acc.7");
5017 AccAXRrl1(x); // s->a:x
5021 case 5 : // AAAAABBB:CCCCCDDD = a:x
5022 tlbl = newiTempLabel(NULL);
5023 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5024 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5025 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5026 emitcode("anl","a,#0x%02x",
5027 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5028 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5029 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5030 emitcode("anl","a,#0x%02x",
5031 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5032 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5033 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5034 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5035 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5036 emitcode("orl","a,#0x%02x",
5037 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5038 emitcode("","%05d$:",tlbl->key+100);
5039 break; // SSSSAAAA:BBBCCCCC
5040 case 6 : // AABBBBBB:CCDDDDDD
5041 tlbl = newiTempLabel(NULL);
5042 emitcode("mov","c,acc.7");
5043 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5044 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5045 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5046 emitcode("anl","a,#0x%02x",
5047 SRMask[shCount]); // 000000AA:BBBBBBCC
5048 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5049 emitcode("orl","a,#0x%02x",
5050 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5051 emitcode("","%05d$:",tlbl->key+100);
5053 case 7 : // ABBBBBBB:CDDDDDDD
5054 tlbl = newiTempLabel(NULL);
5055 emitcode("mov","c,acc.7"); // c = A
5056 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5057 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5058 emitcode("anl","a,#0x%02x",
5059 SRMask[shCount]); // 0000000A:BBBBBBBC
5060 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5061 emitcode("orl","a,#0x%02x",
5062 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5063 emitcode("","%05d$:",tlbl->key+100);
5070 /*-----------------------------------------------------------------*/
5071 /* shiftL2Left2Result - shift left two bytes from left to result */
5072 /*-----------------------------------------------------------------*/
5073 static void shiftL2Left2Result (operand *left, int offl,
5074 operand *result, int offr, int shCount)
5076 if(sameRegs(AOP(result), AOP(left)) &&
5077 ((offl + MSB16) == offr)){
5078 /* don't crash result[offr] */
5079 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5080 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5082 movLeft2Result(left,offl, result, offr, 0);
5083 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5085 /* ax << shCount (x = lsb(result))*/
5086 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5087 aopPut(AOP(result),"a",offr+MSB16);
5091 /*-----------------------------------------------------------------*/
5092 /* shiftR2Left2Result - shift right two bytes from left to result */
5093 /*-----------------------------------------------------------------*/
5094 static void shiftR2Left2Result (operand *left, int offl,
5095 operand *result, int offr,
5096 int shCount, int sign)
5098 if(sameRegs(AOP(result), AOP(left)) &&
5099 ((offl + MSB16) == offr)){
5100 /* don't crash result[offr] */
5101 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5102 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5104 movLeft2Result(left,offl, result, offr, 0);
5105 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5107 /* a:x >> shCount (x = lsb(result))*/
5109 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5111 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5112 if(getDataSize(result) > 1)
5113 aopPut(AOP(result),"a",offr+MSB16);
5116 /*-----------------------------------------------------------------*/
5117 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5118 /*-----------------------------------------------------------------*/
5119 static void shiftLLeftOrResult (operand *left, int offl,
5120 operand *result, int offr, int shCount)
5122 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5123 /* shift left accumulator */
5125 /* or with result */
5126 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5127 /* back to result */
5128 aopPut(AOP(result),"a",offr);
5131 /*-----------------------------------------------------------------*/
5132 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5133 /*-----------------------------------------------------------------*/
5134 static void shiftRLeftOrResult (operand *left, int offl,
5135 operand *result, int offr, int shCount)
5137 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5138 /* shift right accumulator */
5140 /* or with result */
5141 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5142 /* back to result */
5143 aopPut(AOP(result),"a",offr);
5146 /*-----------------------------------------------------------------*/
5147 /* genlshOne - left shift a one byte quantity by known count */
5148 /*-----------------------------------------------------------------*/
5149 static void genlshOne (operand *result, operand *left, int shCount)
5151 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5154 /*-----------------------------------------------------------------*/
5155 /* genlshTwo - left shift two bytes by known amount != 0 */
5156 /*-----------------------------------------------------------------*/
5157 static void genlshTwo (operand *result,operand *left, int shCount)
5161 size = getDataSize(result);
5163 /* if shCount >= 8 */
5169 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5171 movLeft2Result(left, LSB, result, MSB16, 0);
5173 aopPut(AOP(result),zero,LSB);
5176 /* 1 <= shCount <= 7 */
5179 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5181 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5185 /*-----------------------------------------------------------------*/
5186 /* shiftLLong - shift left one long from left to result */
5187 /* offl = LSB or MSB16 */
5188 /*-----------------------------------------------------------------*/
5189 static void shiftLLong (operand *left, operand *result, int offr )
5192 int size = AOP_SIZE(result);
5194 if(size >= LSB+offr){
5195 l = aopGet(AOP(left),LSB,FALSE,FALSE);
5197 emitcode("add","a,acc");
5198 if (sameRegs(AOP(left),AOP(result)) &&
5199 size >= MSB16+offr && offr != LSB )
5200 emitcode("xch","a,%s",
5201 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
5203 aopPut(AOP(result),"a",LSB+offr);
5206 if(size >= MSB16+offr){
5207 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5208 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
5211 emitcode("rlc","a");
5212 if (sameRegs(AOP(left),AOP(result)) &&
5213 size >= MSB24+offr && offr != LSB)
5214 emitcode("xch","a,%s",
5215 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
5217 aopPut(AOP(result),"a",MSB16+offr);
5220 if(size >= MSB24+offr){
5221 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5222 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
5225 emitcode("rlc","a");
5226 if (sameRegs(AOP(left),AOP(result)) &&
5227 size >= MSB32+offr && offr != LSB )
5228 emitcode("xch","a,%s",
5229 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
5231 aopPut(AOP(result),"a",MSB24+offr);
5234 if(size > MSB32+offr){
5235 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5236 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
5239 emitcode("rlc","a");
5240 aopPut(AOP(result),"a",MSB32+offr);
5243 aopPut(AOP(result),zero,LSB);
5246 /*-----------------------------------------------------------------*/
5247 /* genlshFour - shift four byte by a known amount != 0 */
5248 /*-----------------------------------------------------------------*/
5249 static void genlshFour (operand *result, operand *left, int shCount)
5253 size = AOP_SIZE(result);
5255 /* if shifting more that 3 bytes */
5256 if (shCount >= 24 ) {
5259 /* lowest order of left goes to the highest
5260 order of the destination */
5261 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5263 movLeft2Result(left, LSB, result, MSB32, 0);
5264 aopPut(AOP(result),zero,LSB);
5265 aopPut(AOP(result),zero,MSB16);
5266 aopPut(AOP(result),zero,MSB32);
5270 /* more than two bytes */
5271 else if ( shCount >= 16 ) {
5272 /* lower order two bytes goes to higher order two bytes */
5274 /* if some more remaining */
5276 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5278 movLeft2Result(left, MSB16, result, MSB32, 0);
5279 movLeft2Result(left, LSB, result, MSB24, 0);
5281 aopPut(AOP(result),zero,MSB16);
5282 aopPut(AOP(result),zero,LSB);
5286 /* if more than 1 byte */
5287 else if ( shCount >= 8 ) {
5288 /* lower order three bytes goes to higher order three bytes */
5292 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5294 movLeft2Result(left, LSB, result, MSB16, 0);
5296 else{ /* size = 4 */
5298 movLeft2Result(left, MSB24, result, MSB32, 0);
5299 movLeft2Result(left, MSB16, result, MSB24, 0);
5300 movLeft2Result(left, LSB, result, MSB16, 0);
5301 aopPut(AOP(result),zero,LSB);
5303 else if(shCount == 1)
5304 shiftLLong(left, result, MSB16);
5306 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5307 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5308 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5309 aopPut(AOP(result),zero,LSB);
5314 /* 1 <= shCount <= 7 */
5315 else if(shCount <= 2){
5316 shiftLLong(left, result, LSB);
5318 shiftLLong(result, result, LSB);
5320 /* 3 <= shCount <= 7, optimize */
5322 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5323 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5324 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5328 /*-----------------------------------------------------------------*/
5329 /* genLeftShiftLiteral - left shifting by known count */
5330 /*-----------------------------------------------------------------*/
5331 static void genLeftShiftLiteral (operand *left,
5336 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5339 freeAsmop(right,NULL,ic,TRUE);
5341 aopOp(left,ic,FALSE);
5342 aopOp(result,ic,FALSE);
5344 size = getSize(operandType(result));
5347 emitcode("; shift left ","result %d, left %d",size,
5351 /* I suppose that the left size >= result size */
5354 movLeft2Result(left, size, result, size, 0);
5358 else if(shCount >= (size * 8))
5360 aopPut(AOP(result),zero,size);
5364 genlshOne (result,left,shCount);
5369 genlshTwo (result,left,shCount);
5373 genlshFour (result,left,shCount);
5377 freeAsmop(left,NULL,ic,TRUE);
5378 freeAsmop(result,NULL,ic,TRUE);
5381 /*-----------------------------------------------------------------*/
5382 /* genLeftShift - generates code for left shifting */
5383 /*-----------------------------------------------------------------*/
5384 static void genLeftShift (iCode *ic)
5386 operand *left,*right, *result;
5389 symbol *tlbl , *tlbl1;
5391 right = IC_RIGHT(ic);
5393 result = IC_RESULT(ic);
5395 aopOp(right,ic,FALSE);
5397 /* if the shift count is known then do it
5398 as efficiently as possible */
5399 if (AOP_TYPE(right) == AOP_LIT) {
5400 genLeftShiftLiteral (left,right,result,ic);
5404 /* shift count is unknown then we have to form
5405 a loop get the loop count in B : Note: we take
5406 only the lower order byte since shifting
5407 more that 32 bits make no sense anyway, ( the
5408 largest size of an object can be only 32 bits ) */
5410 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5411 emitcode("inc","b");
5412 freeAsmop (right,NULL,ic,TRUE);
5413 aopOp(left,ic,FALSE);
5414 aopOp(result,ic,FALSE);
5416 /* now move the left to the result if they are not the
5418 if (!sameRegs(AOP(left),AOP(result)) &&
5419 AOP_SIZE(result) > 1) {
5421 size = AOP_SIZE(result);
5424 l = aopGet(AOP(left),offset,FALSE,TRUE);
5425 if (*l == '@' && (IS_AOP_PREG(result))) {
5427 emitcode("mov","a,%s",l);
5428 aopPut(AOP(result),"a",offset);
5430 aopPut(AOP(result),l,offset);
5435 tlbl = newiTempLabel(NULL);
5436 size = AOP_SIZE(result);
5438 tlbl1 = newiTempLabel(NULL);
5440 /* if it is only one byte then */
5442 symbol *tlbl1 = newiTempLabel(NULL);
5444 l = aopGet(AOP(left),0,FALSE,FALSE);
5446 emitcode("sjmp","%05d$",tlbl1->key+100);
5447 emitcode("","%05d$:",tlbl->key+100);
5448 emitcode("add","a,acc");
5449 emitcode("","%05d$:",tlbl1->key+100);
5450 emitcode("djnz","b,%05d$",tlbl->key+100);
5451 aopPut(AOP(result),"a",0);
5455 reAdjustPreg(AOP(result));
5457 emitcode("sjmp","%05d$",tlbl1->key+100);
5458 emitcode("","%05d$:",tlbl->key+100);
5459 l = aopGet(AOP(result),offset,FALSE,FALSE);
5461 emitcode("add","a,acc");
5462 aopPut(AOP(result),"a",offset++);
5464 l = aopGet(AOP(result),offset,FALSE,FALSE);
5466 emitcode("rlc","a");
5467 aopPut(AOP(result),"a",offset++);
5469 reAdjustPreg(AOP(result));
5471 emitcode("","%05d$:",tlbl1->key+100);
5472 emitcode("djnz","b,%05d$",tlbl->key+100);
5474 freeAsmop(left,NULL,ic,TRUE);
5475 freeAsmop(result,NULL,ic,TRUE);
5478 /*-----------------------------------------------------------------*/
5479 /* genrshOne - right shift a one byte quantity by known count */
5480 /*-----------------------------------------------------------------*/
5481 static void genrshOne (operand *result, operand *left,
5482 int shCount, int sign)
5484 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
5487 /*-----------------------------------------------------------------*/
5488 /* genrshTwo - right shift two bytes by known amount != 0 */
5489 /*-----------------------------------------------------------------*/
5490 static void genrshTwo (operand *result,operand *left,
5491 int shCount, int sign)
5493 /* if shCount >= 8 */
5497 shiftR1Left2Result(left, MSB16, result, LSB,
5500 movLeft2Result(left, MSB16, result, LSB, sign);
5501 addSign(result, MSB16, sign);
5504 /* 1 <= shCount <= 7 */
5506 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
5509 /*-----------------------------------------------------------------*/
5510 /* shiftRLong - shift right one long from left to result */
5511 /* offl = LSB or MSB16 */
5512 /*-----------------------------------------------------------------*/
5513 static void shiftRLong (operand *left, int offl,
5514 operand *result, int sign)
5517 emitcode("clr","c");
5518 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
5520 emitcode("mov","c,acc.7");
5521 emitcode("rrc","a");
5522 aopPut(AOP(result),"a",MSB32-offl);
5524 /* add sign of "a" */
5525 addSign(result, MSB32, sign);
5527 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
5528 emitcode("rrc","a");
5529 aopPut(AOP(result),"a",MSB24-offl);
5531 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
5532 emitcode("rrc","a");
5533 aopPut(AOP(result),"a",MSB16-offl);
5536 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
5537 emitcode("rrc","a");
5538 aopPut(AOP(result),"a",LSB);
5542 /*-----------------------------------------------------------------*/
5543 /* genrshFour - shift four byte by a known amount != 0 */
5544 /*-----------------------------------------------------------------*/
5545 static void genrshFour (operand *result, operand *left,
5546 int shCount, int sign)
5548 /* if shifting more that 3 bytes */
5549 if(shCount >= 24 ) {
5552 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
5554 movLeft2Result(left, MSB32, result, LSB, sign);
5555 addSign(result, MSB16, sign);
5557 else if(shCount >= 16){
5560 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
5562 movLeft2Result(left, MSB24, result, LSB, 0);
5563 movLeft2Result(left, MSB32, result, MSB16, sign);
5565 addSign(result, MSB24, sign);
5567 else if(shCount >= 8){
5570 shiftRLong(left, MSB16, result, sign);
5571 else if(shCount == 0){
5572 movLeft2Result(left, MSB16, result, LSB, 0);
5573 movLeft2Result(left, MSB24, result, MSB16, 0);
5574 movLeft2Result(left, MSB32, result, MSB24, sign);
5575 addSign(result, MSB32, sign);
5578 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
5579 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
5580 /* the last shift is signed */
5581 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
5582 addSign(result, MSB32, sign);
5585 else{ /* 1 <= shCount <= 7 */
5587 shiftRLong(left, LSB, result, sign);
5589 shiftRLong(result, LSB, result, sign);
5592 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
5593 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
5594 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
5599 /*-----------------------------------------------------------------*/
5600 /* genRightShiftLiteral - right shifting by known count */
5601 /*-----------------------------------------------------------------*/
5602 static void genRightShiftLiteral (operand *left,
5608 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5611 freeAsmop(right,NULL,ic,TRUE);
5613 aopOp(left,ic,FALSE);
5614 aopOp(result,ic,FALSE);
5617 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
5621 size = getDataSize(left);
5622 /* test the LEFT size !!! */
5624 /* I suppose that the left size >= result size */
5626 size = getDataSize(result);
5628 movLeft2Result(left, size, result, size, 0);
5631 else if(shCount >= (size * 8)){
5633 /* get sign in acc.7 */
5634 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
5635 addSign(result, LSB, sign);
5639 genrshOne (result,left,shCount,sign);
5643 genrshTwo (result,left,shCount,sign);
5647 genrshFour (result,left,shCount,sign);
5653 freeAsmop(left,NULL,ic,TRUE);
5654 freeAsmop(result,NULL,ic,TRUE);
5658 /*-----------------------------------------------------------------*/
5659 /* genSignedRightShift - right shift of signed number */
5660 /*-----------------------------------------------------------------*/
5661 static void genSignedRightShift (iCode *ic)
5663 operand *right, *left, *result;
5666 symbol *tlbl, *tlbl1 ;
5668 /* we do it the hard way put the shift count in b
5669 and loop thru preserving the sign */
5671 right = IC_RIGHT(ic);
5673 result = IC_RESULT(ic);
5675 aopOp(right,ic,FALSE);
5678 if ( AOP_TYPE(right) == AOP_LIT) {
5679 genRightShiftLiteral (left,right,result,ic,1);
5682 /* shift count is unknown then we have to form
5683 a loop get the loop count in B : Note: we take
5684 only the lower order byte since shifting
5685 more that 32 bits make no sense anyway, ( the
5686 largest size of an object can be only 32 bits ) */
5688 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5689 emitcode("inc","b");
5690 freeAsmop (right,NULL,ic,TRUE);
5691 aopOp(left,ic,FALSE);
5692 aopOp(result,ic,FALSE);
5694 /* now move the left to the result if they are not the
5696 if (!sameRegs(AOP(left),AOP(result)) &&
5697 AOP_SIZE(result) > 1) {
5699 size = AOP_SIZE(result);
5702 l = aopGet(AOP(left),offset,FALSE,TRUE);
5703 if (*l == '@' && IS_AOP_PREG(result)) {
5705 emitcode("mov","a,%s",l);
5706 aopPut(AOP(result),"a",offset);
5708 aopPut(AOP(result),l,offset);
5713 /* mov the highest order bit to OVR */
5714 tlbl = newiTempLabel(NULL);
5715 tlbl1= newiTempLabel(NULL);
5717 size = AOP_SIZE(result);
5719 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
5720 emitcode("rlc","a");
5721 emitcode("mov","ov,c");
5722 /* if it is only one byte then */
5724 l = aopGet(AOP(left),0,FALSE,FALSE);
5726 emitcode("sjmp","%05d$",tlbl1->key+100);
5727 emitcode("","%05d$:",tlbl->key+100);
5728 emitcode("mov","c,ov");
5729 emitcode("rrc","a");
5730 emitcode("","%05d$:",tlbl1->key+100);
5731 emitcode("djnz","b,%05d$",tlbl->key+100);
5732 aopPut(AOP(result),"a",0);
5736 reAdjustPreg(AOP(result));
5737 emitcode("sjmp","%05d$",tlbl1->key+100);
5738 emitcode("","%05d$:",tlbl->key+100);
5739 emitcode("mov","c,ov");
5741 l = aopGet(AOP(result),offset,FALSE,FALSE);
5743 emitcode("rrc","a");
5744 aopPut(AOP(result),"a",offset--);
5746 reAdjustPreg(AOP(result));
5747 emitcode("","%05d$:",tlbl1->key+100);
5748 emitcode("djnz","b,%05d$",tlbl->key+100);
5751 freeAsmop(left,NULL,ic,TRUE);
5752 freeAsmop(result,NULL,ic,TRUE);
5755 /*-----------------------------------------------------------------*/
5756 /* genRightShift - generate code for right shifting */
5757 /*-----------------------------------------------------------------*/
5758 static void genRightShift (iCode *ic)
5760 operand *right, *left, *result;
5764 symbol *tlbl, *tlbl1 ;
5766 /* if signed then we do it the hard way preserve the
5767 sign bit moving it inwards */
5768 retype = getSpec(operandType(IC_RESULT(ic)));
5770 if (!SPEC_USIGN(retype)) {
5771 genSignedRightShift (ic);
5775 /* signed & unsigned types are treated the same : i.e. the
5776 signed is NOT propagated inwards : quoting from the
5777 ANSI - standard : "for E1 >> E2, is equivalent to division
5778 by 2**E2 if unsigned or if it has a non-negative value,
5779 otherwise the result is implementation defined ", MY definition
5780 is that the sign does not get propagated */
5782 right = IC_RIGHT(ic);
5784 result = IC_RESULT(ic);
5786 aopOp(right,ic,FALSE);
5788 /* if the shift count is known then do it
5789 as efficiently as possible */
5790 if (AOP_TYPE(right) == AOP_LIT) {
5791 genRightShiftLiteral (left,right,result,ic, 0);
5795 /* shift count is unknown then we have to form
5796 a loop get the loop count in B : Note: we take
5797 only the lower order byte since shifting
5798 more that 32 bits make no sense anyway, ( the
5799 largest size of an object can be only 32 bits ) */
5801 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5802 emitcode("inc","b");
5803 freeAsmop (right,NULL,ic,TRUE);
5804 aopOp(left,ic,FALSE);
5805 aopOp(result,ic,FALSE);
5807 /* now move the left to the result if they are not the
5809 if (!sameRegs(AOP(left),AOP(result)) &&
5810 AOP_SIZE(result) > 1) {
5812 size = AOP_SIZE(result);
5815 l = aopGet(AOP(left),offset,FALSE,TRUE);
5816 if (*l == '@' && IS_AOP_PREG(result)) {
5818 emitcode("mov","a,%s",l);
5819 aopPut(AOP(result),"a",offset);
5821 aopPut(AOP(result),l,offset);
5826 tlbl = newiTempLabel(NULL);
5827 tlbl1= newiTempLabel(NULL);
5828 size = AOP_SIZE(result);
5831 /* if it is only one byte then */
5833 l = aopGet(AOP(left),0,FALSE,FALSE);
5835 emitcode("sjmp","%05d$",tlbl1->key+100);
5836 emitcode("","%05d$:",tlbl->key+100);
5838 emitcode("rrc","a");
5839 emitcode("","%05d$:",tlbl1->key+100);
5840 emitcode("djnz","b,%05d$",tlbl->key+100);
5841 aopPut(AOP(result),"a",0);
5845 reAdjustPreg(AOP(result));
5846 emitcode("sjmp","%05d$",tlbl1->key+100);
5847 emitcode("","%05d$:",tlbl->key+100);
5850 l = aopGet(AOP(result),offset,FALSE,FALSE);
5852 emitcode("rrc","a");
5853 aopPut(AOP(result),"a",offset--);
5855 reAdjustPreg(AOP(result));
5857 emitcode("","%05d$:",tlbl1->key+100);
5858 emitcode("djnz","b,%05d$",tlbl->key+100);
5861 freeAsmop(left,NULL,ic,TRUE);
5862 freeAsmop(result,NULL,ic,TRUE);
5865 /*-----------------------------------------------------------------*/
5866 /* genUnpackBits - generates code for unpacking bits */
5867 /*-----------------------------------------------------------------*/
5868 static void genUnpackBits (operand *result, char *rname, int ptype)
5875 etype = getSpec(operandType(result));
5877 /* read the first byte */
5882 emitcode("mov","a,@%s",rname);
5886 emitcode("movx","a,@%s",rname);
5890 emitcode("movx","a,@dptr");
5894 emitcode("clr","a");
5895 emitcode("movc","a","@a+dptr");
5899 emitcode("lcall","__gptrget");
5903 /* if we have bitdisplacement then it fits */
5904 /* into this byte completely or if length is */
5905 /* less than a byte */
5906 if ((shCnt = SPEC_BSTR(etype)) ||
5907 (SPEC_BLEN(etype) <= 8)) {
5909 /* shift right acc */
5912 emitcode("anl","a,#0x%02x",
5913 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
5914 aopPut(AOP(result),"a",offset);
5918 /* bit field did not fit in a byte */
5919 rlen = SPEC_BLEN(etype) - 8;
5920 aopPut(AOP(result),"a",offset++);
5927 emitcode("inc","%s",rname);
5928 emitcode("mov","a,@%s",rname);
5932 emitcode("inc","%s",rname);
5933 emitcode("movx","a,@%s",rname);
5937 emitcode("inc","dptr");
5938 emitcode("movx","a,@dptr");
5942 emitcode("clr","a");
5943 emitcode("inc","dptr");
5944 emitcode("movc","a","@a+dptr");
5948 emitcode("inc","dptr");
5949 emitcode("lcall","__gptrget");
5954 /* if we are done */
5958 aopPut(AOP(result),"a",offset++);
5963 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
5964 aopPut(AOP(result),"a",offset);
5971 /*-----------------------------------------------------------------*/
5972 /* genDataPointerGet - generates code when ptr offset is known */
5973 /*-----------------------------------------------------------------*/
5974 static void genDataPointerGet (operand *left,
5980 int size , offset = 0;
5981 aopOp(result,ic,TRUE);
5983 /* get the string representation of the name */
5984 l = aopGet(AOP(left),0,FALSE,TRUE);
5985 size = AOP_SIZE(result);
5988 sprintf(buffer,"(%s + %d)",l+1,offset);
5990 sprintf(buffer,"%s",l+1);
5991 aopPut(AOP(result),buffer,offset++);
5994 freeAsmop(left,NULL,ic,TRUE);
5995 freeAsmop(result,NULL,ic,TRUE);
5998 /*-----------------------------------------------------------------*/
5999 /* genNearPointerGet - emitcode for near pointer fetch */
6000 /*-----------------------------------------------------------------*/
6001 static void genNearPointerGet (operand *left,
6008 link *rtype, *retype;
6009 link *ltype = operandType(left);
6012 rtype = operandType(result);
6013 retype= getSpec(rtype);
6015 aopOp(left,ic,FALSE);
6017 /* if left is rematerialisable and
6018 result is not bit variable type and
6019 the left is pointer to data space i.e
6020 lower 128 bytes of space */
6021 if (AOP_TYPE(left) == AOP_IMMD &&
6022 !IS_BITVAR(retype) &&
6023 DCL_TYPE(ltype) == POINTER) {
6024 genDataPointerGet (left,result,ic);
6028 /* if the value is already in a pointer register
6029 then don't need anything more */
6030 if (!AOP_INPREG(AOP(left))) {
6031 /* otherwise get a free pointer register */
6033 preg = getFreePtr(ic,&aop,FALSE);
6034 emitcode("mov","%s,%s",
6036 aopGet(AOP(left),0,FALSE,TRUE));
6037 rname = preg->name ;
6039 rname = aopGet(AOP(left),0,FALSE,FALSE);
6041 freeAsmop(left,NULL,ic,TRUE);
6042 aopOp (result,ic,FALSE);
6044 /* if bitfield then unpack the bits */
6045 if (IS_BITVAR(retype))
6046 genUnpackBits (result,rname,POINTER);
6048 /* we have can just get the values */
6049 int size = AOP_SIZE(result);
6053 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6055 emitcode("mov","a,@%s",rname);
6056 aopPut(AOP(result),"a",offset);
6058 sprintf(buffer,"@%s",rname);
6059 aopPut(AOP(result),buffer,offset);
6063 emitcode("inc","%s",rname);
6067 /* now some housekeeping stuff */
6069 /* we had to allocate for this iCode */
6070 freeAsmop(NULL,aop,ic,TRUE);
6072 /* we did not allocate which means left
6073 already in a pointer register, then
6074 if size > 0 && this could be used again
6075 we have to point it back to where it
6077 if (AOP_SIZE(result) > 1 &&
6078 !OP_SYMBOL(left)->remat &&
6079 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6081 int size = AOP_SIZE(result) - 1;
6083 emitcode("dec","%s",rname);
6088 freeAsmop(result,NULL,ic,TRUE);
6092 /*-----------------------------------------------------------------*/
6093 /* genPagedPointerGet - emitcode for paged pointer fetch */
6094 /*-----------------------------------------------------------------*/
6095 static void genPagedPointerGet (operand *left,
6102 link *rtype, *retype;
6104 rtype = operandType(result);
6105 retype= getSpec(rtype);
6107 aopOp(left,ic,FALSE);
6109 /* if the value is already in a pointer register
6110 then don't need anything more */
6111 if (!AOP_INPREG(AOP(left))) {
6112 /* otherwise get a free pointer register */
6114 preg = getFreePtr(ic,&aop,FALSE);
6115 emitcode("mov","%s,%s",
6117 aopGet(AOP(left),0,FALSE,TRUE));
6118 rname = preg->name ;
6120 rname = aopGet(AOP(left),0,FALSE,FALSE);
6122 freeAsmop(left,NULL,ic,TRUE);
6123 aopOp (result,ic,FALSE);
6125 /* if bitfield then unpack the bits */
6126 if (IS_BITVAR(retype))
6127 genUnpackBits (result,rname,PPOINTER);
6129 /* we have can just get the values */
6130 int size = AOP_SIZE(result);
6135 emitcode("movx","a,@%s",rname);
6136 aopPut(AOP(result),"a",offset);
6141 emitcode("inc","%s",rname);
6145 /* now some housekeeping stuff */
6147 /* we had to allocate for this iCode */
6148 freeAsmop(NULL,aop,ic,TRUE);
6150 /* we did not allocate which means left
6151 already in a pointer register, then
6152 if size > 0 && this could be used again
6153 we have to point it back to where it
6155 if (AOP_SIZE(result) > 1 &&
6156 !OP_SYMBOL(left)->remat &&
6157 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6159 int size = AOP_SIZE(result) - 1;
6161 emitcode("dec","%s",rname);
6166 freeAsmop(result,NULL,ic,TRUE);
6171 /*-----------------------------------------------------------------*/
6172 /* genFarPointerGet - gget value from far space */
6173 /*-----------------------------------------------------------------*/
6174 static void genFarPointerGet (operand *left,
6175 operand *result, iCode *ic)
6178 link *retype = getSpec(operandType(result));
6180 aopOp(left,ic,FALSE);
6182 /* if the operand is already in dptr
6183 then we do nothing else we move the value to dptr */
6184 if (AOP_TYPE(left) != AOP_STR) {
6185 /* if this is remateriazable */
6186 if (AOP_TYPE(left) == AOP_IMMD)
6187 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6188 else { /* we need to get it byte by byte */
6189 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6190 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6191 if (options.model == MODEL_FLAT24)
6193 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6197 /* so dptr know contains the address */
6198 freeAsmop(left,NULL,ic,TRUE);
6199 aopOp(result,ic,FALSE);
6201 /* if bit then unpack */
6202 if (IS_BITVAR(retype))
6203 genUnpackBits(result,"dptr",FPOINTER);
6205 size = AOP_SIZE(result);
6209 emitcode("movx","a,@dptr");
6210 aopPut(AOP(result),"a",offset++);
6212 emitcode("inc","dptr");
6216 freeAsmop(result,NULL,ic,TRUE);
6219 /*-----------------------------------------------------------------*/
6220 /* emitcodePointerGet - gget value from code space */
6221 /*-----------------------------------------------------------------*/
6222 static void emitcodePointerGet (operand *left,
6223 operand *result, iCode *ic)
6226 link *retype = getSpec(operandType(result));
6228 aopOp(left,ic,FALSE);
6230 /* if the operand is already in dptr
6231 then we do nothing else we move the value to dptr */
6232 if (AOP_TYPE(left) != AOP_STR) {
6233 /* if this is remateriazable */
6234 if (AOP_TYPE(left) == AOP_IMMD)
6235 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6236 else { /* we need to get it byte by byte */
6237 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6238 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6239 if (options.model == MODEL_FLAT24)
6241 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6245 /* so dptr know contains the address */
6246 freeAsmop(left,NULL,ic,TRUE);
6247 aopOp(result,ic,FALSE);
6249 /* if bit then unpack */
6250 if (IS_BITVAR(retype))
6251 genUnpackBits(result,"dptr",CPOINTER);
6253 size = AOP_SIZE(result);
6257 emitcode("clr","a");
6258 emitcode("movc","a,@a+dptr");
6259 aopPut(AOP(result),"a",offset++);
6261 emitcode("inc","dptr");
6265 freeAsmop(result,NULL,ic,TRUE);
6268 /*-----------------------------------------------------------------*/
6269 /* genGenPointerGet - gget value from generic pointer space */
6270 /*-----------------------------------------------------------------*/
6271 static void genGenPointerGet (operand *left,
6272 operand *result, iCode *ic)
6275 link *retype = getSpec(operandType(result));
6277 aopOp(left,ic,FALSE);
6279 /* if the operand is already in dptr
6280 then we do nothing else we move the value to dptr */
6281 if (AOP_TYPE(left) != AOP_STR) {
6282 /* if this is remateriazable */
6283 if (AOP_TYPE(left) == AOP_IMMD) {
6284 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6285 emitcode("mov","b,#%d",pointerCode(retype));
6287 else { /* we need to get it byte by byte */
6288 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6289 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6290 if (options.model == MODEL_FLAT24)
6292 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6293 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
6297 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
6301 /* so dptr know contains the address */
6302 freeAsmop(left,NULL,ic,TRUE);
6303 aopOp(result,ic,FALSE);
6305 /* if bit then unpack */
6306 if (IS_BITVAR(retype))
6307 genUnpackBits(result,"dptr",GPOINTER);
6309 size = AOP_SIZE(result);
6313 emitcode("lcall","__gptrget");
6314 aopPut(AOP(result),"a",offset++);
6316 emitcode("inc","dptr");
6320 freeAsmop(result,NULL,ic,TRUE);
6323 /*-----------------------------------------------------------------*/
6324 /* genPointerGet - generate code for pointer get */
6325 /*-----------------------------------------------------------------*/
6326 static void genPointerGet (iCode *ic)
6328 operand *left, *result ;
6333 result = IC_RESULT(ic) ;
6335 /* depending on the type of pointer we need to
6336 move it to the correct pointer register */
6337 type = operandType(left);
6338 etype = getSpec(type);
6339 /* if left is of type of pointer then it is simple */
6340 if (IS_PTR(type) && !IS_FUNC(type->next))
6341 p_type = DCL_TYPE(type);
6343 /* we have to go by the storage class */
6344 p_type = PTR_TYPE(SPEC_OCLS(etype));
6346 /* if (SPEC_OCLS(etype)->codesp ) { */
6347 /* p_type = CPOINTER ; */
6350 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6351 /* p_type = FPOINTER ; */
6353 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6354 /* p_type = PPOINTER; */
6356 /* if (SPEC_OCLS(etype) == idata ) */
6357 /* p_type = IPOINTER; */
6359 /* p_type = POINTER ; */
6362 /* now that we have the pointer type we assign
6363 the pointer values */
6368 genNearPointerGet (left,result,ic);
6372 genPagedPointerGet(left,result,ic);
6376 genFarPointerGet (left,result,ic);
6380 emitcodePointerGet (left,result,ic);
6384 genGenPointerGet (left,result,ic);
6390 /*-----------------------------------------------------------------*/
6391 /* genPackBits - generates code for packed bit storage */
6392 /*-----------------------------------------------------------------*/
6393 static void genPackBits (link *etype ,
6395 char *rname, int p_type)
6403 blen = SPEC_BLEN(etype);
6404 bstr = SPEC_BSTR(etype);
6406 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6409 /* if the bit lenth is less than or */
6410 /* it exactly fits a byte then */
6411 if (SPEC_BLEN(etype) <= 8 ) {
6412 shCount = SPEC_BSTR(etype) ;
6414 /* shift left acc */
6417 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6422 emitcode ("mov","b,a");
6423 emitcode("mov","a,@%s",rname);
6427 emitcode ("mov","b,a");
6428 emitcode("movx","a,@dptr");
6432 emitcode ("push","b");
6433 emitcode ("push","acc");
6434 emitcode ("lcall","__gptrget");
6435 emitcode ("pop","b");
6439 emitcode ("anl","a,#0x%02x",(unsigned char)
6440 ((unsigned char)(0xFF << (blen+bstr)) |
6441 (unsigned char)(0xFF >> (8-bstr)) ) );
6442 emitcode ("orl","a,b");
6443 if (p_type == GPOINTER)
6444 emitcode("pop","b");
6450 emitcode("mov","@%s,a",rname);
6454 emitcode("movx","@dptr,a");
6458 emitcode("lcall","__gptrput");
6463 if ( SPEC_BLEN(etype) <= 8 )
6466 emitcode("inc","%s",rname);
6467 rLen = SPEC_BLEN(etype) ;
6469 /* now generate for lengths greater than one byte */
6472 l = aopGet(AOP(right),offset++,FALSE,TRUE);
6482 emitcode("mov","@%s,a",rname);
6484 emitcode("mov","@%s,%s",rname,l);
6489 emitcode("movx","@dptr,a");
6494 emitcode("lcall","__gptrput");
6497 emitcode ("inc","%s",rname);
6502 /* last last was not complete */
6504 /* save the byte & read byte */
6507 emitcode ("mov","b,a");
6508 emitcode("mov","a,@%s",rname);
6512 emitcode ("mov","b,a");
6513 emitcode("movx","a,@dptr");
6517 emitcode ("push","b");
6518 emitcode ("push","acc");
6519 emitcode ("lcall","__gptrget");
6520 emitcode ("pop","b");
6524 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
6525 emitcode ("orl","a,b");
6528 if (p_type == GPOINTER)
6529 emitcode("pop","b");
6534 emitcode("mov","@%s,a",rname);
6538 emitcode("movx","@dptr,a");
6542 emitcode("lcall","__gptrput");
6546 /*-----------------------------------------------------------------*/
6547 /* genDataPointerSet - remat pointer to data space */
6548 /*-----------------------------------------------------------------*/
6549 static void genDataPointerSet(operand *right,
6553 int size, offset = 0 ;
6554 char *l, buffer[256];
6556 aopOp(right,ic,FALSE);
6558 l = aopGet(AOP(result),0,FALSE,TRUE);
6559 size = AOP_SIZE(right);
6562 sprintf(buffer,"(%s + %d)",l+1,offset);
6564 sprintf(buffer,"%s",l+1);
6565 emitcode("mov","%s,%s",buffer,
6566 aopGet(AOP(right),offset++,FALSE,FALSE));
6569 freeAsmop(right,NULL,ic,TRUE);
6570 freeAsmop(result,NULL,ic,TRUE);
6573 /*-----------------------------------------------------------------*/
6574 /* genNearPointerSet - emitcode for near pointer put */
6575 /*-----------------------------------------------------------------*/
6576 static void genNearPointerSet (operand *right,
6584 link *ptype = operandType(result);
6586 retype= getSpec(operandType(right));
6588 aopOp(result,ic,FALSE);
6590 /* if the result is rematerializable &
6591 in data space & not a bit variable */
6592 if (AOP_TYPE(result) == AOP_IMMD &&
6593 DCL_TYPE(ptype) == POINTER &&
6594 !IS_BITVAR(retype)) {
6595 genDataPointerSet (right,result,ic);
6599 /* if the value is already in a pointer register
6600 then don't need anything more */
6601 if (!AOP_INPREG(AOP(result))) {
6602 /* otherwise get a free pointer register */
6604 preg = getFreePtr(ic,&aop,FALSE);
6605 emitcode("mov","%s,%s",
6607 aopGet(AOP(result),0,FALSE,TRUE));
6608 rname = preg->name ;
6610 rname = aopGet(AOP(result),0,FALSE,FALSE);
6612 freeAsmop(result,NULL,ic,TRUE);
6613 aopOp (right,ic,FALSE);
6615 /* if bitfield then unpack the bits */
6616 if (IS_BITVAR(retype))
6617 genPackBits (retype,right,rname,POINTER);
6619 /* we have can just get the values */
6620 int size = AOP_SIZE(right);
6624 l = aopGet(AOP(right),offset,FALSE,TRUE);
6627 emitcode("mov","@%s,a",rname);
6629 emitcode("mov","@%s,%s",rname,l);
6631 emitcode("inc","%s",rname);
6636 /* now some housekeeping stuff */
6638 /* we had to allocate for this iCode */
6639 freeAsmop(NULL,aop,ic,TRUE);
6641 /* we did not allocate which means left
6642 already in a pointer register, then
6643 if size > 0 && this could be used again
6644 we have to point it back to where it
6646 if (AOP_SIZE(right) > 1 &&
6647 !OP_SYMBOL(result)->remat &&
6648 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6650 int size = AOP_SIZE(right) - 1;
6652 emitcode("dec","%s",rname);
6657 freeAsmop(right,NULL,ic,TRUE);
6662 /*-----------------------------------------------------------------*/
6663 /* genPagedPointerSet - emitcode for Paged pointer put */
6664 /*-----------------------------------------------------------------*/
6665 static void genPagedPointerSet (operand *right,
6674 retype= getSpec(operandType(right));
6676 aopOp(result,ic,FALSE);
6678 /* if the value is already in a pointer register
6679 then don't need anything more */
6680 if (!AOP_INPREG(AOP(result))) {
6681 /* otherwise get a free pointer register */
6683 preg = getFreePtr(ic,&aop,FALSE);
6684 emitcode("mov","%s,%s",
6686 aopGet(AOP(result),0,FALSE,TRUE));
6687 rname = preg->name ;
6689 rname = aopGet(AOP(result),0,FALSE,FALSE);
6691 freeAsmop(result,NULL,ic,TRUE);
6692 aopOp (right,ic,FALSE);
6694 /* if bitfield then unpack the bits */
6695 if (IS_BITVAR(retype))
6696 genPackBits (retype,right,rname,PPOINTER);
6698 /* we have can just get the values */
6699 int size = AOP_SIZE(right);
6703 l = aopGet(AOP(right),offset,FALSE,TRUE);
6706 emitcode("movx","@%s,a",rname);
6709 emitcode("inc","%s",rname);
6715 /* now some housekeeping stuff */
6717 /* we had to allocate for this iCode */
6718 freeAsmop(NULL,aop,ic,TRUE);
6720 /* we did not allocate which means left
6721 already in a pointer register, then
6722 if size > 0 && this could be used again
6723 we have to point it back to where it
6725 if (AOP_SIZE(right) > 1 &&
6726 !OP_SYMBOL(result)->remat &&
6727 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6729 int size = AOP_SIZE(right) - 1;
6731 emitcode("dec","%s",rname);
6736 freeAsmop(right,NULL,ic,TRUE);
6741 /*-----------------------------------------------------------------*/
6742 /* genFarPointerSet - set value from far space */
6743 /*-----------------------------------------------------------------*/
6744 static void genFarPointerSet (operand *right,
6745 operand *result, iCode *ic)
6748 link *retype = getSpec(operandType(right));
6750 aopOp(result,ic,FALSE);
6752 /* if the operand is already in dptr
6753 then we do nothing else we move the value to dptr */
6754 if (AOP_TYPE(result) != AOP_STR) {
6755 /* if this is remateriazable */
6756 if (AOP_TYPE(result) == AOP_IMMD)
6757 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6758 else { /* we need to get it byte by byte */
6759 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6760 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6761 if (options.model == MODEL_FLAT24)
6763 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6767 /* so dptr know contains the address */
6768 freeAsmop(result,NULL,ic,TRUE);
6769 aopOp(right,ic,FALSE);
6771 /* if bit then unpack */
6772 if (IS_BITVAR(retype))
6773 genPackBits(retype,right,"dptr",FPOINTER);
6775 size = AOP_SIZE(right);
6779 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6781 emitcode("movx","@dptr,a");
6783 emitcode("inc","dptr");
6787 freeAsmop(right,NULL,ic,TRUE);
6790 /*-----------------------------------------------------------------*/
6791 /* genGenPointerSet - set value from generic pointer space */
6792 /*-----------------------------------------------------------------*/
6793 static void genGenPointerSet (operand *right,
6794 operand *result, iCode *ic)
6797 link *retype = getSpec(operandType(right));
6799 aopOp(result,ic,FALSE);
6801 /* if the operand is already in dptr
6802 then we do nothing else we move the value to dptr */
6803 if (AOP_TYPE(result) != AOP_STR) {
6804 /* if this is remateriazable */
6805 if (AOP_TYPE(result) == AOP_IMMD) {
6806 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6807 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
6809 else { /* we need to get it byte by byte */
6810 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6811 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6812 if (options.model == MODEL_FLAT24)
6814 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6815 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
6819 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
6823 /* so dptr know contains the address */
6824 freeAsmop(result,NULL,ic,TRUE);
6825 aopOp(right,ic,FALSE);
6827 /* if bit then unpack */
6828 if (IS_BITVAR(retype))
6829 genPackBits(retype,right,"dptr",GPOINTER);
6831 size = AOP_SIZE(right);
6835 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6837 emitcode("lcall","__gptrput");
6839 emitcode("inc","dptr");
6843 freeAsmop(right,NULL,ic,TRUE);
6846 /*-----------------------------------------------------------------*/
6847 /* genPointerSet - stores the value into a pointer location */
6848 /*-----------------------------------------------------------------*/
6849 static void genPointerSet (iCode *ic)
6851 operand *right, *result ;
6855 right = IC_RIGHT(ic);
6856 result = IC_RESULT(ic) ;
6858 /* depending on the type of pointer we need to
6859 move it to the correct pointer register */
6860 type = operandType(result);
6861 etype = getSpec(type);
6862 /* if left is of type of pointer then it is simple */
6863 if (IS_PTR(type) && !IS_FUNC(type->next)) {
6864 p_type = DCL_TYPE(type);
6867 /* we have to go by the storage class */
6868 p_type = PTR_TYPE(SPEC_OCLS(etype));
6870 /* if (SPEC_OCLS(etype)->codesp ) { */
6871 /* p_type = CPOINTER ; */
6874 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6875 /* p_type = FPOINTER ; */
6877 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6878 /* p_type = PPOINTER ; */
6880 /* if (SPEC_OCLS(etype) == idata ) */
6881 /* p_type = IPOINTER ; */
6883 /* p_type = POINTER ; */
6886 /* now that we have the pointer type we assign
6887 the pointer values */
6892 genNearPointerSet (right,result,ic);
6896 genPagedPointerSet (right,result,ic);
6900 genFarPointerSet (right,result,ic);
6904 genGenPointerSet (right,result,ic);
6910 /*-----------------------------------------------------------------*/
6911 /* genIfx - generate code for Ifx statement */
6912 /*-----------------------------------------------------------------*/
6913 static void genIfx (iCode *ic, iCode *popIc)
6915 operand *cond = IC_COND(ic);
6918 aopOp(cond,ic,FALSE);
6920 /* get the value into acc */
6921 if (AOP_TYPE(cond) != AOP_CRY)
6925 /* the result is now in the accumulator */
6926 freeAsmop(cond,NULL,ic,TRUE);
6928 /* if there was something to be popped then do it */
6932 /* if the condition is a bit variable */
6933 if (isbit && IS_ITEMP(cond) &&
6935 genIfxJump(ic,SPIL_LOC(cond)->rname);
6937 if (isbit && !IS_ITEMP(cond))
6938 genIfxJump(ic,OP_SYMBOL(cond)->rname);
6945 /*-----------------------------------------------------------------*/
6946 /* genAddrOf - generates code for address of */
6947 /*-----------------------------------------------------------------*/
6948 static void genAddrOf (iCode *ic)
6950 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
6953 aopOp(IC_RESULT(ic),ic,FALSE);
6955 /* if the operand is on the stack then we
6956 need to get the stack offset of this
6959 /* if it has an offset then we need to compute
6962 emitcode("mov","a,_bp");
6963 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
6964 aopPut(AOP(IC_RESULT(ic)),"a",0);
6966 /* we can just move _bp */
6967 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
6969 /* fill the result with zero */
6970 size = AOP_SIZE(IC_RESULT(ic)) - 1;
6973 if (options.stack10bit && size < (FPTRSIZE - 1))
6976 "*** warning: pointer to stack var truncated.\n");
6983 if (options.stack10bit && offset == 2)
6985 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
6989 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
6996 /* object not on stack then we need the name */
6997 size = AOP_SIZE(IC_RESULT(ic));
7001 char s[SDCC_NAME_MAX];
7003 sprintf(s,"#(%s >> %d)",
7007 sprintf(s,"#%s",sym->rname);
7008 aopPut(AOP(IC_RESULT(ic)),s,offset++);
7012 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7016 /*-----------------------------------------------------------------*/
7017 /* genFarFarAssign - assignment when both are in far space */
7018 /*-----------------------------------------------------------------*/
7019 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7021 int size = AOP_SIZE(right);
7024 /* first push the right side on to the stack */
7026 l = aopGet(AOP(right),offset++,FALSE,FALSE);
7028 emitcode ("push","acc");
7031 freeAsmop(right,NULL,ic,FALSE);
7032 /* now assign DPTR to result */
7033 aopOp(result,ic,FALSE);
7034 size = AOP_SIZE(result);
7036 emitcode ("pop","acc");
7037 aopPut(AOP(result),"a",--offset);
7039 freeAsmop(result,NULL,ic,FALSE);
7043 /*-----------------------------------------------------------------*/
7044 /* genAssign - generate code for assignment */
7045 /*-----------------------------------------------------------------*/
7046 static void genAssign (iCode *ic)
7048 operand *result, *right;
7050 unsigned long lit = 0L;
7052 result = IC_RESULT(ic);
7053 right = IC_RIGHT(ic) ;
7055 /* if they are the same */
7056 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7059 aopOp(right,ic,FALSE);
7061 /* special case both in far space */
7062 if ((AOP_TYPE(right) == AOP_DPTR ||
7063 AOP_TYPE(right) == AOP_DPTR2) &&
7064 IS_TRUE_SYMOP(result) &&
7065 isOperandInFarSpace(result)) {
7067 genFarFarAssign (result,right,ic);
7071 aopOp(result,ic,TRUE);
7073 /* if they are the same registers */
7074 if (sameRegs(AOP(right),AOP(result)))
7077 /* if the result is a bit */
7078 if (AOP_TYPE(result) == AOP_CRY) {
7080 /* if the right size is a literal then
7081 we know what the value is */
7082 if (AOP_TYPE(right) == AOP_LIT) {
7083 if (((int) operandLitValue(right)))
7084 aopPut(AOP(result),one,0);
7086 aopPut(AOP(result),zero,0);
7090 /* the right is also a bit variable */
7091 if (AOP_TYPE(right) == AOP_CRY) {
7092 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7093 aopPut(AOP(result),"c",0);
7099 aopPut(AOP(result),"a",0);
7103 /* bit variables done */
7105 size = AOP_SIZE(result);
7107 if(AOP_TYPE(right) == AOP_LIT)
7108 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7110 (AOP_TYPE(result) != AOP_REG) &&
7111 (AOP_TYPE(right) == AOP_LIT) &&
7112 !IS_FLOAT(operandType(right)) &&
7114 emitcode("clr","a");
7116 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7117 aopPut(AOP(result),"a",size);
7120 aopGet(AOP(right),size,FALSE,FALSE),
7126 aopGet(AOP(right),offset,FALSE,FALSE),
7133 freeAsmop (right,NULL,ic,TRUE);
7134 freeAsmop (result,NULL,ic,TRUE);
7137 /*-----------------------------------------------------------------*/
7138 /* genJumpTab - genrates code for jump table */
7139 /*-----------------------------------------------------------------*/
7140 static void genJumpTab (iCode *ic)
7145 aopOp(IC_JTCOND(ic),ic,FALSE);
7146 /* get the condition into accumulator */
7147 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
7149 /* multiply by three */
7150 emitcode("add","a,acc");
7151 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
7152 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7154 jtab = newiTempLabel(NULL);
7155 emitcode("mov","dptr,#%05d$",jtab->key+100);
7156 emitcode("jmp","@a+dptr");
7157 emitcode("","%05d$:",jtab->key+100);
7158 /* now generate the jump labels */
7159 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
7160 jtab = setNextItem(IC_JTLABELS(ic)))
7161 emitcode("ljmp","%05d$",jtab->key+100);
7165 /*-----------------------------------------------------------------*/
7166 /* genCast - gen code for casting */
7167 /*-----------------------------------------------------------------*/
7168 static void genCast (iCode *ic)
7170 operand *result = IC_RESULT(ic);
7171 link *ctype = operandType(IC_LEFT(ic));
7172 link *rtype = operandType(IC_RIGHT(ic));
7173 operand *right = IC_RIGHT(ic);
7176 /* if they are equivalent then do nothing */
7177 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
7180 aopOp(right,ic,FALSE) ;
7181 aopOp(result,ic,FALSE);
7183 /* if the result is a bit */
7184 if (AOP_TYPE(result) == AOP_CRY) {
7185 /* if the right size is a literal then
7186 we know what the value is */
7187 if (AOP_TYPE(right) == AOP_LIT) {
7188 if (((int) operandLitValue(right)))
7189 aopPut(AOP(result),one,0);
7191 aopPut(AOP(result),zero,0);
7196 /* the right is also a bit variable */
7197 if (AOP_TYPE(right) == AOP_CRY) {
7198 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7199 aopPut(AOP(result),"c",0);
7205 aopPut(AOP(result),"a",0);
7209 /* if they are the same size : or less */
7210 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
7212 /* if they are in the same place */
7213 if (sameRegs(AOP(right),AOP(result)))
7216 /* if they in different places then copy */
7217 size = AOP_SIZE(result);
7221 aopGet(AOP(right),offset,FALSE,FALSE),
7229 /* if the result is of type pointer */
7230 if (IS_PTR(ctype)) {
7233 link *type = operandType(right);
7234 link *etype = getSpec(type);
7236 /* pointer to generic pointer */
7237 if (IS_GENPTR(ctype)) {
7241 p_type = DCL_TYPE(type);
7243 /* we have to go by the storage class */
7244 p_type = PTR_TYPE(SPEC_OCLS(etype));
7247 /* the first two bytes are known */
7248 size = GPTRSIZE - 1;
7252 aopGet(AOP(right),offset,FALSE,FALSE),
7256 /* the last byte depending on type */
7273 /* this should never happen */
7274 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7275 "got unknown pointer type");
7278 aopPut(AOP(result),l, GPTRSIZE - 1);
7282 /* just copy the pointers */
7283 size = AOP_SIZE(result);
7287 aopGet(AOP(right),offset,FALSE,FALSE),
7294 /* so we now know that the size of destination is greater
7295 than the size of the source */
7296 /* we move to result for the size of source */
7297 size = AOP_SIZE(right);
7301 aopGet(AOP(right),offset,FALSE,FALSE),
7306 /* now depending on the sign of the source && destination */
7307 size = AOP_SIZE(result) - AOP_SIZE(right);
7308 /* if unsigned or not an integral type */
7309 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
7311 aopPut(AOP(result),zero,offset++);
7313 /* we need to extend the sign :{ */
7314 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
7317 emitcode("rlc","a");
7318 emitcode("subb","a,acc");
7320 aopPut(AOP(result),"a",offset++);
7323 /* we are done hurray !!!! */
7326 freeAsmop(right,NULL,ic,TRUE);
7327 freeAsmop(result,NULL,ic,TRUE);
7331 /*-----------------------------------------------------------------*/
7332 /* genDjnz - generate decrement & jump if not zero instrucion */
7333 /*-----------------------------------------------------------------*/
7334 static int genDjnz (iCode *ic, iCode *ifx)
7340 /* if the if condition has a false label
7341 then we cannot save */
7345 /* if the minus is not of the form
7347 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
7348 !IS_OP_LITERAL(IC_RIGHT(ic)))
7351 if (operandLitValue(IC_RIGHT(ic)) != 1)
7354 /* if the size of this greater than one then no
7356 if (getSize(operandType(IC_RESULT(ic))) > 1)
7359 /* otherwise we can save BIG */
7360 lbl = newiTempLabel(NULL);
7361 lbl1= newiTempLabel(NULL);
7363 aopOp(IC_RESULT(ic),ic,FALSE);
7365 if (IS_AOP_PREG(IC_RESULT(ic))) {
7366 emitcode("dec","%s",
7367 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7368 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7369 emitcode("jnz","%05d$",lbl->key+100);
7371 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
7374 emitcode ("sjmp","%05d$",lbl1->key+100);
7375 emitcode ("","%05d$:",lbl->key+100);
7376 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
7377 emitcode ("","%05d$:",lbl1->key+100);
7379 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7384 /*-----------------------------------------------------------------*/
7385 /* genReceive - generate code for a receive iCode */
7386 /*-----------------------------------------------------------------*/
7387 static void genReceive (iCode *ic)
7389 if (isOperandInFarSpace(IC_RESULT(ic)) &&
7390 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
7391 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
7393 int size = getSize(operandType(IC_RESULT(ic)));
7394 int offset = fReturnSize - size;
7396 emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
7397 fReturn[fReturnSize - offset - 1] : "acc"));
7400 aopOp(IC_RESULT(ic),ic,FALSE);
7401 size = AOP_SIZE(IC_RESULT(ic));
7404 emitcode ("pop","acc");
7405 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
7410 aopOp(IC_RESULT(ic),ic,FALSE);
7412 assignResultValue(IC_RESULT(ic));
7415 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7418 /*-----------------------------------------------------------------*/
7419 /* gen51Code - generate code for 8051 based controllers */
7420 /*-----------------------------------------------------------------*/
7421 void gen51Code (iCode *lic)
7426 lineHead = lineCurr = NULL;
7428 /* print the allocation information */
7430 printAllocInfo( currFunc, codeOutFile);
7431 /* if debug information required */
7432 /* if (options.debug && currFunc) { */
7434 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
7436 if (IS_STATIC(currFunc->etype))
7437 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
7439 emitcode("","G$%s$0$0 ==.",currFunc->name);
7442 /* stack pointer name */
7443 if (options.useXstack)
7449 for (ic = lic ; ic ; ic = ic->next ) {
7451 if ( cln != ic->lineno ) {
7452 if ( options.debug ) {
7454 emitcode("","C$%s$%d$%d$%d ==.",
7455 ic->filename,ic->lineno,
7456 ic->level,ic->block);
7459 emitcode(";","%s %d",ic->filename,ic->lineno);
7462 /* if the result is marked as
7463 spilt and rematerializable or code for
7464 this has already been generated then
7466 if (resultRemat(ic) || ic->generated )
7469 /* depending on the operation */
7488 /* IPOP happens only when trying to restore a
7489 spilt live range, if there is an ifx statement
7490 following this pop then the if statement might
7491 be using some of the registers being popped which
7492 would destory the contents of the register so
7493 we need to check for this condition and handle it */
7495 ic->next->op == IFX &&
7496 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
7497 genIfx (ic->next,ic);
7515 genEndFunction (ic);
7535 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
7552 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
7556 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
7563 /* note these two are xlated by algebraic equivalence
7564 during parsing SDCC.y */
7565 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7566 "got '>=' or '<=' shouldn't have come here");
7570 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
7582 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
7586 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
7590 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
7617 case GET_VALUE_AT_ADDRESS:
7622 if (POINTER_SET(ic))
7649 addSet(&_G.sendSet,ic);
7654 /* piCode(ic,stdout); */
7660 /* now we are ready to call the
7661 peep hole optimizer */
7662 if (!options.nopeep)
7663 peepHole (&lineHead);
7665 /* now do the actual printing */
7666 printLine (lineHead,codeOutFile);