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!
26 -------------------------------------------------------------------------*/
32 #include "SDCCglobl.h"
34 #ifdef HAVE_SYS_ISA_DEFS_H
35 #include <sys/isa_defs.h>
40 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
41 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
48 #include "SDCChasht.h"
51 #include "SDCCicode.h"
52 #include "SDCClabel.h"
53 #include "SDCCBBlock.h"
56 #include "SDCCcflow.h"
57 #include "SDCCdflow.h"
58 #include "SDCClrange.h"
59 #include "SDCCralloc.h"
60 #include "SDCCgen51.h"
61 #include "SDCCpeeph.h"
63 /* this is the down and dirty file with all kinds of
64 kludgy & hacky stuff. This is what it is all about
65 CODE GENERATION for a specific MCU . some of the
66 routines may be reusable, will have to see */
68 static char *zero = "#0x00";
69 static char *one = "#0x01";
71 static char *fReturn[] = {"dpl","dph","b","a" };
72 static char *accUse[] = {"a","b"};
80 extern int ptrRegReq ;
82 extern FILE *codeOutFile;
84 static void saverbank (int, iCode *,bool);
85 #define RESULTONSTACK(x) \
86 (IC_RESULT(x) && IC_RESULT(x)->aop && \
87 IC_RESULT(x)->aop->type == AOP_STK )
89 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x);
90 #define CLRC emitcode("clr","c");
92 lineNode *lineHead = NULL;
93 lineNode *lineCurr = NULL;
95 unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
96 0xE0, 0xC0, 0x80, 0x00};
97 unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
98 0x07, 0x03, 0x01, 0x00};
105 /*-----------------------------------------------------------------*/
106 /* emitcode - writes the code into a file : for now it is simple */
107 /*-----------------------------------------------------------------*/
108 void emitcode (char *inst,char *fmt, ...)
111 char lb[MAX_INLINEASM];
118 sprintf(lb,"%s\t",inst);
120 sprintf(lb,"%s",inst);
121 vsprintf(lb+(strlen(lb)),fmt,ap);
125 while (isspace(*lbp)) lbp++;
128 lineCurr = (lineCurr ?
129 connectLine(lineCurr,newLineNode(lb)) :
130 (lineHead = newLineNode(lb)));
131 lineCurr->isInline = inLine;
132 lineCurr->isDebug = debugLine;
136 /*-----------------------------------------------------------------*/
137 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
138 /*-----------------------------------------------------------------*/
139 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
141 bool r0iu = FALSE , r1iu = FALSE;
142 bool r0ou = FALSE , r1ou = FALSE;
144 /* the logic: if r0 & r1 used in the instruction
145 then we are in trouble otherwise */
147 /* first check if r0 & r1 are used by this
148 instruction, in which case we are in trouble */
149 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
150 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
154 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
155 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
157 /* if no usage of r0 then return it */
158 if (!r0iu && !r0ou) {
159 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
160 (*aopp)->type = AOP_R0;
161 return (*aopp)->aopu.aop_ptr = regWithIdx(R0_IDX);
164 /* if no usage of r1 then return it */
165 if (!r1iu && !r1ou) {
166 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
167 (*aopp)->type = AOP_R1;
168 return (*aopp)->aopu.aop_ptr = regWithIdx(R1_IDX);
171 /* now we know they both have usage */
172 /* if r0 not used in this instruction */
174 /* push it if not already pushed */
176 emitcode ("push","%s",
177 regWithIdx(R0_IDX)->dname);
181 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
182 (*aopp)->type = AOP_R0;
184 return (*aopp)->aopu.aop_ptr = regWithIdx(R0_IDX);
187 /* if r1 not used then */
190 /* push it if not already pushed */
192 emitcode ("push","%s",
193 regWithIdx(R1_IDX)->dname);
197 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
198 (*aopp)->type = AOP_R1;
199 return regWithIdx(R1_IDX);
204 /* I said end of world but not quite end of world yet */
205 /* if this is a result then we canpush it on the stack*/
207 (*aopp)->type = AOP_STK;
212 /* other wise this is true end of the world */
213 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
214 "getFreePtr should never reach here");
218 /*-----------------------------------------------------------------*/
219 /* newAsmop - creates a new asmOp */
220 /*-----------------------------------------------------------------*/
221 static asmop *newAsmop (short type)
225 ALLOC(aop,sizeof(asmop));
230 /*-----------------------------------------------------------------*/
231 /* pointerCode - returns the code for a pointer type */
232 /*-----------------------------------------------------------------*/
233 static int pointerCode (link *etype)
236 if (SPEC_OCLS(etype)->codesp ) {
240 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
243 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
246 if (SPEC_OCLS(etype) == idata )
253 /*-----------------------------------------------------------------*/
254 /* aopForSym - for a true symbol */
255 /*-----------------------------------------------------------------*/
256 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
259 memmap *space= SPEC_OCLS(sym->etype);
261 /* if already has one */
265 /* assign depending on the storage class */
266 /* if it is on the stack or indirectly addressable */
267 /* space we need to assign either r0 or r1 to it */
268 if (sym->onStack || sym->iaccess) {
269 sym->aop = aop = newAsmop(0);
270 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
271 aop->size = getSize(sym->type);
273 /* now assign the address of the variable to
274 the pointer register */
275 if (aop->type != AOP_STK) {
280 emitcode("push","acc");
282 emitcode("mov","a,_bp");
283 emitcode("add","a,#0x%02x",
285 ((char)(sym->stack - nregssaved )) :
286 ((char)sym->stack)) & 0xff);
287 emitcode("mov","%s,a",
288 aop->aopu.aop_ptr->name);
291 emitcode("pop","acc");
294 emitcode("mov","%s,#%s",
295 aop->aopu.aop_ptr->name,
297 aop->paged = space->paged;
299 aop->aopu.aop_stk = sym->stack;
303 /* if in bit space */
304 if (IN_BITSPACE(space)) {
305 sym->aop = aop = newAsmop (AOP_CRY);
306 aop->aopu.aop_dir = sym->rname ;
307 aop->size = getSize(sym->type);
310 /* if it is in direct space */
311 if (IN_DIRSPACE(space)) {
312 sym->aop = aop = newAsmop (AOP_DIR);
313 aop->aopu.aop_dir = sym->rname ;
314 aop->size = getSize(sym->type);
318 /* special case for a function */
319 if (IS_FUNC(sym->type)) {
320 sym->aop = aop = newAsmop(AOP_IMMD);
321 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
322 strcpy(aop->aopu.aop_immd,sym->rname);
327 /* only remaining is far space */
328 /* in which case DPTR gets the address */
329 sym->aop = aop = newAsmop(AOP_DPTR);
330 emitcode ("mov","dptr,#%s", sym->rname);
331 aop->size = getSize(sym->type);
333 /* if it is in code space */
334 if (IN_CODESPACE(space))
340 /*-----------------------------------------------------------------*/
341 /* aopForRemat - rematerialzes an object */
342 /*-----------------------------------------------------------------*/
343 static asmop *aopForRemat (symbol *sym)
346 iCode *ic = sym->rematiCode;
347 asmop *aop = newAsmop(AOP_IMMD);
351 /* if plus or minus print the right hand side */
352 if (ic->op == '+' || ic->op == '-') {
353 sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
356 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
360 /* we reached the end */
361 sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
365 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
366 strcpy(aop->aopu.aop_immd,buffer);
370 /*-----------------------------------------------------------------*/
371 /* regsInCommon - two operands have some registers in common */
372 /*-----------------------------------------------------------------*/
373 bool regsInCommon (operand *op1, operand *op2)
378 /* if they have registers in common */
379 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
382 sym1 = OP_SYMBOL(op1);
383 sym2 = OP_SYMBOL(op2);
385 if (sym1->nRegs == 0 || sym2->nRegs == 0)
388 for (i = 0 ; i < sym1->nRegs ; i++) {
393 for (j = 0 ; j < sym2->nRegs ;j++ ) {
397 if (sym2->regs[j] == sym1->regs[i])
405 /*-----------------------------------------------------------------*/
406 /* operandsEqu - equivalent */
407 /*-----------------------------------------------------------------*/
408 bool operandsEqu ( operand *op1, operand *op2)
412 /* if they not symbols */
413 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
416 sym1 = OP_SYMBOL(op1);
417 sym2 = OP_SYMBOL(op2);
419 /* if both are itemps & one is spilt
420 and the other is not then false */
421 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
422 sym1->isspilt != sym2->isspilt )
425 /* if they are the same */
429 if (strcmp(sym1->rname,sym2->rname) == 0)
433 /* if left is a tmp & right is not */
437 (sym1->usl.spillLoc == sym2))
444 (sym2->usl.spillLoc == sym1))
450 /*-----------------------------------------------------------------*/
451 /* sameRegs - two asmops have the same registers */
452 /*-----------------------------------------------------------------*/
453 bool sameRegs (asmop *aop1, asmop *aop2 )
460 if (aop1->type != AOP_REG ||
461 aop2->type != AOP_REG )
464 if (aop1->size != aop2->size )
467 for (i = 0 ; i < aop1->size ; i++ )
468 if (aop1->aopu.aop_reg[i] !=
469 aop2->aopu.aop_reg[i] )
475 /*-----------------------------------------------------------------*/
476 /* aopOp - allocates an asmop for an operand : */
477 /*-----------------------------------------------------------------*/
478 static void aopOp (operand *op, iCode *ic, bool result)
487 /* if this a literal */
488 if (IS_OP_LITERAL(op)) {
489 op->aop = aop = newAsmop(AOP_LIT);
490 aop->aopu.aop_lit = op->operand.valOperand;
491 aop->size = getSize(operandType(op));
495 /* if already has a asmop then continue */
499 /* if the underlying symbol has a aop */
500 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
501 op->aop = OP_SYMBOL(op)->aop;
505 /* if this is a true symbol */
506 if (IS_TRUE_SYMOP(op)) {
507 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
511 /* this is a temporary : this has
517 e) can be a return use only */
522 /* if the type is a conditional */
523 if (sym->regType == REG_CND) {
524 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
529 /* if it is spilt then two situations
531 b) has a spill location */
532 if (sym->isspilt || sym->nRegs == 0) {
534 /* rematerialize it NOW */
536 sym->aop = op->aop = aop =
538 aop->size = getSize(sym->type);
544 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
545 aop->size = getSize(sym->type);
546 for ( i = 0 ; i < 2 ; i++ )
547 aop->aopu.aop_str[i] = accUse[i];
553 aop = op->aop = sym->aop = newAsmop(AOP_STR);
554 aop->size = getSize(sym->type);
555 for ( i = 0 ; i < 4 ; i++ )
556 aop->aopu.aop_str[i] = fReturn[i];
560 /* else spill location */
561 sym->aop = op->aop = aop =
562 aopForSym(ic,sym->usl.spillLoc,result);
563 aop->size = getSize(sym->type);
567 /* must be in a register */
568 sym->aop = op->aop = aop = newAsmop(AOP_REG);
569 aop->size = sym->nRegs;
570 for ( i = 0 ; i < sym->nRegs ;i++)
571 aop->aopu.aop_reg[i] = sym->regs[i];
574 /*-----------------------------------------------------------------*/
575 /* freeAsmop - free up the asmop given to an operand */
576 /*----------------------------------------------------------------*/
577 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
594 /* depending on the asmop type only three cases need work AOP_RO
595 , AOP_R1 && AOP_STK */
600 emitcode ("pop","ar0");
604 bitVectUnSetBit(ic->rUsed,R0_IDX);
610 emitcode ("pop","ar1");
614 bitVectUnSetBit(ic->rUsed,R1_IDX);
620 int stk = aop->aopu.aop_stk + aop->size;
621 bitVectUnSetBit(ic->rUsed,R0_IDX);
622 bitVectUnSetBit(ic->rUsed,R1_IDX);
624 getFreePtr(ic,&aop,FALSE);
626 emitcode ("mov","a,_bp");
627 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
628 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
630 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
633 emitcode("pop","acc");
634 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
636 emitcode("dec","%s",aop->aopu.aop_ptr->name);
639 freeAsmop(op,NULL,ic,TRUE);
641 emitcode("pop","ar0");
646 emitcode("pop","ar1");
653 /* all other cases just dealloc */
657 OP_SYMBOL(op)->aop = NULL;
658 /* if the symbol has a spill */
660 SPIL_LOC(op)->aop = NULL;
665 /*-----------------------------------------------------------------*/
666 /* aopLiteral - string from a literal value */
667 /*-----------------------------------------------------------------*/
668 char *aopLiteral (value *val, int offset)
676 /* if it is a float then it gets tricky */
677 /* otherwise it is fairly simple */
678 if (!IS_FLOAT(val->type)) {
679 unsigned long v = floatFromVal(val);
682 sprintf(buffer,"#0x%02x",((char) v) & 0xff);
683 ALLOC_ATOMIC(rs,strlen(buffer)+1);
684 return strcpy (rs,buffer);
687 /* it is type float */
688 fl.f = (float) floatFromVal(val);
690 sprintf(buffer,"#0x%02x",fl.c[3-offset]);
692 sprintf(buffer,"#0x%02x",fl.c[offset]);
694 ALLOC_ATOMIC(rs,strlen(buffer)+1);
695 return strcpy (rs,buffer);
698 /*-----------------------------------------------------------------*/
699 /* aopGet - for fetching value of the aop */
700 /*-----------------------------------------------------------------*/
701 static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
706 /* offset is greater than
708 if (offset > (aop->size - 1) &&
709 aop->type != AOP_LIT)
712 /* depending on type */
717 /* if we need to increment it */
718 while (offset > aop->coff) {
719 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
723 while (offset < aop->coff) {
724 emitcode("dec","%s",aop->aopu.aop_ptr->name);
730 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
731 return (dname ? "acc" : "a");
733 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
734 ALLOC_ATOMIC(rs,strlen(s)+1);
739 while (offset > aop->coff) {
740 emitcode ("inc","dptr");
744 while (offset < aop->coff) {
745 emitcode("lcall","__decdptr");
752 emitcode("movc","a,@a+dptr");
755 emitcode("movx","a,@dptr");
756 return (dname ? "acc" : "a");
761 sprintf (s,"#(%s)",aop->aopu.aop_immd);
764 sprintf(s,"#(%s >> %d)",
770 ALLOC_ATOMIC(rs,strlen(s)+1);
776 sprintf(s,"(%s + %d)",
780 sprintf(s,"%s",aop->aopu.aop_dir);
781 ALLOC_ATOMIC(rs,strlen(s)+1);
787 return aop->aopu.aop_reg[offset]->dname;
789 return aop->aopu.aop_reg[offset]->name;
793 emitcode("mov","c,%s",aop->aopu.aop_dir);
794 emitcode("rlc","a") ;
795 return (dname ? "acc" : "a");
798 if (!offset && dname)
800 return aop->aopu.aop_str[offset];
803 return aopLiteral (aop->aopu.aop_lit,offset);
807 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
811 return aop->aopu.aop_str[offset];
815 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
816 "aopget got unsupported aop->type");
819 /*-----------------------------------------------------------------*/
820 /* aopPut - puts a string for a aop */
821 /*-----------------------------------------------------------------*/
822 static void aopPut (asmop *aop, char *s, int offset)
827 if (aop->size && offset > ( aop->size - 1)) {
828 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
829 "aopPut got offset > aop->size");
833 /* will assign value to value */
834 /* depending on where it is ofcourse */
838 sprintf(d,"(%s + %d)",
839 aop->aopu.aop_dir,offset);
841 sprintf(d,"%s",aop->aopu.aop_dir);
844 emitcode("mov","%s,%s",d,s);
849 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
850 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
852 strcmp(s,"r0") == 0 ||
853 strcmp(s,"r1") == 0 ||
854 strcmp(s,"r2") == 0 ||
855 strcmp(s,"r3") == 0 ||
856 strcmp(s,"r4") == 0 ||
857 strcmp(s,"r5") == 0 ||
858 strcmp(s,"r6") == 0 ||
859 strcmp(s,"r7") == 0 )
860 emitcode("mov","%s,%s",
861 aop->aopu.aop_reg[offset]->dname,s);
863 emitcode("mov","%s,%s",
864 aop->aopu.aop_reg[offset]->name,s);
870 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
871 "aopPut writting to code space");
875 while (offset > aop->coff) {
877 emitcode ("inc","dptr");
880 while (offset < aop->coff) {
882 emitcode("lcall","__decdptr");
887 /* if not in accumulater */
890 emitcode ("movx","@dptr,a");
895 while (offset > aop->coff) {
897 emitcode("inc","%s",aop->aopu.aop_ptr->name);
899 while (offset < aop->coff) {
901 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
907 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
912 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
914 if (strcmp(s,"r0") == 0 ||
915 strcmp(s,"r1") == 0 ||
916 strcmp(s,"r2") == 0 ||
917 strcmp(s,"r3") == 0 ||
918 strcmp(s,"r4") == 0 ||
919 strcmp(s,"r5") == 0 ||
920 strcmp(s,"r6") == 0 ||
921 strcmp(s,"r7") == 0 ) {
923 sprintf(buffer,"a%s",s);
924 emitcode("mov","@%s,%s",
925 aop->aopu.aop_ptr->name,buffer);
927 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
932 if (strcmp(s,"a") == 0)
933 emitcode("push","acc");
935 emitcode("push","%s",s);
940 /* if bit variable */
941 if (!aop->aopu.aop_dir) {
946 emitcode("clr","%s",aop->aopu.aop_dir);
949 emitcode("setb","%s",aop->aopu.aop_dir);
952 emitcode("mov","%s,c",aop->aopu.aop_dir);
954 lbl = newiTempLabel(NULL);
959 emitcode("cjne","a,#0x01,%05d$",lbl->key+100);
960 emitcode("","%05d$:",lbl->key+100);
962 emitcode("mov","%s,c",aop->aopu.aop_dir);
969 if (strcmp(aop->aopu.aop_str[offset],s))
970 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
975 if (!offset && (strcmp(s,"acc") == 0))
978 if (strcmp(aop->aopu.aop_str[offset],s))
979 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
983 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
984 "aopPut got unsupported aop->type");
992 /*-----------------------------------------------------------------*/
993 /* pointToEnd :- points to the last byte of the operand */
994 /*-----------------------------------------------------------------*/
995 static void pointToEnd (asmop *aop)
1001 aop->coff = count = (aop->size - 1);
1002 switch (aop->type) {
1006 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1010 emitcode("inc","dptr");
1017 /*-----------------------------------------------------------------*/
1018 /* reAdjustPreg - points a register back to where it should */
1019 /*-----------------------------------------------------------------*/
1020 static void reAdjustPreg (asmop *aop)
1025 if ((size = aop->size) <= 1)
1028 switch (aop->type) {
1032 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1036 emitcode("lcall","__decdptr");
1043 #define AOP(op) op->aop
1044 #define AOP_TYPE(op) AOP(op)->type
1045 #define AOP_SIZE(op) AOP(op)->size
1046 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1047 AOP_TYPE(x) == AOP_R0))
1049 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1050 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1052 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1053 (x->aopu.aop_reg[0] == regWithIdx(R0_IDX) || \
1054 x->aopu.aop_reg[0] == regWithIdx(R1_IDX) )))
1056 /*-----------------------------------------------------------------*/
1057 /* genNotFloat - generates not for float operations */
1058 /*-----------------------------------------------------------------*/
1059 static void genNotFloat (operand *op, operand *res)
1065 /* we will put 127 in the first byte of
1067 aopPut(AOP(res),"#127",0);
1068 size = AOP_SIZE(op) - 1;
1071 l = aopGet(op->aop,offset++,FALSE,FALSE);
1075 emitcode("orl","a,%s",
1077 offset++,FALSE,FALSE));
1079 tlbl = newiTempLabel(NULL);
1081 tlbl = newiTempLabel(NULL);
1082 aopPut(res->aop,one,1);
1083 emitcode("jz","%05d$",(tlbl->key+100));
1084 aopPut(res->aop,zero,1);
1085 emitcode("","%05d$:",(tlbl->key+100));
1087 size = res->aop->size - 2;
1089 /* put zeros in the rest */
1091 aopPut(res->aop,zero,offset++);
1094 /*-----------------------------------------------------------------*/
1095 /* getDataSize - get the operand data size */
1096 /*-----------------------------------------------------------------*/
1097 int getDataSize(operand *op)
1100 size = AOP_SIZE(op);
1107 /*-----------------------------------------------------------------*/
1108 /* outAcc - output Acc */
1109 /*-----------------------------------------------------------------*/
1110 void outAcc(operand *result)
1113 size = getDataSize(result);
1115 aopPut(AOP(result),"a",0);
1118 /* unsigned or positive */
1120 aopPut(AOP(result),zero,offset++);
1125 /*-----------------------------------------------------------------*/
1126 /* outBitC - output a bit C */
1127 /*-----------------------------------------------------------------*/
1128 void outBitC(operand *result)
1130 /* if the result is bit */
1131 if (AOP_TYPE(result) == AOP_CRY)
1132 aopPut(AOP(result),"c",0);
1134 emitcode("clr","a");
1135 emitcode("rlc","a");
1140 /*-----------------------------------------------------------------*/
1141 /* toBoolean - emit code for orl a,operator(sizeop) */
1142 /*-----------------------------------------------------------------*/
1143 void toBoolean(operand *oper)
1145 int size = AOP_SIZE(oper) - 1;
1147 MOVA(aopGet(AOP(oper),0,FALSE,FALSE));
1149 emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE));
1153 /*-----------------------------------------------------------------*/
1154 /* genNot - generate code for ! operation */
1155 /*-----------------------------------------------------------------*/
1156 static void genNot (iCode *ic)
1159 link *optype = operandType(IC_LEFT(ic));
1161 /* assign asmOps to operand & result */
1162 aopOp (IC_LEFT(ic),ic,FALSE);
1163 aopOp (IC_RESULT(ic),ic,TRUE);
1165 /* if in bit space then a special case */
1166 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1167 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1168 emitcode("cpl","c");
1169 outBitC(IC_RESULT(ic));
1173 /* if type float then do float */
1174 if (IS_FLOAT(optype)) {
1175 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1179 toBoolean(IC_LEFT(ic));
1181 tlbl = newiTempLabel(NULL);
1182 emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1183 emitcode("","%05d$:",tlbl->key+100);
1184 outBitC(IC_RESULT(ic));
1187 /* release the aops */
1188 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1189 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1193 /*-----------------------------------------------------------------*/
1194 /* genCpl - generate code for complement */
1195 /*-----------------------------------------------------------------*/
1196 static void genCpl (iCode *ic)
1202 /* assign asmOps to operand & result */
1203 aopOp (IC_LEFT(ic),ic,FALSE);
1204 aopOp (IC_RESULT(ic),ic,TRUE);
1206 /* if both are in bit space then
1208 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1209 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1211 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1212 emitcode("cpl","c");
1213 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1217 size = AOP_SIZE(IC_RESULT(ic));
1219 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1221 emitcode("cpl","a");
1222 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1227 /* release the aops */
1228 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1229 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1232 /*-----------------------------------------------------------------*/
1233 /* genUminusFloat - unary minus for floating points */
1234 /*-----------------------------------------------------------------*/
1235 static void genUminusFloat(operand *op,operand *result)
1237 int size ,offset =0 ;
1239 /* for this we just need to flip the
1240 first it then copy the rest in place */
1241 size = AOP_SIZE(op) - 1;
1242 l = aopGet(AOP(op),3,FALSE,FALSE);
1246 emitcode("cpl","acc.7");
1247 aopPut(AOP(result),"a",3);
1251 aopGet(AOP(op),offset,FALSE,FALSE),
1257 /*-----------------------------------------------------------------*/
1258 /* genUminus - unary minus code generation */
1259 /*-----------------------------------------------------------------*/
1260 static void genUminus (iCode *ic)
1263 link *optype, *rtype;
1267 aopOp(IC_LEFT(ic),ic,FALSE);
1268 aopOp(IC_RESULT(ic),ic,TRUE);
1270 /* if both in bit space then special
1272 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1273 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1275 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1276 emitcode("cpl","c");
1277 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1281 optype = operandType(IC_LEFT(ic));
1282 rtype = operandType(IC_RESULT(ic));
1284 /* if float then do float stuff */
1285 if (IS_FLOAT(optype)) {
1286 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1290 /* otherwise subtract from zero */
1291 size = AOP_SIZE(IC_LEFT(ic));
1295 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1296 if (!strcmp(l,"a")) {
1297 emitcode("cpl","a");
1298 emitcode("inc","a");
1300 emitcode("clr","a");
1301 emitcode("subb","a,%s",l);
1303 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1306 /* if any remaining bytes in the result */
1307 /* we just need to propagate the sign */
1308 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1309 emitcode("rlc","a");
1310 emitcode("subb","a,acc");
1312 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1316 /* release the aops */
1317 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1318 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1321 /*-----------------------------------------------------------------*/
1322 /* saveRegisters - will look for a call and save the registers */
1323 /*-----------------------------------------------------------------*/
1324 static void saveRegisters(iCode *lic)
1332 for (ic = lic ; ic ; ic = ic->next)
1333 if (ic->op == CALL || ic->op == PCALL)
1337 fprintf(stderr,"found parameter push with no function call\n");
1341 /* if the registers have been saved already then
1343 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1346 /* find the registers in use at this time
1347 and push them away to safety */
1348 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1352 if (options.useXstack) {
1353 if (bitVectBitValue(rsave,R0_IDX))
1354 emitcode("mov","b,r0");
1355 emitcode("mov","r0,%s",spname);
1356 for (i = 0 ; i < nRegs ; i++) {
1357 if (bitVectBitValue(rsave,i)) {
1359 emitcode("mov","a,b");
1361 emitcode("mov","a,%s",regWithIdx(i)->name);
1362 emitcode("movx","@r0,a");
1363 emitcode("inc","r0");
1366 emitcode("mov","%s,r0",spname);
1367 if (bitVectBitValue(rsave,R0_IDX))
1368 emitcode("mov","r0,b");
1370 for (i = 0 ; i < nRegs ; i++) {
1371 if (bitVectBitValue(rsave,i))
1372 emitcode("push","%s",regWithIdx(i)->dname);
1375 detype = getSpec(operandType(IC_LEFT(ic)));
1377 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1378 IS_ISR(currFunc->etype) &&
1381 saverbank(SPEC_BANK(detype),ic,TRUE);
1384 /*-----------------------------------------------------------------*/
1385 /* unsaveRegisters - pop the pushed registers */
1386 /*-----------------------------------------------------------------*/
1387 static void unsaveRegisters (iCode *ic)
1391 /* find the registers in use at this time
1392 and push them away to safety */
1393 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1396 if (options.useXstack) {
1397 emitcode("mov","r0,%s",spname);
1398 for (i = nRegs ; i >= 0 ; i--) {
1399 if (bitVectBitValue(rsave,i)) {
1400 emitcode("dec","r0");
1401 emitcode("movx","a,@r0");
1403 emitcode("mov","b,a");
1405 emitcode("mov","%s,a",regWithIdx(i)->name);
1409 emitcode("mov","%s,r0",spname);
1410 if (bitVectBitValue(rsave,R0_IDX))
1411 emitcode("mov","r0,b");
1413 for (i = nRegs ; i >= 0 ; i--) {
1414 if (bitVectBitValue(rsave,i))
1415 emitcode("pop","%s",regWithIdx(i)->dname);
1421 /*-----------------------------------------------------------------*/
1423 /*-----------------------------------------------------------------*/
1424 void pushSide(operand * oper, int size)
1428 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1429 if (AOP_TYPE(oper) != AOP_REG &&
1430 AOP_TYPE(oper) != AOP_DIR &&
1432 emitcode("mov","a,%s",l);
1433 emitcode("push","acc");
1435 emitcode("push","%s",l);
1439 /*-----------------------------------------------------------------*/
1440 /* assignResultValue - */
1441 /*-----------------------------------------------------------------*/
1442 void assignResultValue(operand * oper)
1445 int size = AOP_SIZE(oper);
1447 aopPut(AOP(oper),fReturn[offset],offset);
1453 /*-----------------------------------------------------------------*/
1454 /* genXpush - pushes onto the external stack */
1455 /*-----------------------------------------------------------------*/
1456 static void genXpush (iCode *ic)
1458 asmop *aop = newAsmop(0);
1460 int size,offset = 0;
1462 aopOp(IC_LEFT(ic),ic,FALSE);
1463 r = getFreePtr(ic,&aop,FALSE);
1466 emitcode("mov","%s,_spx",r->name);
1468 size = AOP_SIZE(IC_LEFT(ic));
1471 char *l = aopGet(AOP(IC_LEFT(ic)),
1472 offset++,FALSE,FALSE);
1474 emitcode("movx","@%s,a",r->name);
1475 emitcode("inc","%s",r->name);
1480 emitcode("mov","_spx,%s",r->name);
1482 freeAsmop(NULL,aop,ic,TRUE);
1483 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1486 /*-----------------------------------------------------------------*/
1487 /* genIpush - genrate code for pushing this gets a little complex */
1488 /*-----------------------------------------------------------------*/
1489 static void genIpush (iCode *ic)
1491 int size, offset = 0 ;
1495 /* if this is not a parm push : ie. it is spill push
1496 and spill push is always done on the local stack */
1497 if (!ic->parmPush) {
1499 /* and the item is spilt then do nothing */
1500 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1503 aopOp(IC_LEFT(ic),ic,FALSE);
1504 size = AOP_SIZE(IC_LEFT(ic));
1505 /* push it on the stack */
1507 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1512 emitcode("push","%s",l);
1517 /* this is a paramter push: in this case we call
1518 the routine to find the call and save those
1519 registers that need to be saved */
1522 /* if use external stack then call the external
1523 stack pushing routine */
1524 if (options.useXstack) {
1529 /* then do the push */
1530 aopOp(IC_LEFT(ic),ic,FALSE);
1533 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1534 size = AOP_SIZE(IC_LEFT(ic));
1537 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1538 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1539 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1541 emitcode("mov","a,%s",l);
1542 emitcode("push","acc");
1544 emitcode("push","%s",l);
1547 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1550 /*-----------------------------------------------------------------*/
1551 /* genIpop - recover the registers: can happen only for spilling */
1552 /*-----------------------------------------------------------------*/
1553 static void genIpop (iCode *ic)
1558 /* if the temp was not pushed then */
1559 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1562 aopOp(IC_LEFT(ic),ic,FALSE);
1563 size = AOP_SIZE(IC_LEFT(ic));
1566 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1569 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1572 /*-----------------------------------------------------------------*/
1573 /* unsaverbank - restores the resgister bank from stack */
1574 /*-----------------------------------------------------------------*/
1575 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1582 if (options.useXstack) {
1584 r = getFreePtr(ic,&aop,FALSE);
1587 emitcode("mov","%s,_spx",r->name);
1588 emitcode("movx","a,@%s",r->name);
1589 emitcode("mov","psw,a");
1590 emitcode("dec","%s",r->name);
1593 emitcode ("pop","psw");
1596 for (i = (nRegs - 1) ; i >= 0 ;i--) {
1597 if (options.useXstack) {
1598 emitcode("movx","a,@%s",r->name);
1599 emitcode("mov","(%s+%d),a",
1600 regs8051[i].base,8*bank+regs8051[i].offset);
1601 emitcode("dec","%s",r->name);
1604 emitcode("pop","(%s+%d)",
1605 regs8051[i].base,8*bank+regs8051[i].offset);
1608 if (options.useXstack) {
1610 emitcode("mov","_spx,%s",r->name);
1611 freeAsmop(NULL,aop,ic,TRUE);
1616 /*-----------------------------------------------------------------*/
1617 /* saverbank - saves an entire register bank on the stack */
1618 /*-----------------------------------------------------------------*/
1619 static void saverbank (int bank, iCode *ic, bool pushPsw)
1625 if (options.useXstack) {
1628 r = getFreePtr(ic,&aop,FALSE);
1629 emitcode("mov","%s,_spx",r->name);
1633 for (i = 0 ; i < nRegs ;i++) {
1634 if (options.useXstack) {
1635 emitcode("inc","%s",r->name);
1636 emitcode("mov","a,(%s+%d)",
1637 regs8051[i].base,8*bank+regs8051[i].offset);
1638 emitcode("movx","@%s,a",r->name);
1640 emitcode("push","(%s+%d)",
1641 regs8051[i].base,8*bank+regs8051[i].offset);
1645 if (options.useXstack) {
1646 emitcode("mov","a,psw");
1647 emitcode("movx","@%s,a",r->name);
1648 emitcode("inc","%s",r->name);
1649 emitcode("mov","_spx,%s",r->name);
1650 freeAsmop (NULL,aop,ic,TRUE);
1653 emitcode("push","psw");
1655 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1661 /*-----------------------------------------------------------------*/
1662 /* genCall - generates a call statement */
1663 /*-----------------------------------------------------------------*/
1664 static void genCall (iCode *ic)
1668 /* if caller saves & we have not saved then */
1672 /* if we are calling a function that is not using
1673 the same register bank then we need to save the
1674 destination registers on the stack */
1675 detype = getSpec(operandType(IC_LEFT(ic)));
1677 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1678 IS_ISR(currFunc->etype) &&
1681 saverbank(SPEC_BANK(detype),ic,TRUE);
1683 /* if send set is not empty the assign */
1687 for (sic = setFirstItem(sendSet) ; sic ;
1688 sic = setNextItem(sendSet)) {
1689 int size, offset = 0;
1690 aopOp(IC_LEFT(sic),sic,FALSE);
1691 size = AOP_SIZE(IC_LEFT(sic));
1693 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1695 if (strcmp(l,fReturn[offset]))
1696 emitcode("mov","%s,%s",
1701 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1706 emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1707 OP_SYMBOL(IC_LEFT(ic))->rname :
1708 OP_SYMBOL(IC_LEFT(ic))->name));
1710 /* if we need assign a result value */
1711 if ((IS_ITEMP(IC_RESULT(ic)) &&
1712 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1713 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1714 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1717 aopOp(IC_RESULT(ic),ic,FALSE);
1720 assignResultValue(IC_RESULT(ic));
1722 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1725 /* adjust the stack for parameters if
1727 if (IC_LEFT(ic)->parmBytes) {
1729 if (IC_LEFT(ic)->parmBytes > 3) {
1730 emitcode("mov","a,%s",spname);
1731 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1732 emitcode("mov","%s,a",spname);
1734 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1735 emitcode("dec","%s",spname);
1739 /* if register bank was saved then pop them */
1741 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1743 /* if we hade saved some registers then unsave them */
1744 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1745 unsaveRegisters (ic);
1750 /*-----------------------------------------------------------------*/
1751 /* genPcall - generates a call by pointer statement */
1752 /*-----------------------------------------------------------------*/
1753 static void genPcall (iCode *ic)
1756 symbol *rlbl = newiTempLabel(NULL);
1759 /* if caller saves & we have not saved then */
1763 /* if we are calling a function that is not using
1764 the same register bank then we need to save the
1765 destination registers on the stack */
1766 detype = getSpec(operandType(IC_LEFT(ic)));
1768 IS_ISR(currFunc->etype) &&
1769 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
1770 saverbank(SPEC_BANK(detype),ic,TRUE);
1773 /* push the return address on to the stack */
1774 emitcode("mov","a,#%05d$",(rlbl->key+100));
1775 emitcode("push","acc");
1776 emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
1777 emitcode("push","acc");
1779 /* now push the calling address */
1780 aopOp(IC_LEFT(ic),ic,FALSE);
1782 pushSide(IC_LEFT(ic), 2);
1784 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1786 /* if send set is not empty the assign */
1790 for (sic = setFirstItem(sendSet) ; sic ;
1791 sic = setNextItem(sendSet)) {
1792 int size, offset = 0;
1793 aopOp(IC_LEFT(sic),sic,FALSE);
1794 size = AOP_SIZE(IC_LEFT(sic));
1796 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1798 if (strcmp(l,fReturn[offset]))
1799 emitcode("mov","%s,%s",
1804 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1810 emitcode("","%05d$:",(rlbl->key+100));
1813 /* if we need assign a result value */
1814 if ((IS_ITEMP(IC_RESULT(ic)) &&
1815 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1816 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
1817 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1820 aopOp(IC_RESULT(ic),ic,FALSE);
1823 assignResultValue(IC_RESULT(ic));
1825 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1828 /* adjust the stack for parameters if
1830 if (IC_LEFT(ic)->parmBytes) {
1832 if (IC_LEFT(ic)->parmBytes > 3) {
1833 emitcode("mov","a,%s",spname);
1834 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1835 emitcode("mov","%s,a",spname);
1837 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1838 emitcode("dec","%s",spname);
1842 /* if register bank was saved then unsave them */
1844 (SPEC_BANK(currFunc->etype) !=
1846 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1848 /* if we hade saved some registers then
1851 unsaveRegisters (ic);
1855 /*-----------------------------------------------------------------*/
1856 /* resultRemat - result is rematerializable */
1857 /*-----------------------------------------------------------------*/
1858 static int resultRemat (iCode *ic)
1860 if (SKIP_IC(ic) || ic->op == IFX)
1863 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1864 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1865 if (sym->remat && !POINTER_SET(ic))
1872 /*-----------------------------------------------------------------*/
1873 /* inExcludeList - return 1 if the string is in exclude Reg list */
1874 /*-----------------------------------------------------------------*/
1875 static bool inExcludeList(char *s)
1879 if (options.excludeRegs[i] &&
1880 strcasecmp(options.excludeRegs[i],"none") == 0)
1883 for ( i = 0 ; options.excludeRegs[i]; i++) {
1884 if (options.excludeRegs[i] &&
1885 strcasecmp(s,options.excludeRegs[i]) == 0)
1891 /*-----------------------------------------------------------------*/
1892 /* genFunction - generated code for function entry */
1893 /*-----------------------------------------------------------------*/
1894 static void genFunction (iCode *ic)
1900 /* create the function header */
1901 emitcode(";","-----------------------------------------");
1902 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1903 emitcode(";","-----------------------------------------");
1905 emitcode("","%s:",sym->rname);
1906 fetype = getSpec(operandType(IC_LEFT(ic)));
1908 /* if critical function then turn interrupts off */
1909 if (SPEC_CRTCL(fetype))
1910 emitcode("clr","ea");
1912 /* here we need to generate the equates for the
1913 register bank if required */
1914 if (SPEC_BANK(fetype) != rbank) {
1917 rbank = SPEC_BANK(fetype);
1918 for ( i = 0 ; i < nRegs ; i++ ) {
1919 if (strcmp(regs8051[i].base,"0") == 0)
1920 emitcode("","%s = 0x%02x",
1922 8*rbank+regs8051[i].offset);
1924 emitcode ("","%s = %s + 0x%02x",
1927 8*rbank+regs8051[i].offset);
1931 /* if this is an interrupt service routine then
1932 save acc, b, dpl, dph */
1933 if (IS_ISR(sym->etype)) {
1935 if (!inExcludeList("acc"))
1936 emitcode ("push","acc");
1937 if (!inExcludeList("b"))
1938 emitcode ("push","b");
1939 if (!inExcludeList("dpl"))
1940 emitcode ("push","dpl");
1941 if (!inExcludeList("dph"))
1942 emitcode ("push","dph");
1944 /* if this isr has no bank i.e. is going to
1945 run with bank 0 , then we need to save more
1947 if (!SPEC_BANK(sym->etype)) {
1949 /* if this function does not call any other
1950 function then we can be economical and
1951 save only those registers that are used */
1952 if (! sym->hasFcall) {
1955 /* if any registers used */
1956 if (sym->regsUsed) {
1957 /* save the registers used */
1958 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
1959 if (bitVectBitValue(sym->regsUsed,i) ||
1960 (ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
1961 emitcode("push","%s",regWithIdx(i)->dname);
1966 /* this function has a function call cannot
1967 determines register usage so we will have the
1969 saverbank(0,ic,FALSE);
1973 /* if callee-save to be used for this function
1974 then save the registers being used in this function */
1975 if (sym->calleeSave) {
1978 /* if any registers used */
1979 if (sym->regsUsed) {
1980 /* save the registers used */
1981 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
1982 if (bitVectBitValue(sym->regsUsed,i) ||
1983 (ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
1984 emitcode("push","%s",regWithIdx(i)->dname);
1992 /* set the register bank to the desired value */
1993 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
1994 emitcode("push","psw");
1995 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
1998 if (IS_RENT(sym->etype) || options.stackAuto) {
2000 if (options.useXstack) {
2001 emitcode("mov","r0,%s",spname);
2002 emitcode("mov","a,_bp");
2003 emitcode("movx","@r0,a");
2004 emitcode("inc","%s",spname);
2007 /* set up the stack */
2008 emitcode ("push","_bp"); /* save the callers stack */
2009 emitcode ("mov","_bp,%s",spname);
2012 /* adjust the stack for the function */
2017 werror(W_STACK_OVERFLOW,sym->name);
2019 if (i > 3 && sym->recvSize < 4) {
2021 emitcode ("mov","a,sp");
2022 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2023 emitcode ("mov","sp,a");
2028 emitcode("inc","sp");
2033 emitcode ("mov","a,_spx");
2034 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2035 emitcode ("mov","_spx,a");
2040 /*-----------------------------------------------------------------*/
2041 /* genEndFunction - generates epilogue for functions */
2042 /*-----------------------------------------------------------------*/
2043 static void genEndFunction (iCode *ic)
2045 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2047 if (IS_RENT(sym->etype) || options.stackAuto)
2048 emitcode ("mov","%s,_bp",spname);
2050 /* if use external stack but some variables were
2051 added to the local stack then decrement the
2053 if (options.useXstack && sym->stack) {
2054 emitcode("mov","a,sp");
2055 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2056 emitcode("mov","sp,a");
2060 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2061 if (options.useXstack) {
2062 emitcode("mov","r0,%s",spname);
2063 emitcode("movx","a,@r0");
2064 emitcode("mov","_bp,a");
2065 emitcode("dec","%s",spname);
2068 emitcode ("pop","_bp");
2071 /* restore the register bank */
2072 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2073 emitcode ("pop","psw");
2075 if (IS_ISR(sym->etype)) {
2077 /* now we need to restore the registers */
2078 /* if this isr has no bank i.e. is going to
2079 run with bank 0 , then we need to save more
2081 if (!SPEC_BANK(sym->etype)) {
2083 /* if this function does not call any other
2084 function then we can be economical and
2085 save only those registers that are used */
2086 if (! sym->hasFcall) {
2089 /* if any registers used */
2090 if (sym->regsUsed) {
2091 /* save the registers used */
2092 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2093 if (bitVectBitValue(sym->regsUsed,i) ||
2094 (ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2095 emitcode("pop","%s",regWithIdx(i)->dname);
2100 /* this function has a function call cannot
2101 determines register usage so we will have the
2103 unsaverbank(0,ic,FALSE);
2107 if (!inExcludeList("dph"))
2108 emitcode ("pop","dph");
2109 if (!inExcludeList("dpl"))
2110 emitcode ("pop","dpl");
2111 if (!inExcludeList("b"))
2112 emitcode ("pop","b");
2113 if (!inExcludeList("acc"))
2114 emitcode ("pop","acc");
2116 if (SPEC_CRTCL(sym->etype))
2117 emitcode("setb","ea");
2119 /* if debug then send end of function */
2120 /* if (options.debug && currFunc) { */
2123 emitcode("","C$%s$%d$%d$%d ==.",
2124 ic->filename,currFunc->lastLine,
2125 ic->level,ic->block);
2126 if (IS_STATIC(currFunc->etype))
2127 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2129 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2133 emitcode ("reti","");
2136 if (SPEC_CRTCL(sym->etype))
2137 emitcode("setb","ea");
2139 if (sym->calleeSave) {
2142 /* if any registers used */
2143 if (sym->regsUsed) {
2144 /* save the registers used */
2145 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2146 if (bitVectBitValue(sym->regsUsed,i) ||
2147 (ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2148 emitcode("pop","%s",regWithIdx(i)->dname);
2154 /* if debug then send end of function */
2155 /* if (options.debug && currFunc) { */
2158 emitcode("","C$%s$%d$%d$%d ==.",
2159 ic->filename,currFunc->lastLine,
2160 ic->level,ic->block);
2161 if (IS_STATIC(currFunc->etype))
2162 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2164 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2168 emitcode ("ret","");
2173 /*-----------------------------------------------------------------*/
2174 /* genRet - generate code for return statement */
2175 /*-----------------------------------------------------------------*/
2176 static void genRet (iCode *ic)
2178 int size,offset = 0 , pushed = 0;
2180 /* if we have no return value then
2181 just generate the "ret" */
2185 /* we have something to return then
2186 move the return value into place */
2187 aopOp(IC_LEFT(ic),ic,FALSE);
2188 size = AOP_SIZE(IC_LEFT(ic));
2192 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2193 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2195 emitcode("push","%s",l);
2198 l = aopGet(AOP(IC_LEFT(ic)),offset,
2200 if (strcmp(fReturn[offset],l))
2201 emitcode("mov","%s,%s",fReturn[offset++],l);
2208 if (strcmp(fReturn[pushed],"a"))
2209 emitcode("pop",fReturn[pushed]);
2211 emitcode("pop","acc");
2214 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2217 /* generate a jump to the return label
2218 if the next is not the return statement */
2219 if (!(ic->next && ic->next->op == LABEL &&
2220 IC_LABEL(ic->next) == returnLabel))
2222 emitcode("ljmp","%05d$",(returnLabel->key+100));
2226 /*-----------------------------------------------------------------*/
2227 /* genLabel - generates a label */
2228 /*-----------------------------------------------------------------*/
2229 static void genLabel (iCode *ic)
2231 /* special case never generate */
2232 if (IC_LABEL(ic) == entryLabel)
2235 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2238 /*-----------------------------------------------------------------*/
2239 /* genGoto - generates a ljmp */
2240 /*-----------------------------------------------------------------*/
2241 static void genGoto (iCode *ic)
2243 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2246 /*-----------------------------------------------------------------*/
2247 /* genPlusIncr :- does addition with increment if possible */
2248 /*-----------------------------------------------------------------*/
2249 static bool genPlusIncr (iCode *ic)
2251 unsigned int icount ;
2252 unsigned int size = getDataSize(IC_RESULT(ic));
2254 /* will try to generate an increment */
2255 /* if the right side is not a literal
2257 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2260 /* if the literal value of the right hand side
2261 is greater than 4 then it is not worth it */
2262 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2265 /* if increment 16 bits in register */
2266 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2269 symbol *tlbl = newiTempLabel(NULL);
2270 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2271 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2272 IS_AOP_PREG(IC_RESULT(ic)))
2273 emitcode("cjne","%s,#0x00,%05d$"
2274 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2277 emitcode("clr","a");
2278 emitcode("cjne","a,%s,%05d$"
2279 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2283 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2285 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2286 IS_AOP_PREG(IC_RESULT(ic)))
2287 emitcode("cjne","%s,#0x00,%05d$"
2288 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2291 emitcode("cjne","a,%s,%05d$"
2292 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2295 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2296 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2297 IS_AOP_PREG(IC_RESULT(ic)))
2298 emitcode("cjne","%s,#0x00,%05d$"
2299 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2302 emitcode("cjne","a,%s,%05d$"
2303 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2306 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2308 emitcode("","%05d$:",tlbl->key+100);
2312 /* if the sizes are greater than 1 then we cannot */
2313 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2314 AOP_SIZE(IC_LEFT(ic)) > 1 )
2317 /* we can if the aops of the left & result match or
2318 if they are in registers and the registers are the
2320 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2323 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2324 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2325 aopPut(AOP(IC_RESULT(ic)),"a",0);
2329 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2338 /*-----------------------------------------------------------------*/
2339 /* outBitAcc - output a bit in acc */
2340 /*-----------------------------------------------------------------*/
2341 void outBitAcc(operand *result)
2343 symbol *tlbl = newiTempLabel(NULL);
2344 /* if the result is a bit */
2345 if (AOP_TYPE(result) == AOP_CRY){
2346 aopPut(AOP(result),"a",0);
2349 emitcode("jz","%05d$",tlbl->key+100);
2350 emitcode("mov","a,%s",one);
2351 emitcode("","%05d$:",tlbl->key+100);
2356 /*-----------------------------------------------------------------*/
2357 /* genPlusBits - generates code for addition of two bits */
2358 /*-----------------------------------------------------------------*/
2359 static void genPlusBits (iCode *ic)
2361 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2362 symbol *lbl = newiTempLabel(NULL);
2363 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2364 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2365 emitcode("cpl","c");
2366 emitcode("","%05d$:",(lbl->key+100));
2367 outBitC(IC_RESULT(ic));
2370 emitcode("clr","a");
2371 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2372 emitcode("rlc","a");
2373 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2374 emitcode("addc","a,#0x00");
2375 outAcc(IC_RESULT(ic));
2379 /*-----------------------------------------------------------------*/
2380 /* genPlus - generates code for addition */
2381 /*-----------------------------------------------------------------*/
2382 static void genPlus (iCode *ic)
2384 int size, offset = 0;
2386 /* special cases :- */
2388 aopOp (IC_LEFT(ic),ic,FALSE);
2389 aopOp (IC_RIGHT(ic),ic,FALSE);
2390 aopOp (IC_RESULT(ic),ic,TRUE);
2392 /* if literal, literal on the right or
2393 if left requires ACC or right is already
2395 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2396 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2397 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2398 operand *t = IC_RIGHT(ic);
2399 IC_RIGHT(ic) = IC_LEFT(ic);
2403 /* if both left & right are in bit
2405 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2406 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2411 /* if left in bit space & right literal */
2412 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2413 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2414 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2415 /* if result in bit space */
2416 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2417 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
2418 emitcode("cpl","c");
2419 outBitC(IC_RESULT(ic));
2421 size = getDataSize(IC_RESULT(ic));
2423 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2424 emitcode("addc","a,#00");
2425 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2431 /* if I can do an increment instead
2432 of add then GOOD for ME */
2433 if (genPlusIncr (ic) == TRUE)
2436 size = getDataSize(IC_RESULT(ic));
2439 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2440 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2442 emitcode("add","a,%s",
2443 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2445 emitcode("addc","a,%s",
2446 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2448 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2450 emitcode("add","a,%s",
2451 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2453 emitcode("addc","a,%s",
2454 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2456 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2459 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2460 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2461 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2462 aopPut(AOP(IC_RESULT(ic)),
2463 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2466 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2467 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
2468 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2469 aopPut(AOP(IC_RESULT(ic)),
2470 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2473 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2474 AOP_SIZE(IC_LEFT(ic)) < 3 &&
2475 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
2476 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2477 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2479 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2480 aopPut(AOP(IC_RESULT(ic)),buffer,2);
2483 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2484 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2485 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2488 /*-----------------------------------------------------------------*/
2489 /* genMinusDec :- does subtraction with deccrement if possible */
2490 /*-----------------------------------------------------------------*/
2491 static bool genMinusDec (iCode *ic)
2493 unsigned int icount ;
2494 unsigned int size = getDataSize(IC_RESULT(ic));
2496 /* will try to generate an increment */
2497 /* if the right side is not a literal
2499 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2502 /* if the literal value of the right hand side
2503 is greater than 4 then it is not worth it */
2504 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2507 size = getDataSize(IC_RESULT(ic));
2508 /* if decrement 16 bits in register */
2509 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2512 symbol *tlbl = newiTempLabel(NULL);
2513 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2514 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2515 IS_AOP_PREG(IC_RESULT(ic)))
2516 emitcode("cjne","%s,#0xff,%05d$"
2517 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2520 emitcode("mov","a,#0xff");
2521 emitcode("cjne","a,%s,%05d$"
2522 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2525 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2527 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2528 IS_AOP_PREG(IC_RESULT(ic)))
2529 emitcode("cjne","%s,#0xff,%05d$"
2530 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2533 emitcode("cjne","a,%s,%05d$"
2534 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2537 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2538 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2539 IS_AOP_PREG(IC_RESULT(ic)))
2540 emitcode("cjne","%s,#0xff,%05d$"
2541 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2544 emitcode("cjne","a,%s,%05d$"
2545 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2548 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2550 emitcode("","%05d$:",tlbl->key+100);
2554 /* if the sizes are greater than 1 then we cannot */
2555 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2556 AOP_SIZE(IC_LEFT(ic)) > 1 )
2559 /* we can if the aops of the left & result match or
2560 if they are in registers and the registers are the
2562 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2565 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2573 /*-----------------------------------------------------------------*/
2574 /* addSign - complete with sign */
2575 /*-----------------------------------------------------------------*/
2576 static void addSign(operand *result, int offset, int sign)
2578 int size = (getDataSize(result) - offset);
2581 emitcode("rlc","a");
2582 emitcode("subb","a,acc");
2584 aopPut(AOP(result),"a",offset++);
2587 aopPut(AOP(result),zero,offset++);
2591 /*-----------------------------------------------------------------*/
2592 /* genMinusBits - generates code for subtraction of two bits */
2593 /*-----------------------------------------------------------------*/
2594 static void genMinusBits (iCode *ic)
2596 symbol *lbl = newiTempLabel(NULL);
2597 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2598 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2599 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2600 emitcode("cpl","c");
2601 emitcode("","%05d$:",(lbl->key+100));
2602 outBitC(IC_RESULT(ic));
2605 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2606 emitcode("subb","a,acc");
2607 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
2608 emitcode("inc","a");
2609 emitcode("","%05d$:",(lbl->key+100));
2610 aopPut(AOP(IC_RESULT(ic)),"a",0);
2611 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
2615 /*-----------------------------------------------------------------*/
2616 /* genMinus - generates code for subtraction */
2617 /*-----------------------------------------------------------------*/
2618 static void genMinus (iCode *ic)
2620 int size, offset = 0;
2621 unsigned long lit = 0L;
2623 aopOp (IC_LEFT(ic),ic,FALSE);
2624 aopOp (IC_RIGHT(ic),ic,FALSE);
2625 aopOp (IC_RESULT(ic),ic,TRUE);
2627 /* special cases :- */
2628 /* if both left & right are in bit space */
2629 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2630 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2635 /* if I can do an decrement instead
2636 of subtract then GOOD for ME */
2637 if (genMinusDec (ic) == TRUE)
2640 size = getDataSize(IC_RESULT(ic));
2642 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
2646 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2650 /* if literal, add a,#-lit, else normal subb */
2652 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2653 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2654 emitcode("subb","a,%s",
2655 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2657 /* first add without previous c */
2659 emitcode("add","a,#0x%02x",
2660 (unsigned int)(lit & 0x0FFL));
2662 emitcode("addc","a,#0x%02x",
2663 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
2665 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2668 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2669 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2670 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2671 aopPut(AOP(IC_RESULT(ic)),
2672 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2675 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2676 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
2677 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2678 aopPut(AOP(IC_RESULT(ic)),
2679 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2682 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2683 AOP_SIZE(IC_LEFT(ic)) < 3 &&
2684 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
2685 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2686 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2688 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2689 aopPut(AOP(IC_RESULT(ic)),buffer,2);
2692 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2693 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2694 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2698 /*-----------------------------------------------------------------*/
2699 /* genMultbits :- multiplication of bits */
2700 /*-----------------------------------------------------------------*/
2701 static void genMultbits (operand *left,
2705 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2706 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
2711 /*-----------------------------------------------------------------*/
2712 /* genMultOneByte : 8 bit multiplication & division */
2713 /*-----------------------------------------------------------------*/
2714 static void genMultOneByte (operand *left,
2718 link *opetype = operandType(result);
2723 /* (if two literals, the value is computed before) */
2724 /* if one literal, literal on the right */
2725 if (AOP_TYPE(left) == AOP_LIT){
2731 size = AOP_SIZE(result);
2732 /* signed or unsigned */
2733 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2734 l = aopGet(AOP(left),0,FALSE,FALSE);
2736 emitcode("mul","ab");
2737 /* if result size = 1, mul signed = mul unsigned */
2738 aopPut(AOP(result),"a",0);
2740 if (SPEC_USIGN(opetype)){
2741 aopPut(AOP(result),"b",1);
2743 /* for filling the MSBs */
2744 emitcode("clr","a");
2747 emitcode("mov","a,b");
2749 /* adjust the MSB if left or right neg */
2751 /* if one literal */
2752 if (AOP_TYPE(right) == AOP_LIT){
2753 /* AND literal negative */
2754 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
2755 /* adjust MSB (c==0 after mul) */
2756 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2760 lbl = newiTempLabel(NULL);
2761 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2762 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
2763 emitcode("","%05d$:",(lbl->key+100));
2764 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2765 lbl = newiTempLabel(NULL);
2766 emitcode("jc","%05d$",(lbl->key+100));
2767 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2768 emitcode("","%05d$:",(lbl->key+100));
2771 lbl = newiTempLabel(NULL);
2772 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
2773 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
2774 emitcode("","%05d$:",(lbl->key+100));
2775 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
2776 lbl = newiTempLabel(NULL);
2777 emitcode("jc","%05d$",(lbl->key+100));
2778 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
2779 emitcode("","%05d$:",(lbl->key+100));
2781 aopPut(AOP(result),"a",1);
2784 emitcode("rlc","a");
2785 emitcode("subb","a,acc");
2792 aopPut(AOP(result),"a",offset++);
2796 /*-----------------------------------------------------------------*/
2797 /* genMult - generates code for multiplication */
2798 /*-----------------------------------------------------------------*/
2799 static void genMult (iCode *ic)
2801 operand *left = IC_LEFT(ic);
2802 operand *right = IC_RIGHT(ic);
2803 operand *result= IC_RESULT(ic);
2805 /* assign the amsops */
2806 aopOp (left,ic,FALSE);
2807 aopOp (right,ic,FALSE);
2808 aopOp (result,ic,TRUE);
2810 /* special cases first */
2812 if (AOP_TYPE(left) == AOP_CRY &&
2813 AOP_TYPE(right)== AOP_CRY) {
2814 genMultbits(left,right,result);
2818 /* if both are of size == 1 */
2819 if (AOP_SIZE(left) == 1 &&
2820 AOP_SIZE(right) == 1 ) {
2821 genMultOneByte(left,right,result);
2825 /* should have been converted to function call */
2829 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2830 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2831 freeAsmop(result,NULL,ic,TRUE);
2834 /*-----------------------------------------------------------------*/
2835 /* genDivbits :- division of bits */
2836 /*-----------------------------------------------------------------*/
2837 static void genDivbits (operand *left,
2844 /* the result must be bit */
2845 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
2846 l = aopGet(AOP(left),0,FALSE,FALSE);
2850 emitcode("div","ab");
2851 emitcode("rrc","a");
2852 aopPut(AOP(result),"c",0);
2855 /*-----------------------------------------------------------------*/
2856 /* genDivOneByte : 8 bit division */
2857 /*-----------------------------------------------------------------*/
2858 static void genDivOneByte (operand *left,
2862 link *opetype = operandType(result);
2867 size = AOP_SIZE(result) - 1;
2869 /* signed or unsigned */
2870 if (SPEC_USIGN(opetype)) {
2871 /* unsigned is easy */
2872 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2873 l = aopGet(AOP(left),0,FALSE,FALSE);
2875 emitcode("div","ab");
2876 aopPut(AOP(result),"a",0);
2878 aopPut(AOP(result),zero,offset++);
2882 /* signed is a little bit more difficult */
2884 /* save the signs of the operands */
2885 l = aopGet(AOP(left),0,FALSE,FALSE);
2887 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
2888 emitcode("push","acc"); /* save it on the stack */
2890 /* now sign adjust for both left & right */
2891 l = aopGet(AOP(right),0,FALSE,FALSE);
2893 lbl = newiTempLabel(NULL);
2894 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
2895 emitcode("cpl","a");
2896 emitcode("inc","a");
2897 emitcode("","%05d$:",(lbl->key+100));
2898 emitcode("mov","b,a");
2900 /* sign adjust left side */
2901 l = aopGet(AOP(left),0,FALSE,FALSE);
2904 lbl = newiTempLabel(NULL);
2905 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
2906 emitcode("cpl","a");
2907 emitcode("inc","a");
2908 emitcode("","%05d$:",(lbl->key+100));
2910 /* now the division */
2911 emitcode("div","ab");
2912 /* we are interested in the lower order
2914 emitcode("mov","b,a");
2915 lbl = newiTempLabel(NULL);
2916 emitcode("pop","acc");
2917 /* if there was an over flow we don't
2918 adjust the sign of the result */
2919 emitcode("jb","ov,%05d$",(lbl->key+100));
2920 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
2922 emitcode("clr","a");
2923 emitcode("subb","a,b");
2924 emitcode("mov","b,a");
2925 emitcode("","%05d$:",(lbl->key+100));
2927 /* now we are done */
2928 aopPut(AOP(result),"b",0);
2930 emitcode("mov","c,b.7");
2931 emitcode("subb","a,acc");
2934 aopPut(AOP(result),"a",offset++);
2938 /*-----------------------------------------------------------------*/
2939 /* genDiv - generates code for division */
2940 /*-----------------------------------------------------------------*/
2941 static void genDiv (iCode *ic)
2943 operand *left = IC_LEFT(ic);
2944 operand *right = IC_RIGHT(ic);
2945 operand *result= IC_RESULT(ic);
2947 /* assign the amsops */
2948 aopOp (left,ic,FALSE);
2949 aopOp (right,ic,FALSE);
2950 aopOp (result,ic,TRUE);
2952 /* special cases first */
2954 if (AOP_TYPE(left) == AOP_CRY &&
2955 AOP_TYPE(right)== AOP_CRY) {
2956 genDivbits(left,right,result);
2960 /* if both are of size == 1 */
2961 if (AOP_SIZE(left) == 1 &&
2962 AOP_SIZE(right) == 1 ) {
2963 genDivOneByte(left,right,result);
2967 /* should have been converted to function call */
2970 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2971 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2972 freeAsmop(result,NULL,ic,TRUE);
2975 /*-----------------------------------------------------------------*/
2976 /* genModbits :- modulus of bits */
2977 /*-----------------------------------------------------------------*/
2978 static void genModbits (operand *left,
2985 /* the result must be bit */
2986 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
2987 l = aopGet(AOP(left),0,FALSE,FALSE);
2991 emitcode("div","ab");
2992 emitcode("mov","a,b");
2993 emitcode("rrc","a");
2994 aopPut(AOP(result),"c",0);
2997 /*-----------------------------------------------------------------*/
2998 /* genModOneByte : 8 bit modulus */
2999 /*-----------------------------------------------------------------*/
3000 static void genModOneByte (operand *left,
3004 link *opetype = operandType(result);
3008 /* signed or unsigned */
3009 if (SPEC_USIGN(opetype)) {
3010 /* unsigned is easy */
3011 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3012 l = aopGet(AOP(left),0,FALSE,FALSE);
3014 emitcode("div","ab");
3015 aopPut(AOP(result),"b",0);
3019 /* signed is a little bit more difficult */
3021 /* save the signs of the operands */
3022 l = aopGet(AOP(left),0,FALSE,FALSE);
3025 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3026 emitcode("push","acc"); /* save it on the stack */
3028 /* now sign adjust for both left & right */
3029 l = aopGet(AOP(right),0,FALSE,FALSE);
3032 lbl = newiTempLabel(NULL);
3033 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3034 emitcode("cpl","a");
3035 emitcode("inc","a");
3036 emitcode("","%05d$:",(lbl->key+100));
3037 emitcode("mov","b,a");
3039 /* sign adjust left side */
3040 l = aopGet(AOP(left),0,FALSE,FALSE);
3043 lbl = newiTempLabel(NULL);
3044 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3045 emitcode("cpl","a");
3046 emitcode("inc","a");
3047 emitcode("","%05d$:",(lbl->key+100));
3049 /* now the multiplication */
3050 emitcode("div","ab");
3051 /* we are interested in the lower order
3053 lbl = newiTempLabel(NULL);
3054 emitcode("pop","acc");
3055 /* if there was an over flow we don't
3056 adjust the sign of the result */
3057 emitcode("jb","ov,%05d$",(lbl->key+100));
3058 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3060 emitcode("clr","a");
3061 emitcode("subb","a,b");
3062 emitcode("mov","b,a");
3063 emitcode("","%05d$:",(lbl->key+100));
3065 /* now we are done */
3066 aopPut(AOP(result),"b",0);
3070 /*-----------------------------------------------------------------*/
3071 /* genMod - generates code for division */
3072 /*-----------------------------------------------------------------*/
3073 static void genMod (iCode *ic)
3075 operand *left = IC_LEFT(ic);
3076 operand *right = IC_RIGHT(ic);
3077 operand *result= IC_RESULT(ic);
3079 /* assign the amsops */
3080 aopOp (left,ic,FALSE);
3081 aopOp (right,ic,FALSE);
3082 aopOp (result,ic,TRUE);
3084 /* special cases first */
3086 if (AOP_TYPE(left) == AOP_CRY &&
3087 AOP_TYPE(right)== AOP_CRY) {
3088 genModbits(left,right,result);
3092 /* if both are of size == 1 */
3093 if (AOP_SIZE(left) == 1 &&
3094 AOP_SIZE(right) == 1 ) {
3095 genModOneByte(left,right,result);
3099 /* should have been converted to function call */
3103 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3104 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3105 freeAsmop(result,NULL,ic,TRUE);
3108 /*-----------------------------------------------------------------*/
3109 /* genIfxJump :- will create a jump depending on the ifx */
3110 /*-----------------------------------------------------------------*/
3111 static void genIfxJump (iCode *ic, char *jval)
3114 symbol *tlbl = newiTempLabel(NULL);
3117 /* if true label then we jump if condition
3119 if ( IC_TRUE(ic) ) {
3121 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3122 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3125 /* false label is present */
3126 jlbl = IC_FALSE(ic) ;
3127 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3128 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3130 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3131 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3133 emitcode(inst,"%05d$",tlbl->key+100);
3134 emitcode("ljmp","%05d$",jlbl->key+100);
3135 emitcode("","%05d$:",tlbl->key+100);
3137 /* mark the icode as generated */
3141 /*-----------------------------------------------------------------*/
3142 /* genCmp :- greater or less than comparison */
3143 /*-----------------------------------------------------------------*/
3144 static void genCmp (operand *left,operand *right,
3145 operand *result, iCode *ifx, int sign)
3147 int size, offset = 0 ;
3148 unsigned long lit = 0L;
3150 /* if left & right are bit variables */
3151 if (AOP_TYPE(left) == AOP_CRY &&
3152 AOP_TYPE(right) == AOP_CRY ) {
3153 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3154 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3156 /* subtract right from left if at the
3157 end the carry flag is set then we know that
3158 left is greater than right */
3159 size = max(AOP_SIZE(left),AOP_SIZE(right));
3161 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3162 if((size == 1) && !sign &&
3163 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3164 symbol *lbl = newiTempLabel(NULL);
3165 emitcode("cjne","%s,%s,%05d$",
3166 aopGet(AOP(left),offset,FALSE,FALSE),
3167 aopGet(AOP(right),offset,FALSE,FALSE),
3169 emitcode("","%05d$:",lbl->key+100);
3171 if(AOP_TYPE(right) == AOP_LIT){
3172 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3173 /* optimize if(x < 0) or if(x >= 0) */
3179 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE));
3180 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3181 genIfxJump (ifx,"acc.7");
3185 emitcode("rlc","a");
3192 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3193 if (sign && size == 0) {
3194 emitcode("xrl","a,#0x80");
3195 if (AOP_TYPE(right) == AOP_LIT){
3196 unsigned long lit = (unsigned long)
3197 floatFromVal(AOP(right)->aopu.aop_lit);
3198 emitcode("subb","a,#0x%02x",
3199 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3201 emitcode("mov","b,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3202 emitcode("xrl","b,#0x80");
3203 emitcode("subb","a,b");
3206 emitcode("subb","a,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3212 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3215 /* if the result is used in the next
3216 ifx conditional branch then generate
3217 code a little differently */
3219 genIfxJump (ifx,"c");
3222 /* leave the result in acc */
3226 /*-----------------------------------------------------------------*/
3227 /* genCmpGt :- greater than comparison */
3228 /*-----------------------------------------------------------------*/
3229 static void genCmpGt (iCode *ic, iCode *ifx)
3231 operand *left, *right, *result;
3232 link *letype , *retype;
3236 right= IC_RIGHT(ic);
3237 result = IC_RESULT(ic);
3239 letype = getSpec(operandType(left));
3240 retype =getSpec(operandType(right));
3241 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3242 /* assign the amsops */
3243 aopOp (left,ic,FALSE);
3244 aopOp (right,ic,FALSE);
3245 aopOp (result,ic,TRUE);
3247 genCmp(right, left, result, ifx, sign);
3249 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3250 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3251 freeAsmop(result,NULL,ic,TRUE);
3254 /*-----------------------------------------------------------------*/
3255 /* genCmpLt - less than comparisons */
3256 /*-----------------------------------------------------------------*/
3257 static void genCmpLt (iCode *ic, iCode *ifx)
3259 operand *left, *right, *result;
3260 link *letype , *retype;
3264 right= IC_RIGHT(ic);
3265 result = IC_RESULT(ic);
3267 letype = getSpec(operandType(left));
3268 retype =getSpec(operandType(right));
3269 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3271 /* assign the amsops */
3272 aopOp (left,ic,FALSE);
3273 aopOp (right,ic,FALSE);
3274 aopOp (result,ic,TRUE);
3276 genCmp(left, right, result, ifx, sign);
3278 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3279 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3280 freeAsmop(result,NULL,ic,TRUE);
3283 /*-----------------------------------------------------------------*/
3284 /* gencjneshort - compare and jump if not equal */
3285 /*-----------------------------------------------------------------*/
3286 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3288 int size = max(AOP_SIZE(left),AOP_SIZE(right));
3290 unsigned long lit = 0L;
3292 /* if the left side is a literal or
3293 if the right is in a pointer register and left
3295 if ((AOP_TYPE(left) == AOP_LIT) ||
3296 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3301 if(AOP_TYPE(right) == AOP_LIT)
3302 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3304 /* if the right side is a literal then anything goes */
3305 if (AOP_TYPE(right) == AOP_LIT &&
3306 AOP_TYPE(left) != AOP_DIR ) {
3308 emitcode("cjne","%s,%s,%05d$",
3309 aopGet(AOP(left),offset,FALSE,FALSE),
3310 aopGet(AOP(right),offset,FALSE,FALSE),
3316 /* if the right side is in a register or in direct space or
3317 if the left is a pointer register & right is not */
3318 else if (AOP_TYPE(right) == AOP_REG ||
3319 AOP_TYPE(right) == AOP_DIR ||
3320 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3321 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3323 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3324 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3325 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
3326 emitcode("jnz","%05d$",lbl->key+100);
3328 emitcode("cjne","a,%s,%05d$",
3329 aopGet(AOP(right),offset,FALSE,TRUE),
3334 /* right is a pointer reg need both a & b */
3336 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
3338 emitcode("mov","b,%s",l);
3339 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3340 emitcode("cjne","a,b,%05d$",lbl->key+100);
3346 /*-----------------------------------------------------------------*/
3347 /* gencjne - compare and jump if not equal */
3348 /*-----------------------------------------------------------------*/
3349 static void gencjne(operand *left, operand *right, symbol *lbl)
3351 symbol *tlbl = newiTempLabel(NULL);
3353 gencjneshort(left, right, lbl);
3355 emitcode("mov","a,%s",one);
3356 emitcode("sjmp","%05d$",tlbl->key+100);
3357 emitcode("","%05d$:",lbl->key+100);
3358 emitcode("clr","a");
3359 emitcode("","%05d$:",tlbl->key+100);
3362 /*-----------------------------------------------------------------*/
3363 /* genCmpEq - generates code for equal to */
3364 /*-----------------------------------------------------------------*/
3365 static void genCmpEq (iCode *ic, iCode *ifx)
3367 operand *left, *right, *result;
3369 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3370 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3371 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3373 /* if literal, literal on the right or
3374 if the right is in a pointer register and left
3376 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
3377 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3378 operand *t = IC_RIGHT(ic);
3379 IC_RIGHT(ic) = IC_LEFT(ic);
3383 if(ifx && !AOP_SIZE(result)){
3385 /* if they are both bit variables */
3386 if (AOP_TYPE(left) == AOP_CRY &&
3387 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3388 if(AOP_TYPE(right) == AOP_LIT){
3389 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3391 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3392 emitcode("cpl","c");
3393 } else if(lit == 1L) {
3394 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3396 emitcode("clr","c");
3398 /* AOP_TYPE(right) == AOP_CRY */
3400 symbol *lbl = newiTempLabel(NULL);
3401 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3402 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3403 emitcode("cpl","c");
3404 emitcode("","%05d$:",(lbl->key+100));
3406 /* if true label then we jump if condition
3408 tlbl = newiTempLabel(NULL);
3409 if ( IC_TRUE(ifx) ) {
3410 emitcode("jnc","%05d$",tlbl->key+100);
3411 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3413 emitcode("jc","%05d$",tlbl->key+100);
3414 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3416 emitcode("","%05d$:",tlbl->key+100);
3418 tlbl = newiTempLabel(NULL);
3419 gencjneshort(left, right, tlbl);
3420 if ( IC_TRUE(ifx) ) {
3421 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3422 emitcode("","%05d$:",tlbl->key+100);
3424 symbol *lbl = newiTempLabel(NULL);
3425 emitcode("sjmp","%05d$",lbl->key+100);
3426 emitcode("","%05d$:",tlbl->key+100);
3427 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3428 emitcode("","%05d$:",lbl->key+100);
3431 /* mark the icode as generated */
3436 /* if they are both bit variables */
3437 if (AOP_TYPE(left) == AOP_CRY &&
3438 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3439 if(AOP_TYPE(right) == AOP_LIT){
3440 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3442 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3443 emitcode("cpl","c");
3444 } else if(lit == 1L) {
3445 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3447 emitcode("clr","c");
3449 /* AOP_TYPE(right) == AOP_CRY */
3451 symbol *lbl = newiTempLabel(NULL);
3452 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3453 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3454 emitcode("cpl","c");
3455 emitcode("","%05d$:",(lbl->key+100));
3458 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
3463 genIfxJump (ifx,"c");
3466 /* if the result is used in an arithmetic operation
3467 then put the result in place */
3470 gencjne(left,right,newiTempLabel(NULL));
3471 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3472 aopPut(AOP(result),"a",0);
3476 genIfxJump (ifx,"a");
3479 /* if the result is used in an arithmetic operation
3480 then put the result in place */
3481 if (AOP_TYPE(result) != AOP_CRY)
3483 /* leave the result in acc */
3487 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3488 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3489 freeAsmop(result,NULL,ic,TRUE);
3492 /*-----------------------------------------------------------------*/
3493 /* ifxForOp - returns the icode containing the ifx for operand */
3494 /*-----------------------------------------------------------------*/
3495 static iCode *ifxForOp ( operand *op, iCode *ic )
3497 /* if true symbol then needs to be assigned */
3498 if (IS_TRUE_SYMOP(op))
3501 /* if this has register type condition and
3502 the next instruction is ifx with the same operand
3503 and live to of the operand is upto the ifx only then */
3505 ic->next->op == IFX &&
3506 IC_COND(ic->next)->key == op->key &&
3507 OP_SYMBOL(op)->liveTo <= ic->next->seq )
3512 /*-----------------------------------------------------------------*/
3513 /* genAndOp - for && operation */
3514 /*-----------------------------------------------------------------*/
3515 static void genAndOp (iCode *ic)
3517 operand *left,*right, *result;
3520 /* note here that && operations that are in an
3521 if statement are taken away by backPatchLabels
3522 only those used in arthmetic operations remain */
3523 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3524 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3525 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3527 /* if both are bit variables */
3528 if (AOP_TYPE(left) == AOP_CRY &&
3529 AOP_TYPE(right) == AOP_CRY ) {
3530 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3531 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3534 tlbl = newiTempLabel(NULL);
3536 emitcode("jz","%05d$",tlbl->key+100);
3538 emitcode("","%05d$:",tlbl->key+100);
3542 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3543 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3544 freeAsmop(result,NULL,ic,TRUE);
3548 /*-----------------------------------------------------------------*/
3549 /* genOrOp - for || operation */
3550 /*-----------------------------------------------------------------*/
3551 static void genOrOp (iCode *ic)
3553 operand *left,*right, *result;
3556 /* note here that || operations that are in an
3557 if statement are taken away by backPatchLabels
3558 only those used in arthmetic operations remain */
3559 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3560 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3561 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3563 /* if both are bit variables */
3564 if (AOP_TYPE(left) == AOP_CRY &&
3565 AOP_TYPE(right) == AOP_CRY ) {
3566 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3567 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
3570 tlbl = newiTempLabel(NULL);
3572 emitcode("jnz","%05d$",tlbl->key+100);
3574 emitcode("","%05d$:",tlbl->key+100);
3578 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3579 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3580 freeAsmop(result,NULL,ic,TRUE);
3583 /*-----------------------------------------------------------------*/
3584 /* isLiteralBit - test if lit == 2^n */
3585 /*-----------------------------------------------------------------*/
3586 int isLiteralBit(unsigned long lit)
3588 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
3589 0x100L,0x200L,0x400L,0x800L,
3590 0x1000L,0x2000L,0x4000L,0x8000L,
3591 0x10000L,0x20000L,0x40000L,0x80000L,
3592 0x100000L,0x200000L,0x400000L,0x800000L,
3593 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
3594 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
3597 for(idx = 0; idx < 32; idx++)
3603 /*-----------------------------------------------------------------*/
3604 /* continueIfTrue - */
3605 /*-----------------------------------------------------------------*/
3606 static void continueIfTrue (iCode *ic)
3609 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3613 /*-----------------------------------------------------------------*/
3615 /*-----------------------------------------------------------------*/
3616 static void jumpIfTrue (iCode *ic)
3619 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3623 /*-----------------------------------------------------------------*/
3624 /* jmpTrueOrFalse - */
3625 /*-----------------------------------------------------------------*/
3626 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
3628 // ugly but optimized by peephole
3630 symbol *nlbl = newiTempLabel(NULL);
3631 emitcode("sjmp","%05d$",nlbl->key+100);
3632 emitcode("","%05d$:",tlbl->key+100);
3633 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3634 emitcode("","%05d$:",nlbl->key+100);
3637 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3638 emitcode("","%05d$:",tlbl->key+100);
3643 /*-----------------------------------------------------------------*/
3644 /* genAnd - code for and */
3645 /*-----------------------------------------------------------------*/
3646 static void genAnd (iCode *ic, iCode *ifx)
3648 operand *left, *right, *result;
3650 unsigned long lit = 0L;
3654 aopOp((left = IC_LEFT(ic)),ic,FALSE);
3655 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3656 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3659 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3661 AOP_TYPE(left), AOP_TYPE(right));
3662 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3664 AOP_SIZE(left), AOP_SIZE(right));
3667 /* if left is a literal & right is not then exchange them */
3668 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3669 AOP_NEEDSACC(left)) {
3670 operand *tmp = right ;
3675 /* if result = right then exchange them */
3676 if(sameRegs(AOP(result),AOP(right))){
3677 operand *tmp = right ;
3682 /* if right is bit then exchange them */
3683 if (AOP_TYPE(right) == AOP_CRY &&
3684 AOP_TYPE(left) != AOP_CRY){
3685 operand *tmp = right ;
3689 if(AOP_TYPE(right) == AOP_LIT)
3690 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3692 size = AOP_SIZE(result);
3695 // result = bit & yy;
3696 if (AOP_TYPE(left) == AOP_CRY){
3697 // c = bit & literal;
3698 if(AOP_TYPE(right) == AOP_LIT){
3700 if(size && sameRegs(AOP(result),AOP(left)))
3703 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3706 if(size && (AOP_TYPE(result) == AOP_CRY)){
3707 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
3710 if((AOP_TYPE(result) == AOP_CRY) && ifx){
3714 emitcode("clr","c");
3717 if (AOP_TYPE(right) == AOP_CRY){
3719 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3720 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3723 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
3725 emitcode("rrc","a");
3726 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3734 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
3735 genIfxJump(ifx, "c");
3739 // if(val & 0xZZ) - size = 0, ifx != FALSE -
3740 // bit = val & 0xZZ - size = 1, ifx = FALSE -
3741 if((AOP_TYPE(right) == AOP_LIT) &&
3742 (AOP_TYPE(result) == AOP_CRY) &&
3743 (AOP_TYPE(left) != AOP_CRY)){
3744 int posbit = isLiteralBit(lit);
3748 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
3751 emitcode("mov","c,acc.%d",posbit&0x07);
3755 sprintf(buffer,"acc.%d",posbit&0x07);
3756 genIfxJump(ifx, buffer);
3761 symbol *tlbl = newiTempLabel(NULL);
3762 int sizel = AOP_SIZE(left);
3764 emitcode("setb","c");
3766 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
3767 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
3769 if((posbit = isLiteralBit(bytelit)) != 0)
3770 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
3772 if(bytelit != 0x0FFL)
3773 emitcode("anl","a,%s",
3774 aopGet(AOP(right),offset,FALSE,TRUE));
3775 emitcode("jnz","%05d$",tlbl->key+100);
3780 // bit = left & literal
3782 emitcode("clr","c");
3783 emitcode("","%05d$:",tlbl->key+100);
3785 // if(left & literal)
3788 jmpTrueOrFalse(ifx, tlbl);
3796 /* if left is same as result */
3797 if(sameRegs(AOP(result),AOP(left))){
3798 for(;size--; offset++) {
3799 if(AOP_TYPE(right) == AOP_LIT){
3800 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
3804 aopPut(AOP(result),zero,offset);
3806 if (IS_AOP_PREG(result)) {
3807 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3808 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
3809 aopPut(AOP(result),"a",offset);
3811 emitcode("anl","%s,%s",
3812 aopGet(AOP(left),offset,FALSE,TRUE),
3813 aopGet(AOP(right),offset,FALSE,FALSE));
3815 if (AOP_TYPE(left) == AOP_ACC)
3816 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
3818 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3819 if (IS_AOP_PREG(result)) {
3820 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
3821 aopPut(AOP(result),"a",offset);
3824 emitcode("anl","%s,a",
3825 aopGet(AOP(left),offset,FALSE,TRUE));
3830 // left & result in different registers
3831 if(AOP_TYPE(result) == AOP_CRY){
3833 // if(size), result in bit
3834 // if(!size && ifx), conditional oper: if(left & right)
3835 symbol *tlbl = newiTempLabel(NULL);
3836 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
3838 emitcode("setb","c");
3840 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3841 emitcode("anl","a,%s",
3842 aopGet(AOP(left),offset,FALSE,FALSE));
3843 emitcode("jnz","%05d$",tlbl->key+100);
3848 emitcode("","%05d$:",tlbl->key+100);
3851 jmpTrueOrFalse(ifx, tlbl);
3853 for(;(size--);offset++) {
3855 // result = left & right
3856 if(AOP_TYPE(right) == AOP_LIT){
3857 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
3859 aopGet(AOP(left),offset,FALSE,FALSE),
3862 } else if(bytelit == 0){
3863 aopPut(AOP(result),zero,offset);
3867 // faster than result <- left, anl result,right
3868 // and better if result is SFR
3869 if (AOP_TYPE(left) == AOP_ACC)
3870 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
3872 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3873 emitcode("anl","a,%s",
3874 aopGet(AOP(left),offset,FALSE,FALSE));
3876 aopPut(AOP(result),"a",offset);
3882 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3883 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3884 freeAsmop(result,NULL,ic,TRUE);
3887 /*-----------------------------------------------------------------*/
3888 /* genOr - code for or */
3889 /*-----------------------------------------------------------------*/
3890 static void genOr (iCode *ic, iCode *ifx)
3892 operand *left, *right, *result;
3894 unsigned long lit = 0L;
3896 aopOp((left = IC_LEFT(ic)),ic,FALSE);
3897 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3898 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3901 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3903 AOP_TYPE(left), AOP_TYPE(right));
3904 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3906 AOP_SIZE(left), AOP_SIZE(right));
3909 /* if left is a literal & right is not then exchange them */
3910 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3911 AOP_NEEDSACC(left)) {
3912 operand *tmp = right ;
3917 /* if result = right then exchange them */
3918 if(sameRegs(AOP(result),AOP(right))){
3919 operand *tmp = right ;
3924 /* if right is bit then exchange them */
3925 if (AOP_TYPE(right) == AOP_CRY &&
3926 AOP_TYPE(left) != AOP_CRY){
3927 operand *tmp = right ;
3931 if(AOP_TYPE(right) == AOP_LIT)
3932 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3934 size = AOP_SIZE(result);
3938 if (AOP_TYPE(left) == AOP_CRY){
3939 if(AOP_TYPE(right) == AOP_LIT){
3940 // c = bit & literal;
3942 // lit != 0 => result = 1
3943 if(AOP_TYPE(result) == AOP_CRY){
3945 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
3947 continueIfTrue(ifx);
3950 emitcode("setb","c");
3952 // lit == 0 => result = left
3953 if(size && sameRegs(AOP(result),AOP(left)))
3955 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3958 if (AOP_TYPE(right) == AOP_CRY){
3960 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3961 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
3965 symbol *tlbl = newiTempLabel(NULL);
3966 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
3967 emitcode("setb","c");
3968 emitcode("jb","%s,%05d$",
3969 AOP(left)->aopu.aop_dir,tlbl->key+100);
3971 emitcode("jnz","%05d$",tlbl->key+100);
3972 if((AOP_TYPE(result) == AOP_CRY) && ifx){
3973 jmpTrueOrFalse(ifx, tlbl);
3977 emitcode("","%05d$:",tlbl->key+100);
3986 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
3987 genIfxJump(ifx, "c");
3991 // if(val | 0xZZ) - size = 0, ifx != FALSE -
3992 // bit = val | 0xZZ - size = 1, ifx = FALSE -
3993 if((AOP_TYPE(right) == AOP_LIT) &&
3994 (AOP_TYPE(result) == AOP_CRY) &&
3995 (AOP_TYPE(left) != AOP_CRY)){
3999 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4001 continueIfTrue(ifx);
4004 // lit = 0, result = boolean(left)
4006 emitcode("setb","c");
4009 symbol *tlbl = newiTempLabel(NULL);
4010 emitcode("jnz","%05d$",tlbl->key+100);
4012 emitcode("","%05d$:",tlbl->key+100);
4014 genIfxJump (ifx,"a");
4022 /* if left is same as result */
4023 if(sameRegs(AOP(result),AOP(left))){
4024 for(;size--; offset++) {
4025 if(AOP_TYPE(right) == AOP_LIT){
4026 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4029 if (IS_AOP_PREG(left)) {
4030 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4031 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4032 aopPut(AOP(result),"a",offset);
4034 emitcode("orl","%s,%s",
4035 aopGet(AOP(left),offset,FALSE,TRUE),
4036 aopGet(AOP(right),offset,FALSE,FALSE));
4038 if (AOP_TYPE(left) == AOP_ACC)
4039 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4041 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4042 if (IS_AOP_PREG(left)) {
4043 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4044 aopPut(AOP(result),"a",offset);
4046 emitcode("orl","%s,a",
4047 aopGet(AOP(left),offset,FALSE,TRUE));
4052 // left & result in different registers
4053 if(AOP_TYPE(result) == AOP_CRY){
4055 // if(size), result in bit
4056 // if(!size && ifx), conditional oper: if(left | right)
4057 symbol *tlbl = newiTempLabel(NULL);
4058 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4060 emitcode("setb","c");
4062 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4063 emitcode("orl","a,%s",
4064 aopGet(AOP(left),offset,FALSE,FALSE));
4065 emitcode("jnz","%05d$",tlbl->key+100);
4070 emitcode("","%05d$:",tlbl->key+100);
4073 jmpTrueOrFalse(ifx, tlbl);
4074 } else for(;(size--);offset++){
4076 // result = left & right
4077 if(AOP_TYPE(right) == AOP_LIT){
4078 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4080 aopGet(AOP(left),offset,FALSE,FALSE),
4085 // faster than result <- left, anl result,right
4086 // and better if result is SFR
4087 if (AOP_TYPE(left) == AOP_ACC)
4088 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4090 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4091 emitcode("orl","a,%s",
4092 aopGet(AOP(left),offset,FALSE,FALSE));
4094 aopPut(AOP(result),"a",offset);
4099 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4100 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4101 freeAsmop(result,NULL,ic,TRUE);
4104 /*-----------------------------------------------------------------*/
4105 /* genXor - code for xclusive or */
4106 /*-----------------------------------------------------------------*/
4107 static void genXor (iCode *ic, iCode *ifx)
4109 operand *left, *right, *result;
4111 unsigned long lit = 0L;
4113 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4114 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4115 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4118 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4120 AOP_TYPE(left), AOP_TYPE(right));
4121 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4123 AOP_SIZE(left), AOP_SIZE(right));
4126 /* if left is a literal & right is not ||
4127 if left needs acc & right does not */
4128 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4129 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4130 operand *tmp = right ;
4135 /* if result = right then exchange them */
4136 if(sameRegs(AOP(result),AOP(right))){
4137 operand *tmp = right ;
4142 /* if right is bit then exchange them */
4143 if (AOP_TYPE(right) == AOP_CRY &&
4144 AOP_TYPE(left) != AOP_CRY){
4145 operand *tmp = right ;
4149 if(AOP_TYPE(right) == AOP_LIT)
4150 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4152 size = AOP_SIZE(result);
4156 if (AOP_TYPE(left) == AOP_CRY){
4157 if(AOP_TYPE(right) == AOP_LIT){
4158 // c = bit & literal;
4160 // lit>>1 != 0 => result = 1
4161 if(AOP_TYPE(result) == AOP_CRY){
4163 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4165 continueIfTrue(ifx);
4168 emitcode("setb","c");
4172 // lit == 0, result = left
4173 if(size && sameRegs(AOP(result),AOP(left)))
4175 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4177 // lit == 1, result = not(left)
4178 if(size && sameRegs(AOP(result),AOP(left))){
4179 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4182 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4183 emitcode("cpl","c");
4190 symbol *tlbl = newiTempLabel(NULL);
4191 if (AOP_TYPE(right) == AOP_CRY){
4193 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4196 int sizer = AOP_SIZE(right);
4198 // if val>>1 != 0, result = 1
4199 emitcode("setb","c");
4201 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
4203 // test the msb of the lsb
4204 emitcode("anl","a,#0xfe");
4205 emitcode("jnz","%05d$",tlbl->key+100);
4208 emitcode("rrc","a");
4210 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4211 emitcode("cpl","c");
4212 emitcode("","%05d$:",(tlbl->key+100));
4219 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4220 genIfxJump(ifx, "c");
4224 if(sameRegs(AOP(result),AOP(left))){
4225 /* if left is same as result */
4226 for(;size--; offset++) {
4227 if(AOP_TYPE(right) == AOP_LIT){
4228 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4231 if (IS_AOP_PREG(left)) {
4232 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4233 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4234 aopPut(AOP(result),"a",offset);
4236 emitcode("xrl","%s,%s",
4237 aopGet(AOP(left),offset,FALSE,TRUE),
4238 aopGet(AOP(right),offset,FALSE,FALSE));
4240 if (AOP_TYPE(left) == AOP_ACC)
4241 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4243 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4244 if (IS_AOP_PREG(left)) {
4245 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4246 aopPut(AOP(result),"a",offset);
4248 emitcode("xrl","%s,a",
4249 aopGet(AOP(left),offset,FALSE,TRUE));
4254 // left & result in different registers
4255 if(AOP_TYPE(result) == AOP_CRY){
4257 // if(size), result in bit
4258 // if(!size && ifx), conditional oper: if(left ^ right)
4259 symbol *tlbl = newiTempLabel(NULL);
4260 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4262 emitcode("setb","c");
4264 if((AOP_TYPE(right) == AOP_LIT) &&
4265 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4266 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4268 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4269 emitcode("xrl","a,%s",
4270 aopGet(AOP(left),offset,FALSE,FALSE));
4272 emitcode("jnz","%05d$",tlbl->key+100);
4277 emitcode("","%05d$:",tlbl->key+100);
4280 jmpTrueOrFalse(ifx, tlbl);
4281 } else for(;(size--);offset++){
4283 // result = left & right
4284 if(AOP_TYPE(right) == AOP_LIT){
4285 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4287 aopGet(AOP(left),offset,FALSE,FALSE),
4292 // faster than result <- left, anl result,right
4293 // and better if result is SFR
4294 if (AOP_TYPE(left) == AOP_ACC)
4295 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4297 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4298 emitcode("xrl","a,%s",
4299 aopGet(AOP(left),offset,FALSE,TRUE));
4301 aopPut(AOP(result),"a",offset);
4306 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4307 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4308 freeAsmop(result,NULL,ic,TRUE);
4311 /*-----------------------------------------------------------------*/
4312 /* genInline - write the inline code out */
4313 /*-----------------------------------------------------------------*/
4314 static void genInline (iCode *ic)
4316 char buffer[MAX_INLINEASM];
4320 inLine += (!options.asmpeep);
4321 strcpy(buffer,IC_INLINE(ic));
4323 /* emit each line as a code */
4342 /* emitcode("",buffer); */
4343 inLine -= (!options.asmpeep);
4346 /*-----------------------------------------------------------------*/
4347 /* genRRC - rotate right with carry */
4348 /*-----------------------------------------------------------------*/
4349 static void genRRC (iCode *ic)
4351 operand *left , *result ;
4352 int size, offset = 0;
4355 /* rotate right with carry */
4357 result=IC_RESULT(ic);
4358 aopOp (left,ic,FALSE);
4359 aopOp (result,ic,FALSE);
4361 /* move it to the result */
4362 size = AOP_SIZE(result);
4366 l = aopGet(AOP(left),offset,FALSE,FALSE);
4368 emitcode("rrc","a");
4369 if (AOP_SIZE(result) > 1)
4370 aopPut(AOP(result),"a",offset--);
4372 /* now we need to put the carry into the
4373 highest order byte of the result */
4374 if (AOP_SIZE(result) > 1) {
4375 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
4378 emitcode("mov","acc.7,c");
4379 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
4380 freeAsmop(left,NULL,ic,TRUE);
4381 freeAsmop(result,NULL,ic,TRUE);
4384 /*-----------------------------------------------------------------*/
4385 /* genRLC - generate code for rotate left with carry */
4386 /*-----------------------------------------------------------------*/
4387 static void genRLC (iCode *ic)
4389 operand *left , *result ;
4390 int size, offset = 0;
4393 /* rotate right with carry */
4395 result=IC_RESULT(ic);
4396 aopOp (left,ic,FALSE);
4397 aopOp (result,ic,FALSE);
4399 /* move it to the result */
4400 size = AOP_SIZE(result);
4403 l = aopGet(AOP(left),offset,FALSE,FALSE);
4405 emitcode("add","a,acc");
4406 if (AOP_SIZE(result) > 1)
4407 aopPut(AOP(result),"a",offset++);
4409 l = aopGet(AOP(left),offset,FALSE,FALSE);
4411 emitcode("rlc","a");
4412 if (AOP_SIZE(result) > 1)
4413 aopPut(AOP(result),"a",offset++);
4416 /* now we need to put the carry into the
4417 highest order byte of the result */
4418 if (AOP_SIZE(result) > 1) {
4419 l = aopGet(AOP(result),0,FALSE,FALSE);
4422 emitcode("mov","acc.0,c");
4423 aopPut(AOP(result),"a",0);
4424 freeAsmop(left,NULL,ic,TRUE);
4425 freeAsmop(result,NULL,ic,TRUE);
4428 /*-----------------------------------------------------------------*/
4429 /* genGetHbit - generates code get highest order bit */
4430 /*-----------------------------------------------------------------*/
4431 static void genGetHbit (iCode *ic)
4433 operand *left, *result;
4435 result=IC_RESULT(ic);
4436 aopOp (left,ic,FALSE);
4437 aopOp (result,ic,FALSE);
4439 /* get the highest order byte into a */
4440 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
4441 if(AOP_TYPE(result) == AOP_CRY){
4442 emitcode("rlc","a");
4447 emitcode("anl","a,#0x01");
4452 freeAsmop(left,NULL,ic,TRUE);
4453 freeAsmop(result,NULL,ic,TRUE);
4456 /*-----------------------------------------------------------------*/
4457 /* AccRol - rotate left accumulator by known count */
4458 /*-----------------------------------------------------------------*/
4459 static void AccRol (int shCount)
4461 shCount &= 0x0007; // shCount : 0..7
4473 emitcode("swap","a");
4477 emitcode("swap","a");
4480 emitcode("swap","a");
4493 /*-----------------------------------------------------------------*/
4494 /* AccLsh - left shift accumulator by known count */
4495 /*-----------------------------------------------------------------*/
4496 static void AccLsh (int shCount)
4500 emitcode("add","a,acc");
4503 emitcode("add","a,acc");
4504 emitcode("add","a,acc");
4506 /* rotate left accumulator */
4508 /* and kill the lower order bits */
4509 emitcode("anl","a,#0x%02x", SLMask[shCount]);
4514 /*-----------------------------------------------------------------*/
4515 /* AccRsh - right shift accumulator by known count */
4516 /*-----------------------------------------------------------------*/
4517 static void AccRsh (int shCount)
4522 emitcode("rrc","a");
4524 /* rotate right accumulator */
4525 AccRol(8 - shCount);
4526 /* and kill the higher order bits */
4527 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4532 /*-----------------------------------------------------------------*/
4533 /* AccSRsh - signed right shift accumulator by known count */
4534 /*-----------------------------------------------------------------*/
4535 static void AccSRsh (int shCount)
4540 emitcode("mov","c,acc.7");
4541 emitcode("rrc","a");
4542 } else if(shCount == 2){
4543 emitcode("mov","c,acc.7");
4544 emitcode("rrc","a");
4545 emitcode("mov","c,acc.7");
4546 emitcode("rrc","a");
4548 tlbl = newiTempLabel(NULL);
4549 /* rotate right accumulator */
4550 AccRol(8 - shCount);
4551 /* and kill the higher order bits */
4552 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4553 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4554 emitcode("orl","a,#0x%02x",
4555 (unsigned char)~SRMask[shCount]);
4556 emitcode("","%05d$:",tlbl->key+100);
4561 /*-----------------------------------------------------------------*/
4562 /* shiftR1Left2Result - shift right one byte from left to result */
4563 /*-----------------------------------------------------------------*/
4564 static void shiftR1Left2Result (operand *left, int offl,
4565 operand *result, int offr,
4566 int shCount, int sign)
4568 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4569 /* shift right accumulator */
4574 aopPut(AOP(result),"a",offr);
4577 /*-----------------------------------------------------------------*/
4578 /* shiftL1Left2Result - shift left one byte from left to result */
4579 /*-----------------------------------------------------------------*/
4580 static void shiftL1Left2Result (operand *left, int offl,
4581 operand *result, int offr, int shCount)
4584 l = aopGet(AOP(left),offl,FALSE,FALSE);
4586 /* shift left accumulator */
4588 aopPut(AOP(result),"a",offr);
4591 /*-----------------------------------------------------------------*/
4592 /* movLeft2Result - move byte from left to result */
4593 /*-----------------------------------------------------------------*/
4594 static void movLeft2Result (operand *left, int offl,
4595 operand *result, int offr, int sign)
4598 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
4599 l = aopGet(AOP(left),offl,FALSE,FALSE);
4601 if (*l == '@' && (IS_AOP_PREG(result))) {
4602 emitcode("mov","a,%s",l);
4603 aopPut(AOP(result),"a",offr);
4606 aopPut(AOP(result),l,offr);
4608 /* MSB sign in acc.7 ! */
4609 if(getDataSize(left) == offl+1){
4610 emitcode("mov","a,%s",l);
4611 aopPut(AOP(result),"a",offr);
4618 /*-----------------------------------------------------------------*/
4619 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
4620 /*-----------------------------------------------------------------*/
4621 static void AccAXRrl1 (char *x)
4623 emitcode("rrc","a");
4624 emitcode("xch","a,%s", x);
4625 emitcode("rrc","a");
4626 emitcode("xch","a,%s", x);
4629 /*-----------------------------------------------------------------*/
4630 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
4631 /*-----------------------------------------------------------------*/
4632 static void AccAXLrl1 (char *x)
4634 emitcode("xch","a,%s",x);
4635 emitcode("rlc","a");
4636 emitcode("xch","a,%s",x);
4637 emitcode("rlc","a");
4640 /*-----------------------------------------------------------------*/
4641 /* AccAXLsh1 - left shift a:x<-0 by 1 */
4642 /*-----------------------------------------------------------------*/
4643 static void AccAXLsh1 (char *x)
4645 emitcode("xch","a,%s",x);
4646 emitcode("add","a,acc");
4647 emitcode("xch","a,%s",x);
4648 emitcode("rlc","a");
4651 /*-----------------------------------------------------------------*/
4652 /* AccAXLsh - left shift a:x by known count (0..7) */
4653 /*-----------------------------------------------------------------*/
4654 static void AccAXLsh (char *x, int shCount)
4668 case 5 : // AAAAABBB:CCCCCDDD
4669 AccRol(shCount); // BBBAAAAA:CCCCCDDD
4670 emitcode("anl","a,#0x%02x",
4671 SLMask[shCount]); // BBB00000:CCCCCDDD
4672 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
4673 AccRol(shCount); // DDDCCCCC:BBB00000
4674 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
4675 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
4676 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
4677 emitcode("anl","a,#0x%02x",
4678 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
4679 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
4680 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
4682 case 6 : // AAAAAABB:CCCCCCDD
4683 emitcode("anl","a,#0x%02x",
4684 SRMask[shCount]); // 000000BB:CCCCCCDD
4685 emitcode("mov","c,acc.0"); // c = B
4686 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
4687 AccAXRrl1(x); // BCCCCCCD:D000000B
4688 AccAXRrl1(x); // BBCCCCCC:DD000000
4690 case 7 : // a:x <<= 7
4691 emitcode("anl","a,#0x%02x",
4692 SRMask[shCount]); // 0000000B:CCCCCCCD
4693 emitcode("mov","c,acc.0"); // c = B
4694 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
4695 AccAXRrl1(x); // BCCCCCCC:D0000000
4702 /*-----------------------------------------------------------------*/
4703 /* AccAXRsh - right shift a:x known count (0..7) */
4704 /*-----------------------------------------------------------------*/
4705 static void AccAXRsh (char *x, int shCount)
4712 AccAXRrl1(x); // 0->a:x
4716 AccAXRrl1(x); // 0->a:x
4718 AccAXRrl1(x); // 0->a:x
4722 case 5 : // AAAAABBB:CCCCCDDD = a:x
4723 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
4724 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
4725 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
4726 emitcode("anl","a,#0x%02x",
4727 SRMask[shCount]); // 000CCCCC:BBBAAAAA
4728 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
4729 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
4730 emitcode("anl","a,#0x%02x",
4731 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
4732 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
4733 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
4734 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
4736 case 6 : // AABBBBBB:CCDDDDDD
4737 emitcode("mov","c,acc.7");
4738 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
4739 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
4740 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
4741 emitcode("anl","a,#0x%02x",
4742 SRMask[shCount]); // 000000AA:BBBBBBCC
4744 case 7 : // ABBBBBBB:CDDDDDDD
4745 emitcode("mov","c,acc.7"); // c = A
4746 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
4747 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
4748 emitcode("anl","a,#0x%02x",
4749 SRMask[shCount]); // 0000000A:BBBBBBBC
4756 /*-----------------------------------------------------------------*/
4757 /* AccAXRshS - right shift signed a:x known count (0..7) */
4758 /*-----------------------------------------------------------------*/
4759 static void AccAXRshS (char *x, int shCount)
4766 emitcode("mov","c,acc.7");
4767 AccAXRrl1(x); // s->a:x
4770 emitcode("mov","c,acc.7");
4771 AccAXRrl1(x); // s->a:x
4772 emitcode("mov","c,acc.7");
4773 AccAXRrl1(x); // s->a:x
4777 case 5 : // AAAAABBB:CCCCCDDD = a:x
4778 tlbl = newiTempLabel(NULL);
4779 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
4780 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
4781 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
4782 emitcode("anl","a,#0x%02x",
4783 SRMask[shCount]); // 000CCCCC:BBBAAAAA
4784 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
4785 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
4786 emitcode("anl","a,#0x%02x",
4787 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
4788 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
4789 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
4790 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
4791 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4792 emitcode("orl","a,#0x%02x",
4793 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
4794 emitcode("","%05d$:",tlbl->key+100);
4795 break; // SSSSAAAA:BBBCCCCC
4796 case 6 : // AABBBBBB:CCDDDDDD
4797 tlbl = newiTempLabel(NULL);
4798 emitcode("mov","c,acc.7");
4799 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
4800 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
4801 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
4802 emitcode("anl","a,#0x%02x",
4803 SRMask[shCount]); // 000000AA:BBBBBBCC
4804 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4805 emitcode("orl","a,#0x%02x",
4806 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
4807 emitcode("","%05d$:",tlbl->key+100);
4809 case 7 : // ABBBBBBB:CDDDDDDD
4810 tlbl = newiTempLabel(NULL);
4811 emitcode("mov","c,acc.7"); // c = A
4812 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
4813 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
4814 emitcode("anl","a,#0x%02x",
4815 SRMask[shCount]); // 0000000A:BBBBBBBC
4816 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4817 emitcode("orl","a,#0x%02x",
4818 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
4819 emitcode("","%05d$:",tlbl->key+100);
4826 /*-----------------------------------------------------------------*/
4827 /* shiftL2Left2Result - shift left two bytes from left to result */
4828 /*-----------------------------------------------------------------*/
4829 static void shiftL2Left2Result (operand *left, int offl,
4830 operand *result, int offr, int shCount)
4832 if(sameRegs(AOP(result), AOP(left)) &&
4833 ((offl + MSB16) == offr)){
4834 /* don't crash result[offr] */
4835 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4836 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4838 movLeft2Result(left,offl, result, offr, 0);
4839 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4841 /* ax << shCount (x = lsb(result))*/
4842 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
4843 aopPut(AOP(result),"a",offr+MSB16);
4847 /*-----------------------------------------------------------------*/
4848 /* shiftR2Left2Result - shift right two bytes from left to result */
4849 /*-----------------------------------------------------------------*/
4850 static void shiftR2Left2Result (operand *left, int offl,
4851 operand *result, int offr,
4852 int shCount, int sign)
4854 if(sameRegs(AOP(result), AOP(left)) &&
4855 ((offl + MSB16) == offr)){
4856 /* don't crash result[offr] */
4857 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4858 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4860 movLeft2Result(left,offl, result, offr, 0);
4861 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4863 /* a:x >> shCount (x = lsb(result))*/
4865 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
4867 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
4868 if(getDataSize(result) > 1)
4869 aopPut(AOP(result),"a",offr+MSB16);
4872 /*-----------------------------------------------------------------*/
4873 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
4874 /*-----------------------------------------------------------------*/
4875 static void shiftLLeftOrResult (operand *left, int offl,
4876 operand *result, int offr, int shCount)
4878 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4879 /* shift left accumulator */
4881 /* or with result */
4882 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
4883 /* back to result */
4884 aopPut(AOP(result),"a",offr);
4887 /*-----------------------------------------------------------------*/
4888 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
4889 /*-----------------------------------------------------------------*/
4890 static void shiftRLeftOrResult (operand *left, int offl,
4891 operand *result, int offr, int shCount)
4893 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4894 /* shift right accumulator */
4896 /* or with result */
4897 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
4898 /* back to result */
4899 aopPut(AOP(result),"a",offr);
4902 /*-----------------------------------------------------------------*/
4903 /* genlshOne - left shift a one byte quantity by known count */
4904 /*-----------------------------------------------------------------*/
4905 static void genlshOne (operand *result, operand *left, int shCount)
4907 shiftL1Left2Result(left, LSB, result, LSB, shCount);
4910 /*-----------------------------------------------------------------*/
4911 /* genlshTwo - left shift two bytes by known amount != 0 */
4912 /*-----------------------------------------------------------------*/
4913 static void genlshTwo (operand *result,operand *left, int shCount)
4915 int size = AOP_SIZE(result);
4920 /* if shCount >= 8 */
4926 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
4928 movLeft2Result(left, LSB, result, MSB16, 0);
4930 aopPut(AOP(result),zero,LSB);
4933 /* 1 <= shCount <= 7 */
4936 shiftL1Left2Result(left, LSB, result, LSB, shCount);
4938 shiftL2Left2Result(left, LSB, result, LSB, shCount);
4942 /*-----------------------------------------------------------------*/
4943 /* shiftLLong - shift left one long from left to result */
4944 /* offl = LSB or MSB16 */
4945 /*-----------------------------------------------------------------*/
4946 static void shiftLLong (operand *left, operand *result, int offr )
4949 int size = AOP_SIZE(result);
4951 if(size >= LSB+offr){
4952 l = aopGet(AOP(left),LSB,FALSE,FALSE);
4954 emitcode("add","a,acc");
4955 if (sameRegs(AOP(left),AOP(result)) &&
4956 size >= MSB16+offr && offr != LSB )
4957 emitcode("xch","a,%s",
4958 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
4960 aopPut(AOP(result),"a",LSB+offr);
4963 if(size >= MSB16+offr){
4964 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
4965 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
4968 emitcode("rlc","a");
4969 if (sameRegs(AOP(left),AOP(result)) &&
4970 size >= MSB24+offr && offr != LSB)
4971 emitcode("xch","a,%s",
4972 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
4974 aopPut(AOP(result),"a",MSB16+offr);
4977 if(size >= MSB24+offr){
4978 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
4979 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
4982 emitcode("rlc","a");
4983 if (sameRegs(AOP(left),AOP(result)) &&
4984 size >= MSB32+offr && offr != LSB )
4985 emitcode("xch","a,%s",
4986 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
4988 aopPut(AOP(result),"a",MSB24+offr);
4991 if(size > MSB32+offr){
4992 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
4993 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
4996 emitcode("rlc","a");
4997 aopPut(AOP(result),"a",MSB32+offr);
5000 aopPut(AOP(result),zero,LSB);
5003 /*-----------------------------------------------------------------*/
5004 /* genlshFour - shift four byte by a known amount != 0 */
5005 /*-----------------------------------------------------------------*/
5006 static void genlshFour (operand *result, operand *left, int shCount)
5010 size = AOP_SIZE(result);
5012 /* if shifting more that 3 bytes */
5013 if (shCount >= 24 ) {
5016 /* lowest order of left goes to the highest
5017 order of the destination */
5018 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5020 movLeft2Result(left, LSB, result, MSB32, 0);
5021 aopPut(AOP(result),zero,LSB);
5022 aopPut(AOP(result),zero,MSB16);
5023 aopPut(AOP(result),zero,MSB32);
5027 /* more than two bytes */
5028 else if ( shCount >= 16 ) {
5029 /* lower order two bytes goes to higher order two bytes */
5031 /* if some more remaining */
5033 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5035 movLeft2Result(left, MSB16, result, MSB32, 0);
5036 movLeft2Result(left, LSB, result, MSB24, 0);
5038 aopPut(AOP(result),zero,MSB16);
5039 aopPut(AOP(result),zero,LSB);
5043 /* if more than 1 byte */
5044 else if ( shCount >= 8 ) {
5045 /* lower order three bytes goes to higher order three bytes */
5049 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5051 movLeft2Result(left, LSB, result, MSB16, 0);
5053 else{ /* size = 4 */
5055 movLeft2Result(left, MSB24, result, MSB32, 0);
5056 movLeft2Result(left, MSB16, result, MSB24, 0);
5057 movLeft2Result(left, LSB, result, MSB16, 0);
5058 aopPut(AOP(result),zero,LSB);
5060 else if(shCount == 1)
5061 shiftLLong(left, result, MSB16);
5063 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5064 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5065 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5066 aopPut(AOP(result),zero,LSB);
5071 /* 1 <= shCount <= 7 */
5072 else if(shCount <= 2){
5073 shiftLLong(left, result, LSB);
5075 shiftLLong(result, result, LSB);
5077 /* 3 <= shCount <= 7, optimize */
5079 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5080 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5081 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5085 /*-----------------------------------------------------------------*/
5086 /* genLeftShiftLiteral - left shifting by known count */
5087 /*-----------------------------------------------------------------*/
5088 static void genLeftShiftLiteral (operand *left,
5093 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5096 freeAsmop(right,NULL,ic,TRUE);
5098 aopOp(left,ic,FALSE);
5099 aopOp(result,ic,FALSE);
5101 size = getSize(operandType(result));
5104 emitcode("; shift left ","result %d, left %d",size,
5108 /* I suppose that the left size >= result size */
5111 movLeft2Result(left, size, result, size, 0);
5115 else if(shCount >= (size * 8))
5117 aopPut(AOP(result),zero,size);
5121 genlshOne (result,left,shCount);
5126 genlshTwo (result,left,shCount);
5130 genlshFour (result,left,shCount);
5134 freeAsmop(left,NULL,ic,TRUE);
5135 freeAsmop(result,NULL,ic,TRUE);
5138 /*-----------------------------------------------------------------*/
5139 /* genLeftShift - generates code for left shifting */
5140 /*-----------------------------------------------------------------*/
5141 static void genLeftShift (iCode *ic)
5143 operand *left,*right, *result;
5146 symbol *tlbl , *tlbl1;
5148 right = IC_RIGHT(ic);
5150 result = IC_RESULT(ic);
5152 aopOp(right,ic,FALSE);
5154 /* if the shift count is known then do it
5155 as efficiently as possible */
5156 if (AOP_TYPE(right) == AOP_LIT) {
5157 genLeftShiftLiteral (left,right,result,ic);
5161 /* shift count is unknown then we have to form
5162 a loop get the loop count in B : Note: we take
5163 only the lower order byte since shifting
5164 more that 32 bits make no sense anyway, ( the
5165 largest size of an object can be only 32 bits ) */
5167 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5168 emitcode("inc","b");
5169 freeAsmop (right,NULL,ic,TRUE);
5170 aopOp(left,ic,FALSE);
5171 aopOp(result,ic,FALSE);
5173 /* now move the left to the result if they are not the
5175 if (!sameRegs(AOP(left),AOP(result)) &&
5176 AOP_SIZE(result) > 1) {
5178 size = AOP_SIZE(result);
5181 l = aopGet(AOP(left),offset,FALSE,TRUE);
5182 if (*l == '@' && (IS_AOP_PREG(result))) {
5184 emitcode("mov","a,%s",l);
5185 aopPut(AOP(result),"a",offset);
5187 aopPut(AOP(result),l,offset);
5192 tlbl = newiTempLabel(NULL);
5193 size = AOP_SIZE(result);
5195 tlbl1 = newiTempLabel(NULL);
5197 /* if it is only one byte then */
5199 symbol *tlbl1 = newiTempLabel(NULL);
5201 l = aopGet(AOP(left),0,FALSE,FALSE);
5203 emitcode("sjmp","%05d$",tlbl1->key+100);
5204 emitcode("","%05d$:",tlbl->key+100);
5205 emitcode("add","a,acc");
5206 emitcode("","%05d$:",tlbl1->key+100);
5207 emitcode("djnz","b,%05d$",tlbl->key+100);
5208 aopPut(AOP(result),"a",0);
5212 reAdjustPreg(AOP(result));
5214 emitcode("sjmp","%05d$",tlbl1->key+100);
5215 emitcode("","%05d$:",tlbl->key+100);
5216 l = aopGet(AOP(result),offset,FALSE,FALSE);
5218 emitcode("add","a,acc");
5219 aopPut(AOP(result),"a",offset++);
5221 l = aopGet(AOP(result),offset,FALSE,FALSE);
5223 emitcode("rlc","a");
5224 aopPut(AOP(result),"a",offset++);
5226 reAdjustPreg(AOP(result));
5228 emitcode("","%05d$:",tlbl1->key+100);
5229 emitcode("djnz","b,%05d$",tlbl->key+100);
5231 freeAsmop(left,NULL,ic,TRUE);
5232 freeAsmop(result,NULL,ic,TRUE);
5235 /*-----------------------------------------------------------------*/
5236 /* genrshOne - right shift a one byte quantity by known count */
5237 /*-----------------------------------------------------------------*/
5238 static void genrshOne (operand *result, operand *left,
5239 int shCount, int sign)
5241 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
5244 /*-----------------------------------------------------------------*/
5245 /* genrshTwo - right shift two bytes by known amount != 0 */
5246 /*-----------------------------------------------------------------*/
5247 static void genrshTwo (operand *result,operand *left,
5248 int shCount, int sign)
5250 /* if shCount >= 8 */
5254 shiftR1Left2Result(left, MSB16, result, LSB,
5257 movLeft2Result(left, MSB16, result, LSB, sign);
5258 addSign(result, MSB16, sign);
5261 /* 1 <= shCount <= 7 */
5263 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
5266 /*-----------------------------------------------------------------*/
5267 /* shiftRLong - shift right one long from left to result */
5268 /* offl = LSB or MSB16 */
5269 /*-----------------------------------------------------------------*/
5270 static void shiftRLong (operand *left, int offl,
5271 operand *result, int sign)
5274 emitcode("clr","c");
5275 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
5277 emitcode("mov","c,acc.7");
5278 emitcode("rrc","a");
5279 aopPut(AOP(result),"a",MSB32-offl);
5281 /* add sign of "a" */
5282 addSign(result, MSB32, sign);
5284 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
5285 emitcode("rrc","a");
5286 aopPut(AOP(result),"a",MSB24-offl);
5288 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
5289 emitcode("rrc","a");
5290 aopPut(AOP(result),"a",MSB16-offl);
5293 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
5294 emitcode("rrc","a");
5295 aopPut(AOP(result),"a",LSB);
5299 /*-----------------------------------------------------------------*/
5300 /* genrshFour - shift four byte by a known amount != 0 */
5301 /*-----------------------------------------------------------------*/
5302 static void genrshFour (operand *result, operand *left,
5303 int shCount, int sign)
5305 /* if shifting more that 3 bytes */
5306 if(shCount >= 24 ) {
5309 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
5311 movLeft2Result(left, MSB32, result, LSB, sign);
5312 addSign(result, MSB16, sign);
5314 else if(shCount >= 16){
5317 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
5319 movLeft2Result(left, MSB24, result, LSB, 0);
5320 movLeft2Result(left, MSB32, result, MSB16, sign);
5322 addSign(result, MSB24, sign);
5324 else if(shCount >= 8){
5327 shiftRLong(left, MSB16, result, sign);
5328 else if(shCount == 0){
5329 movLeft2Result(left, MSB16, result, LSB, 0);
5330 movLeft2Result(left, MSB24, result, MSB16, 0);
5331 movLeft2Result(left, MSB32, result, MSB24, sign);
5332 addSign(result, MSB32, sign);
5335 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
5336 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
5337 /* the last shift is signed */
5338 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
5339 addSign(result, MSB32, sign);
5342 else{ /* 1 <= shCount <= 7 */
5344 shiftRLong(left, LSB, result, sign);
5346 shiftRLong(result, LSB, result, sign);
5349 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
5350 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
5351 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
5356 /*-----------------------------------------------------------------*/
5357 /* genRightShiftLiteral - right shifting by known count */
5358 /*-----------------------------------------------------------------*/
5359 static void genRightShiftLiteral (operand *left,
5365 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5368 freeAsmop(right,NULL,ic,TRUE);
5370 aopOp(left,ic,FALSE);
5371 aopOp(result,ic,FALSE);
5374 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
5378 size = getDataSize(left);
5379 /* test the LEFT size !!! */
5381 /* I suppose that the left size >= result size */
5383 size = getDataSize(result);
5385 movLeft2Result(left, size, result, size, 0);
5388 else if(shCount >= (size * 8)){
5390 /* get sign in acc.7 */
5391 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
5392 addSign(result, LSB, sign);
5396 genrshOne (result,left,shCount,sign);
5400 genrshTwo (result,left,shCount,sign);
5404 genrshFour (result,left,shCount,sign);
5410 freeAsmop(left,NULL,ic,TRUE);
5411 freeAsmop(result,NULL,ic,TRUE);
5415 /*-----------------------------------------------------------------*/
5416 /* genSignedRightShift - right shift of signed number */
5417 /*-----------------------------------------------------------------*/
5418 static void genSignedRightShift (iCode *ic)
5420 operand *right, *left, *result;
5423 symbol *tlbl, *tlbl1 ;
5425 /* we do it the hard way put the shift count in b
5426 and loop thru preserving the sign */
5428 right = IC_RIGHT(ic);
5430 result = IC_RESULT(ic);
5432 aopOp(right,ic,FALSE);
5435 if ( AOP_TYPE(right) == AOP_LIT) {
5436 genRightShiftLiteral (left,right,result,ic,1);
5439 /* shift count is unknown then we have to form
5440 a loop get the loop count in B : Note: we take
5441 only the lower order byte since shifting
5442 more that 32 bits make no sense anyway, ( the
5443 largest size of an object can be only 32 bits ) */
5445 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5446 emitcode("inc","b");
5447 freeAsmop (right,NULL,ic,TRUE);
5448 aopOp(left,ic,FALSE);
5449 aopOp(result,ic,FALSE);
5451 /* now move the left to the result if they are not the
5453 if (!sameRegs(AOP(left),AOP(result)) &&
5454 AOP_SIZE(result) > 1) {
5456 size = AOP_SIZE(result);
5459 l = aopGet(AOP(left),offset,FALSE,TRUE);
5460 if (*l == '@' && IS_AOP_PREG(result)) {
5462 emitcode("mov","a,%s",l);
5463 aopPut(AOP(result),"a",offset);
5465 aopPut(AOP(result),l,offset);
5470 /* mov the highest order bit to OVR */
5471 tlbl = newiTempLabel(NULL);
5472 tlbl1= newiTempLabel(NULL);
5474 size = AOP_SIZE(result);
5476 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
5477 emitcode("rlc","a");
5478 emitcode("mov","ov,c");
5479 /* if it is only one byte then */
5481 l = aopGet(AOP(left),0,FALSE,FALSE);
5483 emitcode("sjmp","%05d$",tlbl1->key+100);
5484 emitcode("","%05d$:",tlbl->key+100);
5485 emitcode("mov","c,ov");
5486 emitcode("rrc","a");
5487 emitcode("","%05d$:",tlbl1->key+100);
5488 emitcode("djnz","b,%05d$",tlbl->key+100);
5489 aopPut(AOP(result),"a",0);
5493 reAdjustPreg(AOP(result));
5494 emitcode("sjmp","%05d$",tlbl1->key+100);
5495 emitcode("","%05d$:",tlbl->key+100);
5496 emitcode("mov","c,ov");
5498 l = aopGet(AOP(result),offset,FALSE,FALSE);
5500 emitcode("rrc","a");
5501 aopPut(AOP(result),"a",offset--);
5503 reAdjustPreg(AOP(result));
5504 emitcode("","%05d$:",tlbl1->key+100);
5505 emitcode("djnz","b,%05d$",tlbl->key+100);
5508 freeAsmop(left,NULL,ic,TRUE);
5509 freeAsmop(result,NULL,ic,TRUE);
5512 /*-----------------------------------------------------------------*/
5513 /* genRightShift - generate code for right shifting */
5514 /*-----------------------------------------------------------------*/
5515 static void genRightShift (iCode *ic)
5517 operand *right, *left, *result;
5521 symbol *tlbl, *tlbl1 ;
5523 /* if signed then we do it the hard way preserve the
5524 sign bit moving it inwards */
5525 retype = getSpec(operandType(IC_RESULT(ic)));
5527 if (!SPEC_USIGN(retype)) {
5528 genSignedRightShift (ic);
5532 /* signed & unsigned types are treated the same : i.e. the
5533 signed is NOT propagated inwards : quoting from the
5534 ANSI - standard : "for E1 >> E2, is equivalent to division
5535 by 2**E2 if unsigned or if it has a non-negative value,
5536 otherwise the result is implementation defined ", MY definition
5537 is that the sign does not get propagated */
5539 right = IC_RIGHT(ic);
5541 result = IC_RESULT(ic);
5543 aopOp(right,ic,FALSE);
5545 /* if the shift count is known then do it
5546 as efficiently as possible */
5547 if (AOP_TYPE(right) == AOP_LIT) {
5548 genRightShiftLiteral (left,right,result,ic, 0);
5552 /* shift count is unknown then we have to form
5553 a loop get the loop count in B : Note: we take
5554 only the lower order byte since shifting
5555 more that 32 bits make no sense anyway, ( the
5556 largest size of an object can be only 32 bits ) */
5558 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5559 emitcode("inc","b");
5560 freeAsmop (right,NULL,ic,TRUE);
5561 aopOp(left,ic,FALSE);
5562 aopOp(result,ic,FALSE);
5564 /* now move the left to the result if they are not the
5566 if (!sameRegs(AOP(left),AOP(result)) &&
5567 AOP_SIZE(result) > 1) {
5569 size = AOP_SIZE(result);
5572 l = aopGet(AOP(left),offset,FALSE,TRUE);
5573 if (*l == '@' && IS_AOP_PREG(result)) {
5575 emitcode("mov","a,%s",l);
5576 aopPut(AOP(result),"a",offset);
5578 aopPut(AOP(result),l,offset);
5583 tlbl = newiTempLabel(NULL);
5584 tlbl1= newiTempLabel(NULL);
5585 size = AOP_SIZE(result);
5588 /* if it is only one byte then */
5590 l = aopGet(AOP(left),0,FALSE,FALSE);
5592 emitcode("sjmp","%05d$",tlbl1->key+100);
5593 emitcode("","%05d$:",tlbl->key+100);
5595 emitcode("rrc","a");
5596 emitcode("","%05d$:",tlbl1->key+100);
5597 emitcode("djnz","b,%05d$",tlbl->key+100);
5598 aopPut(AOP(result),"a",0);
5602 reAdjustPreg(AOP(result));
5603 emitcode("sjmp","%05d$",tlbl1->key+100);
5604 emitcode("","%05d$:",tlbl->key+100);
5607 l = aopGet(AOP(result),offset,FALSE,FALSE);
5609 emitcode("rrc","a");
5610 aopPut(AOP(result),"a",offset--);
5612 reAdjustPreg(AOP(result));
5614 emitcode("","%05d$:",tlbl1->key+100);
5615 emitcode("djnz","b,%05d$",tlbl->key+100);
5618 freeAsmop(left,NULL,ic,TRUE);
5619 freeAsmop(result,NULL,ic,TRUE);
5622 /*-----------------------------------------------------------------*/
5623 /* genUnpackBits - generates code for unpacking bits */
5624 /*-----------------------------------------------------------------*/
5625 static void genUnpackBits (operand *result, char *rname, int ptype)
5632 etype = getSpec(operandType(result));
5634 /* read the first byte */
5639 emitcode("mov","a,@%s",rname);
5643 emitcode("movx","a,@%s",rname);
5647 emitcode("movx","a,@dptr");
5651 emitcode("clr","a");
5652 emitcode("movc","a","@a+dptr");
5656 emitcode("lcall","__gptrget");
5660 /* if we have bitdisplacement then it fits */
5661 /* into this byte completely or if length is */
5662 /* less than a byte */
5663 if ((shCnt = SPEC_BSTR(etype)) ||
5664 (SPEC_BLEN(etype) <= 8)) {
5666 /* shift right acc */
5669 emitcode("anl","a,#0x%02x",
5670 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
5671 aopPut(AOP(result),"a",offset);
5675 /* bit field did not fit in a byte */
5676 rlen = SPEC_BLEN(etype) - 8;
5677 aopPut(AOP(result),"a",offset++);
5684 emitcode("inc","%s",rname);
5685 emitcode("mov","a,@%s",rname);
5689 emitcode("inc","%s",rname);
5690 emitcode("movx","a,@%s",rname);
5694 emitcode("inc","dptr");
5695 emitcode("movx","a,@dptr");
5699 emitcode("clr","a");
5700 emitcode("inc","dptr");
5701 emitcode("movc","a","@a+dptr");
5705 emitcode("inc","dptr");
5706 emitcode("lcall","__gptrget");
5711 /* if we are done */
5715 aopPut(AOP(result),"a",offset++);
5720 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
5721 aopPut(AOP(result),"a",offset);
5728 /*-----------------------------------------------------------------*/
5729 /* genDataPointerGet - generates code when ptr offset is known */
5730 /*-----------------------------------------------------------------*/
5731 static void genDataPointerGet (operand *left,
5737 int size , offset = 0;
5738 aopOp(result,ic,TRUE);
5740 /* get the string representation of the name */
5741 l = aopGet(AOP(left),0,FALSE,TRUE);
5742 size = AOP_SIZE(result);
5745 sprintf(buffer,"(%s + %d)",l+1,offset);
5747 sprintf(buffer,"%s",l+1);
5748 aopPut(AOP(result),buffer,offset++);
5751 freeAsmop(left,NULL,ic,TRUE);
5752 freeAsmop(result,NULL,ic,TRUE);
5755 /*-----------------------------------------------------------------*/
5756 /* genNearPointerGet - emitcode for near pointer fetch */
5757 /*-----------------------------------------------------------------*/
5758 static void genNearPointerGet (operand *left,
5765 link *rtype, *retype;
5766 link *ltype = operandType(left);
5769 rtype = operandType(result);
5770 retype= getSpec(rtype);
5772 aopOp(left,ic,FALSE);
5774 /* if left is rematerialisable and
5775 result is not bit variable type and
5776 the left is pointer to data space i.e
5777 lower 128 bytes of space */
5778 if (AOP_TYPE(left) == AOP_IMMD &&
5779 !IS_BITVAR(retype) &&
5780 DCL_TYPE(ltype) == POINTER) {
5781 genDataPointerGet (left,result,ic);
5785 /* if the value is already in a pointer register
5786 then don't need anything more */
5787 if (!AOP_INPREG(AOP(left))) {
5788 /* otherwise get a free pointer register */
5790 preg = getFreePtr(ic,&aop,FALSE);
5791 emitcode("mov","%s,%s",
5793 aopGet(AOP(left),0,FALSE,TRUE));
5794 rname = preg->name ;
5796 rname = aopGet(AOP(left),0,FALSE,FALSE);
5798 freeAsmop(left,NULL,ic,TRUE);
5799 aopOp (result,ic,FALSE);
5801 /* if bitfield then unpack the bits */
5802 if (IS_BITVAR(retype))
5803 genUnpackBits (result,rname,POINTER);
5805 /* we have can just get the values */
5806 int size = AOP_SIZE(result);
5810 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
5812 emitcode("mov","a,@%s",rname);
5813 aopPut(AOP(result),"a",offset);
5815 sprintf(buffer,"@%s",rname);
5816 aopPut(AOP(result),buffer,offset);
5820 emitcode("inc","%s",rname);
5824 /* now some housekeeping stuff */
5826 /* we had to allocate for this iCode */
5827 freeAsmop(NULL,aop,ic,TRUE);
5829 /* we did not allocate which means left
5830 already in a pointer register, then
5831 if size > 0 && this could be used again
5832 we have to point it back to where it
5834 if (AOP_SIZE(result) > 1 &&
5835 !OP_SYMBOL(left)->remat &&
5836 ( OP_SYMBOL(left)->liveTo > ic->seq ||
5838 int size = AOP_SIZE(result) - 1;
5840 emitcode("dec","%s",rname);
5845 freeAsmop(result,NULL,ic,TRUE);
5849 /*-----------------------------------------------------------------*/
5850 /* genPagedPointerGet - emitcode for paged pointer fetch */
5851 /*-----------------------------------------------------------------*/
5852 static void genPagedPointerGet (operand *left,
5859 link *rtype, *retype;
5861 rtype = operandType(result);
5862 retype= getSpec(rtype);
5864 aopOp(left,ic,FALSE);
5866 /* if the value is already in a pointer register
5867 then don't need anything more */
5868 if (!AOP_INPREG(AOP(left))) {
5869 /* otherwise get a free pointer register */
5871 preg = getFreePtr(ic,&aop,FALSE);
5872 emitcode("mov","%s,%s",
5874 aopGet(AOP(left),0,FALSE,TRUE));
5875 rname = preg->name ;
5877 rname = aopGet(AOP(left),0,FALSE,FALSE);
5879 freeAsmop(left,NULL,ic,TRUE);
5880 aopOp (result,ic,FALSE);
5882 /* if bitfield then unpack the bits */
5883 if (IS_BITVAR(retype))
5884 genUnpackBits (result,rname,PPOINTER);
5886 /* we have can just get the values */
5887 int size = AOP_SIZE(result);
5892 emitcode("movx","a,@%s",rname);
5893 aopPut(AOP(result),"a",offset);
5898 emitcode("inc","%s",rname);
5902 /* now some housekeeping stuff */
5904 /* we had to allocate for this iCode */
5905 freeAsmop(NULL,aop,ic,TRUE);
5907 /* we did not allocate which means left
5908 already in a pointer register, then
5909 if size > 0 && this could be used again
5910 we have to point it back to where it
5912 if (AOP_SIZE(result) > 1 &&
5913 !OP_SYMBOL(left)->remat &&
5914 ( OP_SYMBOL(left)->liveTo > ic->seq ||
5916 int size = AOP_SIZE(result) - 1;
5918 emitcode("dec","%s",rname);
5923 freeAsmop(result,NULL,ic,TRUE);
5928 /*-----------------------------------------------------------------*/
5929 /* genFarPointerGet - gget value from far space */
5930 /*-----------------------------------------------------------------*/
5931 static void genFarPointerGet (operand *left,
5932 operand *result, iCode *ic)
5935 link *retype = getSpec(operandType(result));
5937 aopOp(left,ic,FALSE);
5939 /* if the operand is already in dptr
5940 then we do nothing else we move the value to dptr */
5941 if (AOP_TYPE(left) != AOP_STR) {
5942 /* if this is remateriazable */
5943 if (AOP_TYPE(left) == AOP_IMMD)
5944 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
5945 else { /* we need to get it byte by byte */
5946 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
5947 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
5950 /* so dptr know contains the address */
5951 freeAsmop(left,NULL,ic,TRUE);
5952 aopOp(result,ic,FALSE);
5954 /* if bit then unpack */
5955 if (IS_BITVAR(retype))
5956 genUnpackBits(result,"dptr",FPOINTER);
5958 size = AOP_SIZE(result);
5962 emitcode("movx","a,@dptr");
5963 aopPut(AOP(result),"a",offset++);
5965 emitcode("inc","dptr");
5969 freeAsmop(result,NULL,ic,TRUE);
5972 /*-----------------------------------------------------------------*/
5973 /* emitcodePointerGet - gget value from code space */
5974 /*-----------------------------------------------------------------*/
5975 static void emitcodePointerGet (operand *left,
5976 operand *result, iCode *ic)
5979 link *retype = getSpec(operandType(result));
5981 aopOp(left,ic,FALSE);
5983 /* if the operand is already in dptr
5984 then we do nothing else we move the value to dptr */
5985 if (AOP_TYPE(left) != AOP_STR) {
5986 /* if this is remateriazable */
5987 if (AOP_TYPE(left) == AOP_IMMD)
5988 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
5989 else { /* we need to get it byte by byte */
5990 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
5991 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
5994 /* so dptr know contains the address */
5995 freeAsmop(left,NULL,ic,TRUE);
5996 aopOp(result,ic,FALSE);
5998 /* if bit then unpack */
5999 if (IS_BITVAR(retype))
6000 genUnpackBits(result,"dptr",CPOINTER);
6002 size = AOP_SIZE(result);
6006 emitcode("clr","a");
6007 emitcode("movc","a,@a+dptr");
6008 aopPut(AOP(result),"a",offset++);
6010 emitcode("inc","dptr");
6014 freeAsmop(result,NULL,ic,TRUE);
6017 /*-----------------------------------------------------------------*/
6018 /* genGenPointerGet - gget value from generic pointer space */
6019 /*-----------------------------------------------------------------*/
6020 static void genGenPointerGet (operand *left,
6021 operand *result, iCode *ic)
6024 link *retype = getSpec(operandType(result));
6026 aopOp(left,ic,FALSE);
6028 /* if the operand is already in dptr
6029 then we do nothing else we move the value to dptr */
6030 if (AOP_TYPE(left) != AOP_STR) {
6031 /* if this is remateriazable */
6032 if (AOP_TYPE(left) == AOP_IMMD) {
6033 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6034 emitcode("mov","b,#%d",pointerCode(retype));
6036 else { /* we need to get it byte by byte */
6037 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6038 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6039 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
6042 /* so dptr know contains the address */
6043 freeAsmop(left,NULL,ic,TRUE);
6044 aopOp(result,ic,FALSE);
6046 /* if bit then unpack */
6047 if (IS_BITVAR(retype))
6048 genUnpackBits(result,"dptr",GPOINTER);
6050 size = AOP_SIZE(result);
6054 emitcode("lcall","__gptrget");
6055 aopPut(AOP(result),"a",offset++);
6057 emitcode("inc","dptr");
6061 freeAsmop(result,NULL,ic,TRUE);
6064 /*-----------------------------------------------------------------*/
6065 /* genPointerGet - generate code for pointer get */
6066 /*-----------------------------------------------------------------*/
6067 static void genPointerGet (iCode *ic)
6069 operand *left, *result ;
6074 result = IC_RESULT(ic) ;
6076 /* depending on the type of pointer we need to
6077 move it to the correct pointer register */
6078 type = operandType(left);
6079 etype = getSpec(type);
6080 /* if left is of type of pointer then it is simple */
6081 if (IS_PTR(type) && !IS_FUNC(type->next))
6082 p_type = DCL_TYPE(type);
6085 /* we have to go by the storage class */
6086 if (SPEC_OCLS(etype)->codesp ) {
6090 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
6093 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
6096 if (SPEC_OCLS(etype) == idata )
6102 /* now that we have the pointer type we assign
6103 the pointer values */
6108 genNearPointerGet (left,result,ic);
6112 genPagedPointerGet(left,result,ic);
6116 genFarPointerGet (left,result,ic);
6120 emitcodePointerGet (left,result,ic);
6124 genGenPointerGet (left,result,ic);
6130 /*-----------------------------------------------------------------*/
6131 /* genPackBits - generates code for packed bit storage */
6132 /*-----------------------------------------------------------------*/
6133 static void genPackBits (link *etype ,
6135 char *rname, int p_type)
6143 blen = SPEC_BLEN(etype);
6144 bstr = SPEC_BSTR(etype);
6146 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6149 /* if the bit lenth is less than or */
6150 /* it exactly fits a byte then */
6151 if (SPEC_BLEN(etype) <= 8 ) {
6152 shCount = SPEC_BSTR(etype) ;
6154 /* shift left acc */
6157 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6162 emitcode ("mov","b,a");
6163 emitcode("mov","a,@%s",rname);
6167 emitcode ("mov","b,a");
6168 emitcode("movx","a,@dptr");
6172 emitcode ("push","b");
6173 emitcode ("push","acc");
6174 emitcode ("lcall","__gptrget");
6175 emitcode ("pop","b");
6179 emitcode ("anl","a,#0x%02x",(unsigned char)
6180 ((unsigned char)(0xFF << (blen+bstr)) |
6181 (unsigned char)(0xFF >> (8-bstr)) ) );
6182 emitcode ("orl","a,b");
6183 if (p_type == GPOINTER)
6184 emitcode("pop","b");
6190 emitcode("mov","@%s,a",rname);
6194 emitcode("movx","@dptr,a");
6198 emitcode("lcall","__gptrput");
6203 if ( SPEC_BLEN(etype) <= 8 )
6206 emitcode("inc","%s",rname);
6207 rLen = SPEC_BLEN(etype) ;
6209 /* now generate for lengths greater than one byte */
6212 l = aopGet(AOP(right),offset++,FALSE,TRUE);
6222 emitcode("mov","@%s,a",rname);
6224 emitcode("mov","@%s,%s",rname,l);
6229 emitcode("movx","@dptr,a");
6234 emitcode("lcall","__gptrput");
6237 emitcode ("inc","%s",rname);
6242 /* last last was not complete */
6244 /* save the byte & read byte */
6247 emitcode ("mov","b,a");
6248 emitcode("mov","a,@%s",rname);
6252 emitcode ("mov","b,a");
6253 emitcode("movx","a,@dptr");
6257 emitcode ("push","b");
6258 emitcode ("push","acc");
6259 emitcode ("lcall","__gptrget");
6260 emitcode ("pop","b");
6264 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
6265 emitcode ("orl","a,b");
6268 if (p_type == GPOINTER)
6269 emitcode("pop","b");
6274 emitcode("mov","@%s,a",rname);
6278 emitcode("movx","@dptr,a");
6282 emitcode("lcall","__gptrput");
6286 /*-----------------------------------------------------------------*/
6287 /* genDataPointerSet - remat pointer to data space */
6288 /*-----------------------------------------------------------------*/
6289 static void genDataPointerSet(operand *right,
6293 int size, offset = 0 ;
6294 char *l, buffer[256];
6296 aopOp(right,ic,FALSE);
6298 l = aopGet(AOP(result),0,FALSE,TRUE);
6299 size = AOP_SIZE(right);
6302 sprintf(buffer,"(%s + %d)",l+1,offset);
6304 sprintf(buffer,"%s",l+1);
6305 emitcode("mov","%s,%s",buffer,
6306 aopGet(AOP(right),offset++,FALSE,FALSE));
6309 freeAsmop(right,NULL,ic,TRUE);
6310 freeAsmop(result,NULL,ic,TRUE);
6313 /*-----------------------------------------------------------------*/
6314 /* genNearPointerSet - emitcode for near pointer put */
6315 /*-----------------------------------------------------------------*/
6316 static void genNearPointerSet (operand *right,
6324 link *ptype = operandType(result);
6326 retype= getSpec(operandType(right));
6328 aopOp(result,ic,FALSE);
6330 /* if the result is rematerializable &
6331 in data space & not a bit variable */
6332 if (AOP_TYPE(result) == AOP_IMMD &&
6333 DCL_TYPE(ptype) == POINTER &&
6334 !IS_BITVAR(retype)) {
6335 genDataPointerSet (right,result,ic);
6339 /* if the value is already in a pointer register
6340 then don't need anything more */
6341 if (!AOP_INPREG(AOP(result))) {
6342 /* otherwise get a free pointer register */
6344 preg = getFreePtr(ic,&aop,FALSE);
6345 emitcode("mov","%s,%s",
6347 aopGet(AOP(result),0,FALSE,TRUE));
6348 rname = preg->name ;
6350 rname = aopGet(AOP(result),0,FALSE,FALSE);
6352 freeAsmop(result,NULL,ic,TRUE);
6353 aopOp (right,ic,FALSE);
6355 /* if bitfield then unpack the bits */
6356 if (IS_BITVAR(retype))
6357 genPackBits (retype,right,rname,POINTER);
6359 /* we have can just get the values */
6360 int size = AOP_SIZE(right);
6364 l = aopGet(AOP(right),offset,FALSE,TRUE);
6367 emitcode("mov","@%s,a",rname);
6369 emitcode("mov","@%s,%s",rname,l);
6371 emitcode("inc","%s",rname);
6376 /* now some housekeeping stuff */
6378 /* we had to allocate for this iCode */
6379 freeAsmop(NULL,aop,ic,TRUE);
6381 /* we did not allocate which means left
6382 already in a pointer register, then
6383 if size > 0 && this could be used again
6384 we have to point it back to where it
6386 if (AOP_SIZE(right) > 1 &&
6387 !OP_SYMBOL(result)->remat &&
6388 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6390 int size = AOP_SIZE(right) - 1;
6392 emitcode("dec","%s",rname);
6397 freeAsmop(right,NULL,ic,TRUE);
6402 /*-----------------------------------------------------------------*/
6403 /* genPagedPointerSet - emitcode for Paged pointer put */
6404 /*-----------------------------------------------------------------*/
6405 static void genPagedPointerSet (operand *right,
6414 retype= getSpec(operandType(right));
6416 aopOp(result,ic,FALSE);
6418 /* if the value is already in a pointer register
6419 then don't need anything more */
6420 if (!AOP_INPREG(AOP(result))) {
6421 /* otherwise get a free pointer register */
6423 preg = getFreePtr(ic,&aop,FALSE);
6424 emitcode("mov","%s,%s",
6426 aopGet(AOP(result),0,FALSE,TRUE));
6427 rname = preg->name ;
6429 rname = aopGet(AOP(result),0,FALSE,FALSE);
6431 freeAsmop(result,NULL,ic,TRUE);
6432 aopOp (right,ic,FALSE);
6434 /* if bitfield then unpack the bits */
6435 if (IS_BITVAR(retype))
6436 genPackBits (retype,right,rname,PPOINTER);
6438 /* we have can just get the values */
6439 int size = AOP_SIZE(right);
6443 l = aopGet(AOP(right),offset,FALSE,TRUE);
6446 emitcode("movx","@%s,a",rname);
6449 emitcode("inc","%s",rname);
6455 /* now some housekeeping stuff */
6457 /* we had to allocate for this iCode */
6458 freeAsmop(NULL,aop,ic,TRUE);
6460 /* we did not allocate which means left
6461 already in a pointer register, then
6462 if size > 0 && this could be used again
6463 we have to point it back to where it
6465 if (AOP_SIZE(right) > 1 &&
6466 !OP_SYMBOL(result)->remat &&
6467 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6469 int size = AOP_SIZE(right) - 1;
6471 emitcode("dec","%s",rname);
6476 freeAsmop(right,NULL,ic,TRUE);
6481 /*-----------------------------------------------------------------*/
6482 /* genFarPointerSet - set value from far space */
6483 /*-----------------------------------------------------------------*/
6484 static void genFarPointerSet (operand *right,
6485 operand *result, iCode *ic)
6488 link *retype = getSpec(operandType(right));
6490 aopOp(result,ic,FALSE);
6492 /* if the operand is already in dptr
6493 then we do nothing else we move the value to dptr */
6494 if (AOP_TYPE(result) != AOP_STR) {
6495 /* if this is remateriazable */
6496 if (AOP_TYPE(result) == AOP_IMMD)
6497 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6498 else { /* we need to get it byte by byte */
6499 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6500 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6503 /* so dptr know contains the address */
6504 freeAsmop(result,NULL,ic,TRUE);
6505 aopOp(right,ic,FALSE);
6507 /* if bit then unpack */
6508 if (IS_BITVAR(retype))
6509 genPackBits(retype,right,"dptr",FPOINTER);
6511 size = AOP_SIZE(right);
6515 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6517 emitcode("movx","@dptr,a");
6519 emitcode("inc","dptr");
6523 freeAsmop(right,NULL,ic,TRUE);
6526 /*-----------------------------------------------------------------*/
6527 /* genGenPointerSet - set value from generic pointer space */
6528 /*-----------------------------------------------------------------*/
6529 static void genGenPointerSet (operand *right,
6530 operand *result, iCode *ic)
6533 link *retype = getSpec(operandType(right));
6535 aopOp(result,ic,FALSE);
6537 /* if the operand is already in dptr
6538 then we do nothing else we move the value to dptr */
6539 if (AOP_TYPE(result) != AOP_STR) {
6540 /* if this is remateriazable */
6541 if (AOP_TYPE(result) == AOP_IMMD) {
6542 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6543 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
6545 else { /* we need to get it byte by byte */
6546 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6547 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6548 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
6551 /* so dptr know contains the address */
6552 freeAsmop(result,NULL,ic,TRUE);
6553 aopOp(right,ic,FALSE);
6555 /* if bit then unpack */
6556 if (IS_BITVAR(retype))
6557 genPackBits(retype,right,"dptr",GPOINTER);
6559 size = AOP_SIZE(right);
6563 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6565 emitcode("lcall","__gptrput");
6567 emitcode("inc","dptr");
6571 freeAsmop(right,NULL,ic,TRUE);
6574 /*-----------------------------------------------------------------*/
6575 /* genPointerSet - stores the value into a pointer location */
6576 /*-----------------------------------------------------------------*/
6577 static void genPointerSet (iCode *ic)
6579 operand *right, *result ;
6583 right = IC_RIGHT(ic);
6584 result = IC_RESULT(ic) ;
6586 /* depending on the type of pointer we need to
6587 move it to the correct pointer register */
6588 type = operandType(result);
6589 etype = getSpec(type);
6590 /* if left is of type of pointer then it is simple */
6591 if (IS_PTR(type) && !IS_FUNC(type->next)) {
6592 p_type = DCL_TYPE(type);
6596 /* we have to go by the storage class */
6597 if (SPEC_OCLS(etype)->codesp ) {
6601 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
6604 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
6607 if (SPEC_OCLS(etype) == idata )
6613 /* now that we have the pointer type we assign
6614 the pointer values */
6619 genNearPointerSet (right,result,ic);
6623 genPagedPointerSet (right,result,ic);
6627 genFarPointerSet (right,result,ic);
6631 genGenPointerSet (right,result,ic);
6637 /*-----------------------------------------------------------------*/
6638 /* genIfx - generate code for Ifx statement */
6639 /*-----------------------------------------------------------------*/
6640 static void genIfx (iCode *ic, iCode *popIc)
6642 operand *cond = IC_COND(ic);
6645 aopOp(cond,ic,FALSE);
6647 /* get the value into acc */
6648 if (AOP_TYPE(cond) != AOP_CRY)
6652 /* the result is now in the accumulator */
6653 freeAsmop(cond,NULL,ic,TRUE);
6655 /* if there was something to be popped then do it */
6659 /* if the condition is a bit variable */
6660 if (isbit && IS_ITEMP(cond) &&
6662 genIfxJump(ic,SPIL_LOC(cond)->rname);
6664 if (isbit && !IS_ITEMP(cond))
6665 genIfxJump(ic,OP_SYMBOL(cond)->rname);
6672 /*-----------------------------------------------------------------*/
6673 /* genAddrOf - generates code for address of */
6674 /*-----------------------------------------------------------------*/
6675 static void genAddrOf (iCode *ic)
6677 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
6680 aopOp(IC_RESULT(ic),ic,FALSE);
6682 /* if the operand is on the stack then we
6683 need to get the stack offset of this
6686 /* if it has an offset then we need to compute
6689 emitcode("mov","a,_bp");
6690 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
6691 aopPut(AOP(IC_RESULT(ic)),"a",0);
6693 /* we can just move _bp */
6694 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
6695 /* fill the result with zero */
6696 size = AOP_SIZE(IC_RESULT(ic)) - 1;
6699 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
6704 /* object not on stack then we need the name */
6705 size = AOP_SIZE(IC_RESULT(ic));
6709 char s[SDCC_NAME_MAX];
6711 sprintf(s,"#(%s >> %d)",
6715 sprintf(s,"#%s",sym->rname);
6716 aopPut(AOP(IC_RESULT(ic)),s,offset++);
6720 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
6724 /*-----------------------------------------------------------------*/
6725 /* genFarFarAssign - assignment when both are in far space */
6726 /*-----------------------------------------------------------------*/
6727 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
6729 int size = AOP_SIZE(right);
6732 /* first push the right side on to the stack */
6734 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6736 emitcode ("push","acc");
6739 freeAsmop(right,NULL,ic,FALSE);
6740 /* now assign DPTR to result */
6741 aopOp(result,ic,FALSE);
6742 size = AOP_SIZE(result);
6744 emitcode ("pop","acc");
6745 aopPut(AOP(result),"a",--offset);
6747 freeAsmop(result,NULL,ic,FALSE);
6751 /*-----------------------------------------------------------------*/
6752 /* genAssign - generate code for assignment */
6753 /*-----------------------------------------------------------------*/
6754 static void genAssign (iCode *ic)
6756 operand *result, *right;
6758 unsigned long lit = 0L;
6760 result = IC_RESULT(ic);
6761 right = IC_RIGHT(ic) ;
6763 /* if they are the same */
6764 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
6767 aopOp(right,ic,FALSE);
6769 /* special case both in far space */
6770 if (AOP_TYPE(right) == AOP_DPTR &&
6771 IS_TRUE_SYMOP(result) &&
6772 isOperandInFarSpace(result)) {
6774 genFarFarAssign (result,right,ic);
6778 aopOp(result,ic,TRUE);
6780 /* if they are the same registers */
6781 if (sameRegs(AOP(right),AOP(result)))
6784 /* if the result is a bit */
6785 if (AOP_TYPE(result) == AOP_CRY) {
6787 /* if the right size is a literal then
6788 we know what the value is */
6789 if (AOP_TYPE(right) == AOP_LIT) {
6790 if (((int) operandLitValue(right)))
6791 aopPut(AOP(result),one,0);
6793 aopPut(AOP(result),zero,0);
6797 /* the right is also a bit variable */
6798 if (AOP_TYPE(right) == AOP_CRY) {
6799 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6800 aopPut(AOP(result),"c",0);
6806 aopPut(AOP(result),"a",0);
6810 /* bit variables done */
6812 size = AOP_SIZE(result);
6814 if(AOP_TYPE(right) == AOP_LIT)
6815 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6817 (AOP_TYPE(result) != AOP_REG) &&
6818 (AOP_TYPE(right) == AOP_LIT) &&
6819 !IS_FLOAT(operandType(right)) &&
6821 emitcode("clr","a");
6823 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
6824 aopPut(AOP(result),"a",size);
6827 aopGet(AOP(right),size,FALSE,FALSE),
6833 aopGet(AOP(right),offset,FALSE,FALSE),
6840 freeAsmop (right,NULL,ic,FALSE);
6841 freeAsmop (result,NULL,ic,TRUE);
6844 /*-----------------------------------------------------------------*/
6845 /* genJumpTab - genrates code for jump table */
6846 /*-----------------------------------------------------------------*/
6847 static void genJumpTab (iCode *ic)
6852 aopOp(IC_JTCOND(ic),ic,FALSE);
6853 /* get the condition into accumulator */
6854 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
6856 /* multiply by three */
6857 emitcode("add","a,acc");
6858 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
6859 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
6861 jtab = newiTempLabel(NULL);
6862 emitcode("mov","dptr,#%05d$",jtab->key+100);
6863 emitcode("jmp","@a+dptr");
6864 emitcode("","%05d$:",jtab->key+100);
6865 /* now generate the jump labels */
6866 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
6867 jtab = setNextItem(IC_JTLABELS(ic)))
6868 emitcode("ljmp","%05d$",jtab->key+100);
6872 /*-----------------------------------------------------------------*/
6873 /* genCast - gen code for casting */
6874 /*-----------------------------------------------------------------*/
6875 static void genCast (iCode *ic)
6877 operand *result = IC_RESULT(ic);
6878 link *ctype = operandType(IC_LEFT(ic));
6879 operand *right = IC_RIGHT(ic);
6882 /* if they are equivalent then do nothing */
6883 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
6886 aopOp(right,ic,FALSE) ;
6887 aopOp(result,ic,FALSE);
6889 /* if the result is a bit */
6890 if (AOP_TYPE(result) == AOP_CRY) {
6891 /* if the right size is a literal then
6892 we know what the value is */
6893 if (AOP_TYPE(right) == AOP_LIT) {
6894 if (((int) operandLitValue(right)))
6895 aopPut(AOP(result),one,0);
6897 aopPut(AOP(result),zero,0);
6902 /* the right is also a bit variable */
6903 if (AOP_TYPE(right) == AOP_CRY) {
6904 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6905 aopPut(AOP(result),"c",0);
6911 aopPut(AOP(result),"a",0);
6915 /* if they are the same size : or less */
6916 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
6918 /* if they are in the same place */
6919 if (sameRegs(AOP(right),AOP(result)))
6922 /* if they in different places then copy */
6923 size = AOP_SIZE(result);
6927 aopGet(AOP(right),offset,FALSE,FALSE),
6935 /* if the result is of type pointer */
6936 if (IS_PTR(ctype)) {
6939 link *type = operandType(right);
6940 link *etype = getSpec(type);
6942 /* pointer to generic pointer */
6943 if (IS_GENPTR(ctype)) {
6947 p_type = DCL_TYPE(type);
6949 /* we have to go by the storage class */
6950 if (SPEC_OCLS(etype)->codesp )
6953 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
6956 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
6959 if (SPEC_OCLS(etype) == idata )
6965 /* the first two bytes are known */
6970 aopGet(AOP(right),offset,FALSE,FALSE),
6974 /* the last byte depending on type */
6991 /* this should never happen */
6992 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
6993 "got unknown pointer type");
6996 aopPut(AOP(result),l,2);
7000 /* just copy the pointers */
7001 size = AOP_SIZE(result);
7005 aopGet(AOP(right),offset,FALSE,FALSE),
7012 /* so we now know that the size of destination is greater
7013 than the size of the source */
7014 /* we move to result for the size of source */
7015 size = AOP_SIZE(right);
7019 aopGet(AOP(right),offset,FALSE,FALSE),
7024 /* now depending on the sign of the destination */
7025 size = AOP_SIZE(result) - AOP_SIZE(right);
7026 /* if unsigned or not an integral type */
7027 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
7029 aopPut(AOP(result),zero,offset++);
7031 /* we need to extend the sign :{ */
7032 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
7035 emitcode("rlc","a");
7036 emitcode("subb","a,acc");
7038 aopPut(AOP(result),"a",offset++);
7041 /* we are done hurray !!!! */
7044 freeAsmop(right,NULL,ic,TRUE);
7045 freeAsmop(result,NULL,ic,TRUE);
7049 /*-----------------------------------------------------------------*/
7050 /* genDjnz - generate decrement & jump if not zero instrucion */
7051 /*-----------------------------------------------------------------*/
7052 static int genDjnz (iCode *ic, iCode *ifx)
7058 /* if the if condition has a false label
7059 then we cannot save */
7063 /* if the minus is not of the form
7065 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
7066 !IS_OP_LITERAL(IC_RIGHT(ic)))
7069 if (operandLitValue(IC_RIGHT(ic)) != 1)
7072 /* if the size of this greater than one then no
7074 if (getSize(operandType(IC_RESULT(ic))) > 1)
7077 /* otherwise we can save BIG */
7078 lbl = newiTempLabel(NULL);
7079 lbl1= newiTempLabel(NULL);
7081 aopOp(IC_RESULT(ic),ic,FALSE);
7083 if (IS_AOP_PREG(IC_RESULT(ic))) {
7084 emitcode("dec","%s",
7085 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7086 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7087 emitcode("jnz","%05d$",lbl->key+100);
7089 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
7092 emitcode ("sjmp","%05d$",lbl1->key+100);
7093 emitcode ("","%05d$:",lbl->key+100);
7094 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
7095 emitcode ("","%05d$:",lbl1->key+100);
7097 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7102 /*-----------------------------------------------------------------*/
7103 /* genReceive - generate code for a receive iCode */
7104 /*-----------------------------------------------------------------*/
7105 static void genReceive (iCode *ic)
7107 if (isOperandInFarSpace(IC_RESULT(ic)) &&
7108 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
7109 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
7111 int size = getSize(operandType(IC_RESULT(ic)));
7112 int offset = 4 - size;
7114 emitcode ("push","%s", (strcmp(fReturn[3 - offset],"a") ?
7115 fReturn[3 - offset] : "acc"));
7118 aopOp(IC_RESULT(ic),ic,FALSE);
7119 size = AOP_SIZE(IC_RESULT(ic));
7122 emitcode ("pop","acc");
7123 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
7128 aopOp(IC_RESULT(ic),ic,FALSE);
7130 assignResultValue(IC_RESULT(ic));
7133 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7136 /*-----------------------------------------------------------------*/
7137 /* gen51Code - generate code for 8051 based controllers */
7138 /*-----------------------------------------------------------------*/
7139 void gen51Code (iCode *lic)
7144 lineHead = lineCurr = NULL;
7146 /* if debug information required */
7147 /* if (options.debug && currFunc) { */
7149 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
7151 if (IS_STATIC(currFunc->etype))
7152 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
7154 emitcode("","G$%s$0$0 ==.",currFunc->name);
7157 /* stack pointer name */
7158 if (options.useXstack)
7164 for (ic = lic ; ic ; ic = ic->next ) {
7166 if ( cln != ic->lineno ) {
7167 if ( options.debug ) {
7169 emitcode("","C$%s$%d$%d$%d ==.",
7170 ic->filename,ic->lineno,
7171 ic->level,ic->block);
7174 emitcode(";","%s %d",ic->filename,ic->lineno);
7177 /* if the result is marked as
7178 spilt and rematerializable or code for
7179 this has already been generated then
7181 if (resultRemat(ic) || ic->generated )
7184 /* depending on the operation */
7203 /* IPOP happens only when trying to restore a
7204 spilt live range, if there is an ifx statement
7205 following this pop then the if statement might
7206 be using some of the registers being popped which
7207 would destory the contents of the register so
7208 we need to check for this condition and handle it */
7210 ic->next->op == IFX &&
7211 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
7212 genIfx (ic->next,ic);
7230 genEndFunction (ic);
7250 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
7267 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
7271 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
7278 /* note these two are xlated by algebraic equivalence
7279 during parsing SDCC.y */
7280 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7281 "got '>=' or '<=' shouldn't have come here");
7285 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
7297 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
7301 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
7305 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
7332 case GET_VALUE_AT_ADDRESS:
7337 if (POINTER_SET(ic))
7364 addSet(&sendSet,ic);
7369 /* piCode(ic,stdout); */
7375 /* now we are ready to call the
7376 peep hole optimizer */
7377 if (!options.nopeep)
7378 peepHole (&lineHead);
7380 /* now do the actual printing */
7381 printLine (lineHead,codeOutFile);