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)
5864 etype = getSpec(operandType(result));
5866 /* read the first byte */
5871 emitcode("mov","a,@%s",rname);
5875 emitcode("movx","a,@%s",rname);
5879 emitcode("movx","a,@dptr");
5883 emitcode("clr","a");
5884 emitcode("movc","a","@a+dptr");
5888 emitcode("lcall","__gptrget");
5892 /* if we have bitdisplacement then it fits */
5893 /* into this byte completely or if length is */
5894 /* less than a byte */
5895 if ((shCnt = SPEC_BSTR(etype)) ||
5896 (SPEC_BLEN(etype) <= 8)) {
5898 /* shift right acc */
5901 emitcode("anl","a,#0x%02x",
5902 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
5903 aopPut(AOP(result),"a",offset);
5907 /* bit field did not fit in a byte */
5908 rlen = SPEC_BLEN(etype) - 8;
5909 aopPut(AOP(result),"a",offset++);
5916 emitcode("inc","%s",rname);
5917 emitcode("mov","a,@%s",rname);
5921 emitcode("inc","%s",rname);
5922 emitcode("movx","a,@%s",rname);
5926 emitcode("inc","dptr");
5927 emitcode("movx","a,@dptr");
5931 emitcode("clr","a");
5932 emitcode("inc","dptr");
5933 emitcode("movc","a","@a+dptr");
5937 emitcode("inc","dptr");
5938 emitcode("lcall","__gptrget");
5943 /* if we are done */
5947 aopPut(AOP(result),"a",offset++);
5952 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
5953 aopPut(AOP(result),"a",offset);
5960 /*-----------------------------------------------------------------*/
5961 /* genDataPointerGet - generates code when ptr offset is known */
5962 /*-----------------------------------------------------------------*/
5963 static void genDataPointerGet (operand *left,
5969 int size , offset = 0;
5970 aopOp(result,ic,TRUE);
5972 /* get the string representation of the name */
5973 l = aopGet(AOP(left),0,FALSE,TRUE);
5974 size = AOP_SIZE(result);
5977 sprintf(buffer,"(%s + %d)",l+1,offset);
5979 sprintf(buffer,"%s",l+1);
5980 aopPut(AOP(result),buffer,offset++);
5983 freeAsmop(left,NULL,ic,TRUE);
5984 freeAsmop(result,NULL,ic,TRUE);
5987 /*-----------------------------------------------------------------*/
5988 /* genNearPointerGet - emitcode for near pointer fetch */
5989 /*-----------------------------------------------------------------*/
5990 static void genNearPointerGet (operand *left,
5997 link *rtype, *retype;
5998 link *ltype = operandType(left);
6001 rtype = operandType(result);
6002 retype= getSpec(rtype);
6004 aopOp(left,ic,FALSE);
6006 /* if left is rematerialisable and
6007 result is not bit variable type and
6008 the left is pointer to data space i.e
6009 lower 128 bytes of space */
6010 if (AOP_TYPE(left) == AOP_IMMD &&
6011 !IS_BITVAR(retype) &&
6012 DCL_TYPE(ltype) == POINTER) {
6013 genDataPointerGet (left,result,ic);
6017 /* if the value is already in a pointer register
6018 then don't need anything more */
6019 if (!AOP_INPREG(AOP(left))) {
6020 /* otherwise get a free pointer register */
6022 preg = getFreePtr(ic,&aop,FALSE);
6023 emitcode("mov","%s,%s",
6025 aopGet(AOP(left),0,FALSE,TRUE));
6026 rname = preg->name ;
6028 rname = aopGet(AOP(left),0,FALSE,FALSE);
6030 freeAsmop(left,NULL,ic,TRUE);
6031 aopOp (result,ic,FALSE);
6033 /* if bitfield then unpack the bits */
6034 if (IS_BITVAR(retype))
6035 genUnpackBits (result,rname,POINTER);
6037 /* we have can just get the values */
6038 int size = AOP_SIZE(result);
6042 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6044 emitcode("mov","a,@%s",rname);
6045 aopPut(AOP(result),"a",offset);
6047 sprintf(buffer,"@%s",rname);
6048 aopPut(AOP(result),buffer,offset);
6052 emitcode("inc","%s",rname);
6056 /* now some housekeeping stuff */
6058 /* we had to allocate for this iCode */
6059 freeAsmop(NULL,aop,ic,TRUE);
6061 /* we did not allocate which means left
6062 already in a pointer register, then
6063 if size > 0 && this could be used again
6064 we have to point it back to where it
6066 if (AOP_SIZE(result) > 1 &&
6067 !OP_SYMBOL(left)->remat &&
6068 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6070 int size = AOP_SIZE(result) - 1;
6072 emitcode("dec","%s",rname);
6077 freeAsmop(result,NULL,ic,TRUE);
6081 /*-----------------------------------------------------------------*/
6082 /* genPagedPointerGet - emitcode for paged pointer fetch */
6083 /*-----------------------------------------------------------------*/
6084 static void genPagedPointerGet (operand *left,
6091 link *rtype, *retype;
6093 rtype = operandType(result);
6094 retype= getSpec(rtype);
6096 aopOp(left,ic,FALSE);
6098 /* if the value is already in a pointer register
6099 then don't need anything more */
6100 if (!AOP_INPREG(AOP(left))) {
6101 /* otherwise get a free pointer register */
6103 preg = getFreePtr(ic,&aop,FALSE);
6104 emitcode("mov","%s,%s",
6106 aopGet(AOP(left),0,FALSE,TRUE));
6107 rname = preg->name ;
6109 rname = aopGet(AOP(left),0,FALSE,FALSE);
6111 freeAsmop(left,NULL,ic,TRUE);
6112 aopOp (result,ic,FALSE);
6114 /* if bitfield then unpack the bits */
6115 if (IS_BITVAR(retype))
6116 genUnpackBits (result,rname,PPOINTER);
6118 /* we have can just get the values */
6119 int size = AOP_SIZE(result);
6124 emitcode("movx","a,@%s",rname);
6125 aopPut(AOP(result),"a",offset);
6130 emitcode("inc","%s",rname);
6134 /* now some housekeeping stuff */
6136 /* we had to allocate for this iCode */
6137 freeAsmop(NULL,aop,ic,TRUE);
6139 /* we did not allocate which means left
6140 already in a pointer register, then
6141 if size > 0 && this could be used again
6142 we have to point it back to where it
6144 if (AOP_SIZE(result) > 1 &&
6145 !OP_SYMBOL(left)->remat &&
6146 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6148 int size = AOP_SIZE(result) - 1;
6150 emitcode("dec","%s",rname);
6155 freeAsmop(result,NULL,ic,TRUE);
6160 /*-----------------------------------------------------------------*/
6161 /* genFarPointerGet - gget value from far space */
6162 /*-----------------------------------------------------------------*/
6163 static void genFarPointerGet (operand *left,
6164 operand *result, iCode *ic)
6167 link *retype = getSpec(operandType(result));
6169 aopOp(left,ic,FALSE);
6171 /* if the operand is already in dptr
6172 then we do nothing else we move the value to dptr */
6173 if (AOP_TYPE(left) != AOP_STR) {
6174 /* if this is remateriazable */
6175 if (AOP_TYPE(left) == AOP_IMMD)
6176 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6177 else { /* we need to get it byte by byte */
6178 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6179 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6180 if (options.model == MODEL_FLAT24)
6182 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6186 /* so dptr know contains the address */
6187 freeAsmop(left,NULL,ic,TRUE);
6188 aopOp(result,ic,FALSE);
6190 /* if bit then unpack */
6191 if (IS_BITVAR(retype))
6192 genUnpackBits(result,"dptr",FPOINTER);
6194 size = AOP_SIZE(result);
6198 emitcode("movx","a,@dptr");
6199 aopPut(AOP(result),"a",offset++);
6201 emitcode("inc","dptr");
6205 freeAsmop(result,NULL,ic,TRUE);
6208 /*-----------------------------------------------------------------*/
6209 /* emitcodePointerGet - gget value from code space */
6210 /*-----------------------------------------------------------------*/
6211 static void emitcodePointerGet (operand *left,
6212 operand *result, iCode *ic)
6215 link *retype = getSpec(operandType(result));
6217 aopOp(left,ic,FALSE);
6219 /* if the operand is already in dptr
6220 then we do nothing else we move the value to dptr */
6221 if (AOP_TYPE(left) != AOP_STR) {
6222 /* if this is remateriazable */
6223 if (AOP_TYPE(left) == AOP_IMMD)
6224 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6225 else { /* we need to get it byte by byte */
6226 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6227 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6228 if (options.model == MODEL_FLAT24)
6230 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6234 /* so dptr know contains the address */
6235 freeAsmop(left,NULL,ic,TRUE);
6236 aopOp(result,ic,FALSE);
6238 /* if bit then unpack */
6239 if (IS_BITVAR(retype))
6240 genUnpackBits(result,"dptr",CPOINTER);
6242 size = AOP_SIZE(result);
6246 emitcode("clr","a");
6247 emitcode("movc","a,@a+dptr");
6248 aopPut(AOP(result),"a",offset++);
6250 emitcode("inc","dptr");
6254 freeAsmop(result,NULL,ic,TRUE);
6257 /*-----------------------------------------------------------------*/
6258 /* genGenPointerGet - gget value from generic pointer space */
6259 /*-----------------------------------------------------------------*/
6260 static void genGenPointerGet (operand *left,
6261 operand *result, iCode *ic)
6264 link *retype = getSpec(operandType(result));
6266 aopOp(left,ic,FALSE);
6268 /* if the operand is already in dptr
6269 then we do nothing else we move the value to dptr */
6270 if (AOP_TYPE(left) != AOP_STR) {
6271 /* if this is remateriazable */
6272 if (AOP_TYPE(left) == AOP_IMMD) {
6273 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6274 emitcode("mov","b,#%d",pointerCode(retype));
6276 else { /* we need to get it byte by byte */
6277 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6278 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6279 if (options.model == MODEL_FLAT24)
6281 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6282 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
6286 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
6290 /* so dptr know contains the address */
6291 freeAsmop(left,NULL,ic,TRUE);
6292 aopOp(result,ic,FALSE);
6294 /* if bit then unpack */
6295 if (IS_BITVAR(retype))
6296 genUnpackBits(result,"dptr",GPOINTER);
6298 size = AOP_SIZE(result);
6302 emitcode("lcall","__gptrget");
6303 aopPut(AOP(result),"a",offset++);
6305 emitcode("inc","dptr");
6309 freeAsmop(result,NULL,ic,TRUE);
6312 /*-----------------------------------------------------------------*/
6313 /* genPointerGet - generate code for pointer get */
6314 /*-----------------------------------------------------------------*/
6315 static void genPointerGet (iCode *ic)
6317 operand *left, *result ;
6322 result = IC_RESULT(ic) ;
6324 /* depending on the type of pointer we need to
6325 move it to the correct pointer register */
6326 type = operandType(left);
6327 etype = getSpec(type);
6328 /* if left is of type of pointer then it is simple */
6329 if (IS_PTR(type) && !IS_FUNC(type->next))
6330 p_type = DCL_TYPE(type);
6332 /* we have to go by the storage class */
6333 p_type = PTR_TYPE(SPEC_OCLS(etype));
6335 /* if (SPEC_OCLS(etype)->codesp ) { */
6336 /* p_type = CPOINTER ; */
6339 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6340 /* p_type = FPOINTER ; */
6342 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6343 /* p_type = PPOINTER; */
6345 /* if (SPEC_OCLS(etype) == idata ) */
6346 /* p_type = IPOINTER; */
6348 /* p_type = POINTER ; */
6351 /* now that we have the pointer type we assign
6352 the pointer values */
6357 genNearPointerGet (left,result,ic);
6361 genPagedPointerGet(left,result,ic);
6365 genFarPointerGet (left,result,ic);
6369 emitcodePointerGet (left,result,ic);
6373 genGenPointerGet (left,result,ic);
6379 /*-----------------------------------------------------------------*/
6380 /* genPackBits - generates code for packed bit storage */
6381 /*-----------------------------------------------------------------*/
6382 static void genPackBits (link *etype ,
6384 char *rname, int p_type)
6392 blen = SPEC_BLEN(etype);
6393 bstr = SPEC_BSTR(etype);
6395 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6398 /* if the bit lenth is less than or */
6399 /* it exactly fits a byte then */
6400 if (SPEC_BLEN(etype) <= 8 ) {
6401 shCount = SPEC_BSTR(etype) ;
6403 /* shift left acc */
6406 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6411 emitcode ("mov","b,a");
6412 emitcode("mov","a,@%s",rname);
6416 emitcode ("mov","b,a");
6417 emitcode("movx","a,@dptr");
6421 emitcode ("push","b");
6422 emitcode ("push","acc");
6423 emitcode ("lcall","__gptrget");
6424 emitcode ("pop","b");
6428 emitcode ("anl","a,#0x%02x",(unsigned char)
6429 ((unsigned char)(0xFF << (blen+bstr)) |
6430 (unsigned char)(0xFF >> (8-bstr)) ) );
6431 emitcode ("orl","a,b");
6432 if (p_type == GPOINTER)
6433 emitcode("pop","b");
6439 emitcode("mov","@%s,a",rname);
6443 emitcode("movx","@dptr,a");
6447 emitcode("lcall","__gptrput");
6452 if ( SPEC_BLEN(etype) <= 8 )
6455 emitcode("inc","%s",rname);
6456 rLen = SPEC_BLEN(etype) ;
6458 /* now generate for lengths greater than one byte */
6461 l = aopGet(AOP(right),offset++,FALSE,TRUE);
6471 emitcode("mov","@%s,a",rname);
6473 emitcode("mov","@%s,%s",rname,l);
6478 emitcode("movx","@dptr,a");
6483 emitcode("lcall","__gptrput");
6486 emitcode ("inc","%s",rname);
6491 /* last last was not complete */
6493 /* save the byte & read byte */
6496 emitcode ("mov","b,a");
6497 emitcode("mov","a,@%s",rname);
6501 emitcode ("mov","b,a");
6502 emitcode("movx","a,@dptr");
6506 emitcode ("push","b");
6507 emitcode ("push","acc");
6508 emitcode ("lcall","__gptrget");
6509 emitcode ("pop","b");
6513 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
6514 emitcode ("orl","a,b");
6517 if (p_type == GPOINTER)
6518 emitcode("pop","b");
6523 emitcode("mov","@%s,a",rname);
6527 emitcode("movx","@dptr,a");
6531 emitcode("lcall","__gptrput");
6535 /*-----------------------------------------------------------------*/
6536 /* genDataPointerSet - remat pointer to data space */
6537 /*-----------------------------------------------------------------*/
6538 static void genDataPointerSet(operand *right,
6542 int size, offset = 0 ;
6543 char *l, buffer[256];
6545 aopOp(right,ic,FALSE);
6547 l = aopGet(AOP(result),0,FALSE,TRUE);
6548 size = AOP_SIZE(right);
6551 sprintf(buffer,"(%s + %d)",l+1,offset);
6553 sprintf(buffer,"%s",l+1);
6554 emitcode("mov","%s,%s",buffer,
6555 aopGet(AOP(right),offset++,FALSE,FALSE));
6558 freeAsmop(right,NULL,ic,TRUE);
6559 freeAsmop(result,NULL,ic,TRUE);
6562 /*-----------------------------------------------------------------*/
6563 /* genNearPointerSet - emitcode for near pointer put */
6564 /*-----------------------------------------------------------------*/
6565 static void genNearPointerSet (operand *right,
6573 link *ptype = operandType(result);
6575 retype= getSpec(operandType(right));
6577 aopOp(result,ic,FALSE);
6579 /* if the result is rematerializable &
6580 in data space & not a bit variable */
6581 if (AOP_TYPE(result) == AOP_IMMD &&
6582 DCL_TYPE(ptype) == POINTER &&
6583 !IS_BITVAR(retype)) {
6584 genDataPointerSet (right,result,ic);
6588 /* if the value is already in a pointer register
6589 then don't need anything more */
6590 if (!AOP_INPREG(AOP(result))) {
6591 /* otherwise get a free pointer register */
6593 preg = getFreePtr(ic,&aop,FALSE);
6594 emitcode("mov","%s,%s",
6596 aopGet(AOP(result),0,FALSE,TRUE));
6597 rname = preg->name ;
6599 rname = aopGet(AOP(result),0,FALSE,FALSE);
6601 freeAsmop(result,NULL,ic,TRUE);
6602 aopOp (right,ic,FALSE);
6604 /* if bitfield then unpack the bits */
6605 if (IS_BITVAR(retype))
6606 genPackBits (retype,right,rname,POINTER);
6608 /* we have can just get the values */
6609 int size = AOP_SIZE(right);
6613 l = aopGet(AOP(right),offset,FALSE,TRUE);
6616 emitcode("mov","@%s,a",rname);
6618 emitcode("mov","@%s,%s",rname,l);
6620 emitcode("inc","%s",rname);
6625 /* now some housekeeping stuff */
6627 /* we had to allocate for this iCode */
6628 freeAsmop(NULL,aop,ic,TRUE);
6630 /* we did not allocate which means left
6631 already in a pointer register, then
6632 if size > 0 && this could be used again
6633 we have to point it back to where it
6635 if (AOP_SIZE(right) > 1 &&
6636 !OP_SYMBOL(result)->remat &&
6637 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6639 int size = AOP_SIZE(right) - 1;
6641 emitcode("dec","%s",rname);
6646 freeAsmop(right,NULL,ic,TRUE);
6651 /*-----------------------------------------------------------------*/
6652 /* genPagedPointerSet - emitcode for Paged pointer put */
6653 /*-----------------------------------------------------------------*/
6654 static void genPagedPointerSet (operand *right,
6663 retype= getSpec(operandType(right));
6665 aopOp(result,ic,FALSE);
6667 /* if the value is already in a pointer register
6668 then don't need anything more */
6669 if (!AOP_INPREG(AOP(result))) {
6670 /* otherwise get a free pointer register */
6672 preg = getFreePtr(ic,&aop,FALSE);
6673 emitcode("mov","%s,%s",
6675 aopGet(AOP(result),0,FALSE,TRUE));
6676 rname = preg->name ;
6678 rname = aopGet(AOP(result),0,FALSE,FALSE);
6680 freeAsmop(result,NULL,ic,TRUE);
6681 aopOp (right,ic,FALSE);
6683 /* if bitfield then unpack the bits */
6684 if (IS_BITVAR(retype))
6685 genPackBits (retype,right,rname,PPOINTER);
6687 /* we have can just get the values */
6688 int size = AOP_SIZE(right);
6692 l = aopGet(AOP(right),offset,FALSE,TRUE);
6695 emitcode("movx","@%s,a",rname);
6698 emitcode("inc","%s",rname);
6704 /* now some housekeeping stuff */
6706 /* we had to allocate for this iCode */
6707 freeAsmop(NULL,aop,ic,TRUE);
6709 /* we did not allocate which means left
6710 already in a pointer register, then
6711 if size > 0 && this could be used again
6712 we have to point it back to where it
6714 if (AOP_SIZE(right) > 1 &&
6715 !OP_SYMBOL(result)->remat &&
6716 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6718 int size = AOP_SIZE(right) - 1;
6720 emitcode("dec","%s",rname);
6725 freeAsmop(right,NULL,ic,TRUE);
6730 /*-----------------------------------------------------------------*/
6731 /* genFarPointerSet - set value from far space */
6732 /*-----------------------------------------------------------------*/
6733 static void genFarPointerSet (operand *right,
6734 operand *result, iCode *ic)
6737 link *retype = getSpec(operandType(right));
6739 aopOp(result,ic,FALSE);
6741 /* if the operand is already in dptr
6742 then we do nothing else we move the value to dptr */
6743 if (AOP_TYPE(result) != AOP_STR) {
6744 /* if this is remateriazable */
6745 if (AOP_TYPE(result) == AOP_IMMD)
6746 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6747 else { /* we need to get it byte by byte */
6748 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6749 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6750 if (options.model == MODEL_FLAT24)
6752 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6756 /* so dptr know contains the address */
6757 freeAsmop(result,NULL,ic,TRUE);
6758 aopOp(right,ic,FALSE);
6760 /* if bit then unpack */
6761 if (IS_BITVAR(retype))
6762 genPackBits(retype,right,"dptr",FPOINTER);
6764 size = AOP_SIZE(right);
6768 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6770 emitcode("movx","@dptr,a");
6772 emitcode("inc","dptr");
6776 freeAsmop(right,NULL,ic,TRUE);
6779 /*-----------------------------------------------------------------*/
6780 /* genGenPointerSet - set value from generic pointer space */
6781 /*-----------------------------------------------------------------*/
6782 static void genGenPointerSet (operand *right,
6783 operand *result, iCode *ic)
6786 link *retype = getSpec(operandType(right));
6788 aopOp(result,ic,FALSE);
6790 /* if the operand is already in dptr
6791 then we do nothing else we move the value to dptr */
6792 if (AOP_TYPE(result) != AOP_STR) {
6793 /* if this is remateriazable */
6794 if (AOP_TYPE(result) == AOP_IMMD) {
6795 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6796 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
6798 else { /* we need to get it byte by byte */
6799 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6800 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6801 if (options.model == MODEL_FLAT24)
6803 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6804 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
6808 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
6812 /* so dptr know contains the address */
6813 freeAsmop(result,NULL,ic,TRUE);
6814 aopOp(right,ic,FALSE);
6816 /* if bit then unpack */
6817 if (IS_BITVAR(retype))
6818 genPackBits(retype,right,"dptr",GPOINTER);
6820 size = AOP_SIZE(right);
6824 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6826 emitcode("lcall","__gptrput");
6828 emitcode("inc","dptr");
6832 freeAsmop(right,NULL,ic,TRUE);
6835 /*-----------------------------------------------------------------*/
6836 /* genPointerSet - stores the value into a pointer location */
6837 /*-----------------------------------------------------------------*/
6838 static void genPointerSet (iCode *ic)
6840 operand *right, *result ;
6844 right = IC_RIGHT(ic);
6845 result = IC_RESULT(ic) ;
6847 /* depending on the type of pointer we need to
6848 move it to the correct pointer register */
6849 type = operandType(result);
6850 etype = getSpec(type);
6851 /* if left is of type of pointer then it is simple */
6852 if (IS_PTR(type) && !IS_FUNC(type->next)) {
6853 p_type = DCL_TYPE(type);
6856 /* we have to go by the storage class */
6857 p_type = PTR_TYPE(SPEC_OCLS(etype));
6859 /* if (SPEC_OCLS(etype)->codesp ) { */
6860 /* p_type = CPOINTER ; */
6863 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6864 /* p_type = FPOINTER ; */
6866 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6867 /* p_type = PPOINTER ; */
6869 /* if (SPEC_OCLS(etype) == idata ) */
6870 /* p_type = IPOINTER ; */
6872 /* p_type = POINTER ; */
6875 /* now that we have the pointer type we assign
6876 the pointer values */
6881 genNearPointerSet (right,result,ic);
6885 genPagedPointerSet (right,result,ic);
6889 genFarPointerSet (right,result,ic);
6893 genGenPointerSet (right,result,ic);
6899 /*-----------------------------------------------------------------*/
6900 /* genIfx - generate code for Ifx statement */
6901 /*-----------------------------------------------------------------*/
6902 static void genIfx (iCode *ic, iCode *popIc)
6904 operand *cond = IC_COND(ic);
6907 aopOp(cond,ic,FALSE);
6909 /* get the value into acc */
6910 if (AOP_TYPE(cond) != AOP_CRY)
6914 /* the result is now in the accumulator */
6915 freeAsmop(cond,NULL,ic,TRUE);
6917 /* if there was something to be popped then do it */
6921 /* if the condition is a bit variable */
6922 if (isbit && IS_ITEMP(cond) &&
6924 genIfxJump(ic,SPIL_LOC(cond)->rname);
6926 if (isbit && !IS_ITEMP(cond))
6927 genIfxJump(ic,OP_SYMBOL(cond)->rname);
6934 /*-----------------------------------------------------------------*/
6935 /* genAddrOf - generates code for address of */
6936 /*-----------------------------------------------------------------*/
6937 static void genAddrOf (iCode *ic)
6939 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
6942 aopOp(IC_RESULT(ic),ic,FALSE);
6944 /* if the operand is on the stack then we
6945 need to get the stack offset of this
6948 /* if it has an offset then we need to compute
6951 emitcode("mov","a,_bp");
6952 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
6953 aopPut(AOP(IC_RESULT(ic)),"a",0);
6955 /* we can just move _bp */
6956 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
6958 /* fill the result with zero */
6959 size = AOP_SIZE(IC_RESULT(ic)) - 1;
6962 if (options.stack10bit && size < (FPTRSIZE - 1))
6965 "*** warning: pointer to stack var truncated.\n");
6972 if (options.stack10bit && offset == 2)
6974 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
6978 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
6985 /* object not on stack then we need the name */
6986 size = AOP_SIZE(IC_RESULT(ic));
6990 char s[SDCC_NAME_MAX];
6992 sprintf(s,"#(%s >> %d)",
6996 sprintf(s,"#%s",sym->rname);
6997 aopPut(AOP(IC_RESULT(ic)),s,offset++);
7001 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7005 /*-----------------------------------------------------------------*/
7006 /* genFarFarAssign - assignment when both are in far space */
7007 /*-----------------------------------------------------------------*/
7008 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7010 int size = AOP_SIZE(right);
7013 /* first push the right side on to the stack */
7015 l = aopGet(AOP(right),offset++,FALSE,FALSE);
7017 emitcode ("push","acc");
7020 freeAsmop(right,NULL,ic,FALSE);
7021 /* now assign DPTR to result */
7022 aopOp(result,ic,FALSE);
7023 size = AOP_SIZE(result);
7025 emitcode ("pop","acc");
7026 aopPut(AOP(result),"a",--offset);
7028 freeAsmop(result,NULL,ic,FALSE);
7032 /*-----------------------------------------------------------------*/
7033 /* genAssign - generate code for assignment */
7034 /*-----------------------------------------------------------------*/
7035 static void genAssign (iCode *ic)
7037 operand *result, *right;
7039 unsigned long lit = 0L;
7041 result = IC_RESULT(ic);
7042 right = IC_RIGHT(ic) ;
7044 /* if they are the same */
7045 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7048 aopOp(right,ic,FALSE);
7050 /* special case both in far space */
7051 if ((AOP_TYPE(right) == AOP_DPTR ||
7052 AOP_TYPE(right) == AOP_DPTR2) &&
7053 IS_TRUE_SYMOP(result) &&
7054 isOperandInFarSpace(result)) {
7056 genFarFarAssign (result,right,ic);
7060 aopOp(result,ic,TRUE);
7062 /* if they are the same registers */
7063 if (sameRegs(AOP(right),AOP(result)))
7066 /* if the result is a bit */
7067 if (AOP_TYPE(result) == AOP_CRY) {
7069 /* if the right size is a literal then
7070 we know what the value is */
7071 if (AOP_TYPE(right) == AOP_LIT) {
7072 if (((int) operandLitValue(right)))
7073 aopPut(AOP(result),one,0);
7075 aopPut(AOP(result),zero,0);
7079 /* the right is also a bit variable */
7080 if (AOP_TYPE(right) == AOP_CRY) {
7081 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7082 aopPut(AOP(result),"c",0);
7088 aopPut(AOP(result),"a",0);
7092 /* bit variables done */
7094 size = AOP_SIZE(result);
7096 if(AOP_TYPE(right) == AOP_LIT)
7097 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7099 (AOP_TYPE(result) != AOP_REG) &&
7100 (AOP_TYPE(right) == AOP_LIT) &&
7101 !IS_FLOAT(operandType(right)) &&
7103 emitcode("clr","a");
7105 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7106 aopPut(AOP(result),"a",size);
7109 aopGet(AOP(right),size,FALSE,FALSE),
7115 aopGet(AOP(right),offset,FALSE,FALSE),
7122 freeAsmop (right,NULL,ic,TRUE);
7123 freeAsmop (result,NULL,ic,TRUE);
7126 /*-----------------------------------------------------------------*/
7127 /* genJumpTab - genrates code for jump table */
7128 /*-----------------------------------------------------------------*/
7129 static void genJumpTab (iCode *ic)
7134 aopOp(IC_JTCOND(ic),ic,FALSE);
7135 /* get the condition into accumulator */
7136 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
7138 /* multiply by three */
7139 emitcode("add","a,acc");
7140 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
7141 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7143 jtab = newiTempLabel(NULL);
7144 emitcode("mov","dptr,#%05d$",jtab->key+100);
7145 emitcode("jmp","@a+dptr");
7146 emitcode("","%05d$:",jtab->key+100);
7147 /* now generate the jump labels */
7148 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
7149 jtab = setNextItem(IC_JTLABELS(ic)))
7150 emitcode("ljmp","%05d$",jtab->key+100);
7154 /*-----------------------------------------------------------------*/
7155 /* genCast - gen code for casting */
7156 /*-----------------------------------------------------------------*/
7157 static void genCast (iCode *ic)
7159 operand *result = IC_RESULT(ic);
7160 link *ctype = operandType(IC_LEFT(ic));
7161 link *rtype = operandType(IC_RIGHT(ic));
7162 operand *right = IC_RIGHT(ic);
7165 /* if they are equivalent then do nothing */
7166 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
7169 aopOp(right,ic,FALSE) ;
7170 aopOp(result,ic,FALSE);
7172 /* if the result is a bit */
7173 if (AOP_TYPE(result) == AOP_CRY) {
7174 /* if the right size is a literal then
7175 we know what the value is */
7176 if (AOP_TYPE(right) == AOP_LIT) {
7177 if (((int) operandLitValue(right)))
7178 aopPut(AOP(result),one,0);
7180 aopPut(AOP(result),zero,0);
7185 /* the right is also a bit variable */
7186 if (AOP_TYPE(right) == AOP_CRY) {
7187 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7188 aopPut(AOP(result),"c",0);
7194 aopPut(AOP(result),"a",0);
7198 /* if they are the same size : or less */
7199 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
7201 /* if they are in the same place */
7202 if (sameRegs(AOP(right),AOP(result)))
7205 /* if they in different places then copy */
7206 size = AOP_SIZE(result);
7210 aopGet(AOP(right),offset,FALSE,FALSE),
7218 /* if the result is of type pointer */
7219 if (IS_PTR(ctype)) {
7222 link *type = operandType(right);
7223 link *etype = getSpec(type);
7225 /* pointer to generic pointer */
7226 if (IS_GENPTR(ctype)) {
7230 p_type = DCL_TYPE(type);
7232 /* we have to go by the storage class */
7233 p_type = PTR_TYPE(SPEC_OCLS(etype));
7236 /* the first two bytes are known */
7237 size = GPTRSIZE - 1;
7241 aopGet(AOP(right),offset,FALSE,FALSE),
7245 /* the last byte depending on type */
7262 /* this should never happen */
7263 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7264 "got unknown pointer type");
7267 aopPut(AOP(result),l, GPTRSIZE - 1);
7271 /* just copy the pointers */
7272 size = AOP_SIZE(result);
7276 aopGet(AOP(right),offset,FALSE,FALSE),
7283 /* so we now know that the size of destination is greater
7284 than the size of the source */
7285 /* we move to result for the size of source */
7286 size = AOP_SIZE(right);
7290 aopGet(AOP(right),offset,FALSE,FALSE),
7295 /* now depending on the sign of the source && destination */
7296 size = AOP_SIZE(result) - AOP_SIZE(right);
7297 /* if unsigned or not an integral type */
7298 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
7300 aopPut(AOP(result),zero,offset++);
7302 /* we need to extend the sign :{ */
7303 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
7306 emitcode("rlc","a");
7307 emitcode("subb","a,acc");
7309 aopPut(AOP(result),"a",offset++);
7312 /* we are done hurray !!!! */
7315 freeAsmop(right,NULL,ic,TRUE);
7316 freeAsmop(result,NULL,ic,TRUE);
7320 /*-----------------------------------------------------------------*/
7321 /* genDjnz - generate decrement & jump if not zero instrucion */
7322 /*-----------------------------------------------------------------*/
7323 static int genDjnz (iCode *ic, iCode *ifx)
7329 /* if the if condition has a false label
7330 then we cannot save */
7334 /* if the minus is not of the form
7336 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
7337 !IS_OP_LITERAL(IC_RIGHT(ic)))
7340 if (operandLitValue(IC_RIGHT(ic)) != 1)
7343 /* if the size of this greater than one then no
7345 if (getSize(operandType(IC_RESULT(ic))) > 1)
7348 /* otherwise we can save BIG */
7349 lbl = newiTempLabel(NULL);
7350 lbl1= newiTempLabel(NULL);
7352 aopOp(IC_RESULT(ic),ic,FALSE);
7354 if (IS_AOP_PREG(IC_RESULT(ic))) {
7355 emitcode("dec","%s",
7356 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7357 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7358 emitcode("jnz","%05d$",lbl->key+100);
7360 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
7363 emitcode ("sjmp","%05d$",lbl1->key+100);
7364 emitcode ("","%05d$:",lbl->key+100);
7365 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
7366 emitcode ("","%05d$:",lbl1->key+100);
7368 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7373 /*-----------------------------------------------------------------*/
7374 /* genReceive - generate code for a receive iCode */
7375 /*-----------------------------------------------------------------*/
7376 static void genReceive (iCode *ic)
7378 if (isOperandInFarSpace(IC_RESULT(ic)) &&
7379 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
7380 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
7382 int size = getSize(operandType(IC_RESULT(ic)));
7383 int offset = fReturnSize - size;
7385 emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
7386 fReturn[fReturnSize - offset - 1] : "acc"));
7389 aopOp(IC_RESULT(ic),ic,FALSE);
7390 size = AOP_SIZE(IC_RESULT(ic));
7393 emitcode ("pop","acc");
7394 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
7399 aopOp(IC_RESULT(ic),ic,FALSE);
7401 assignResultValue(IC_RESULT(ic));
7404 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7407 /*-----------------------------------------------------------------*/
7408 /* gen51Code - generate code for 8051 based controllers */
7409 /*-----------------------------------------------------------------*/
7410 void gen51Code (iCode *lic)
7415 lineHead = lineCurr = NULL;
7417 /* print the allocation information */
7419 printAllocInfo( currFunc, codeOutFile);
7420 /* if debug information required */
7421 /* if (options.debug && currFunc) { */
7423 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
7425 if (IS_STATIC(currFunc->etype))
7426 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
7428 emitcode("","G$%s$0$0 ==.",currFunc->name);
7431 /* stack pointer name */
7432 if (options.useXstack)
7438 for (ic = lic ; ic ; ic = ic->next ) {
7440 if ( cln != ic->lineno ) {
7441 if ( options.debug ) {
7443 emitcode("","C$%s$%d$%d$%d ==.",
7444 ic->filename,ic->lineno,
7445 ic->level,ic->block);
7448 emitcode(";","%s %d",ic->filename,ic->lineno);
7451 /* if the result is marked as
7452 spilt and rematerializable or code for
7453 this has already been generated then
7455 if (resultRemat(ic) || ic->generated )
7458 /* depending on the operation */
7477 /* IPOP happens only when trying to restore a
7478 spilt live range, if there is an ifx statement
7479 following this pop then the if statement might
7480 be using some of the registers being popped which
7481 would destory the contents of the register so
7482 we need to check for this condition and handle it */
7484 ic->next->op == IFX &&
7485 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
7486 genIfx (ic->next,ic);
7504 genEndFunction (ic);
7524 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
7541 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
7545 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
7552 /* note these two are xlated by algebraic equivalence
7553 during parsing SDCC.y */
7554 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7555 "got '>=' or '<=' shouldn't have come here");
7559 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
7571 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
7575 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
7579 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
7606 case GET_VALUE_AT_ADDRESS:
7611 if (POINTER_SET(ic))
7638 addSet(&_G.sendSet,ic);
7643 /* piCode(ic,stdout); */
7649 /* now we are ready to call the
7650 peep hole optimizer */
7651 if (!options.nopeep)
7652 peepHole (&lineHead);
7654 /* now do the actual printing */
7655 printLine (lineHead,codeOutFile);