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 emitcode("mov","r0,%s",spname);
2110 emitcode("mov","a,_bp");
2111 emitcode("movx","@r0,a");
2112 emitcode("inc","%s",spname);
2116 /* set up the stack */
2117 emitcode ("push","_bp"); /* save the callers stack */
2119 emitcode ("mov","_bp,%s",spname);
2122 /* adjust the stack for the function */
2127 werror(W_STACK_OVERFLOW,sym->name);
2129 if (i > 3 && sym->recvSize < 4) {
2131 emitcode ("mov","a,sp");
2132 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2133 emitcode ("mov","sp,a");
2138 emitcode("inc","sp");
2143 emitcode ("mov","a,_spx");
2144 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2145 emitcode ("mov","_spx,a");
2150 /*-----------------------------------------------------------------*/
2151 /* genEndFunction - generates epilogue for functions */
2152 /*-----------------------------------------------------------------*/
2153 static void genEndFunction (iCode *ic)
2155 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2157 if (IS_RENT(sym->etype) || options.stackAuto)
2159 emitcode ("mov","%s,_bp",spname);
2162 /* if use external stack but some variables were
2163 added to the local stack then decrement the
2165 if (options.useXstack && sym->stack) {
2166 emitcode("mov","a,sp");
2167 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2168 emitcode("mov","sp,a");
2172 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2173 if (options.useXstack) {
2174 emitcode("mov","r0,%s",spname);
2175 emitcode("movx","a,@r0");
2176 emitcode("mov","_bp,a");
2177 emitcode("dec","%s",spname);
2181 emitcode ("pop","_bp");
2185 /* restore the register bank */
2186 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2187 emitcode ("pop","psw");
2189 if (IS_ISR(sym->etype)) {
2191 /* now we need to restore the registers */
2192 /* if this isr has no bank i.e. is going to
2193 run with bank 0 , then we need to save more
2195 if (!SPEC_BANK(sym->etype)) {
2197 /* if this function does not call any other
2198 function then we can be economical and
2199 save only those registers that are used */
2200 if (! sym->hasFcall) {
2203 /* if any registers used */
2204 if (sym->regsUsed) {
2205 /* save the registers used */
2206 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2207 if (bitVectBitValue(sym->regsUsed,i) ||
2208 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2209 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
2214 /* this function has a function call cannot
2215 determines register usage so we will have the
2217 unsaverbank(0,ic,FALSE);
2221 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2223 if (options.stack10bit)
2225 emitcode ("pop", "dpx1");
2226 emitcode ("pop", "dph1");
2227 emitcode ("pop", "dpl1");
2229 emitcode ("pop", "dps");
2230 emitcode ("pop", "dpx");
2232 if (!inExcludeList("dph"))
2233 emitcode ("pop","dph");
2234 if (!inExcludeList("dpl"))
2235 emitcode ("pop","dpl");
2236 if (!inExcludeList("b"))
2237 emitcode ("pop","b");
2238 if (!inExcludeList("acc"))
2239 emitcode ("pop","acc");
2241 if (SPEC_CRTCL(sym->etype))
2242 emitcode("setb","ea");
2244 /* if debug then send end of function */
2245 /* if (options.debug && currFunc) { */
2248 emitcode("","C$%s$%d$%d$%d ==.",
2249 ic->filename,currFunc->lastLine,
2250 ic->level,ic->block);
2251 if (IS_STATIC(currFunc->etype))
2252 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2254 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2258 emitcode ("reti","");
2261 if (SPEC_CRTCL(sym->etype))
2262 emitcode("setb","ea");
2264 if (sym->calleeSave) {
2267 /* if any registers used */
2268 if (sym->regsUsed) {
2269 /* save the registers used */
2270 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2271 if (bitVectBitValue(sym->regsUsed,i) ||
2272 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2273 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
2279 /* if debug then send end of function */
2282 emitcode("","C$%s$%d$%d$%d ==.",
2283 ic->filename,currFunc->lastLine,
2284 ic->level,ic->block);
2285 if (IS_STATIC(currFunc->etype))
2286 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2288 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2292 emitcode ("ret","");
2297 /*-----------------------------------------------------------------*/
2298 /* genRet - generate code for return statement */
2299 /*-----------------------------------------------------------------*/
2300 static void genRet (iCode *ic)
2302 int size,offset = 0 , pushed = 0;
2304 /* if we have no return value then
2305 just generate the "ret" */
2309 /* we have something to return then
2310 move the return value into place */
2311 aopOp(IC_LEFT(ic),ic,FALSE);
2312 size = AOP_SIZE(IC_LEFT(ic));
2316 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2318 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2320 emitcode("push","%s",l);
2323 l = aopGet(AOP(IC_LEFT(ic)),offset,
2325 if (strcmp(fReturn[offset],l))
2326 emitcode("mov","%s,%s",fReturn[offset++],l);
2333 if (strcmp(fReturn[pushed],"a"))
2334 emitcode("pop",fReturn[pushed]);
2336 emitcode("pop","acc");
2339 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2342 /* generate a jump to the return label
2343 if the next is not the return statement */
2344 if (!(ic->next && ic->next->op == LABEL &&
2345 IC_LABEL(ic->next) == returnLabel))
2347 emitcode("ljmp","%05d$",(returnLabel->key+100));
2351 /*-----------------------------------------------------------------*/
2352 /* genLabel - generates a label */
2353 /*-----------------------------------------------------------------*/
2354 static void genLabel (iCode *ic)
2356 /* special case never generate */
2357 if (IC_LABEL(ic) == entryLabel)
2360 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2363 /*-----------------------------------------------------------------*/
2364 /* genGoto - generates a ljmp */
2365 /*-----------------------------------------------------------------*/
2366 static void genGoto (iCode *ic)
2368 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2371 /*-----------------------------------------------------------------*/
2372 /* findLabelBackwards: walks back through the iCode chain looking */
2373 /* for the given label. Returns number of iCode instructions */
2374 /* between that label and given ic. */
2375 /* Returns zero if label not found. */
2376 /*-----------------------------------------------------------------*/
2377 static int findLabelBackwards(iCode *ic, int key)
2386 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2388 /* printf("findLabelBackwards = %d\n", count); */
2396 /*-----------------------------------------------------------------*/
2397 /* genPlusIncr :- does addition with increment if possible */
2398 /*-----------------------------------------------------------------*/
2399 static bool genPlusIncr (iCode *ic)
2401 unsigned int icount ;
2402 unsigned int size = getDataSize(IC_RESULT(ic));
2404 /* will try to generate an increment */
2405 /* if the right side is not a literal
2407 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2410 /* if the literal value of the right hand side
2411 is greater than 4 then it is not worth it */
2412 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2415 /* if increment 16 bits in register */
2416 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2423 /* If the next instruction is a goto and the goto target
2424 * is < 10 instructions previous to this, we can generate
2425 * jumps straight to that target.
2427 if (ic->next && ic->next->op == GOTO
2428 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2429 && labelRange <= 10 )
2431 emitcode(";", "tail increment optimized");
2432 tlbl = IC_LABEL(ic->next);
2437 tlbl = newiTempLabel(NULL);
2440 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2441 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2442 IS_AOP_PREG(IC_RESULT(ic)))
2443 emitcode("cjne","%s,#0x00,%05d$"
2444 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2447 emitcode("clr","a");
2448 emitcode("cjne","a,%s,%05d$"
2449 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2453 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2456 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2457 IS_AOP_PREG(IC_RESULT(ic)))
2458 emitcode("cjne","%s,#0x00,%05d$"
2459 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2462 emitcode("cjne","a,%s,%05d$"
2463 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2466 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2470 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2471 IS_AOP_PREG(IC_RESULT(ic)))
2472 emitcode("cjne","%s,#0x00,%05d$"
2473 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2476 emitcode("cjne","a,%s,%05d$"
2477 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2480 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2485 emitcode("","%05d$:",tlbl->key+100);
2490 /* if the sizes are greater than 1 then we cannot */
2491 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2492 AOP_SIZE(IC_LEFT(ic)) > 1 )
2495 /* we can if the aops of the left & result match or
2496 if they are in registers and the registers are the
2498 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2501 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2502 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2503 aopPut(AOP(IC_RESULT(ic)),"a",0);
2507 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2516 /*-----------------------------------------------------------------*/
2517 /* outBitAcc - output a bit in acc */
2518 /*-----------------------------------------------------------------*/
2519 static void outBitAcc(operand *result)
2521 symbol *tlbl = newiTempLabel(NULL);
2522 /* if the result is a bit */
2523 if (AOP_TYPE(result) == AOP_CRY){
2524 aopPut(AOP(result),"a",0);
2527 emitcode("jz","%05d$",tlbl->key+100);
2528 emitcode("mov","a,%s",one);
2529 emitcode("","%05d$:",tlbl->key+100);
2534 /*-----------------------------------------------------------------*/
2535 /* genPlusBits - generates code for addition of two bits */
2536 /*-----------------------------------------------------------------*/
2537 static void genPlusBits (iCode *ic)
2539 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2540 symbol *lbl = newiTempLabel(NULL);
2541 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2542 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2543 emitcode("cpl","c");
2544 emitcode("","%05d$:",(lbl->key+100));
2545 outBitC(IC_RESULT(ic));
2548 emitcode("clr","a");
2549 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2550 emitcode("rlc","a");
2551 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2552 emitcode("addc","a,#0x00");
2553 outAcc(IC_RESULT(ic));
2558 /* This is the original version of this code.
2560 * This is being kept around for reference,
2561 * because I am not entirely sure I got it right...
2563 static void adjustArithmeticResult(iCode *ic)
2565 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2566 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2567 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2568 aopPut(AOP(IC_RESULT(ic)),
2569 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2572 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2573 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
2574 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2575 aopPut(AOP(IC_RESULT(ic)),
2576 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2579 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2580 AOP_SIZE(IC_LEFT(ic)) < 3 &&
2581 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
2582 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2583 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2585 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2586 aopPut(AOP(IC_RESULT(ic)),buffer,2);
2590 /* This is the pure and virtuous version of this code.
2591 * I'm pretty certain it's right, but not enough to toss the old
2594 static void adjustArithmeticResult(iCode *ic)
2596 if (opIsGptr(IC_RESULT(ic)) &&
2597 opIsGptr(IC_LEFT(ic)) &&
2598 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2600 aopPut(AOP(IC_RESULT(ic)),
2601 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
2605 if (opIsGptr(IC_RESULT(ic)) &&
2606 opIsGptr(IC_RIGHT(ic)) &&
2607 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2609 aopPut(AOP(IC_RESULT(ic)),
2610 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
2614 if (opIsGptr(IC_RESULT(ic)) &&
2615 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2616 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2617 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2618 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2620 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2621 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2626 /*-----------------------------------------------------------------*/
2627 /* genPlus - generates code for addition */
2628 /*-----------------------------------------------------------------*/
2629 static void genPlus (iCode *ic)
2631 int size, offset = 0;
2633 /* special cases :- */
2635 aopOp (IC_LEFT(ic),ic,FALSE);
2636 aopOp (IC_RIGHT(ic),ic,FALSE);
2637 aopOp (IC_RESULT(ic),ic,TRUE);
2639 /* if literal, literal on the right or
2640 if left requires ACC or right is already
2642 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2643 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2644 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2645 operand *t = IC_RIGHT(ic);
2646 IC_RIGHT(ic) = IC_LEFT(ic);
2650 /* if both left & right are in bit
2652 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2653 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2658 /* if left in bit space & right literal */
2659 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2660 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2661 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2662 /* if result in bit space */
2663 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2664 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
2665 emitcode("cpl","c");
2666 outBitC(IC_RESULT(ic));
2668 size = getDataSize(IC_RESULT(ic));
2670 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2671 emitcode("addc","a,#00");
2672 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2678 /* if I can do an increment instead
2679 of add then GOOD for ME */
2680 if (genPlusIncr (ic) == TRUE)
2683 size = getDataSize(IC_RESULT(ic));
2686 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2687 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2689 emitcode("add","a,%s",
2690 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2692 emitcode("addc","a,%s",
2693 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2695 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2697 emitcode("add","a,%s",
2698 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2700 emitcode("addc","a,%s",
2701 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2703 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2706 adjustArithmeticResult(ic);
2709 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2710 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2711 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2714 /*-----------------------------------------------------------------*/
2715 /* genMinusDec :- does subtraction with deccrement if possible */
2716 /*-----------------------------------------------------------------*/
2717 static bool genMinusDec (iCode *ic)
2719 unsigned int icount ;
2720 unsigned int size = getDataSize(IC_RESULT(ic));
2722 /* will try to generate an increment */
2723 /* if the right side is not a literal
2725 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2728 /* if the literal value of the right hand side
2729 is greater than 4 then it is not worth it */
2730 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2733 /* if decrement 16 bits in register */
2734 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2741 /* If the next instruction is a goto and the goto target
2742 * is <= 10 instructions previous to this, we can generate
2743 * jumps straight to that target.
2745 if (ic->next && ic->next->op == GOTO
2746 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2747 && labelRange <= 10 )
2749 emitcode(";", "tail decrement optimized");
2750 tlbl = IC_LABEL(ic->next);
2755 tlbl = newiTempLabel(NULL);
2759 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2760 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2761 IS_AOP_PREG(IC_RESULT(ic)))
2762 emitcode("cjne","%s,#0xff,%05d$"
2763 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2766 emitcode("mov","a,#0xff");
2767 emitcode("cjne","a,%s,%05d$"
2768 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2771 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2774 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2775 IS_AOP_PREG(IC_RESULT(ic)))
2776 emitcode("cjne","%s,#0xff,%05d$"
2777 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2780 emitcode("cjne","a,%s,%05d$"
2781 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2784 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2788 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2789 IS_AOP_PREG(IC_RESULT(ic)))
2790 emitcode("cjne","%s,#0xff,%05d$"
2791 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2794 emitcode("cjne","a,%s,%05d$"
2795 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2798 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2802 emitcode("","%05d$:",tlbl->key+100);
2807 /* if the sizes are greater than 1 then we cannot */
2808 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2809 AOP_SIZE(IC_LEFT(ic)) > 1 )
2812 /* we can if the aops of the left & result match or
2813 if they are in registers and the registers are the
2815 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2818 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2826 /*-----------------------------------------------------------------*/
2827 /* addSign - complete with sign */
2828 /*-----------------------------------------------------------------*/
2829 static void addSign(operand *result, int offset, int sign)
2831 int size = (getDataSize(result) - offset);
2834 emitcode("rlc","a");
2835 emitcode("subb","a,acc");
2837 aopPut(AOP(result),"a",offset++);
2840 aopPut(AOP(result),zero,offset++);
2844 /*-----------------------------------------------------------------*/
2845 /* genMinusBits - generates code for subtraction of two bits */
2846 /*-----------------------------------------------------------------*/
2847 static void genMinusBits (iCode *ic)
2849 symbol *lbl = newiTempLabel(NULL);
2850 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2851 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2852 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2853 emitcode("cpl","c");
2854 emitcode("","%05d$:",(lbl->key+100));
2855 outBitC(IC_RESULT(ic));
2858 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2859 emitcode("subb","a,acc");
2860 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
2861 emitcode("inc","a");
2862 emitcode("","%05d$:",(lbl->key+100));
2863 aopPut(AOP(IC_RESULT(ic)),"a",0);
2864 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
2868 /*-----------------------------------------------------------------*/
2869 /* genMinus - generates code for subtraction */
2870 /*-----------------------------------------------------------------*/
2871 static void genMinus (iCode *ic)
2873 int size, offset = 0;
2874 unsigned long lit = 0L;
2876 aopOp (IC_LEFT(ic),ic,FALSE);
2877 aopOp (IC_RIGHT(ic),ic,FALSE);
2878 aopOp (IC_RESULT(ic),ic,TRUE);
2880 /* special cases :- */
2881 /* if both left & right are in bit space */
2882 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2883 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2888 /* if I can do an decrement instead
2889 of subtract then GOOD for ME */
2890 if (genMinusDec (ic) == TRUE)
2893 size = getDataSize(IC_RESULT(ic));
2895 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
2899 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2903 /* if literal, add a,#-lit, else normal subb */
2905 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2906 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2907 emitcode("subb","a,%s",
2908 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2910 /* first add without previous c */
2912 emitcode("add","a,#0x%02x",
2913 (unsigned int)(lit & 0x0FFL));
2915 emitcode("addc","a,#0x%02x",
2916 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
2918 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2921 adjustArithmeticResult(ic);
2924 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2925 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2926 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2930 /*-----------------------------------------------------------------*/
2931 /* genMultbits :- multiplication of bits */
2932 /*-----------------------------------------------------------------*/
2933 static void genMultbits (operand *left,
2937 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2938 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
2943 /*-----------------------------------------------------------------*/
2944 /* genMultOneByte : 8 bit multiplication & division */
2945 /*-----------------------------------------------------------------*/
2946 static void genMultOneByte (operand *left,
2950 link *opetype = operandType(result);
2955 /* (if two literals, the value is computed before) */
2956 /* if one literal, literal on the right */
2957 if (AOP_TYPE(left) == AOP_LIT){
2963 size = AOP_SIZE(result);
2964 /* signed or unsigned */
2965 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2966 l = aopGet(AOP(left),0,FALSE,FALSE);
2968 emitcode("mul","ab");
2969 /* if result size = 1, mul signed = mul unsigned */
2970 aopPut(AOP(result),"a",0);
2972 if (SPEC_USIGN(opetype)){
2973 aopPut(AOP(result),"b",1);
2975 /* for filling the MSBs */
2976 emitcode("clr","a");
2979 emitcode("mov","a,b");
2981 /* adjust the MSB if left or right neg */
2983 /* if one literal */
2984 if (AOP_TYPE(right) == AOP_LIT){
2985 /* AND literal negative */
2986 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
2987 /* adjust MSB (c==0 after mul) */
2988 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2992 lbl = newiTempLabel(NULL);
2993 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2994 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
2995 emitcode("","%05d$:",(lbl->key+100));
2996 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2997 lbl = newiTempLabel(NULL);
2998 emitcode("jc","%05d$",(lbl->key+100));
2999 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3000 emitcode("","%05d$:",(lbl->key+100));
3003 lbl = newiTempLabel(NULL);
3004 emitcode("xch","a,%s",aopGet(AOP(left),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(left),0,FALSE,FALSE));
3008 lbl = newiTempLabel(NULL);
3009 emitcode("jc","%05d$",(lbl->key+100));
3010 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
3011 emitcode("","%05d$:",(lbl->key+100));
3013 aopPut(AOP(result),"a",1);
3016 emitcode("rlc","a");
3017 emitcode("subb","a,acc");
3024 aopPut(AOP(result),"a",offset++);
3028 /*-----------------------------------------------------------------*/
3029 /* genMult - generates code for multiplication */
3030 /*-----------------------------------------------------------------*/
3031 static void genMult (iCode *ic)
3033 operand *left = IC_LEFT(ic);
3034 operand *right = IC_RIGHT(ic);
3035 operand *result= IC_RESULT(ic);
3037 /* assign the amsops */
3038 aopOp (left,ic,FALSE);
3039 aopOp (right,ic,FALSE);
3040 aopOp (result,ic,TRUE);
3042 /* special cases first */
3044 if (AOP_TYPE(left) == AOP_CRY &&
3045 AOP_TYPE(right)== AOP_CRY) {
3046 genMultbits(left,right,result);
3050 /* if both are of size == 1 */
3051 if (AOP_SIZE(left) == 1 &&
3052 AOP_SIZE(right) == 1 ) {
3053 genMultOneByte(left,right,result);
3057 /* should have been converted to function call */
3061 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3062 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3063 freeAsmop(result,NULL,ic,TRUE);
3066 /*-----------------------------------------------------------------*/
3067 /* genDivbits :- division of bits */
3068 /*-----------------------------------------------------------------*/
3069 static void genDivbits (operand *left,
3076 /* the result must be bit */
3077 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3078 l = aopGet(AOP(left),0,FALSE,FALSE);
3082 emitcode("div","ab");
3083 emitcode("rrc","a");
3084 aopPut(AOP(result),"c",0);
3087 /*-----------------------------------------------------------------*/
3088 /* genDivOneByte : 8 bit division */
3089 /*-----------------------------------------------------------------*/
3090 static void genDivOneByte (operand *left,
3094 link *opetype = operandType(result);
3099 size = AOP_SIZE(result) - 1;
3101 /* signed or unsigned */
3102 if (SPEC_USIGN(opetype)) {
3103 /* unsigned is easy */
3104 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3105 l = aopGet(AOP(left),0,FALSE,FALSE);
3107 emitcode("div","ab");
3108 aopPut(AOP(result),"a",0);
3110 aopPut(AOP(result),zero,offset++);
3114 /* signed is a little bit more difficult */
3116 /* save the signs of the operands */
3117 l = aopGet(AOP(left),0,FALSE,FALSE);
3119 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3120 emitcode("push","acc"); /* save it on the stack */
3122 /* now sign adjust for both left & right */
3123 l = aopGet(AOP(right),0,FALSE,FALSE);
3125 lbl = newiTempLabel(NULL);
3126 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3127 emitcode("cpl","a");
3128 emitcode("inc","a");
3129 emitcode("","%05d$:",(lbl->key+100));
3130 emitcode("mov","b,a");
3132 /* sign adjust left side */
3133 l = aopGet(AOP(left),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));
3142 /* now the division */
3143 emitcode("div","ab");
3144 /* we are interested in the lower order
3146 emitcode("mov","b,a");
3147 lbl = newiTempLabel(NULL);
3148 emitcode("pop","acc");
3149 /* if there was an over flow we don't
3150 adjust the sign of the result */
3151 emitcode("jb","ov,%05d$",(lbl->key+100));
3152 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3154 emitcode("clr","a");
3155 emitcode("subb","a,b");
3156 emitcode("mov","b,a");
3157 emitcode("","%05d$:",(lbl->key+100));
3159 /* now we are done */
3160 aopPut(AOP(result),"b",0);
3162 emitcode("mov","c,b.7");
3163 emitcode("subb","a,acc");
3166 aopPut(AOP(result),"a",offset++);
3170 /*-----------------------------------------------------------------*/
3171 /* genDiv - generates code for division */
3172 /*-----------------------------------------------------------------*/
3173 static void genDiv (iCode *ic)
3175 operand *left = IC_LEFT(ic);
3176 operand *right = IC_RIGHT(ic);
3177 operand *result= IC_RESULT(ic);
3179 /* assign the amsops */
3180 aopOp (left,ic,FALSE);
3181 aopOp (right,ic,FALSE);
3182 aopOp (result,ic,TRUE);
3184 /* special cases first */
3186 if (AOP_TYPE(left) == AOP_CRY &&
3187 AOP_TYPE(right)== AOP_CRY) {
3188 genDivbits(left,right,result);
3192 /* if both are of size == 1 */
3193 if (AOP_SIZE(left) == 1 &&
3194 AOP_SIZE(right) == 1 ) {
3195 genDivOneByte(left,right,result);
3199 /* should have been converted to function call */
3202 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3203 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3204 freeAsmop(result,NULL,ic,TRUE);
3207 /*-----------------------------------------------------------------*/
3208 /* genModbits :- modulus of bits */
3209 /*-----------------------------------------------------------------*/
3210 static void genModbits (operand *left,
3217 /* the result must be bit */
3218 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3219 l = aopGet(AOP(left),0,FALSE,FALSE);
3223 emitcode("div","ab");
3224 emitcode("mov","a,b");
3225 emitcode("rrc","a");
3226 aopPut(AOP(result),"c",0);
3229 /*-----------------------------------------------------------------*/
3230 /* genModOneByte : 8 bit modulus */
3231 /*-----------------------------------------------------------------*/
3232 static void genModOneByte (operand *left,
3236 link *opetype = operandType(result);
3240 /* signed or unsigned */
3241 if (SPEC_USIGN(opetype)) {
3242 /* unsigned is easy */
3243 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3244 l = aopGet(AOP(left),0,FALSE,FALSE);
3246 emitcode("div","ab");
3247 aopPut(AOP(result),"b",0);
3251 /* signed is a little bit more difficult */
3253 /* save the signs of the operands */
3254 l = aopGet(AOP(left),0,FALSE,FALSE);
3257 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3258 emitcode("push","acc"); /* save it on the stack */
3260 /* now sign adjust for both left & right */
3261 l = aopGet(AOP(right),0,FALSE,FALSE);
3264 lbl = newiTempLabel(NULL);
3265 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3266 emitcode("cpl","a");
3267 emitcode("inc","a");
3268 emitcode("","%05d$:",(lbl->key+100));
3269 emitcode("mov","b,a");
3271 /* sign adjust left side */
3272 l = aopGet(AOP(left),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));
3281 /* now the multiplication */
3282 emitcode("div","ab");
3283 /* we are interested in the lower order
3285 lbl = newiTempLabel(NULL);
3286 emitcode("pop","acc");
3287 /* if there was an over flow we don't
3288 adjust the sign of the result */
3289 emitcode("jb","ov,%05d$",(lbl->key+100));
3290 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3292 emitcode("clr","a");
3293 emitcode("subb","a,b");
3294 emitcode("mov","b,a");
3295 emitcode("","%05d$:",(lbl->key+100));
3297 /* now we are done */
3298 aopPut(AOP(result),"b",0);
3302 /*-----------------------------------------------------------------*/
3303 /* genMod - generates code for division */
3304 /*-----------------------------------------------------------------*/
3305 static void genMod (iCode *ic)
3307 operand *left = IC_LEFT(ic);
3308 operand *right = IC_RIGHT(ic);
3309 operand *result= IC_RESULT(ic);
3311 /* assign the amsops */
3312 aopOp (left,ic,FALSE);
3313 aopOp (right,ic,FALSE);
3314 aopOp (result,ic,TRUE);
3316 /* special cases first */
3318 if (AOP_TYPE(left) == AOP_CRY &&
3319 AOP_TYPE(right)== AOP_CRY) {
3320 genModbits(left,right,result);
3324 /* if both are of size == 1 */
3325 if (AOP_SIZE(left) == 1 &&
3326 AOP_SIZE(right) == 1 ) {
3327 genModOneByte(left,right,result);
3331 /* should have been converted to function call */
3335 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3336 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3337 freeAsmop(result,NULL,ic,TRUE);
3340 /*-----------------------------------------------------------------*/
3341 /* genIfxJump :- will create a jump depending on the ifx */
3342 /*-----------------------------------------------------------------*/
3343 static void genIfxJump (iCode *ic, char *jval)
3346 symbol *tlbl = newiTempLabel(NULL);
3349 /* if true label then we jump if condition
3351 if ( IC_TRUE(ic) ) {
3353 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3354 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3357 /* false label is present */
3358 jlbl = IC_FALSE(ic) ;
3359 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3360 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3362 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3363 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3365 emitcode(inst,"%05d$",tlbl->key+100);
3366 emitcode("ljmp","%05d$",jlbl->key+100);
3367 emitcode("","%05d$:",tlbl->key+100);
3369 /* mark the icode as generated */
3373 /*-----------------------------------------------------------------*/
3374 /* genCmp :- greater or less than comparison */
3375 /*-----------------------------------------------------------------*/
3376 static void genCmp (operand *left,operand *right,
3377 operand *result, iCode *ifx, int sign)
3379 int size, offset = 0 ;
3380 unsigned long lit = 0L;
3382 /* if left & right are bit variables */
3383 if (AOP_TYPE(left) == AOP_CRY &&
3384 AOP_TYPE(right) == AOP_CRY ) {
3385 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3386 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3388 /* subtract right from left if at the
3389 end the carry flag is set then we know that
3390 left is greater than right */
3391 size = max(AOP_SIZE(left),AOP_SIZE(right));
3393 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3394 if((size == 1) && !sign &&
3395 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3396 symbol *lbl = newiTempLabel(NULL);
3397 emitcode("cjne","%s,%s,%05d$",
3398 aopGet(AOP(left),offset,FALSE,FALSE),
3399 aopGet(AOP(right),offset,FALSE,FALSE),
3401 emitcode("","%05d$:",lbl->key+100);
3403 if(AOP_TYPE(right) == AOP_LIT){
3404 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3405 /* optimize if(x < 0) or if(x >= 0) */
3411 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE));
3412 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3413 genIfxJump (ifx,"acc.7");
3417 emitcode("rlc","a");
3424 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3425 if (sign && size == 0) {
3426 emitcode("xrl","a,#0x80");
3427 if (AOP_TYPE(right) == AOP_LIT){
3428 unsigned long lit = (unsigned long)
3429 floatFromVal(AOP(right)->aopu.aop_lit);
3430 emitcode("subb","a,#0x%02x",
3431 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3433 emitcode("mov","b,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3434 emitcode("xrl","b,#0x80");
3435 emitcode("subb","a,b");
3438 emitcode("subb","a,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3444 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3447 /* if the result is used in the next
3448 ifx conditional branch then generate
3449 code a little differently */
3451 genIfxJump (ifx,"c");
3454 /* leave the result in acc */
3458 /*-----------------------------------------------------------------*/
3459 /* genCmpGt :- greater than comparison */
3460 /*-----------------------------------------------------------------*/
3461 static void genCmpGt (iCode *ic, iCode *ifx)
3463 operand *left, *right, *result;
3464 link *letype , *retype;
3468 right= IC_RIGHT(ic);
3469 result = IC_RESULT(ic);
3471 letype = getSpec(operandType(left));
3472 retype =getSpec(operandType(right));
3473 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3474 /* assign the amsops */
3475 aopOp (left,ic,FALSE);
3476 aopOp (right,ic,FALSE);
3477 aopOp (result,ic,TRUE);
3479 genCmp(right, left, result, ifx, sign);
3481 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3482 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3483 freeAsmop(result,NULL,ic,TRUE);
3486 /*-----------------------------------------------------------------*/
3487 /* genCmpLt - less than comparisons */
3488 /*-----------------------------------------------------------------*/
3489 static void genCmpLt (iCode *ic, iCode *ifx)
3491 operand *left, *right, *result;
3492 link *letype , *retype;
3496 right= IC_RIGHT(ic);
3497 result = IC_RESULT(ic);
3499 letype = getSpec(operandType(left));
3500 retype =getSpec(operandType(right));
3501 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3503 /* assign the amsops */
3504 aopOp (left,ic,FALSE);
3505 aopOp (right,ic,FALSE);
3506 aopOp (result,ic,TRUE);
3508 genCmp(left, right, result, ifx, sign);
3510 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3511 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3512 freeAsmop(result,NULL,ic,TRUE);
3515 /*-----------------------------------------------------------------*/
3516 /* gencjneshort - compare and jump if not equal */
3517 /*-----------------------------------------------------------------*/
3518 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3520 int size = max(AOP_SIZE(left),AOP_SIZE(right));
3522 unsigned long lit = 0L;
3524 /* if the left side is a literal or
3525 if the right is in a pointer register and left
3527 if ((AOP_TYPE(left) == AOP_LIT) ||
3528 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3533 if(AOP_TYPE(right) == AOP_LIT)
3534 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3536 /* if the right side is a literal then anything goes */
3537 if (AOP_TYPE(right) == AOP_LIT &&
3538 AOP_TYPE(left) != AOP_DIR ) {
3540 emitcode("cjne","%s,%s,%05d$",
3541 aopGet(AOP(left),offset,FALSE,FALSE),
3542 aopGet(AOP(right),offset,FALSE,FALSE),
3548 /* if the right side is in a register or in direct space or
3549 if the left is a pointer register & right is not */
3550 else if (AOP_TYPE(right) == AOP_REG ||
3551 AOP_TYPE(right) == AOP_DIR ||
3552 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3553 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3555 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3556 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3557 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
3558 emitcode("jnz","%05d$",lbl->key+100);
3560 emitcode("cjne","a,%s,%05d$",
3561 aopGet(AOP(right),offset,FALSE,TRUE),
3566 /* right is a pointer reg need both a & b */
3568 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
3570 emitcode("mov","b,%s",l);
3571 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3572 emitcode("cjne","a,b,%05d$",lbl->key+100);
3578 /*-----------------------------------------------------------------*/
3579 /* gencjne - compare and jump if not equal */
3580 /*-----------------------------------------------------------------*/
3581 static void gencjne(operand *left, operand *right, symbol *lbl)
3583 symbol *tlbl = newiTempLabel(NULL);
3585 gencjneshort(left, right, lbl);
3587 emitcode("mov","a,%s",one);
3588 emitcode("sjmp","%05d$",tlbl->key+100);
3589 emitcode("","%05d$:",lbl->key+100);
3590 emitcode("clr","a");
3591 emitcode("","%05d$:",tlbl->key+100);
3594 /*-----------------------------------------------------------------*/
3595 /* genCmpEq - generates code for equal to */
3596 /*-----------------------------------------------------------------*/
3597 static void genCmpEq (iCode *ic, iCode *ifx)
3599 operand *left, *right, *result;
3601 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3602 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3603 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3605 /* if literal, literal on the right or
3606 if the right is in a pointer register and left
3608 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
3609 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3610 operand *t = IC_RIGHT(ic);
3611 IC_RIGHT(ic) = IC_LEFT(ic);
3615 if(ifx && !AOP_SIZE(result)){
3617 /* if they are both bit variables */
3618 if (AOP_TYPE(left) == AOP_CRY &&
3619 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3620 if(AOP_TYPE(right) == AOP_LIT){
3621 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3623 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3624 emitcode("cpl","c");
3625 } else if(lit == 1L) {
3626 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3628 emitcode("clr","c");
3630 /* AOP_TYPE(right) == AOP_CRY */
3632 symbol *lbl = newiTempLabel(NULL);
3633 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3634 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3635 emitcode("cpl","c");
3636 emitcode("","%05d$:",(lbl->key+100));
3638 /* if true label then we jump if condition
3640 tlbl = newiTempLabel(NULL);
3641 if ( IC_TRUE(ifx) ) {
3642 emitcode("jnc","%05d$",tlbl->key+100);
3643 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3645 emitcode("jc","%05d$",tlbl->key+100);
3646 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3648 emitcode("","%05d$:",tlbl->key+100);
3650 tlbl = newiTempLabel(NULL);
3651 gencjneshort(left, right, tlbl);
3652 if ( IC_TRUE(ifx) ) {
3653 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3654 emitcode("","%05d$:",tlbl->key+100);
3656 symbol *lbl = newiTempLabel(NULL);
3657 emitcode("sjmp","%05d$",lbl->key+100);
3658 emitcode("","%05d$:",tlbl->key+100);
3659 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3660 emitcode("","%05d$:",lbl->key+100);
3663 /* mark the icode as generated */
3668 /* if they are both bit variables */
3669 if (AOP_TYPE(left) == AOP_CRY &&
3670 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3671 if(AOP_TYPE(right) == AOP_LIT){
3672 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3674 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3675 emitcode("cpl","c");
3676 } else if(lit == 1L) {
3677 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3679 emitcode("clr","c");
3681 /* AOP_TYPE(right) == AOP_CRY */
3683 symbol *lbl = newiTempLabel(NULL);
3684 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3685 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3686 emitcode("cpl","c");
3687 emitcode("","%05d$:",(lbl->key+100));
3690 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
3695 genIfxJump (ifx,"c");
3698 /* if the result is used in an arithmetic operation
3699 then put the result in place */
3702 gencjne(left,right,newiTempLabel(NULL));
3703 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3704 aopPut(AOP(result),"a",0);
3708 genIfxJump (ifx,"a");
3711 /* if the result is used in an arithmetic operation
3712 then put the result in place */
3713 if (AOP_TYPE(result) != AOP_CRY)
3715 /* leave the result in acc */
3719 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3720 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3721 freeAsmop(result,NULL,ic,TRUE);
3724 /*-----------------------------------------------------------------*/
3725 /* ifxForOp - returns the icode containing the ifx for operand */
3726 /*-----------------------------------------------------------------*/
3727 static iCode *ifxForOp ( operand *op, iCode *ic )
3729 /* if true symbol then needs to be assigned */
3730 if (IS_TRUE_SYMOP(op))
3733 /* if this has register type condition and
3734 the next instruction is ifx with the same operand
3735 and live to of the operand is upto the ifx only then */
3737 ic->next->op == IFX &&
3738 IC_COND(ic->next)->key == op->key &&
3739 OP_SYMBOL(op)->liveTo <= ic->next->seq )
3744 /*-----------------------------------------------------------------*/
3745 /* genAndOp - for && operation */
3746 /*-----------------------------------------------------------------*/
3747 static void genAndOp (iCode *ic)
3749 operand *left,*right, *result;
3752 /* note here that && operations that are in an
3753 if statement are taken away by backPatchLabels
3754 only those used in arthmetic operations remain */
3755 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3756 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3757 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3759 /* if both are bit variables */
3760 if (AOP_TYPE(left) == AOP_CRY &&
3761 AOP_TYPE(right) == AOP_CRY ) {
3762 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3763 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3766 tlbl = newiTempLabel(NULL);
3768 emitcode("jz","%05d$",tlbl->key+100);
3770 emitcode("","%05d$:",tlbl->key+100);
3774 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3775 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3776 freeAsmop(result,NULL,ic,TRUE);
3780 /*-----------------------------------------------------------------*/
3781 /* genOrOp - for || operation */
3782 /*-----------------------------------------------------------------*/
3783 static void genOrOp (iCode *ic)
3785 operand *left,*right, *result;
3788 /* note here that || operations that are in an
3789 if statement are taken away by backPatchLabels
3790 only those used in arthmetic operations remain */
3791 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3792 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3793 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3795 /* if both are bit variables */
3796 if (AOP_TYPE(left) == AOP_CRY &&
3797 AOP_TYPE(right) == AOP_CRY ) {
3798 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3799 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
3802 tlbl = newiTempLabel(NULL);
3804 emitcode("jnz","%05d$",tlbl->key+100);
3806 emitcode("","%05d$:",tlbl->key+100);
3810 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3811 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3812 freeAsmop(result,NULL,ic,TRUE);
3815 /*-----------------------------------------------------------------*/
3816 /* isLiteralBit - test if lit == 2^n */
3817 /*-----------------------------------------------------------------*/
3818 static int isLiteralBit(unsigned long lit)
3820 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
3821 0x100L,0x200L,0x400L,0x800L,
3822 0x1000L,0x2000L,0x4000L,0x8000L,
3823 0x10000L,0x20000L,0x40000L,0x80000L,
3824 0x100000L,0x200000L,0x400000L,0x800000L,
3825 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
3826 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
3829 for(idx = 0; idx < 32; idx++)
3835 /*-----------------------------------------------------------------*/
3836 /* continueIfTrue - */
3837 /*-----------------------------------------------------------------*/
3838 static void continueIfTrue (iCode *ic)
3841 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3845 /*-----------------------------------------------------------------*/
3847 /*-----------------------------------------------------------------*/
3848 static void jumpIfTrue (iCode *ic)
3851 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3855 /*-----------------------------------------------------------------*/
3856 /* jmpTrueOrFalse - */
3857 /*-----------------------------------------------------------------*/
3858 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
3860 // ugly but optimized by peephole
3862 symbol *nlbl = newiTempLabel(NULL);
3863 emitcode("sjmp","%05d$",nlbl->key+100);
3864 emitcode("","%05d$:",tlbl->key+100);
3865 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3866 emitcode("","%05d$:",nlbl->key+100);
3869 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3870 emitcode("","%05d$:",tlbl->key+100);
3875 /*-----------------------------------------------------------------*/
3876 /* genAnd - code for and */
3877 /*-----------------------------------------------------------------*/
3878 static void genAnd (iCode *ic, iCode *ifx)
3880 operand *left, *right, *result;
3882 unsigned long lit = 0L;
3886 aopOp((left = IC_LEFT(ic)),ic,FALSE);
3887 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3888 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3891 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3893 AOP_TYPE(left), AOP_TYPE(right));
3894 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3896 AOP_SIZE(left), AOP_SIZE(right));
3899 /* if left is a literal & right is not then exchange them */
3900 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3901 AOP_NEEDSACC(left)) {
3902 operand *tmp = right ;
3907 /* if result = right then exchange them */
3908 if(sameRegs(AOP(result),AOP(right))){
3909 operand *tmp = right ;
3914 /* if right is bit then exchange them */
3915 if (AOP_TYPE(right) == AOP_CRY &&
3916 AOP_TYPE(left) != AOP_CRY){
3917 operand *tmp = right ;
3921 if(AOP_TYPE(right) == AOP_LIT)
3922 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3924 size = AOP_SIZE(result);
3927 // result = bit & yy;
3928 if (AOP_TYPE(left) == AOP_CRY){
3929 // c = bit & literal;
3930 if(AOP_TYPE(right) == AOP_LIT){
3932 if(size && sameRegs(AOP(result),AOP(left)))
3935 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3938 if(size && (AOP_TYPE(result) == AOP_CRY)){
3939 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
3942 if((AOP_TYPE(result) == AOP_CRY) && ifx){
3946 emitcode("clr","c");
3949 if (AOP_TYPE(right) == AOP_CRY){
3951 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3952 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3955 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
3957 emitcode("rrc","a");
3958 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3966 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
3967 genIfxJump(ifx, "c");
3971 // if(val & 0xZZ) - size = 0, ifx != FALSE -
3972 // bit = val & 0xZZ - size = 1, ifx = FALSE -
3973 if((AOP_TYPE(right) == AOP_LIT) &&
3974 (AOP_TYPE(result) == AOP_CRY) &&
3975 (AOP_TYPE(left) != AOP_CRY)){
3976 int posbit = isLiteralBit(lit);
3980 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
3983 emitcode("mov","c,acc.%d",posbit&0x07);
3987 sprintf(buffer,"acc.%d",posbit&0x07);
3988 genIfxJump(ifx, buffer);
3993 symbol *tlbl = newiTempLabel(NULL);
3994 int sizel = AOP_SIZE(left);
3996 emitcode("setb","c");
3998 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
3999 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
4001 if((posbit = isLiteralBit(bytelit)) != 0)
4002 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
4004 if(bytelit != 0x0FFL)
4005 emitcode("anl","a,%s",
4006 aopGet(AOP(right),offset,FALSE,TRUE));
4007 emitcode("jnz","%05d$",tlbl->key+100);
4012 // bit = left & literal
4014 emitcode("clr","c");
4015 emitcode("","%05d$:",tlbl->key+100);
4017 // if(left & literal)
4020 jmpTrueOrFalse(ifx, tlbl);
4028 /* if left is same as result */
4029 if(sameRegs(AOP(result),AOP(left))){
4030 for(;size--; offset++) {
4031 if(AOP_TYPE(right) == AOP_LIT){
4032 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4036 aopPut(AOP(result),zero,offset);
4038 if (IS_AOP_PREG(result)) {
4039 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4040 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4041 aopPut(AOP(result),"a",offset);
4043 emitcode("anl","%s,%s",
4044 aopGet(AOP(left),offset,FALSE,TRUE),
4045 aopGet(AOP(right),offset,FALSE,FALSE));
4047 if (AOP_TYPE(left) == AOP_ACC)
4048 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4050 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4051 if (IS_AOP_PREG(result)) {
4052 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4053 aopPut(AOP(result),"a",offset);
4056 emitcode("anl","%s,a",
4057 aopGet(AOP(left),offset,FALSE,TRUE));
4062 // left & result in different registers
4063 if(AOP_TYPE(result) == AOP_CRY){
4065 // if(size), result in bit
4066 // if(!size && ifx), conditional oper: if(left & right)
4067 symbol *tlbl = newiTempLabel(NULL);
4068 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4070 emitcode("setb","c");
4072 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4073 emitcode("anl","a,%s",
4074 aopGet(AOP(left),offset,FALSE,FALSE));
4075 emitcode("jnz","%05d$",tlbl->key+100);
4080 emitcode("","%05d$:",tlbl->key+100);
4083 jmpTrueOrFalse(ifx, tlbl);
4085 for(;(size--);offset++) {
4087 // result = left & right
4088 if(AOP_TYPE(right) == AOP_LIT){
4089 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
4091 aopGet(AOP(left),offset,FALSE,FALSE),
4094 } else if(bytelit == 0){
4095 aopPut(AOP(result),zero,offset);
4099 // faster than result <- left, anl result,right
4100 // and better if result is SFR
4101 if (AOP_TYPE(left) == AOP_ACC)
4102 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4104 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4105 emitcode("anl","a,%s",
4106 aopGet(AOP(left),offset,FALSE,FALSE));
4108 aopPut(AOP(result),"a",offset);
4114 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4115 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4116 freeAsmop(result,NULL,ic,TRUE);
4119 /*-----------------------------------------------------------------*/
4120 /* genOr - code for or */
4121 /*-----------------------------------------------------------------*/
4122 static void genOr (iCode *ic, iCode *ifx)
4124 operand *left, *right, *result;
4126 unsigned long lit = 0L;
4128 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4129 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4130 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4133 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4135 AOP_TYPE(left), AOP_TYPE(right));
4136 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4138 AOP_SIZE(left), AOP_SIZE(right));
4141 /* if left is a literal & right is not then exchange them */
4142 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4143 AOP_NEEDSACC(left)) {
4144 operand *tmp = right ;
4149 /* if result = right then exchange them */
4150 if(sameRegs(AOP(result),AOP(right))){
4151 operand *tmp = right ;
4156 /* if right is bit then exchange them */
4157 if (AOP_TYPE(right) == AOP_CRY &&
4158 AOP_TYPE(left) != AOP_CRY){
4159 operand *tmp = right ;
4163 if(AOP_TYPE(right) == AOP_LIT)
4164 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4166 size = AOP_SIZE(result);
4170 if (AOP_TYPE(left) == AOP_CRY){
4171 if(AOP_TYPE(right) == AOP_LIT){
4172 // c = bit & literal;
4174 // lit != 0 => result = 1
4175 if(AOP_TYPE(result) == AOP_CRY){
4177 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4179 continueIfTrue(ifx);
4182 emitcode("setb","c");
4184 // lit == 0 => result = left
4185 if(size && sameRegs(AOP(result),AOP(left)))
4187 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4190 if (AOP_TYPE(right) == AOP_CRY){
4192 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4193 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4197 symbol *tlbl = newiTempLabel(NULL);
4198 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4199 emitcode("setb","c");
4200 emitcode("jb","%s,%05d$",
4201 AOP(left)->aopu.aop_dir,tlbl->key+100);
4203 emitcode("jnz","%05d$",tlbl->key+100);
4204 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4205 jmpTrueOrFalse(ifx, tlbl);
4209 emitcode("","%05d$:",tlbl->key+100);
4218 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4219 genIfxJump(ifx, "c");
4223 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4224 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4225 if((AOP_TYPE(right) == AOP_LIT) &&
4226 (AOP_TYPE(result) == AOP_CRY) &&
4227 (AOP_TYPE(left) != AOP_CRY)){
4231 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4233 continueIfTrue(ifx);
4236 // lit = 0, result = boolean(left)
4238 emitcode("setb","c");
4241 symbol *tlbl = newiTempLabel(NULL);
4242 emitcode("jnz","%05d$",tlbl->key+100);
4244 emitcode("","%05d$:",tlbl->key+100);
4246 genIfxJump (ifx,"a");
4254 /* if left is same as result */
4255 if(sameRegs(AOP(result),AOP(left))){
4256 for(;size--; offset++) {
4257 if(AOP_TYPE(right) == AOP_LIT){
4258 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4261 if (IS_AOP_PREG(left)) {
4262 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4263 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4264 aopPut(AOP(result),"a",offset);
4266 emitcode("orl","%s,%s",
4267 aopGet(AOP(left),offset,FALSE,TRUE),
4268 aopGet(AOP(right),offset,FALSE,FALSE));
4270 if (AOP_TYPE(left) == AOP_ACC)
4271 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4273 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4274 if (IS_AOP_PREG(left)) {
4275 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4276 aopPut(AOP(result),"a",offset);
4278 emitcode("orl","%s,a",
4279 aopGet(AOP(left),offset,FALSE,TRUE));
4284 // left & result in different registers
4285 if(AOP_TYPE(result) == AOP_CRY){
4287 // if(size), result in bit
4288 // if(!size && ifx), conditional oper: if(left | right)
4289 symbol *tlbl = newiTempLabel(NULL);
4290 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4292 emitcode("setb","c");
4294 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4295 emitcode("orl","a,%s",
4296 aopGet(AOP(left),offset,FALSE,FALSE));
4297 emitcode("jnz","%05d$",tlbl->key+100);
4302 emitcode("","%05d$:",tlbl->key+100);
4305 jmpTrueOrFalse(ifx, tlbl);
4306 } else for(;(size--);offset++){
4308 // result = left & right
4309 if(AOP_TYPE(right) == AOP_LIT){
4310 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4312 aopGet(AOP(left),offset,FALSE,FALSE),
4317 // faster than result <- left, anl result,right
4318 // and better if result is SFR
4319 if (AOP_TYPE(left) == AOP_ACC)
4320 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4322 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4323 emitcode("orl","a,%s",
4324 aopGet(AOP(left),offset,FALSE,FALSE));
4326 aopPut(AOP(result),"a",offset);
4331 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4332 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4333 freeAsmop(result,NULL,ic,TRUE);
4336 /*-----------------------------------------------------------------*/
4337 /* genXor - code for xclusive or */
4338 /*-----------------------------------------------------------------*/
4339 static void genXor (iCode *ic, iCode *ifx)
4341 operand *left, *right, *result;
4343 unsigned long lit = 0L;
4345 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4346 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4347 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4350 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4352 AOP_TYPE(left), AOP_TYPE(right));
4353 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4355 AOP_SIZE(left), AOP_SIZE(right));
4358 /* if left is a literal & right is not ||
4359 if left needs acc & right does not */
4360 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4361 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4362 operand *tmp = right ;
4367 /* if result = right then exchange them */
4368 if(sameRegs(AOP(result),AOP(right))){
4369 operand *tmp = right ;
4374 /* if right is bit then exchange them */
4375 if (AOP_TYPE(right) == AOP_CRY &&
4376 AOP_TYPE(left) != AOP_CRY){
4377 operand *tmp = right ;
4381 if(AOP_TYPE(right) == AOP_LIT)
4382 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4384 size = AOP_SIZE(result);
4388 if (AOP_TYPE(left) == AOP_CRY){
4389 if(AOP_TYPE(right) == AOP_LIT){
4390 // c = bit & literal;
4392 // lit>>1 != 0 => result = 1
4393 if(AOP_TYPE(result) == AOP_CRY){
4395 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4397 continueIfTrue(ifx);
4400 emitcode("setb","c");
4404 // lit == 0, result = left
4405 if(size && sameRegs(AOP(result),AOP(left)))
4407 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4409 // lit == 1, result = not(left)
4410 if(size && sameRegs(AOP(result),AOP(left))){
4411 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4414 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4415 emitcode("cpl","c");
4422 symbol *tlbl = newiTempLabel(NULL);
4423 if (AOP_TYPE(right) == AOP_CRY){
4425 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4428 int sizer = AOP_SIZE(right);
4430 // if val>>1 != 0, result = 1
4431 emitcode("setb","c");
4433 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
4435 // test the msb of the lsb
4436 emitcode("anl","a,#0xfe");
4437 emitcode("jnz","%05d$",tlbl->key+100);
4441 emitcode("rrc","a");
4443 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4444 emitcode("cpl","c");
4445 emitcode("","%05d$:",(tlbl->key+100));
4452 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4453 genIfxJump(ifx, "c");
4457 if(sameRegs(AOP(result),AOP(left))){
4458 /* if left is same as result */
4459 for(;size--; offset++) {
4460 if(AOP_TYPE(right) == AOP_LIT){
4461 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4464 if (IS_AOP_PREG(left)) {
4465 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4466 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4467 aopPut(AOP(result),"a",offset);
4469 emitcode("xrl","%s,%s",
4470 aopGet(AOP(left),offset,FALSE,TRUE),
4471 aopGet(AOP(right),offset,FALSE,FALSE));
4473 if (AOP_TYPE(left) == AOP_ACC)
4474 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4476 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4477 if (IS_AOP_PREG(left)) {
4478 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4479 aopPut(AOP(result),"a",offset);
4481 emitcode("xrl","%s,a",
4482 aopGet(AOP(left),offset,FALSE,TRUE));
4487 // left & result in different registers
4488 if(AOP_TYPE(result) == AOP_CRY){
4490 // if(size), result in bit
4491 // if(!size && ifx), conditional oper: if(left ^ right)
4492 symbol *tlbl = newiTempLabel(NULL);
4493 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4495 emitcode("setb","c");
4497 if((AOP_TYPE(right) == AOP_LIT) &&
4498 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4499 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4501 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4502 emitcode("xrl","a,%s",
4503 aopGet(AOP(left),offset,FALSE,FALSE));
4505 emitcode("jnz","%05d$",tlbl->key+100);
4510 emitcode("","%05d$:",tlbl->key+100);
4513 jmpTrueOrFalse(ifx, tlbl);
4514 } else for(;(size--);offset++){
4516 // result = left & right
4517 if(AOP_TYPE(right) == AOP_LIT){
4518 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4520 aopGet(AOP(left),offset,FALSE,FALSE),
4525 // faster than result <- left, anl result,right
4526 // and better if result is SFR
4527 if (AOP_TYPE(left) == AOP_ACC)
4528 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4530 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4531 emitcode("xrl","a,%s",
4532 aopGet(AOP(left),offset,FALSE,TRUE));
4534 aopPut(AOP(result),"a",offset);
4539 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4540 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4541 freeAsmop(result,NULL,ic,TRUE);
4544 /*-----------------------------------------------------------------*/
4545 /* genInline - write the inline code out */
4546 /*-----------------------------------------------------------------*/
4547 static void genInline (iCode *ic)
4549 char buffer[MAX_INLINEASM];
4553 _G.inLine += (!options.asmpeep);
4554 strcpy(buffer,IC_INLINE(ic));
4556 /* emit each line as a code */
4575 /* emitcode("",buffer); */
4576 _G.inLine -= (!options.asmpeep);
4579 /*-----------------------------------------------------------------*/
4580 /* genRRC - rotate right with carry */
4581 /*-----------------------------------------------------------------*/
4582 static void genRRC (iCode *ic)
4584 operand *left , *result ;
4585 int size, offset = 0;
4588 /* rotate right with carry */
4590 result=IC_RESULT(ic);
4591 aopOp (left,ic,FALSE);
4592 aopOp (result,ic,FALSE);
4594 /* move it to the result */
4595 size = AOP_SIZE(result);
4599 l = aopGet(AOP(left),offset,FALSE,FALSE);
4601 emitcode("rrc","a");
4602 if (AOP_SIZE(result) > 1)
4603 aopPut(AOP(result),"a",offset--);
4605 /* now we need to put the carry into the
4606 highest order byte of the result */
4607 if (AOP_SIZE(result) > 1) {
4608 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
4611 emitcode("mov","acc.7,c");
4612 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
4613 freeAsmop(left,NULL,ic,TRUE);
4614 freeAsmop(result,NULL,ic,TRUE);
4617 /*-----------------------------------------------------------------*/
4618 /* genRLC - generate code for rotate left with carry */
4619 /*-----------------------------------------------------------------*/
4620 static void genRLC (iCode *ic)
4622 operand *left , *result ;
4623 int size, offset = 0;
4626 /* rotate right with carry */
4628 result=IC_RESULT(ic);
4629 aopOp (left,ic,FALSE);
4630 aopOp (result,ic,FALSE);
4632 /* move it to the result */
4633 size = AOP_SIZE(result);
4636 l = aopGet(AOP(left),offset,FALSE,FALSE);
4638 emitcode("add","a,acc");
4639 if (AOP_SIZE(result) > 1)
4640 aopPut(AOP(result),"a",offset++);
4642 l = aopGet(AOP(left),offset,FALSE,FALSE);
4644 emitcode("rlc","a");
4645 if (AOP_SIZE(result) > 1)
4646 aopPut(AOP(result),"a",offset++);
4649 /* now we need to put the carry into the
4650 highest order byte of the result */
4651 if (AOP_SIZE(result) > 1) {
4652 l = aopGet(AOP(result),0,FALSE,FALSE);
4655 emitcode("mov","acc.0,c");
4656 aopPut(AOP(result),"a",0);
4657 freeAsmop(left,NULL,ic,TRUE);
4658 freeAsmop(result,NULL,ic,TRUE);
4661 /*-----------------------------------------------------------------*/
4662 /* genGetHbit - generates code get highest order bit */
4663 /*-----------------------------------------------------------------*/
4664 static void genGetHbit (iCode *ic)
4666 operand *left, *result;
4668 result=IC_RESULT(ic);
4669 aopOp (left,ic,FALSE);
4670 aopOp (result,ic,FALSE);
4672 /* get the highest order byte into a */
4673 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
4674 if(AOP_TYPE(result) == AOP_CRY){
4675 emitcode("rlc","a");
4680 emitcode("anl","a,#0x01");
4685 freeAsmop(left,NULL,ic,TRUE);
4686 freeAsmop(result,NULL,ic,TRUE);
4689 /*-----------------------------------------------------------------*/
4690 /* AccRol - rotate left accumulator by known count */
4691 /*-----------------------------------------------------------------*/
4692 static void AccRol (int shCount)
4694 shCount &= 0x0007; // shCount : 0..7
4706 emitcode("swap","a");
4710 emitcode("swap","a");
4713 emitcode("swap","a");
4726 /*-----------------------------------------------------------------*/
4727 /* AccLsh - left shift accumulator by known count */
4728 /*-----------------------------------------------------------------*/
4729 static void AccLsh (int shCount)
4733 emitcode("add","a,acc");
4736 emitcode("add","a,acc");
4737 emitcode("add","a,acc");
4739 /* rotate left accumulator */
4741 /* and kill the lower order bits */
4742 emitcode("anl","a,#0x%02x", SLMask[shCount]);
4747 /*-----------------------------------------------------------------*/
4748 /* AccRsh - right shift accumulator by known count */
4749 /*-----------------------------------------------------------------*/
4750 static void AccRsh (int shCount)
4755 emitcode("rrc","a");
4757 /* rotate right accumulator */
4758 AccRol(8 - shCount);
4759 /* and kill the higher order bits */
4760 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4765 /*-----------------------------------------------------------------*/
4766 /* AccSRsh - signed right shift accumulator by known count */
4767 /*-----------------------------------------------------------------*/
4768 static void AccSRsh (int shCount)
4773 emitcode("mov","c,acc.7");
4774 emitcode("rrc","a");
4775 } else if(shCount == 2){
4776 emitcode("mov","c,acc.7");
4777 emitcode("rrc","a");
4778 emitcode("mov","c,acc.7");
4779 emitcode("rrc","a");
4781 tlbl = newiTempLabel(NULL);
4782 /* rotate right accumulator */
4783 AccRol(8 - shCount);
4784 /* and kill the higher order bits */
4785 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4786 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4787 emitcode("orl","a,#0x%02x",
4788 (unsigned char)~SRMask[shCount]);
4789 emitcode("","%05d$:",tlbl->key+100);
4794 /*-----------------------------------------------------------------*/
4795 /* shiftR1Left2Result - shift right one byte from left to result */
4796 /*-----------------------------------------------------------------*/
4797 static void shiftR1Left2Result (operand *left, int offl,
4798 operand *result, int offr,
4799 int shCount, int sign)
4801 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4802 /* shift right accumulator */
4807 aopPut(AOP(result),"a",offr);
4810 /*-----------------------------------------------------------------*/
4811 /* shiftL1Left2Result - shift left one byte from left to result */
4812 /*-----------------------------------------------------------------*/
4813 static void shiftL1Left2Result (operand *left, int offl,
4814 operand *result, int offr, int shCount)
4817 l = aopGet(AOP(left),offl,FALSE,FALSE);
4819 /* shift left accumulator */
4821 aopPut(AOP(result),"a",offr);
4824 /*-----------------------------------------------------------------*/
4825 /* movLeft2Result - move byte from left to result */
4826 /*-----------------------------------------------------------------*/
4827 static void movLeft2Result (operand *left, int offl,
4828 operand *result, int offr, int sign)
4831 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
4832 l = aopGet(AOP(left),offl,FALSE,FALSE);
4834 if (*l == '@' && (IS_AOP_PREG(result))) {
4835 emitcode("mov","a,%s",l);
4836 aopPut(AOP(result),"a",offr);
4839 aopPut(AOP(result),l,offr);
4841 /* MSB sign in acc.7 ! */
4842 if(getDataSize(left) == offl+1){
4843 emitcode("mov","a,%s",l);
4844 aopPut(AOP(result),"a",offr);
4851 /*-----------------------------------------------------------------*/
4852 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
4853 /*-----------------------------------------------------------------*/
4854 static void AccAXRrl1 (char *x)
4856 emitcode("rrc","a");
4857 emitcode("xch","a,%s", x);
4858 emitcode("rrc","a");
4859 emitcode("xch","a,%s", x);
4862 /*-----------------------------------------------------------------*/
4863 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
4864 /*-----------------------------------------------------------------*/
4865 static void AccAXLrl1 (char *x)
4867 emitcode("xch","a,%s",x);
4868 emitcode("rlc","a");
4869 emitcode("xch","a,%s",x);
4870 emitcode("rlc","a");
4873 /*-----------------------------------------------------------------*/
4874 /* AccAXLsh1 - left shift a:x<-0 by 1 */
4875 /*-----------------------------------------------------------------*/
4876 static void AccAXLsh1 (char *x)
4878 emitcode("xch","a,%s",x);
4879 emitcode("add","a,acc");
4880 emitcode("xch","a,%s",x);
4881 emitcode("rlc","a");
4884 /*-----------------------------------------------------------------*/
4885 /* AccAXLsh - left shift a:x by known count (0..7) */
4886 /*-----------------------------------------------------------------*/
4887 static void AccAXLsh (char *x, int shCount)
4901 case 5 : // AAAAABBB:CCCCCDDD
4902 AccRol(shCount); // BBBAAAAA:CCCCCDDD
4903 emitcode("anl","a,#0x%02x",
4904 SLMask[shCount]); // BBB00000:CCCCCDDD
4905 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
4906 AccRol(shCount); // DDDCCCCC:BBB00000
4907 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
4908 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
4909 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
4910 emitcode("anl","a,#0x%02x",
4911 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
4912 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
4913 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
4915 case 6 : // AAAAAABB:CCCCCCDD
4916 emitcode("anl","a,#0x%02x",
4917 SRMask[shCount]); // 000000BB:CCCCCCDD
4918 emitcode("mov","c,acc.0"); // c = B
4919 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
4920 AccAXRrl1(x); // BCCCCCCD:D000000B
4921 AccAXRrl1(x); // BBCCCCCC:DD000000
4923 case 7 : // a:x <<= 7
4924 emitcode("anl","a,#0x%02x",
4925 SRMask[shCount]); // 0000000B:CCCCCCCD
4926 emitcode("mov","c,acc.0"); // c = B
4927 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
4928 AccAXRrl1(x); // BCCCCCCC:D0000000
4935 /*-----------------------------------------------------------------*/
4936 /* AccAXRsh - right shift a:x known count (0..7) */
4937 /*-----------------------------------------------------------------*/
4938 static void AccAXRsh (char *x, int shCount)
4945 AccAXRrl1(x); // 0->a:x
4949 AccAXRrl1(x); // 0->a:x
4951 AccAXRrl1(x); // 0->a:x
4955 case 5 : // AAAAABBB:CCCCCDDD = a:x
4956 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
4957 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
4958 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
4959 emitcode("anl","a,#0x%02x",
4960 SRMask[shCount]); // 000CCCCC:BBBAAAAA
4961 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
4962 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
4963 emitcode("anl","a,#0x%02x",
4964 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
4965 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
4966 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
4967 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
4969 case 6 : // AABBBBBB:CCDDDDDD
4970 emitcode("mov","c,acc.7");
4971 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
4972 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
4973 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
4974 emitcode("anl","a,#0x%02x",
4975 SRMask[shCount]); // 000000AA:BBBBBBCC
4977 case 7 : // ABBBBBBB:CDDDDDDD
4978 emitcode("mov","c,acc.7"); // c = A
4979 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
4980 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
4981 emitcode("anl","a,#0x%02x",
4982 SRMask[shCount]); // 0000000A:BBBBBBBC
4989 /*-----------------------------------------------------------------*/
4990 /* AccAXRshS - right shift signed a:x known count (0..7) */
4991 /*-----------------------------------------------------------------*/
4992 static void AccAXRshS (char *x, int shCount)
4999 emitcode("mov","c,acc.7");
5000 AccAXRrl1(x); // s->a:x
5003 emitcode("mov","c,acc.7");
5004 AccAXRrl1(x); // s->a:x
5005 emitcode("mov","c,acc.7");
5006 AccAXRrl1(x); // s->a:x
5010 case 5 : // AAAAABBB:CCCCCDDD = a:x
5011 tlbl = newiTempLabel(NULL);
5012 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5013 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5014 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5015 emitcode("anl","a,#0x%02x",
5016 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5017 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5018 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5019 emitcode("anl","a,#0x%02x",
5020 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5021 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5022 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5023 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5024 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5025 emitcode("orl","a,#0x%02x",
5026 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5027 emitcode("","%05d$:",tlbl->key+100);
5028 break; // SSSSAAAA:BBBCCCCC
5029 case 6 : // AABBBBBB:CCDDDDDD
5030 tlbl = newiTempLabel(NULL);
5031 emitcode("mov","c,acc.7");
5032 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5033 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5034 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5035 emitcode("anl","a,#0x%02x",
5036 SRMask[shCount]); // 000000AA:BBBBBBCC
5037 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5038 emitcode("orl","a,#0x%02x",
5039 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5040 emitcode("","%05d$:",tlbl->key+100);
5042 case 7 : // ABBBBBBB:CDDDDDDD
5043 tlbl = newiTempLabel(NULL);
5044 emitcode("mov","c,acc.7"); // c = A
5045 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5046 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5047 emitcode("anl","a,#0x%02x",
5048 SRMask[shCount]); // 0000000A:BBBBBBBC
5049 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5050 emitcode("orl","a,#0x%02x",
5051 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5052 emitcode("","%05d$:",tlbl->key+100);
5059 /*-----------------------------------------------------------------*/
5060 /* shiftL2Left2Result - shift left two bytes from left to result */
5061 /*-----------------------------------------------------------------*/
5062 static void shiftL2Left2Result (operand *left, int offl,
5063 operand *result, int offr, int shCount)
5065 if(sameRegs(AOP(result), AOP(left)) &&
5066 ((offl + MSB16) == offr)){
5067 /* don't crash result[offr] */
5068 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5069 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5071 movLeft2Result(left,offl, result, offr, 0);
5072 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5074 /* ax << shCount (x = lsb(result))*/
5075 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5076 aopPut(AOP(result),"a",offr+MSB16);
5080 /*-----------------------------------------------------------------*/
5081 /* shiftR2Left2Result - shift right two bytes from left to result */
5082 /*-----------------------------------------------------------------*/
5083 static void shiftR2Left2Result (operand *left, int offl,
5084 operand *result, int offr,
5085 int shCount, int sign)
5087 if(sameRegs(AOP(result), AOP(left)) &&
5088 ((offl + MSB16) == offr)){
5089 /* don't crash result[offr] */
5090 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5091 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5093 movLeft2Result(left,offl, result, offr, 0);
5094 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5096 /* a:x >> shCount (x = lsb(result))*/
5098 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5100 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5101 if(getDataSize(result) > 1)
5102 aopPut(AOP(result),"a",offr+MSB16);
5105 /*-----------------------------------------------------------------*/
5106 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5107 /*-----------------------------------------------------------------*/
5108 static void shiftLLeftOrResult (operand *left, int offl,
5109 operand *result, int offr, int shCount)
5111 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5112 /* shift left accumulator */
5114 /* or with result */
5115 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5116 /* back to result */
5117 aopPut(AOP(result),"a",offr);
5120 /*-----------------------------------------------------------------*/
5121 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5122 /*-----------------------------------------------------------------*/
5123 static void shiftRLeftOrResult (operand *left, int offl,
5124 operand *result, int offr, int shCount)
5126 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5127 /* shift right accumulator */
5129 /* or with result */
5130 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5131 /* back to result */
5132 aopPut(AOP(result),"a",offr);
5135 /*-----------------------------------------------------------------*/
5136 /* genlshOne - left shift a one byte quantity by known count */
5137 /*-----------------------------------------------------------------*/
5138 static void genlshOne (operand *result, operand *left, int shCount)
5140 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5143 /*-----------------------------------------------------------------*/
5144 /* genlshTwo - left shift two bytes by known amount != 0 */
5145 /*-----------------------------------------------------------------*/
5146 static void genlshTwo (operand *result,operand *left, int shCount)
5150 size = getDataSize(result);
5152 /* if shCount >= 8 */
5158 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5160 movLeft2Result(left, LSB, result, MSB16, 0);
5162 aopPut(AOP(result),zero,LSB);
5165 /* 1 <= shCount <= 7 */
5168 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5170 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5174 /*-----------------------------------------------------------------*/
5175 /* shiftLLong - shift left one long from left to result */
5176 /* offl = LSB or MSB16 */
5177 /*-----------------------------------------------------------------*/
5178 static void shiftLLong (operand *left, operand *result, int offr )
5181 int size = AOP_SIZE(result);
5183 if(size >= LSB+offr){
5184 l = aopGet(AOP(left),LSB,FALSE,FALSE);
5186 emitcode("add","a,acc");
5187 if (sameRegs(AOP(left),AOP(result)) &&
5188 size >= MSB16+offr && offr != LSB )
5189 emitcode("xch","a,%s",
5190 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
5192 aopPut(AOP(result),"a",LSB+offr);
5195 if(size >= MSB16+offr){
5196 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5197 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
5200 emitcode("rlc","a");
5201 if (sameRegs(AOP(left),AOP(result)) &&
5202 size >= MSB24+offr && offr != LSB)
5203 emitcode("xch","a,%s",
5204 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
5206 aopPut(AOP(result),"a",MSB16+offr);
5209 if(size >= MSB24+offr){
5210 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5211 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
5214 emitcode("rlc","a");
5215 if (sameRegs(AOP(left),AOP(result)) &&
5216 size >= MSB32+offr && offr != LSB )
5217 emitcode("xch","a,%s",
5218 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
5220 aopPut(AOP(result),"a",MSB24+offr);
5223 if(size > MSB32+offr){
5224 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5225 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
5228 emitcode("rlc","a");
5229 aopPut(AOP(result),"a",MSB32+offr);
5232 aopPut(AOP(result),zero,LSB);
5235 /*-----------------------------------------------------------------*/
5236 /* genlshFour - shift four byte by a known amount != 0 */
5237 /*-----------------------------------------------------------------*/
5238 static void genlshFour (operand *result, operand *left, int shCount)
5242 size = AOP_SIZE(result);
5244 /* if shifting more that 3 bytes */
5245 if (shCount >= 24 ) {
5248 /* lowest order of left goes to the highest
5249 order of the destination */
5250 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5252 movLeft2Result(left, LSB, result, MSB32, 0);
5253 aopPut(AOP(result),zero,LSB);
5254 aopPut(AOP(result),zero,MSB16);
5255 aopPut(AOP(result),zero,MSB32);
5259 /* more than two bytes */
5260 else if ( shCount >= 16 ) {
5261 /* lower order two bytes goes to higher order two bytes */
5263 /* if some more remaining */
5265 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5267 movLeft2Result(left, MSB16, result, MSB32, 0);
5268 movLeft2Result(left, LSB, result, MSB24, 0);
5270 aopPut(AOP(result),zero,MSB16);
5271 aopPut(AOP(result),zero,LSB);
5275 /* if more than 1 byte */
5276 else if ( shCount >= 8 ) {
5277 /* lower order three bytes goes to higher order three bytes */
5281 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5283 movLeft2Result(left, LSB, result, MSB16, 0);
5285 else{ /* size = 4 */
5287 movLeft2Result(left, MSB24, result, MSB32, 0);
5288 movLeft2Result(left, MSB16, result, MSB24, 0);
5289 movLeft2Result(left, LSB, result, MSB16, 0);
5290 aopPut(AOP(result),zero,LSB);
5292 else if(shCount == 1)
5293 shiftLLong(left, result, MSB16);
5295 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5296 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5297 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5298 aopPut(AOP(result),zero,LSB);
5303 /* 1 <= shCount <= 7 */
5304 else if(shCount <= 2){
5305 shiftLLong(left, result, LSB);
5307 shiftLLong(result, result, LSB);
5309 /* 3 <= shCount <= 7, optimize */
5311 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5312 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5313 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5317 /*-----------------------------------------------------------------*/
5318 /* genLeftShiftLiteral - left shifting by known count */
5319 /*-----------------------------------------------------------------*/
5320 static void genLeftShiftLiteral (operand *left,
5325 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5328 freeAsmop(right,NULL,ic,TRUE);
5330 aopOp(left,ic,FALSE);
5331 aopOp(result,ic,FALSE);
5333 size = getSize(operandType(result));
5336 emitcode("; shift left ","result %d, left %d",size,
5340 /* I suppose that the left size >= result size */
5343 movLeft2Result(left, size, result, size, 0);
5347 else if(shCount >= (size * 8))
5349 aopPut(AOP(result),zero,size);
5353 genlshOne (result,left,shCount);
5358 genlshTwo (result,left,shCount);
5362 genlshFour (result,left,shCount);
5366 freeAsmop(left,NULL,ic,TRUE);
5367 freeAsmop(result,NULL,ic,TRUE);
5370 /*-----------------------------------------------------------------*/
5371 /* genLeftShift - generates code for left shifting */
5372 /*-----------------------------------------------------------------*/
5373 static void genLeftShift (iCode *ic)
5375 operand *left,*right, *result;
5378 symbol *tlbl , *tlbl1;
5380 right = IC_RIGHT(ic);
5382 result = IC_RESULT(ic);
5384 aopOp(right,ic,FALSE);
5386 /* if the shift count is known then do it
5387 as efficiently as possible */
5388 if (AOP_TYPE(right) == AOP_LIT) {
5389 genLeftShiftLiteral (left,right,result,ic);
5393 /* shift count is unknown then we have to form
5394 a loop get the loop count in B : Note: we take
5395 only the lower order byte since shifting
5396 more that 32 bits make no sense anyway, ( the
5397 largest size of an object can be only 32 bits ) */
5399 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5400 emitcode("inc","b");
5401 freeAsmop (right,NULL,ic,TRUE);
5402 aopOp(left,ic,FALSE);
5403 aopOp(result,ic,FALSE);
5405 /* now move the left to the result if they are not the
5407 if (!sameRegs(AOP(left),AOP(result)) &&
5408 AOP_SIZE(result) > 1) {
5410 size = AOP_SIZE(result);
5413 l = aopGet(AOP(left),offset,FALSE,TRUE);
5414 if (*l == '@' && (IS_AOP_PREG(result))) {
5416 emitcode("mov","a,%s",l);
5417 aopPut(AOP(result),"a",offset);
5419 aopPut(AOP(result),l,offset);
5424 tlbl = newiTempLabel(NULL);
5425 size = AOP_SIZE(result);
5427 tlbl1 = newiTempLabel(NULL);
5429 /* if it is only one byte then */
5431 symbol *tlbl1 = newiTempLabel(NULL);
5433 l = aopGet(AOP(left),0,FALSE,FALSE);
5435 emitcode("sjmp","%05d$",tlbl1->key+100);
5436 emitcode("","%05d$:",tlbl->key+100);
5437 emitcode("add","a,acc");
5438 emitcode("","%05d$:",tlbl1->key+100);
5439 emitcode("djnz","b,%05d$",tlbl->key+100);
5440 aopPut(AOP(result),"a",0);
5444 reAdjustPreg(AOP(result));
5446 emitcode("sjmp","%05d$",tlbl1->key+100);
5447 emitcode("","%05d$:",tlbl->key+100);
5448 l = aopGet(AOP(result),offset,FALSE,FALSE);
5450 emitcode("add","a,acc");
5451 aopPut(AOP(result),"a",offset++);
5453 l = aopGet(AOP(result),offset,FALSE,FALSE);
5455 emitcode("rlc","a");
5456 aopPut(AOP(result),"a",offset++);
5458 reAdjustPreg(AOP(result));
5460 emitcode("","%05d$:",tlbl1->key+100);
5461 emitcode("djnz","b,%05d$",tlbl->key+100);
5463 freeAsmop(left,NULL,ic,TRUE);
5464 freeAsmop(result,NULL,ic,TRUE);
5467 /*-----------------------------------------------------------------*/
5468 /* genrshOne - right shift a one byte quantity by known count */
5469 /*-----------------------------------------------------------------*/
5470 static void genrshOne (operand *result, operand *left,
5471 int shCount, int sign)
5473 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
5476 /*-----------------------------------------------------------------*/
5477 /* genrshTwo - right shift two bytes by known amount != 0 */
5478 /*-----------------------------------------------------------------*/
5479 static void genrshTwo (operand *result,operand *left,
5480 int shCount, int sign)
5482 /* if shCount >= 8 */
5486 shiftR1Left2Result(left, MSB16, result, LSB,
5489 movLeft2Result(left, MSB16, result, LSB, sign);
5490 addSign(result, MSB16, sign);
5493 /* 1 <= shCount <= 7 */
5495 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
5498 /*-----------------------------------------------------------------*/
5499 /* shiftRLong - shift right one long from left to result */
5500 /* offl = LSB or MSB16 */
5501 /*-----------------------------------------------------------------*/
5502 static void shiftRLong (operand *left, int offl,
5503 operand *result, int sign)
5506 emitcode("clr","c");
5507 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
5509 emitcode("mov","c,acc.7");
5510 emitcode("rrc","a");
5511 aopPut(AOP(result),"a",MSB32-offl);
5513 /* add sign of "a" */
5514 addSign(result, MSB32, sign);
5516 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
5517 emitcode("rrc","a");
5518 aopPut(AOP(result),"a",MSB24-offl);
5520 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
5521 emitcode("rrc","a");
5522 aopPut(AOP(result),"a",MSB16-offl);
5525 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
5526 emitcode("rrc","a");
5527 aopPut(AOP(result),"a",LSB);
5531 /*-----------------------------------------------------------------*/
5532 /* genrshFour - shift four byte by a known amount != 0 */
5533 /*-----------------------------------------------------------------*/
5534 static void genrshFour (operand *result, operand *left,
5535 int shCount, int sign)
5537 /* if shifting more that 3 bytes */
5538 if(shCount >= 24 ) {
5541 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
5543 movLeft2Result(left, MSB32, result, LSB, sign);
5544 addSign(result, MSB16, sign);
5546 else if(shCount >= 16){
5549 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
5551 movLeft2Result(left, MSB24, result, LSB, 0);
5552 movLeft2Result(left, MSB32, result, MSB16, sign);
5554 addSign(result, MSB24, sign);
5556 else if(shCount >= 8){
5559 shiftRLong(left, MSB16, result, sign);
5560 else if(shCount == 0){
5561 movLeft2Result(left, MSB16, result, LSB, 0);
5562 movLeft2Result(left, MSB24, result, MSB16, 0);
5563 movLeft2Result(left, MSB32, result, MSB24, sign);
5564 addSign(result, MSB32, sign);
5567 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
5568 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
5569 /* the last shift is signed */
5570 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
5571 addSign(result, MSB32, sign);
5574 else{ /* 1 <= shCount <= 7 */
5576 shiftRLong(left, LSB, result, sign);
5578 shiftRLong(result, LSB, result, sign);
5581 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
5582 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
5583 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
5588 /*-----------------------------------------------------------------*/
5589 /* genRightShiftLiteral - right shifting by known count */
5590 /*-----------------------------------------------------------------*/
5591 static void genRightShiftLiteral (operand *left,
5597 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5600 freeAsmop(right,NULL,ic,TRUE);
5602 aopOp(left,ic,FALSE);
5603 aopOp(result,ic,FALSE);
5606 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
5610 size = getDataSize(left);
5611 /* test the LEFT size !!! */
5613 /* I suppose that the left size >= result size */
5615 size = getDataSize(result);
5617 movLeft2Result(left, size, result, size, 0);
5620 else if(shCount >= (size * 8)){
5622 /* get sign in acc.7 */
5623 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
5624 addSign(result, LSB, sign);
5628 genrshOne (result,left,shCount,sign);
5632 genrshTwo (result,left,shCount,sign);
5636 genrshFour (result,left,shCount,sign);
5642 freeAsmop(left,NULL,ic,TRUE);
5643 freeAsmop(result,NULL,ic,TRUE);
5647 /*-----------------------------------------------------------------*/
5648 /* genSignedRightShift - right shift of signed number */
5649 /*-----------------------------------------------------------------*/
5650 static void genSignedRightShift (iCode *ic)
5652 operand *right, *left, *result;
5655 symbol *tlbl, *tlbl1 ;
5657 /* we do it the hard way put the shift count in b
5658 and loop thru preserving the sign */
5660 right = IC_RIGHT(ic);
5662 result = IC_RESULT(ic);
5664 aopOp(right,ic,FALSE);
5667 if ( AOP_TYPE(right) == AOP_LIT) {
5668 genRightShiftLiteral (left,right,result,ic,1);
5671 /* shift count is unknown then we have to form
5672 a loop get the loop count in B : Note: we take
5673 only the lower order byte since shifting
5674 more that 32 bits make no sense anyway, ( the
5675 largest size of an object can be only 32 bits ) */
5677 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5678 emitcode("inc","b");
5679 freeAsmop (right,NULL,ic,TRUE);
5680 aopOp(left,ic,FALSE);
5681 aopOp(result,ic,FALSE);
5683 /* now move the left to the result if they are not the
5685 if (!sameRegs(AOP(left),AOP(result)) &&
5686 AOP_SIZE(result) > 1) {
5688 size = AOP_SIZE(result);
5691 l = aopGet(AOP(left),offset,FALSE,TRUE);
5692 if (*l == '@' && IS_AOP_PREG(result)) {
5694 emitcode("mov","a,%s",l);
5695 aopPut(AOP(result),"a",offset);
5697 aopPut(AOP(result),l,offset);
5702 /* mov the highest order bit to OVR */
5703 tlbl = newiTempLabel(NULL);
5704 tlbl1= newiTempLabel(NULL);
5706 size = AOP_SIZE(result);
5708 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
5709 emitcode("rlc","a");
5710 emitcode("mov","ov,c");
5711 /* if it is only one byte then */
5713 l = aopGet(AOP(left),0,FALSE,FALSE);
5715 emitcode("sjmp","%05d$",tlbl1->key+100);
5716 emitcode("","%05d$:",tlbl->key+100);
5717 emitcode("mov","c,ov");
5718 emitcode("rrc","a");
5719 emitcode("","%05d$:",tlbl1->key+100);
5720 emitcode("djnz","b,%05d$",tlbl->key+100);
5721 aopPut(AOP(result),"a",0);
5725 reAdjustPreg(AOP(result));
5726 emitcode("sjmp","%05d$",tlbl1->key+100);
5727 emitcode("","%05d$:",tlbl->key+100);
5728 emitcode("mov","c,ov");
5730 l = aopGet(AOP(result),offset,FALSE,FALSE);
5732 emitcode("rrc","a");
5733 aopPut(AOP(result),"a",offset--);
5735 reAdjustPreg(AOP(result));
5736 emitcode("","%05d$:",tlbl1->key+100);
5737 emitcode("djnz","b,%05d$",tlbl->key+100);
5740 freeAsmop(left,NULL,ic,TRUE);
5741 freeAsmop(result,NULL,ic,TRUE);
5744 /*-----------------------------------------------------------------*/
5745 /* genRightShift - generate code for right shifting */
5746 /*-----------------------------------------------------------------*/
5747 static void genRightShift (iCode *ic)
5749 operand *right, *left, *result;
5753 symbol *tlbl, *tlbl1 ;
5755 /* if signed then we do it the hard way preserve the
5756 sign bit moving it inwards */
5757 retype = getSpec(operandType(IC_RESULT(ic)));
5759 if (!SPEC_USIGN(retype)) {
5760 genSignedRightShift (ic);
5764 /* signed & unsigned types are treated the same : i.e. the
5765 signed is NOT propagated inwards : quoting from the
5766 ANSI - standard : "for E1 >> E2, is equivalent to division
5767 by 2**E2 if unsigned or if it has a non-negative value,
5768 otherwise the result is implementation defined ", MY definition
5769 is that the sign does not get propagated */
5771 right = IC_RIGHT(ic);
5773 result = IC_RESULT(ic);
5775 aopOp(right,ic,FALSE);
5777 /* if the shift count is known then do it
5778 as efficiently as possible */
5779 if (AOP_TYPE(right) == AOP_LIT) {
5780 genRightShiftLiteral (left,right,result,ic, 0);
5784 /* shift count is unknown then we have to form
5785 a loop get the loop count in B : Note: we take
5786 only the lower order byte since shifting
5787 more that 32 bits make no sense anyway, ( the
5788 largest size of an object can be only 32 bits ) */
5790 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5791 emitcode("inc","b");
5792 freeAsmop (right,NULL,ic,TRUE);
5793 aopOp(left,ic,FALSE);
5794 aopOp(result,ic,FALSE);
5796 /* now move the left to the result if they are not the
5798 if (!sameRegs(AOP(left),AOP(result)) &&
5799 AOP_SIZE(result) > 1) {
5801 size = AOP_SIZE(result);
5804 l = aopGet(AOP(left),offset,FALSE,TRUE);
5805 if (*l == '@' && IS_AOP_PREG(result)) {
5807 emitcode("mov","a,%s",l);
5808 aopPut(AOP(result),"a",offset);
5810 aopPut(AOP(result),l,offset);
5815 tlbl = newiTempLabel(NULL);
5816 tlbl1= newiTempLabel(NULL);
5817 size = AOP_SIZE(result);
5820 /* if it is only one byte then */
5822 l = aopGet(AOP(left),0,FALSE,FALSE);
5824 emitcode("sjmp","%05d$",tlbl1->key+100);
5825 emitcode("","%05d$:",tlbl->key+100);
5827 emitcode("rrc","a");
5828 emitcode("","%05d$:",tlbl1->key+100);
5829 emitcode("djnz","b,%05d$",tlbl->key+100);
5830 aopPut(AOP(result),"a",0);
5834 reAdjustPreg(AOP(result));
5835 emitcode("sjmp","%05d$",tlbl1->key+100);
5836 emitcode("","%05d$:",tlbl->key+100);
5839 l = aopGet(AOP(result),offset,FALSE,FALSE);
5841 emitcode("rrc","a");
5842 aopPut(AOP(result),"a",offset--);
5844 reAdjustPreg(AOP(result));
5846 emitcode("","%05d$:",tlbl1->key+100);
5847 emitcode("djnz","b,%05d$",tlbl->key+100);
5850 freeAsmop(left,NULL,ic,TRUE);
5851 freeAsmop(result,NULL,ic,TRUE);
5854 /*-----------------------------------------------------------------*/
5855 /* genUnpackBits - generates code for unpacking bits */
5856 /*-----------------------------------------------------------------*/
5857 static void genUnpackBits (operand *result, char *rname, int ptype)
5865 etype = getSpec(operandType(result));
5866 rsize = getSize(operandType(result));
5867 /* read the first byte */
5872 emitcode("mov","a,@%s",rname);
5876 emitcode("movx","a,@%s",rname);
5880 emitcode("movx","a,@dptr");
5884 emitcode("clr","a");
5885 emitcode("movc","a","@a+dptr");
5889 emitcode("lcall","__gptrget");
5893 rlen = SPEC_BLEN(etype) ;
5895 /* if we have bitdisplacement then it fits */
5896 /* into this byte completely or if length is */
5897 /* less than a byte */
5898 if ((shCnt = SPEC_BSTR(etype)) ||
5899 (SPEC_BLEN(etype) <= 8)) {
5901 /* shift right acc */
5904 emitcode("anl","a,#0x%02x",
5905 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
5906 aopPut(AOP(result),"a",offset++);
5910 /* bit field did not fit in a byte */
5911 aopPut(AOP(result),"a",offset++);
5918 emitcode("inc","%s",rname);
5919 emitcode("mov","a,@%s",rname);
5923 emitcode("inc","%s",rname);
5924 emitcode("movx","a,@%s",rname);
5928 emitcode("inc","dptr");
5929 emitcode("movx","a,@dptr");
5933 emitcode("clr","a");
5934 emitcode("inc","dptr");
5935 emitcode("movc","a","@a+dptr");
5939 emitcode("inc","dptr");
5940 emitcode("lcall","__gptrget");
5945 /* if we are done */
5949 aopPut(AOP(result),"a",offset++);
5954 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
5956 aopPut(AOP(result),"a",offset++);
5960 if (offset < rsize) {
5962 while (rsize--) aopPut(AOP(result),zero,offset++);
5968 /*-----------------------------------------------------------------*/
5969 /* genDataPointerGet - generates code when ptr offset is known */
5970 /*-----------------------------------------------------------------*/
5971 static void genDataPointerGet (operand *left,
5977 int size , offset = 0;
5978 aopOp(result,ic,TRUE);
5980 /* get the string representation of the name */
5981 l = aopGet(AOP(left),0,FALSE,TRUE);
5982 size = AOP_SIZE(result);
5985 sprintf(buffer,"(%s + %d)",l+1,offset);
5987 sprintf(buffer,"%s",l+1);
5988 aopPut(AOP(result),buffer,offset++);
5991 freeAsmop(left,NULL,ic,TRUE);
5992 freeAsmop(result,NULL,ic,TRUE);
5995 /*-----------------------------------------------------------------*/
5996 /* genNearPointerGet - emitcode for near pointer fetch */
5997 /*-----------------------------------------------------------------*/
5998 static void genNearPointerGet (operand *left,
6005 link *rtype, *retype;
6006 link *ltype = operandType(left);
6009 rtype = operandType(result);
6010 retype= getSpec(rtype);
6012 aopOp(left,ic,FALSE);
6014 /* if left is rematerialisable and
6015 result is not bit variable type and
6016 the left is pointer to data space i.e
6017 lower 128 bytes of space */
6018 if (AOP_TYPE(left) == AOP_IMMD &&
6019 !IS_BITVAR(retype) &&
6020 DCL_TYPE(ltype) == POINTER) {
6021 genDataPointerGet (left,result,ic);
6025 /* if the value is already in a pointer register
6026 then don't need anything more */
6027 if (!AOP_INPREG(AOP(left))) {
6028 /* otherwise get a free pointer register */
6030 preg = getFreePtr(ic,&aop,FALSE);
6031 emitcode("mov","%s,%s",
6033 aopGet(AOP(left),0,FALSE,TRUE));
6034 rname = preg->name ;
6036 rname = aopGet(AOP(left),0,FALSE,FALSE);
6038 freeAsmop(left,NULL,ic,TRUE);
6039 aopOp (result,ic,FALSE);
6041 /* if bitfield then unpack the bits */
6042 if (IS_BITVAR(retype))
6043 genUnpackBits (result,rname,POINTER);
6045 /* we have can just get the values */
6046 int size = AOP_SIZE(result);
6050 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6052 emitcode("mov","a,@%s",rname);
6053 aopPut(AOP(result),"a",offset);
6055 sprintf(buffer,"@%s",rname);
6056 aopPut(AOP(result),buffer,offset);
6060 emitcode("inc","%s",rname);
6064 /* now some housekeeping stuff */
6066 /* we had to allocate for this iCode */
6067 freeAsmop(NULL,aop,ic,TRUE);
6069 /* we did not allocate which means left
6070 already in a pointer register, then
6071 if size > 0 && this could be used again
6072 we have to point it back to where it
6074 if (AOP_SIZE(result) > 1 &&
6075 !OP_SYMBOL(left)->remat &&
6076 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6078 int size = AOP_SIZE(result) - 1;
6080 emitcode("dec","%s",rname);
6085 freeAsmop(result,NULL,ic,TRUE);
6089 /*-----------------------------------------------------------------*/
6090 /* genPagedPointerGet - emitcode for paged pointer fetch */
6091 /*-----------------------------------------------------------------*/
6092 static void genPagedPointerGet (operand *left,
6099 link *rtype, *retype;
6101 rtype = operandType(result);
6102 retype= getSpec(rtype);
6104 aopOp(left,ic,FALSE);
6106 /* if the value is already in a pointer register
6107 then don't need anything more */
6108 if (!AOP_INPREG(AOP(left))) {
6109 /* otherwise get a free pointer register */
6111 preg = getFreePtr(ic,&aop,FALSE);
6112 emitcode("mov","%s,%s",
6114 aopGet(AOP(left),0,FALSE,TRUE));
6115 rname = preg->name ;
6117 rname = aopGet(AOP(left),0,FALSE,FALSE);
6119 freeAsmop(left,NULL,ic,TRUE);
6120 aopOp (result,ic,FALSE);
6122 /* if bitfield then unpack the bits */
6123 if (IS_BITVAR(retype))
6124 genUnpackBits (result,rname,PPOINTER);
6126 /* we have can just get the values */
6127 int size = AOP_SIZE(result);
6132 emitcode("movx","a,@%s",rname);
6133 aopPut(AOP(result),"a",offset);
6138 emitcode("inc","%s",rname);
6142 /* now some housekeeping stuff */
6144 /* we had to allocate for this iCode */
6145 freeAsmop(NULL,aop,ic,TRUE);
6147 /* we did not allocate which means left
6148 already in a pointer register, then
6149 if size > 0 && this could be used again
6150 we have to point it back to where it
6152 if (AOP_SIZE(result) > 1 &&
6153 !OP_SYMBOL(left)->remat &&
6154 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6156 int size = AOP_SIZE(result) - 1;
6158 emitcode("dec","%s",rname);
6163 freeAsmop(result,NULL,ic,TRUE);
6168 /*-----------------------------------------------------------------*/
6169 /* genFarPointerGet - gget value from far space */
6170 /*-----------------------------------------------------------------*/
6171 static void genFarPointerGet (operand *left,
6172 operand *result, iCode *ic)
6175 link *retype = getSpec(operandType(result));
6177 aopOp(left,ic,FALSE);
6179 /* if the operand is already in dptr
6180 then we do nothing else we move the value to dptr */
6181 if (AOP_TYPE(left) != AOP_STR) {
6182 /* if this is remateriazable */
6183 if (AOP_TYPE(left) == AOP_IMMD)
6184 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6185 else { /* we need to get it byte by byte */
6186 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6187 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6188 if (options.model == MODEL_FLAT24)
6190 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6194 /* so dptr know contains the address */
6195 freeAsmop(left,NULL,ic,TRUE);
6196 aopOp(result,ic,FALSE);
6198 /* if bit then unpack */
6199 if (IS_BITVAR(retype))
6200 genUnpackBits(result,"dptr",FPOINTER);
6202 size = AOP_SIZE(result);
6206 emitcode("movx","a,@dptr");
6207 aopPut(AOP(result),"a",offset++);
6209 emitcode("inc","dptr");
6213 freeAsmop(result,NULL,ic,TRUE);
6216 /*-----------------------------------------------------------------*/
6217 /* emitcodePointerGet - gget value from code space */
6218 /*-----------------------------------------------------------------*/
6219 static void emitcodePointerGet (operand *left,
6220 operand *result, iCode *ic)
6223 link *retype = getSpec(operandType(result));
6225 aopOp(left,ic,FALSE);
6227 /* if the operand is already in dptr
6228 then we do nothing else we move the value to dptr */
6229 if (AOP_TYPE(left) != AOP_STR) {
6230 /* if this is remateriazable */
6231 if (AOP_TYPE(left) == AOP_IMMD)
6232 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6233 else { /* we need to get it byte by byte */
6234 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6235 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6236 if (options.model == MODEL_FLAT24)
6238 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6242 /* so dptr know contains the address */
6243 freeAsmop(left,NULL,ic,TRUE);
6244 aopOp(result,ic,FALSE);
6246 /* if bit then unpack */
6247 if (IS_BITVAR(retype))
6248 genUnpackBits(result,"dptr",CPOINTER);
6250 size = AOP_SIZE(result);
6254 emitcode("clr","a");
6255 emitcode("movc","a,@a+dptr");
6256 aopPut(AOP(result),"a",offset++);
6258 emitcode("inc","dptr");
6262 freeAsmop(result,NULL,ic,TRUE);
6265 /*-----------------------------------------------------------------*/
6266 /* genGenPointerGet - gget value from generic pointer space */
6267 /*-----------------------------------------------------------------*/
6268 static void genGenPointerGet (operand *left,
6269 operand *result, iCode *ic)
6272 link *retype = getSpec(operandType(result));
6274 aopOp(left,ic,FALSE);
6276 /* if the operand is already in dptr
6277 then we do nothing else we move the value to dptr */
6278 if (AOP_TYPE(left) != AOP_STR) {
6279 /* if this is remateriazable */
6280 if (AOP_TYPE(left) == AOP_IMMD) {
6281 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6282 emitcode("mov","b,#%d",pointerCode(retype));
6284 else { /* we need to get it byte by byte */
6285 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6286 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6287 if (options.model == MODEL_FLAT24)
6289 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6290 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
6294 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
6298 /* so dptr know contains the address */
6299 freeAsmop(left,NULL,ic,TRUE);
6300 aopOp(result,ic,FALSE);
6302 /* if bit then unpack */
6303 if (IS_BITVAR(retype))
6304 genUnpackBits(result,"dptr",GPOINTER);
6306 size = AOP_SIZE(result);
6310 emitcode("lcall","__gptrget");
6311 aopPut(AOP(result),"a",offset++);
6313 emitcode("inc","dptr");
6317 freeAsmop(result,NULL,ic,TRUE);
6320 /*-----------------------------------------------------------------*/
6321 /* genPointerGet - generate code for pointer get */
6322 /*-----------------------------------------------------------------*/
6323 static void genPointerGet (iCode *ic)
6325 operand *left, *result ;
6330 result = IC_RESULT(ic) ;
6332 /* depending on the type of pointer we need to
6333 move it to the correct pointer register */
6334 type = operandType(left);
6335 etype = getSpec(type);
6336 /* if left is of type of pointer then it is simple */
6337 if (IS_PTR(type) && !IS_FUNC(type->next))
6338 p_type = DCL_TYPE(type);
6340 /* we have to go by the storage class */
6341 p_type = PTR_TYPE(SPEC_OCLS(etype));
6343 /* if (SPEC_OCLS(etype)->codesp ) { */
6344 /* p_type = CPOINTER ; */
6347 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6348 /* p_type = FPOINTER ; */
6350 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6351 /* p_type = PPOINTER; */
6353 /* if (SPEC_OCLS(etype) == idata ) */
6354 /* p_type = IPOINTER; */
6356 /* p_type = POINTER ; */
6359 /* now that we have the pointer type we assign
6360 the pointer values */
6365 genNearPointerGet (left,result,ic);
6369 genPagedPointerGet(left,result,ic);
6373 genFarPointerGet (left,result,ic);
6377 emitcodePointerGet (left,result,ic);
6381 genGenPointerGet (left,result,ic);
6387 /*-----------------------------------------------------------------*/
6388 /* genPackBits - generates code for packed bit storage */
6389 /*-----------------------------------------------------------------*/
6390 static void genPackBits (link *etype ,
6392 char *rname, int p_type)
6400 blen = SPEC_BLEN(etype);
6401 bstr = SPEC_BSTR(etype);
6403 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6406 /* if the bit lenth is less than or */
6407 /* it exactly fits a byte then */
6408 if (SPEC_BLEN(etype) <= 8 ) {
6409 shCount = SPEC_BSTR(etype) ;
6411 /* shift left acc */
6414 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6419 emitcode ("mov","b,a");
6420 emitcode("mov","a,@%s",rname);
6424 emitcode ("mov","b,a");
6425 emitcode("movx","a,@dptr");
6429 emitcode ("push","b");
6430 emitcode ("push","acc");
6431 emitcode ("lcall","__gptrget");
6432 emitcode ("pop","b");
6436 emitcode ("anl","a,#0x%02x",(unsigned char)
6437 ((unsigned char)(0xFF << (blen+bstr)) |
6438 (unsigned char)(0xFF >> (8-bstr)) ) );
6439 emitcode ("orl","a,b");
6440 if (p_type == GPOINTER)
6441 emitcode("pop","b");
6447 emitcode("mov","@%s,a",rname);
6451 emitcode("movx","@dptr,a");
6455 emitcode("lcall","__gptrput");
6460 if ( SPEC_BLEN(etype) <= 8 )
6463 emitcode("inc","%s",rname);
6464 rLen = SPEC_BLEN(etype) ;
6466 /* now generate for lengths greater than one byte */
6469 l = aopGet(AOP(right),offset++,FALSE,TRUE);
6479 emitcode("mov","@%s,a",rname);
6481 emitcode("mov","@%s,%s",rname,l);
6486 emitcode("movx","@dptr,a");
6491 emitcode("lcall","__gptrput");
6494 emitcode ("inc","%s",rname);
6499 /* last last was not complete */
6501 /* save the byte & read byte */
6504 emitcode ("mov","b,a");
6505 emitcode("mov","a,@%s",rname);
6509 emitcode ("mov","b,a");
6510 emitcode("movx","a,@dptr");
6514 emitcode ("push","b");
6515 emitcode ("push","acc");
6516 emitcode ("lcall","__gptrget");
6517 emitcode ("pop","b");
6521 emitcode ("anl","a,#0x%02x",(((unsigned char)-1 << rLen) & 0xff) );
6522 emitcode ("orl","a,b");
6525 if (p_type == GPOINTER)
6526 emitcode("pop","b");
6531 emitcode("mov","@%s,a",rname);
6535 emitcode("movx","@dptr,a");
6539 emitcode("lcall","__gptrput");
6543 /*-----------------------------------------------------------------*/
6544 /* genDataPointerSet - remat pointer to data space */
6545 /*-----------------------------------------------------------------*/
6546 static void genDataPointerSet(operand *right,
6550 int size, offset = 0 ;
6551 char *l, buffer[256];
6553 aopOp(right,ic,FALSE);
6555 l = aopGet(AOP(result),0,FALSE,TRUE);
6556 size = AOP_SIZE(right);
6559 sprintf(buffer,"(%s + %d)",l+1,offset);
6561 sprintf(buffer,"%s",l+1);
6562 emitcode("mov","%s,%s",buffer,
6563 aopGet(AOP(right),offset++,FALSE,FALSE));
6566 freeAsmop(right,NULL,ic,TRUE);
6567 freeAsmop(result,NULL,ic,TRUE);
6570 /*-----------------------------------------------------------------*/
6571 /* genNearPointerSet - emitcode for near pointer put */
6572 /*-----------------------------------------------------------------*/
6573 static void genNearPointerSet (operand *right,
6580 link *retype, *letype;
6581 link *ptype = operandType(result);
6583 retype= getSpec(operandType(right));
6584 letype= getSpec(ptype);
6585 aopOp(result,ic,FALSE);
6587 /* if the result is rematerializable &
6588 in data space & not a bit variable */
6589 if (AOP_TYPE(result) == AOP_IMMD &&
6590 DCL_TYPE(ptype) == POINTER &&
6591 !IS_BITVAR(retype) &&
6592 !IS_BITVAR(letype)) {
6593 genDataPointerSet (right,result,ic);
6597 /* if the value is already in a pointer register
6598 then don't need anything more */
6599 if (!AOP_INPREG(AOP(result))) {
6600 /* otherwise get a free pointer register */
6602 preg = getFreePtr(ic,&aop,FALSE);
6603 emitcode("mov","%s,%s",
6605 aopGet(AOP(result),0,FALSE,TRUE));
6606 rname = preg->name ;
6608 rname = aopGet(AOP(result),0,FALSE,FALSE);
6610 freeAsmop(result,NULL,ic,TRUE);
6611 aopOp (right,ic,FALSE);
6613 /* if bitfield then unpack the bits */
6614 if (IS_BITVAR(retype) || IS_BITVAR(letype))
6615 genPackBits ((IS_BITVAR(retype) ? retype : letype),right,rname,POINTER);
6617 /* we have can just get the values */
6618 int size = AOP_SIZE(right);
6622 l = aopGet(AOP(right),offset,FALSE,TRUE);
6625 emitcode("mov","@%s,a",rname);
6627 emitcode("mov","@%s,%s",rname,l);
6629 emitcode("inc","%s",rname);
6634 /* now some housekeeping stuff */
6636 /* we had to allocate for this iCode */
6637 freeAsmop(NULL,aop,ic,TRUE);
6639 /* we did not allocate which means left
6640 already in a pointer register, then
6641 if size > 0 && this could be used again
6642 we have to point it back to where it
6644 if (AOP_SIZE(right) > 1 &&
6645 !OP_SYMBOL(result)->remat &&
6646 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6648 int size = AOP_SIZE(right) - 1;
6650 emitcode("dec","%s",rname);
6655 freeAsmop(right,NULL,ic,TRUE);
6660 /*-----------------------------------------------------------------*/
6661 /* genPagedPointerSet - emitcode for Paged pointer put */
6662 /*-----------------------------------------------------------------*/
6663 static void genPagedPointerSet (operand *right,
6670 link *retype, *letype;
6672 retype= getSpec(operandType(right));
6673 letype= getSpec(operandType(result));
6675 aopOp(result,ic,FALSE);
6677 /* if the value is already in a pointer register
6678 then don't need anything more */
6679 if (!AOP_INPREG(AOP(result))) {
6680 /* otherwise get a free pointer register */
6682 preg = getFreePtr(ic,&aop,FALSE);
6683 emitcode("mov","%s,%s",
6685 aopGet(AOP(result),0,FALSE,TRUE));
6686 rname = preg->name ;
6688 rname = aopGet(AOP(result),0,FALSE,FALSE);
6690 freeAsmop(result,NULL,ic,TRUE);
6691 aopOp (right,ic,FALSE);
6693 /* if bitfield then unpack the bits */
6694 if (IS_BITVAR(retype) || IS_BITVAR(letype))
6695 genPackBits ((IS_BITVAR(retype) ? retype : letype),right,rname,PPOINTER);
6697 /* we have can just get the values */
6698 int size = AOP_SIZE(right);
6702 l = aopGet(AOP(right),offset,FALSE,TRUE);
6705 emitcode("movx","@%s,a",rname);
6708 emitcode("inc","%s",rname);
6714 /* now some housekeeping stuff */
6716 /* we had to allocate for this iCode */
6717 freeAsmop(NULL,aop,ic,TRUE);
6719 /* we did not allocate which means left
6720 already in a pointer register, then
6721 if size > 0 && this could be used again
6722 we have to point it back to where it
6724 if (AOP_SIZE(right) > 1 &&
6725 !OP_SYMBOL(result)->remat &&
6726 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6728 int size = AOP_SIZE(right) - 1;
6730 emitcode("dec","%s",rname);
6735 freeAsmop(right,NULL,ic,TRUE);
6740 /*-----------------------------------------------------------------*/
6741 /* genFarPointerSet - set value from far space */
6742 /*-----------------------------------------------------------------*/
6743 static void genFarPointerSet (operand *right,
6744 operand *result, iCode *ic)
6747 link *retype = getSpec(operandType(right));
6748 link *letype = getSpec(operandType(result));
6749 aopOp(result,ic,FALSE);
6751 /* if the operand is already in dptr
6752 then we do nothing else we move the value to dptr */
6753 if (AOP_TYPE(result) != AOP_STR) {
6754 /* if this is remateriazable */
6755 if (AOP_TYPE(result) == AOP_IMMD)
6756 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6757 else { /* we need to get it byte by byte */
6758 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6759 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6760 if (options.model == MODEL_FLAT24)
6762 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6766 /* so dptr know contains the address */
6767 freeAsmop(result,NULL,ic,TRUE);
6768 aopOp(right,ic,FALSE);
6770 /* if bit then unpack */
6771 if (IS_BITVAR(retype) || IS_BITVAR(letype))
6772 genPackBits((IS_BITVAR(retype) ? retype : letype),right,"dptr",FPOINTER);
6774 size = AOP_SIZE(right);
6778 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6780 emitcode("movx","@dptr,a");
6782 emitcode("inc","dptr");
6786 freeAsmop(right,NULL,ic,TRUE);
6789 /*-----------------------------------------------------------------*/
6790 /* genGenPointerSet - set value from generic pointer space */
6791 /*-----------------------------------------------------------------*/
6792 static void genGenPointerSet (operand *right,
6793 operand *result, iCode *ic)
6796 link *retype = getSpec(operandType(right));
6797 link *letype = getSpec(operandType(result));
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) || IS_BITVAR(letype))
6829 genPackBits((IS_BITVAR(retype) ? retype : letype),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));
6871 /* now that we have the pointer type we assign
6872 the pointer values */
6877 genNearPointerSet (right,result,ic);
6881 genPagedPointerSet (right,result,ic);
6885 genFarPointerSet (right,result,ic);
6889 genGenPointerSet (right,result,ic);
6895 /*-----------------------------------------------------------------*/
6896 /* genIfx - generate code for Ifx statement */
6897 /*-----------------------------------------------------------------*/
6898 static void genIfx (iCode *ic, iCode *popIc)
6900 operand *cond = IC_COND(ic);
6903 aopOp(cond,ic,FALSE);
6905 /* get the value into acc */
6906 if (AOP_TYPE(cond) != AOP_CRY)
6910 /* the result is now in the accumulator */
6911 freeAsmop(cond,NULL,ic,TRUE);
6913 /* if there was something to be popped then do it */
6917 /* if the condition is a bit variable */
6918 if (isbit && IS_ITEMP(cond) &&
6920 genIfxJump(ic,SPIL_LOC(cond)->rname);
6922 if (isbit && !IS_ITEMP(cond))
6923 genIfxJump(ic,OP_SYMBOL(cond)->rname);
6930 /*-----------------------------------------------------------------*/
6931 /* genAddrOf - generates code for address of */
6932 /*-----------------------------------------------------------------*/
6933 static void genAddrOf (iCode *ic)
6935 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
6938 aopOp(IC_RESULT(ic),ic,FALSE);
6940 /* if the operand is on the stack then we
6941 need to get the stack offset of this
6944 /* if it has an offset then we need to compute
6947 emitcode("mov","a,_bp");
6948 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
6949 aopPut(AOP(IC_RESULT(ic)),"a",0);
6951 /* we can just move _bp */
6952 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
6954 /* fill the result with zero */
6955 size = AOP_SIZE(IC_RESULT(ic)) - 1;
6958 if (options.stack10bit && size < (FPTRSIZE - 1))
6961 "*** warning: pointer to stack var truncated.\n");
6968 if (options.stack10bit && offset == 2)
6970 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
6974 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
6981 /* object not on stack then we need the name */
6982 size = AOP_SIZE(IC_RESULT(ic));
6986 char s[SDCC_NAME_MAX];
6988 sprintf(s,"#(%s >> %d)",
6992 sprintf(s,"#%s",sym->rname);
6993 aopPut(AOP(IC_RESULT(ic)),s,offset++);
6997 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7001 /*-----------------------------------------------------------------*/
7002 /* genFarFarAssign - assignment when both are in far space */
7003 /*-----------------------------------------------------------------*/
7004 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7006 int size = AOP_SIZE(right);
7009 /* first push the right side on to the stack */
7011 l = aopGet(AOP(right),offset++,FALSE,FALSE);
7013 emitcode ("push","acc");
7016 freeAsmop(right,NULL,ic,FALSE);
7017 /* now assign DPTR to result */
7018 aopOp(result,ic,FALSE);
7019 size = AOP_SIZE(result);
7021 emitcode ("pop","acc");
7022 aopPut(AOP(result),"a",--offset);
7024 freeAsmop(result,NULL,ic,FALSE);
7028 /*-----------------------------------------------------------------*/
7029 /* genAssign - generate code for assignment */
7030 /*-----------------------------------------------------------------*/
7031 static void genAssign (iCode *ic)
7033 operand *result, *right;
7035 unsigned long lit = 0L;
7037 result = IC_RESULT(ic);
7038 right = IC_RIGHT(ic) ;
7040 /* if they are the same */
7041 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7044 aopOp(right,ic,FALSE);
7046 /* special case both in far space */
7047 if ((AOP_TYPE(right) == AOP_DPTR ||
7048 AOP_TYPE(right) == AOP_DPTR2) &&
7049 IS_TRUE_SYMOP(result) &&
7050 isOperandInFarSpace(result)) {
7052 genFarFarAssign (result,right,ic);
7056 aopOp(result,ic,TRUE);
7058 /* if they are the same registers */
7059 if (sameRegs(AOP(right),AOP(result)))
7062 /* if the result is a bit */
7063 if (AOP_TYPE(result) == AOP_CRY) {
7065 /* if the right size is a literal then
7066 we know what the value is */
7067 if (AOP_TYPE(right) == AOP_LIT) {
7068 if (((int) operandLitValue(right)))
7069 aopPut(AOP(result),one,0);
7071 aopPut(AOP(result),zero,0);
7075 /* the right is also a bit variable */
7076 if (AOP_TYPE(right) == AOP_CRY) {
7077 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7078 aopPut(AOP(result),"c",0);
7084 aopPut(AOP(result),"a",0);
7088 /* bit variables done */
7090 size = AOP_SIZE(result);
7092 if(AOP_TYPE(right) == AOP_LIT)
7093 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7095 (AOP_TYPE(result) != AOP_REG) &&
7096 (AOP_TYPE(right) == AOP_LIT) &&
7097 !IS_FLOAT(operandType(right)) &&
7099 emitcode("clr","a");
7101 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7102 aopPut(AOP(result),"a",size);
7105 aopGet(AOP(right),size,FALSE,FALSE),
7111 aopGet(AOP(right),offset,FALSE,FALSE),
7118 freeAsmop (right,NULL,ic,TRUE);
7119 freeAsmop (result,NULL,ic,TRUE);
7122 /*-----------------------------------------------------------------*/
7123 /* genJumpTab - genrates code for jump table */
7124 /*-----------------------------------------------------------------*/
7125 static void genJumpTab (iCode *ic)
7130 aopOp(IC_JTCOND(ic),ic,FALSE);
7131 /* get the condition into accumulator */
7132 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
7134 /* multiply by three */
7135 emitcode("add","a,acc");
7136 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
7137 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7139 jtab = newiTempLabel(NULL);
7140 emitcode("mov","dptr,#%05d$",jtab->key+100);
7141 emitcode("jmp","@a+dptr");
7142 emitcode("","%05d$:",jtab->key+100);
7143 /* now generate the jump labels */
7144 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
7145 jtab = setNextItem(IC_JTLABELS(ic)))
7146 emitcode("ljmp","%05d$",jtab->key+100);
7150 /*-----------------------------------------------------------------*/
7151 /* genCast - gen code for casting */
7152 /*-----------------------------------------------------------------*/
7153 static void genCast (iCode *ic)
7155 operand *result = IC_RESULT(ic);
7156 link *ctype = operandType(IC_LEFT(ic));
7157 link *rtype = operandType(IC_RIGHT(ic));
7158 operand *right = IC_RIGHT(ic);
7161 /* if they are equivalent then do nothing */
7162 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
7165 aopOp(right,ic,FALSE) ;
7166 aopOp(result,ic,FALSE);
7168 /* if the result is a bit */
7169 if (AOP_TYPE(result) == AOP_CRY) {
7170 /* if the right size is a literal then
7171 we know what the value is */
7172 if (AOP_TYPE(right) == AOP_LIT) {
7173 if (((int) operandLitValue(right)))
7174 aopPut(AOP(result),one,0);
7176 aopPut(AOP(result),zero,0);
7181 /* the right is also a bit variable */
7182 if (AOP_TYPE(right) == AOP_CRY) {
7183 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7184 aopPut(AOP(result),"c",0);
7190 aopPut(AOP(result),"a",0);
7194 /* if they are the same size : or less */
7195 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
7197 /* if they are in the same place */
7198 if (sameRegs(AOP(right),AOP(result)))
7201 /* if they in different places then copy */
7202 size = AOP_SIZE(result);
7206 aopGet(AOP(right),offset,FALSE,FALSE),
7214 /* if the result is of type pointer */
7215 if (IS_PTR(ctype)) {
7218 link *type = operandType(right);
7219 link *etype = getSpec(type);
7221 /* pointer to generic pointer */
7222 if (IS_GENPTR(ctype)) {
7226 p_type = DCL_TYPE(type);
7228 /* we have to go by the storage class */
7229 p_type = PTR_TYPE(SPEC_OCLS(etype));
7232 /* the first two bytes are known */
7233 size = GPTRSIZE - 1;
7237 aopGet(AOP(right),offset,FALSE,FALSE),
7241 /* the last byte depending on type */
7258 /* this should never happen */
7259 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7260 "got unknown pointer type");
7263 aopPut(AOP(result),l, GPTRSIZE - 1);
7267 /* just copy the pointers */
7268 size = AOP_SIZE(result);
7272 aopGet(AOP(right),offset,FALSE,FALSE),
7279 /* so we now know that the size of destination is greater
7280 than the size of the source */
7281 /* we move to result for the size of source */
7282 size = AOP_SIZE(right);
7286 aopGet(AOP(right),offset,FALSE,FALSE),
7291 /* now depending on the sign of the source && destination */
7292 size = AOP_SIZE(result) - AOP_SIZE(right);
7293 /* if unsigned or not an integral type */
7294 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
7296 aopPut(AOP(result),zero,offset++);
7298 /* we need to extend the sign :{ */
7299 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
7302 emitcode("rlc","a");
7303 emitcode("subb","a,acc");
7305 aopPut(AOP(result),"a",offset++);
7308 /* we are done hurray !!!! */
7311 freeAsmop(right,NULL,ic,TRUE);
7312 freeAsmop(result,NULL,ic,TRUE);
7316 /*-----------------------------------------------------------------*/
7317 /* genDjnz - generate decrement & jump if not zero instrucion */
7318 /*-----------------------------------------------------------------*/
7319 static int genDjnz (iCode *ic, iCode *ifx)
7325 /* if the if condition has a false label
7326 then we cannot save */
7330 /* if the minus is not of the form
7332 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
7333 !IS_OP_LITERAL(IC_RIGHT(ic)))
7336 if (operandLitValue(IC_RIGHT(ic)) != 1)
7339 /* if the size of this greater than one then no
7341 if (getSize(operandType(IC_RESULT(ic))) > 1)
7344 /* otherwise we can save BIG */
7345 lbl = newiTempLabel(NULL);
7346 lbl1= newiTempLabel(NULL);
7348 aopOp(IC_RESULT(ic),ic,FALSE);
7350 if (IS_AOP_PREG(IC_RESULT(ic))) {
7351 emitcode("dec","%s",
7352 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7353 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7354 emitcode("jnz","%05d$",lbl->key+100);
7356 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
7359 emitcode ("sjmp","%05d$",lbl1->key+100);
7360 emitcode ("","%05d$:",lbl->key+100);
7361 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
7362 emitcode ("","%05d$:",lbl1->key+100);
7364 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7369 /*-----------------------------------------------------------------*/
7370 /* genReceive - generate code for a receive iCode */
7371 /*-----------------------------------------------------------------*/
7372 static void genReceive (iCode *ic)
7374 if (isOperandInFarSpace(IC_RESULT(ic)) &&
7375 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
7376 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
7378 int size = getSize(operandType(IC_RESULT(ic)));
7379 int offset = fReturnSize - size;
7381 emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
7382 fReturn[fReturnSize - offset - 1] : "acc"));
7385 aopOp(IC_RESULT(ic),ic,FALSE);
7386 size = AOP_SIZE(IC_RESULT(ic));
7389 emitcode ("pop","acc");
7390 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
7395 aopOp(IC_RESULT(ic),ic,FALSE);
7397 assignResultValue(IC_RESULT(ic));
7400 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7403 /*-----------------------------------------------------------------*/
7404 /* gen51Code - generate code for 8051 based controllers */
7405 /*-----------------------------------------------------------------*/
7406 void gen51Code (iCode *lic)
7411 lineHead = lineCurr = NULL;
7413 /* print the allocation information */
7415 printAllocInfo( currFunc, codeOutFile);
7416 /* if debug information required */
7417 /* if (options.debug && currFunc) { */
7419 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
7421 if (IS_STATIC(currFunc->etype))
7422 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
7424 emitcode("","G$%s$0$0 ==.",currFunc->name);
7427 /* stack pointer name */
7428 if (options.useXstack)
7434 for (ic = lic ; ic ; ic = ic->next ) {
7436 if ( cln != ic->lineno ) {
7437 if ( options.debug ) {
7439 emitcode("","C$%s$%d$%d$%d ==.",
7440 ic->filename,ic->lineno,
7441 ic->level,ic->block);
7444 emitcode(";","%s %d",ic->filename,ic->lineno);
7447 /* if the result is marked as
7448 spilt and rematerializable or code for
7449 this has already been generated then
7451 if (resultRemat(ic) || ic->generated )
7454 /* depending on the operation */
7473 /* IPOP happens only when trying to restore a
7474 spilt live range, if there is an ifx statement
7475 following this pop then the if statement might
7476 be using some of the registers being popped which
7477 would destory the contents of the register so
7478 we need to check for this condition and handle it */
7480 ic->next->op == IFX &&
7481 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
7482 genIfx (ic->next,ic);
7500 genEndFunction (ic);
7520 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
7537 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
7541 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
7548 /* note these two are xlated by algebraic equivalence
7549 during parsing SDCC.y */
7550 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7551 "got '>=' or '<=' shouldn't have come here");
7555 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
7567 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
7571 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
7575 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
7602 case GET_VALUE_AT_ADDRESS:
7607 if (POINTER_SET(ic))
7634 addSet(&_G.sendSet,ic);
7639 /* piCode(ic,stdout); */
7645 /* now we are ready to call the
7646 peep hole optimizer */
7647 if (!options.nopeep)
7648 peepHole (&lineHead);
7650 /* now do the actual printing */
7651 printLine (lineHead,codeOutFile);