1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
35 #include "SDCCglobl.h"
37 #ifdef HAVE_SYS_ISA_DEFS_H
38 #include <sys/isa_defs.h>
43 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
44 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
49 #include "SDCCpeeph.h"
53 char *aopLiteral (value *val, int offset);
55 /* this is the down and dirty file with all kinds of
56 kludgy & hacky stuff. This is what it is all about
57 CODE GENERATION for a specific MCU . some of the
58 routines may be reusable, will have to see */
60 static char *zero = "#0x00";
61 static char *one = "#0x01";
63 static char *fReturn[] = {"dpl","dph","b","a" };
64 static char *accUse[] = {"a","b"};
66 static short rbank = -1;
78 extern int mcs51_ptrRegReq ;
79 extern int mcs51_nRegs;
80 extern FILE *codeOutFile;
81 static void saverbank (int, iCode *,bool);
82 #define RESULTONSTACK(x) \
83 (IC_RESULT(x) && IC_RESULT(x)->aop && \
84 IC_RESULT(x)->aop->type == AOP_STK )
86 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x);
87 #define CLRC emitcode("clr","c");
89 static lineNode *lineHead = NULL;
90 static lineNode *lineCurr = NULL;
92 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
93 0xE0, 0xC0, 0x80, 0x00};
94 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
95 0x07, 0x03, 0x01, 0x00};
102 /*-----------------------------------------------------------------*/
103 /* emitcode - writes the code into a file : for now it is simple */
104 /*-----------------------------------------------------------------*/
105 static void emitcode (char *inst,char *fmt, ...)
108 char lb[MAX_INLINEASM];
115 sprintf(lb,"%s\t",inst);
117 sprintf(lb,"%s",inst);
118 vsprintf(lb+(strlen(lb)),fmt,ap);
122 while (isspace(*lbp)) lbp++;
125 lineCurr = (lineCurr ?
126 connectLine(lineCurr,newLineNode(lb)) :
127 (lineHead = newLineNode(lb)));
128 lineCurr->isInline = _G.inLine;
129 lineCurr->isDebug = _G.debugLine;
133 /*-----------------------------------------------------------------*/
134 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
135 /*-----------------------------------------------------------------*/
136 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
138 bool r0iu = FALSE , r1iu = FALSE;
139 bool r0ou = FALSE , r1ou = FALSE;
141 /* the logic: if r0 & r1 used in the instruction
142 then we are in trouble otherwise */
144 /* first check if r0 & r1 are used by this
145 instruction, in which case we are in trouble */
146 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
147 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
151 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
152 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
154 /* if no usage of r0 then return it */
155 if (!r0iu && !r0ou) {
156 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
157 (*aopp)->type = AOP_R0;
158 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R0_IDX);
161 /* if no usage of r1 then return it */
162 if (!r1iu && !r1ou) {
163 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
164 (*aopp)->type = AOP_R1;
165 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R1_IDX);
168 /* now we know they both have usage */
169 /* if r0 not used in this instruction */
171 /* push it if not already pushed */
173 emitcode ("push","%s",
174 mcs51_regWithIdx(R0_IDX)->dname);
178 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
179 (*aopp)->type = AOP_R0;
181 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R0_IDX);
184 /* if r1 not used then */
187 /* push it if not already pushed */
189 emitcode ("push","%s",
190 mcs51_regWithIdx(R1_IDX)->dname);
194 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
195 (*aopp)->type = AOP_R1;
196 return mcs51_regWithIdx(R1_IDX);
201 /* I said end of world but not quite end of world yet */
202 /* if this is a result then we canpush it on the stack*/
204 (*aopp)->type = AOP_STK;
209 /* other wise this is true end of the world */
210 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
211 "getFreePtr should never reach here");
215 /*-----------------------------------------------------------------*/
216 /* newAsmop - creates a new asmOp */
217 /*-----------------------------------------------------------------*/
218 static asmop *newAsmop (short type)
222 ALLOC(aop,sizeof(asmop));
227 /*-----------------------------------------------------------------*/
228 /* pointerCode - returns the code for a pointer type */
229 /*-----------------------------------------------------------------*/
230 static int pointerCode (link *etype)
233 if (SPEC_OCLS(etype)->codesp ) {
237 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
240 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
243 if (SPEC_OCLS(etype) == idata )
250 /*-----------------------------------------------------------------*/
251 /* aopForSym - for a true symbol */
252 /*-----------------------------------------------------------------*/
253 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
256 memmap *space= SPEC_OCLS(sym->etype);
258 /* if already has one */
262 /* assign depending on the storage class */
263 /* if it is on the stack or indirectly addressable */
264 /* space we need to assign either r0 or r1 to it */
265 if (sym->onStack || sym->iaccess) {
266 sym->aop = aop = newAsmop(0);
267 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
268 aop->size = getSize(sym->type);
270 /* now assign the address of the variable to
271 the pointer register */
272 if (aop->type != AOP_STK) {
277 emitcode("push","acc");
279 emitcode("mov","a,_bp");
280 emitcode("add","a,#0x%02x",
282 ((char)(sym->stack - _G.nRegsSaved )) :
283 ((char)sym->stack)) & 0xff);
284 emitcode("mov","%s,a",
285 aop->aopu.aop_ptr->name);
288 emitcode("pop","acc");
291 emitcode("mov","%s,#%s",
292 aop->aopu.aop_ptr->name,
294 aop->paged = space->paged;
296 aop->aopu.aop_stk = sym->stack;
300 /* if in bit space */
301 if (IN_BITSPACE(space)) {
302 sym->aop = aop = newAsmop (AOP_CRY);
303 aop->aopu.aop_dir = sym->rname ;
304 aop->size = getSize(sym->type);
307 /* if it is in direct space */
308 if (IN_DIRSPACE(space)) {
309 sym->aop = aop = newAsmop (AOP_DIR);
310 aop->aopu.aop_dir = sym->rname ;
311 aop->size = getSize(sym->type);
315 /* special case for a function */
316 if (IS_FUNC(sym->type)) {
317 sym->aop = aop = newAsmop(AOP_IMMD);
318 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
319 strcpy(aop->aopu.aop_immd,sym->rname);
324 /* only remaining is far space */
325 /* in which case DPTR gets the address */
326 sym->aop = aop = newAsmop(AOP_DPTR);
327 emitcode ("mov","dptr,#%s", sym->rname);
328 aop->size = getSize(sym->type);
330 /* if it is in code space */
331 if (IN_CODESPACE(space))
337 /*-----------------------------------------------------------------*/
338 /* aopForRemat - rematerialzes an object */
339 /*-----------------------------------------------------------------*/
340 static asmop *aopForRemat (symbol *sym)
343 iCode *ic = sym->rematiCode;
344 asmop *aop = newAsmop(AOP_IMMD);
348 /* if plus or minus print the right hand side */
349 if (ic->op == '+' || ic->op == '-') {
350 sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
353 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
357 /* we reached the end */
358 sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
362 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
363 strcpy(aop->aopu.aop_immd,buffer);
367 /*-----------------------------------------------------------------*/
368 /* regsInCommon - two operands have some registers in common */
369 /*-----------------------------------------------------------------*/
370 static bool regsInCommon (operand *op1, operand *op2)
375 /* if they have registers in common */
376 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
379 sym1 = OP_SYMBOL(op1);
380 sym2 = OP_SYMBOL(op2);
382 if (sym1->nRegs == 0 || sym2->nRegs == 0)
385 for (i = 0 ; i < sym1->nRegs ; i++) {
390 for (j = 0 ; j < sym2->nRegs ;j++ ) {
394 if (sym2->regs[j] == sym1->regs[i])
402 /*-----------------------------------------------------------------*/
403 /* operandsEqu - equivalent */
404 /*-----------------------------------------------------------------*/
405 static bool operandsEqu ( operand *op1, operand *op2)
409 /* if they not symbols */
410 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
413 sym1 = OP_SYMBOL(op1);
414 sym2 = OP_SYMBOL(op2);
416 /* if both are itemps & one is spilt
417 and the other is not then false */
418 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
419 sym1->isspilt != sym2->isspilt )
422 /* if they are the same */
426 if (strcmp(sym1->rname,sym2->rname) == 0)
430 /* if left is a tmp & right is not */
434 (sym1->usl.spillLoc == sym2))
441 (sym2->usl.spillLoc == sym1))
447 /*-----------------------------------------------------------------*/
448 /* sameRegs - two asmops have the same registers */
449 /*-----------------------------------------------------------------*/
450 static bool sameRegs (asmop *aop1, asmop *aop2 )
457 if (aop1->type != AOP_REG ||
458 aop2->type != AOP_REG )
461 if (aop1->size != aop2->size )
464 for (i = 0 ; i < aop1->size ; i++ )
465 if (aop1->aopu.aop_reg[i] !=
466 aop2->aopu.aop_reg[i] )
472 /*-----------------------------------------------------------------*/
473 /* aopOp - allocates an asmop for an operand : */
474 /*-----------------------------------------------------------------*/
475 static void aopOp (operand *op, iCode *ic, bool result)
484 /* if this a literal */
485 if (IS_OP_LITERAL(op)) {
486 op->aop = aop = newAsmop(AOP_LIT);
487 aop->aopu.aop_lit = op->operand.valOperand;
488 aop->size = getSize(operandType(op));
492 /* if already has a asmop then continue */
496 /* if the underlying symbol has a aop */
497 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
498 op->aop = OP_SYMBOL(op)->aop;
502 /* if this is a true symbol */
503 if (IS_TRUE_SYMOP(op)) {
504 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
508 /* this is a temporary : this has
514 e) can be a return use only */
519 /* if the type is a conditional */
520 if (sym->regType == REG_CND) {
521 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
526 /* if it is spilt then two situations
528 b) has a spill location */
529 if (sym->isspilt || sym->nRegs == 0) {
531 /* rematerialize it NOW */
533 sym->aop = op->aop = aop =
535 aop->size = getSize(sym->type);
541 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
542 aop->size = getSize(sym->type);
543 for ( i = 0 ; i < 2 ; i++ )
544 aop->aopu.aop_str[i] = accUse[i];
550 aop = op->aop = sym->aop = newAsmop(AOP_STR);
551 aop->size = getSize(sym->type);
552 for ( i = 0 ; i < 4 ; i++ )
553 aop->aopu.aop_str[i] = fReturn[i];
557 /* else spill location */
558 sym->aop = op->aop = aop =
559 aopForSym(ic,sym->usl.spillLoc,result);
560 aop->size = getSize(sym->type);
564 /* must be in a register */
565 sym->aop = op->aop = aop = newAsmop(AOP_REG);
566 aop->size = sym->nRegs;
567 for ( i = 0 ; i < sym->nRegs ;i++)
568 aop->aopu.aop_reg[i] = sym->regs[i];
571 /*-----------------------------------------------------------------*/
572 /* freeAsmop - free up the asmop given to an operand */
573 /*----------------------------------------------------------------*/
574 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
591 /* depending on the asmop type only three cases need work AOP_RO
592 , AOP_R1 && AOP_STK */
597 emitcode ("pop","ar0");
601 bitVectUnSetBit(ic->rUsed,R0_IDX);
607 emitcode ("pop","ar1");
611 bitVectUnSetBit(ic->rUsed,R1_IDX);
617 int stk = aop->aopu.aop_stk + aop->size;
618 bitVectUnSetBit(ic->rUsed,R0_IDX);
619 bitVectUnSetBit(ic->rUsed,R1_IDX);
621 getFreePtr(ic,&aop,FALSE);
623 emitcode ("mov","a,_bp");
624 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
625 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
627 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
630 emitcode("pop","acc");
631 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
633 emitcode("dec","%s",aop->aopu.aop_ptr->name);
636 freeAsmop(op,NULL,ic,TRUE);
638 emitcode("pop","ar0");
643 emitcode("pop","ar1");
650 /* all other cases just dealloc */
654 OP_SYMBOL(op)->aop = NULL;
655 /* if the symbol has a spill */
657 SPIL_LOC(op)->aop = NULL;
662 /*-----------------------------------------------------------------*/
663 /* aopGet - for fetching value of the aop */
664 /*-----------------------------------------------------------------*/
665 static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
670 /* offset is greater than
672 if (offset > (aop->size - 1) &&
673 aop->type != AOP_LIT)
676 /* depending on type */
681 /* if we need to increment it */
682 while (offset > aop->coff) {
683 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
687 while (offset < aop->coff) {
688 emitcode("dec","%s",aop->aopu.aop_ptr->name);
694 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
695 return (dname ? "acc" : "a");
697 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
698 ALLOC_ATOMIC(rs,strlen(s)+1);
703 while (offset > aop->coff) {
704 emitcode ("inc","dptr");
708 while (offset < aop->coff) {
709 emitcode("lcall","__decdptr");
716 emitcode("movc","a,@a+dptr");
719 emitcode("movx","a,@dptr");
720 return (dname ? "acc" : "a");
725 sprintf (s,"#(%s)",aop->aopu.aop_immd);
728 sprintf(s,"#(%s >> %d)",
734 ALLOC_ATOMIC(rs,strlen(s)+1);
740 sprintf(s,"(%s + %d)",
744 sprintf(s,"%s",aop->aopu.aop_dir);
745 ALLOC_ATOMIC(rs,strlen(s)+1);
751 return aop->aopu.aop_reg[offset]->dname;
753 return aop->aopu.aop_reg[offset]->name;
757 emitcode("mov","c,%s",aop->aopu.aop_dir);
758 emitcode("rlc","a") ;
759 return (dname ? "acc" : "a");
762 if (!offset && dname)
764 return aop->aopu.aop_str[offset];
767 return aopLiteral (aop->aopu.aop_lit,offset);
771 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
775 return aop->aopu.aop_str[offset];
779 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
780 "aopget got unsupported aop->type");
783 /*-----------------------------------------------------------------*/
784 /* aopPut - puts a string for a aop */
785 /*-----------------------------------------------------------------*/
786 static void aopPut (asmop *aop, char *s, int offset)
791 if (aop->size && offset > ( aop->size - 1)) {
792 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
793 "aopPut got offset > aop->size");
797 /* will assign value to value */
798 /* depending on where it is ofcourse */
802 sprintf(d,"(%s + %d)",
803 aop->aopu.aop_dir,offset);
805 sprintf(d,"%s",aop->aopu.aop_dir);
808 emitcode("mov","%s,%s",d,s);
813 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
814 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
816 strcmp(s,"r0") == 0 ||
817 strcmp(s,"r1") == 0 ||
818 strcmp(s,"r2") == 0 ||
819 strcmp(s,"r3") == 0 ||
820 strcmp(s,"r4") == 0 ||
821 strcmp(s,"r5") == 0 ||
822 strcmp(s,"r6") == 0 ||
823 strcmp(s,"r7") == 0 )
824 emitcode("mov","%s,%s",
825 aop->aopu.aop_reg[offset]->dname,s);
827 emitcode("mov","%s,%s",
828 aop->aopu.aop_reg[offset]->name,s);
834 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
835 "aopPut writting to code space");
839 while (offset > aop->coff) {
841 emitcode ("inc","dptr");
844 while (offset < aop->coff) {
846 emitcode("lcall","__decdptr");
851 /* if not in accumulater */
854 emitcode ("movx","@dptr,a");
859 while (offset > aop->coff) {
861 emitcode("inc","%s",aop->aopu.aop_ptr->name);
863 while (offset < aop->coff) {
865 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
871 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
876 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
878 if (strcmp(s,"r0") == 0 ||
879 strcmp(s,"r1") == 0 ||
880 strcmp(s,"r2") == 0 ||
881 strcmp(s,"r3") == 0 ||
882 strcmp(s,"r4") == 0 ||
883 strcmp(s,"r5") == 0 ||
884 strcmp(s,"r6") == 0 ||
885 strcmp(s,"r7") == 0 ) {
887 sprintf(buffer,"a%s",s);
888 emitcode("mov","@%s,%s",
889 aop->aopu.aop_ptr->name,buffer);
891 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
896 if (strcmp(s,"a") == 0)
897 emitcode("push","acc");
899 emitcode("push","%s",s);
904 /* if bit variable */
905 if (!aop->aopu.aop_dir) {
910 emitcode("clr","%s",aop->aopu.aop_dir);
913 emitcode("setb","%s",aop->aopu.aop_dir);
916 emitcode("mov","%s,c",aop->aopu.aop_dir);
918 lbl = newiTempLabel(NULL);
923 emitcode("cjne","a,#0x01,%05d$",lbl->key+100);
924 emitcode("","%05d$:",lbl->key+100);
926 emitcode("mov","%s,c",aop->aopu.aop_dir);
933 if (strcmp(aop->aopu.aop_str[offset],s))
934 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
939 if (!offset && (strcmp(s,"acc") == 0))
942 if (strcmp(aop->aopu.aop_str[offset],s))
943 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
947 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
948 "aopPut got unsupported aop->type");
956 /*-----------------------------------------------------------------*/
957 /* pointToEnd :- points to the last byte of the operand */
958 /*-----------------------------------------------------------------*/
959 static void pointToEnd (asmop *aop)
965 aop->coff = count = (aop->size - 1);
970 emitcode("inc","%s",aop->aopu.aop_ptr->name);
974 emitcode("inc","dptr");
981 /*-----------------------------------------------------------------*/
982 /* reAdjustPreg - points a register back to where it should */
983 /*-----------------------------------------------------------------*/
984 static void reAdjustPreg (asmop *aop)
989 if ((size = aop->size) <= 1)
996 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1000 emitcode("lcall","__decdptr");
1007 #define AOP(op) op->aop
1008 #define AOP_TYPE(op) AOP(op)->type
1009 #define AOP_SIZE(op) AOP(op)->size
1010 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1011 AOP_TYPE(x) == AOP_R0))
1013 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1014 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1016 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1017 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1018 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1020 /*-----------------------------------------------------------------*/
1021 /* genNotFloat - generates not for float operations */
1022 /*-----------------------------------------------------------------*/
1023 static void genNotFloat (operand *op, operand *res)
1029 /* we will put 127 in the first byte of
1031 aopPut(AOP(res),"#127",0);
1032 size = AOP_SIZE(op) - 1;
1035 l = aopGet(op->aop,offset++,FALSE,FALSE);
1039 emitcode("orl","a,%s",
1041 offset++,FALSE,FALSE));
1043 tlbl = newiTempLabel(NULL);
1045 tlbl = newiTempLabel(NULL);
1046 aopPut(res->aop,one,1);
1047 emitcode("jz","%05d$",(tlbl->key+100));
1048 aopPut(res->aop,zero,1);
1049 emitcode("","%05d$:",(tlbl->key+100));
1051 size = res->aop->size - 2;
1053 /* put zeros in the rest */
1055 aopPut(res->aop,zero,offset++);
1058 /*-----------------------------------------------------------------*/
1059 /* getDataSize - get the operand data size */
1060 /*-----------------------------------------------------------------*/
1061 static int getDataSize(operand *op)
1064 size = AOP_SIZE(op);
1071 /*-----------------------------------------------------------------*/
1072 /* outAcc - output Acc */
1073 /*-----------------------------------------------------------------*/
1074 static void outAcc(operand *result)
1077 size = getDataSize(result);
1079 aopPut(AOP(result),"a",0);
1082 /* unsigned or positive */
1084 aopPut(AOP(result),zero,offset++);
1089 /*-----------------------------------------------------------------*/
1090 /* outBitC - output a bit C */
1091 /*-----------------------------------------------------------------*/
1092 static void outBitC(operand *result)
1094 /* if the result is bit */
1095 if (AOP_TYPE(result) == AOP_CRY)
1096 aopPut(AOP(result),"c",0);
1098 emitcode("clr","a");
1099 emitcode("rlc","a");
1104 /*-----------------------------------------------------------------*/
1105 /* toBoolean - emit code for orl a,operator(sizeop) */
1106 /*-----------------------------------------------------------------*/
1107 static void toBoolean(operand *oper)
1109 int size = AOP_SIZE(oper) - 1;
1111 MOVA(aopGet(AOP(oper),0,FALSE,FALSE));
1113 emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE));
1117 /*-----------------------------------------------------------------*/
1118 /* genNot - generate code for ! operation */
1119 /*-----------------------------------------------------------------*/
1120 static void genNot (iCode *ic)
1123 link *optype = operandType(IC_LEFT(ic));
1125 /* assign asmOps to operand & result */
1126 aopOp (IC_LEFT(ic),ic,FALSE);
1127 aopOp (IC_RESULT(ic),ic,TRUE);
1129 /* if in bit space then a special case */
1130 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1131 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1132 emitcode("cpl","c");
1133 outBitC(IC_RESULT(ic));
1137 /* if type float then do float */
1138 if (IS_FLOAT(optype)) {
1139 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1143 toBoolean(IC_LEFT(ic));
1145 tlbl = newiTempLabel(NULL);
1146 emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1147 emitcode("","%05d$:",tlbl->key+100);
1148 outBitC(IC_RESULT(ic));
1151 /* release the aops */
1152 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1153 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1157 /*-----------------------------------------------------------------*/
1158 /* genCpl - generate code for complement */
1159 /*-----------------------------------------------------------------*/
1160 static void genCpl (iCode *ic)
1166 /* assign asmOps to operand & result */
1167 aopOp (IC_LEFT(ic),ic,FALSE);
1168 aopOp (IC_RESULT(ic),ic,TRUE);
1170 /* if both are in bit space then
1172 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1173 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1175 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1176 emitcode("cpl","c");
1177 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1181 size = AOP_SIZE(IC_RESULT(ic));
1183 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1185 emitcode("cpl","a");
1186 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1191 /* release the aops */
1192 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1193 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1196 /*-----------------------------------------------------------------*/
1197 /* genUminusFloat - unary minus for floating points */
1198 /*-----------------------------------------------------------------*/
1199 static void genUminusFloat(operand *op,operand *result)
1201 int size ,offset =0 ;
1203 /* for this we just need to flip the
1204 first it then copy the rest in place */
1205 size = AOP_SIZE(op) - 1;
1206 l = aopGet(AOP(op),3,FALSE,FALSE);
1210 emitcode("cpl","acc.7");
1211 aopPut(AOP(result),"a",3);
1215 aopGet(AOP(op),offset,FALSE,FALSE),
1221 /*-----------------------------------------------------------------*/
1222 /* genUminus - unary minus code generation */
1223 /*-----------------------------------------------------------------*/
1224 static void genUminus (iCode *ic)
1227 link *optype, *rtype;
1231 aopOp(IC_LEFT(ic),ic,FALSE);
1232 aopOp(IC_RESULT(ic),ic,TRUE);
1234 /* if both in bit space then special
1236 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1237 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1239 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1240 emitcode("cpl","c");
1241 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1245 optype = operandType(IC_LEFT(ic));
1246 rtype = operandType(IC_RESULT(ic));
1248 /* if float then do float stuff */
1249 if (IS_FLOAT(optype)) {
1250 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1254 /* otherwise subtract from zero */
1255 size = AOP_SIZE(IC_LEFT(ic));
1259 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1260 if (!strcmp(l,"a")) {
1261 emitcode("cpl","a");
1262 emitcode("inc","a");
1264 emitcode("clr","a");
1265 emitcode("subb","a,%s",l);
1267 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1270 /* if any remaining bytes in the result */
1271 /* we just need to propagate the sign */
1272 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1273 emitcode("rlc","a");
1274 emitcode("subb","a,acc");
1276 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1280 /* release the aops */
1281 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1282 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1285 /*-----------------------------------------------------------------*/
1286 /* saveRegisters - will look for a call and save the registers */
1287 /*-----------------------------------------------------------------*/
1288 static void saveRegisters(iCode *lic)
1296 for (ic = lic ; ic ; ic = ic->next)
1297 if (ic->op == CALL || ic->op == PCALL)
1301 fprintf(stderr,"found parameter push with no function call\n");
1305 /* if the registers have been saved already then
1307 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1310 /* find the registers in use at this time
1311 and push them away to safety */
1312 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1316 if (options.useXstack) {
1317 if (bitVectBitValue(rsave,R0_IDX))
1318 emitcode("mov","b,r0");
1319 emitcode("mov","r0,%s",spname);
1320 for (i = 0 ; i < mcs51_nRegs ; i++) {
1321 if (bitVectBitValue(rsave,i)) {
1323 emitcode("mov","a,b");
1325 emitcode("mov","a,%s",mcs51_regWithIdx(i)->name);
1326 emitcode("movx","@r0,a");
1327 emitcode("inc","r0");
1330 emitcode("mov","%s,r0",spname);
1331 if (bitVectBitValue(rsave,R0_IDX))
1332 emitcode("mov","r0,b");
1334 for (i = 0 ; i < mcs51_nRegs ; i++) {
1335 if (bitVectBitValue(rsave,i))
1336 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
1339 detype = getSpec(operandType(IC_LEFT(ic)));
1341 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1342 IS_ISR(currFunc->etype) &&
1345 saverbank(SPEC_BANK(detype),ic,TRUE);
1348 /*-----------------------------------------------------------------*/
1349 /* unsaveRegisters - pop the pushed registers */
1350 /*-----------------------------------------------------------------*/
1351 static void unsaveRegisters (iCode *ic)
1355 /* find the registers in use at this time
1356 and push them away to safety */
1357 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1360 if (options.useXstack) {
1361 emitcode("mov","r0,%s",spname);
1362 for (i = mcs51_nRegs ; i >= 0 ; i--) {
1363 if (bitVectBitValue(rsave,i)) {
1364 emitcode("dec","r0");
1365 emitcode("movx","a,@r0");
1367 emitcode("mov","b,a");
1369 emitcode("mov","%s,a",mcs51_regWithIdx(i)->name);
1373 emitcode("mov","%s,r0",spname);
1374 if (bitVectBitValue(rsave,R0_IDX))
1375 emitcode("mov","r0,b");
1377 for (i = mcs51_nRegs ; i >= 0 ; i--) {
1378 if (bitVectBitValue(rsave,i))
1379 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
1385 /*-----------------------------------------------------------------*/
1387 /*-----------------------------------------------------------------*/
1388 static void pushSide(operand * oper, int size)
1392 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1393 if (AOP_TYPE(oper) != AOP_REG &&
1394 AOP_TYPE(oper) != AOP_DIR &&
1396 emitcode("mov","a,%s",l);
1397 emitcode("push","acc");
1399 emitcode("push","%s",l);
1403 /*-----------------------------------------------------------------*/
1404 /* assignResultValue - */
1405 /*-----------------------------------------------------------------*/
1406 static void assignResultValue(operand * oper)
1409 int size = AOP_SIZE(oper);
1411 aopPut(AOP(oper),fReturn[offset],offset);
1417 /*-----------------------------------------------------------------*/
1418 /* genXpush - pushes onto the external stack */
1419 /*-----------------------------------------------------------------*/
1420 static void genXpush (iCode *ic)
1422 asmop *aop = newAsmop(0);
1424 int size,offset = 0;
1426 aopOp(IC_LEFT(ic),ic,FALSE);
1427 r = getFreePtr(ic,&aop,FALSE);
1430 emitcode("mov","%s,_spx",r->name);
1432 size = AOP_SIZE(IC_LEFT(ic));
1435 char *l = aopGet(AOP(IC_LEFT(ic)),
1436 offset++,FALSE,FALSE);
1438 emitcode("movx","@%s,a",r->name);
1439 emitcode("inc","%s",r->name);
1444 emitcode("mov","_spx,%s",r->name);
1446 freeAsmop(NULL,aop,ic,TRUE);
1447 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1450 /*-----------------------------------------------------------------*/
1451 /* genIpush - genrate code for pushing this gets a little complex */
1452 /*-----------------------------------------------------------------*/
1453 static void genIpush (iCode *ic)
1455 int size, offset = 0 ;
1459 /* if this is not a parm push : ie. it is spill push
1460 and spill push is always done on the local stack */
1461 if (!ic->parmPush) {
1463 /* and the item is spilt then do nothing */
1464 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1467 aopOp(IC_LEFT(ic),ic,FALSE);
1468 size = AOP_SIZE(IC_LEFT(ic));
1469 /* push it on the stack */
1471 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1476 emitcode("push","%s",l);
1481 /* this is a paramter push: in this case we call
1482 the routine to find the call and save those
1483 registers that need to be saved */
1486 /* if use external stack then call the external
1487 stack pushing routine */
1488 if (options.useXstack) {
1493 /* then do the push */
1494 aopOp(IC_LEFT(ic),ic,FALSE);
1497 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1498 size = AOP_SIZE(IC_LEFT(ic));
1501 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1502 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1503 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1505 emitcode("mov","a,%s",l);
1506 emitcode("push","acc");
1508 emitcode("push","%s",l);
1511 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1514 /*-----------------------------------------------------------------*/
1515 /* genIpop - recover the registers: can happen only for spilling */
1516 /*-----------------------------------------------------------------*/
1517 static void genIpop (iCode *ic)
1522 /* if the temp was not pushed then */
1523 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1526 aopOp(IC_LEFT(ic),ic,FALSE);
1527 size = AOP_SIZE(IC_LEFT(ic));
1530 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1533 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1536 /*-----------------------------------------------------------------*/
1537 /* unsaverbank - restores the resgister bank from stack */
1538 /*-----------------------------------------------------------------*/
1539 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1546 if (options.useXstack) {
1548 r = getFreePtr(ic,&aop,FALSE);
1551 emitcode("mov","%s,_spx",r->name);
1552 emitcode("movx","a,@%s",r->name);
1553 emitcode("mov","psw,a");
1554 emitcode("dec","%s",r->name);
1557 emitcode ("pop","psw");
1560 for (i = (mcs51_nRegs - 1) ; i >= 0 ;i--) {
1561 if (options.useXstack) {
1562 emitcode("movx","a,@%s",r->name);
1563 emitcode("mov","(%s+%d),a",
1564 regs8051[i].base,8*bank+regs8051[i].offset);
1565 emitcode("dec","%s",r->name);
1568 emitcode("pop","(%s+%d)",
1569 regs8051[i].base,8*bank+regs8051[i].offset);
1572 if (options.useXstack) {
1574 emitcode("mov","_spx,%s",r->name);
1575 freeAsmop(NULL,aop,ic,TRUE);
1580 /*-----------------------------------------------------------------*/
1581 /* saverbank - saves an entire register bank on the stack */
1582 /*-----------------------------------------------------------------*/
1583 static void saverbank (int bank, iCode *ic, bool pushPsw)
1589 if (options.useXstack) {
1592 r = getFreePtr(ic,&aop,FALSE);
1593 emitcode("mov","%s,_spx",r->name);
1597 for (i = 0 ; i < mcs51_nRegs ;i++) {
1598 if (options.useXstack) {
1599 emitcode("inc","%s",r->name);
1600 emitcode("mov","a,(%s+%d)",
1601 regs8051[i].base,8*bank+regs8051[i].offset);
1602 emitcode("movx","@%s,a",r->name);
1604 emitcode("push","(%s+%d)",
1605 regs8051[i].base,8*bank+regs8051[i].offset);
1609 if (options.useXstack) {
1610 emitcode("mov","a,psw");
1611 emitcode("movx","@%s,a",r->name);
1612 emitcode("inc","%s",r->name);
1613 emitcode("mov","_spx,%s",r->name);
1614 freeAsmop (NULL,aop,ic,TRUE);
1617 emitcode("push","psw");
1619 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1625 /*-----------------------------------------------------------------*/
1626 /* genCall - generates a call statement */
1627 /*-----------------------------------------------------------------*/
1628 static void genCall (iCode *ic)
1632 /* if caller saves & we have not saved then */
1636 /* if we are calling a function that is not using
1637 the same register bank then we need to save the
1638 destination registers on the stack */
1639 detype = getSpec(operandType(IC_LEFT(ic)));
1641 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1642 IS_ISR(currFunc->etype) &&
1645 saverbank(SPEC_BANK(detype),ic,TRUE);
1647 /* if send set is not empty the assign */
1651 for (sic = setFirstItem(_G.sendSet) ; sic ;
1652 sic = setNextItem(_G.sendSet)) {
1653 int size, offset = 0;
1654 aopOp(IC_LEFT(sic),sic,FALSE);
1655 size = AOP_SIZE(IC_LEFT(sic));
1657 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1659 if (strcmp(l,fReturn[offset]))
1660 emitcode("mov","%s,%s",
1665 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1670 emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1671 OP_SYMBOL(IC_LEFT(ic))->rname :
1672 OP_SYMBOL(IC_LEFT(ic))->name));
1674 /* if we need assign a result value */
1675 if ((IS_ITEMP(IC_RESULT(ic)) &&
1676 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1677 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1678 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1681 aopOp(IC_RESULT(ic),ic,FALSE);
1684 assignResultValue(IC_RESULT(ic));
1686 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1689 /* adjust the stack for parameters if
1691 if (IC_LEFT(ic)->parmBytes) {
1693 if (IC_LEFT(ic)->parmBytes > 3) {
1694 emitcode("mov","a,%s",spname);
1695 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1696 emitcode("mov","%s,a",spname);
1698 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1699 emitcode("dec","%s",spname);
1703 /* if register bank was saved then pop them */
1705 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1707 /* if we hade saved some registers then unsave them */
1708 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1709 unsaveRegisters (ic);
1714 /*-----------------------------------------------------------------*/
1715 /* genPcall - generates a call by pointer statement */
1716 /*-----------------------------------------------------------------*/
1717 static void genPcall (iCode *ic)
1720 symbol *rlbl = newiTempLabel(NULL);
1723 /* if caller saves & we have not saved then */
1727 /* if we are calling a function that is not using
1728 the same register bank then we need to save the
1729 destination registers on the stack */
1730 detype = getSpec(operandType(IC_LEFT(ic)));
1732 IS_ISR(currFunc->etype) &&
1733 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
1734 saverbank(SPEC_BANK(detype),ic,TRUE);
1737 /* push the return address on to the stack */
1738 emitcode("mov","a,#%05d$",(rlbl->key+100));
1739 emitcode("push","acc");
1740 emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
1741 emitcode("push","acc");
1743 /* now push the calling address */
1744 aopOp(IC_LEFT(ic),ic,FALSE);
1746 pushSide(IC_LEFT(ic), 2);
1748 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1750 /* if send set is not empty the assign */
1754 for (sic = setFirstItem(_G.sendSet) ; sic ;
1755 sic = setNextItem(_G.sendSet)) {
1756 int size, offset = 0;
1757 aopOp(IC_LEFT(sic),sic,FALSE);
1758 size = AOP_SIZE(IC_LEFT(sic));
1760 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1762 if (strcmp(l,fReturn[offset]))
1763 emitcode("mov","%s,%s",
1768 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1774 emitcode("","%05d$:",(rlbl->key+100));
1777 /* if we need assign a result value */
1778 if ((IS_ITEMP(IC_RESULT(ic)) &&
1779 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1780 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
1781 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1784 aopOp(IC_RESULT(ic),ic,FALSE);
1787 assignResultValue(IC_RESULT(ic));
1789 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1792 /* adjust the stack for parameters if
1794 if (IC_LEFT(ic)->parmBytes) {
1796 if (IC_LEFT(ic)->parmBytes > 3) {
1797 emitcode("mov","a,%s",spname);
1798 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1799 emitcode("mov","%s,a",spname);
1801 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1802 emitcode("dec","%s",spname);
1806 /* if register bank was saved then unsave them */
1808 (SPEC_BANK(currFunc->etype) !=
1810 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1812 /* if we hade saved some registers then
1815 unsaveRegisters (ic);
1819 /*-----------------------------------------------------------------*/
1820 /* resultRemat - result is rematerializable */
1821 /*-----------------------------------------------------------------*/
1822 static int resultRemat (iCode *ic)
1824 if (SKIP_IC(ic) || ic->op == IFX)
1827 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1828 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1829 if (sym->remat && !POINTER_SET(ic))
1836 /*-----------------------------------------------------------------*/
1837 /* inExcludeList - return 1 if the string is in exclude Reg list */
1838 /*-----------------------------------------------------------------*/
1839 static bool inExcludeList(char *s)
1843 if (options.excludeRegs[i] &&
1844 strcasecmp(options.excludeRegs[i],"none") == 0)
1847 for ( i = 0 ; options.excludeRegs[i]; i++) {
1848 if (options.excludeRegs[i] &&
1849 strcasecmp(s,options.excludeRegs[i]) == 0)
1855 /*-----------------------------------------------------------------*/
1856 /* genFunction - generated code for function entry */
1857 /*-----------------------------------------------------------------*/
1858 static void genFunction (iCode *ic)
1864 /* create the function header */
1865 emitcode(";","-----------------------------------------");
1866 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1867 emitcode(";","-----------------------------------------");
1869 emitcode("","%s:",sym->rname);
1870 fetype = getSpec(operandType(IC_LEFT(ic)));
1872 /* if critical function then turn interrupts off */
1873 if (SPEC_CRTCL(fetype))
1874 emitcode("clr","ea");
1876 /* here we need to generate the equates for the
1877 register bank if required */
1878 if (SPEC_BANK(fetype) != rbank) {
1881 rbank = SPEC_BANK(fetype);
1882 for ( i = 0 ; i < mcs51_nRegs ; i++ ) {
1883 if (strcmp(regs8051[i].base,"0") == 0)
1884 emitcode("","%s = 0x%02x",
1886 8*rbank+regs8051[i].offset);
1888 emitcode ("","%s = %s + 0x%02x",
1891 8*rbank+regs8051[i].offset);
1895 /* if this is an interrupt service routine then
1896 save acc, b, dpl, dph */
1897 if (IS_ISR(sym->etype)) {
1899 if (!inExcludeList("acc"))
1900 emitcode ("push","acc");
1901 if (!inExcludeList("b"))
1902 emitcode ("push","b");
1903 if (!inExcludeList("dpl"))
1904 emitcode ("push","dpl");
1905 if (!inExcludeList("dph"))
1906 emitcode ("push","dph");
1908 /* if this isr has no bank i.e. is going to
1909 run with bank 0 , then we need to save more
1911 if (!SPEC_BANK(sym->etype)) {
1913 /* if this function does not call any other
1914 function then we can be economical and
1915 save only those registers that are used */
1916 if (! sym->hasFcall) {
1919 /* if any registers used */
1920 if (sym->regsUsed) {
1921 /* save the registers used */
1922 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
1923 if (bitVectBitValue(sym->regsUsed,i) ||
1924 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
1925 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
1930 /* this function has a function call cannot
1931 determines register usage so we will have the
1933 saverbank(0,ic,FALSE);
1937 /* if callee-save to be used for this function
1938 then save the registers being used in this function */
1939 if (sym->calleeSave) {
1942 /* if any registers used */
1943 if (sym->regsUsed) {
1944 /* save the registers used */
1945 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
1946 if (bitVectBitValue(sym->regsUsed,i) ||
1947 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
1948 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
1956 /* set the register bank to the desired value */
1957 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
1958 emitcode("push","psw");
1959 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
1962 if (IS_RENT(sym->etype) || options.stackAuto) {
1964 if (options.useXstack) {
1965 emitcode("mov","r0,%s",spname);
1966 emitcode("mov","a,_bp");
1967 emitcode("movx","@r0,a");
1968 emitcode("inc","%s",spname);
1971 /* set up the stack */
1972 emitcode ("push","_bp"); /* save the callers stack */
1973 emitcode ("mov","_bp,%s",spname);
1976 /* adjust the stack for the function */
1981 werror(W_STACK_OVERFLOW,sym->name);
1983 if (i > 3 && sym->recvSize < 4) {
1985 emitcode ("mov","a,sp");
1986 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
1987 emitcode ("mov","sp,a");
1992 emitcode("inc","sp");
1997 emitcode ("mov","a,_spx");
1998 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
1999 emitcode ("mov","_spx,a");
2004 /*-----------------------------------------------------------------*/
2005 /* genEndFunction - generates epilogue for functions */
2006 /*-----------------------------------------------------------------*/
2007 static void genEndFunction (iCode *ic)
2009 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2011 if (IS_RENT(sym->etype) || options.stackAuto)
2012 emitcode ("mov","%s,_bp",spname);
2014 /* if use external stack but some variables were
2015 added to the local stack then decrement the
2017 if (options.useXstack && sym->stack) {
2018 emitcode("mov","a,sp");
2019 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2020 emitcode("mov","sp,a");
2024 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2025 if (options.useXstack) {
2026 emitcode("mov","r0,%s",spname);
2027 emitcode("movx","a,@r0");
2028 emitcode("mov","_bp,a");
2029 emitcode("dec","%s",spname);
2032 emitcode ("pop","_bp");
2035 /* restore the register bank */
2036 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2037 emitcode ("pop","psw");
2039 if (IS_ISR(sym->etype)) {
2041 /* now we need to restore the registers */
2042 /* if this isr has no bank i.e. is going to
2043 run with bank 0 , then we need to save more
2045 if (!SPEC_BANK(sym->etype)) {
2047 /* if this function does not call any other
2048 function then we can be economical and
2049 save only those registers that are used */
2050 if (! sym->hasFcall) {
2053 /* if any registers used */
2054 if (sym->regsUsed) {
2055 /* save the registers used */
2056 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2057 if (bitVectBitValue(sym->regsUsed,i) ||
2058 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2059 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
2064 /* this function has a function call cannot
2065 determines register usage so we will have the
2067 unsaverbank(0,ic,FALSE);
2071 if (!inExcludeList("dph"))
2072 emitcode ("pop","dph");
2073 if (!inExcludeList("dpl"))
2074 emitcode ("pop","dpl");
2075 if (!inExcludeList("b"))
2076 emitcode ("pop","b");
2077 if (!inExcludeList("acc"))
2078 emitcode ("pop","acc");
2080 if (SPEC_CRTCL(sym->etype))
2081 emitcode("setb","ea");
2083 /* if debug then send end of function */
2084 /* if (options.debug && currFunc) { */
2087 emitcode("","C$%s$%d$%d$%d ==.",
2088 ic->filename,currFunc->lastLine,
2089 ic->level,ic->block);
2090 if (IS_STATIC(currFunc->etype))
2091 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2093 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2097 emitcode ("reti","");
2100 if (SPEC_CRTCL(sym->etype))
2101 emitcode("setb","ea");
2103 if (sym->calleeSave) {
2106 /* if any registers used */
2107 if (sym->regsUsed) {
2108 /* save the registers used */
2109 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2110 if (bitVectBitValue(sym->regsUsed,i) ||
2111 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2112 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
2118 /* if debug then send end of function */
2119 /* if (options.debug && currFunc) { */
2122 emitcode("","C$%s$%d$%d$%d ==.",
2123 ic->filename,currFunc->lastLine,
2124 ic->level,ic->block);
2125 if (IS_STATIC(currFunc->etype))
2126 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2128 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2132 emitcode ("ret","");
2137 /*-----------------------------------------------------------------*/
2138 /* genRet - generate code for return statement */
2139 /*-----------------------------------------------------------------*/
2140 static void genRet (iCode *ic)
2142 int size,offset = 0 , pushed = 0;
2144 /* if we have no return value then
2145 just generate the "ret" */
2149 /* we have something to return then
2150 move the return value into place */
2151 aopOp(IC_LEFT(ic),ic,FALSE);
2152 size = AOP_SIZE(IC_LEFT(ic));
2156 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2157 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2159 emitcode("push","%s",l);
2162 l = aopGet(AOP(IC_LEFT(ic)),offset,
2164 if (strcmp(fReturn[offset],l))
2165 emitcode("mov","%s,%s",fReturn[offset++],l);
2172 if (strcmp(fReturn[pushed],"a"))
2173 emitcode("pop",fReturn[pushed]);
2175 emitcode("pop","acc");
2178 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2181 /* generate a jump to the return label
2182 if the next is not the return statement */
2183 if (!(ic->next && ic->next->op == LABEL &&
2184 IC_LABEL(ic->next) == returnLabel))
2186 emitcode("ljmp","%05d$",(returnLabel->key+100));
2190 /*-----------------------------------------------------------------*/
2191 /* genLabel - generates a label */
2192 /*-----------------------------------------------------------------*/
2193 static void genLabel (iCode *ic)
2195 /* special case never generate */
2196 if (IC_LABEL(ic) == entryLabel)
2199 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2202 /*-----------------------------------------------------------------*/
2203 /* genGoto - generates a ljmp */
2204 /*-----------------------------------------------------------------*/
2205 static void genGoto (iCode *ic)
2207 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2210 /*-----------------------------------------------------------------*/
2211 /* genPlusIncr :- does addition with increment if possible */
2212 /*-----------------------------------------------------------------*/
2213 static bool genPlusIncr (iCode *ic)
2215 unsigned int icount ;
2216 unsigned int size = getDataSize(IC_RESULT(ic));
2218 /* will try to generate an increment */
2219 /* if the right side is not a literal
2221 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2224 /* if the literal value of the right hand side
2225 is greater than 4 then it is not worth it */
2226 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2229 /* if increment 16 bits in register */
2230 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2233 symbol *tlbl = newiTempLabel(NULL);
2234 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2235 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2236 IS_AOP_PREG(IC_RESULT(ic)))
2237 emitcode("cjne","%s,#0x00,%05d$"
2238 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2241 emitcode("clr","a");
2242 emitcode("cjne","a,%s,%05d$"
2243 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2247 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2249 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2250 IS_AOP_PREG(IC_RESULT(ic)))
2251 emitcode("cjne","%s,#0x00,%05d$"
2252 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2255 emitcode("cjne","a,%s,%05d$"
2256 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2259 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2260 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2261 IS_AOP_PREG(IC_RESULT(ic)))
2262 emitcode("cjne","%s,#0x00,%05d$"
2263 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2266 emitcode("cjne","a,%s,%05d$"
2267 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2270 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2272 emitcode("","%05d$:",tlbl->key+100);
2276 /* if the sizes are greater than 1 then we cannot */
2277 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2278 AOP_SIZE(IC_LEFT(ic)) > 1 )
2281 /* we can if the aops of the left & result match or
2282 if they are in registers and the registers are the
2284 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2287 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2288 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2289 aopPut(AOP(IC_RESULT(ic)),"a",0);
2293 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2302 /*-----------------------------------------------------------------*/
2303 /* outBitAcc - output a bit in acc */
2304 /*-----------------------------------------------------------------*/
2305 static void outBitAcc(operand *result)
2307 symbol *tlbl = newiTempLabel(NULL);
2308 /* if the result is a bit */
2309 if (AOP_TYPE(result) == AOP_CRY){
2310 aopPut(AOP(result),"a",0);
2313 emitcode("jz","%05d$",tlbl->key+100);
2314 emitcode("mov","a,%s",one);
2315 emitcode("","%05d$:",tlbl->key+100);
2320 /*-----------------------------------------------------------------*/
2321 /* genPlusBits - generates code for addition of two bits */
2322 /*-----------------------------------------------------------------*/
2323 static void genPlusBits (iCode *ic)
2325 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2326 symbol *lbl = newiTempLabel(NULL);
2327 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2328 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2329 emitcode("cpl","c");
2330 emitcode("","%05d$:",(lbl->key+100));
2331 outBitC(IC_RESULT(ic));
2334 emitcode("clr","a");
2335 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2336 emitcode("rlc","a");
2337 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2338 emitcode("addc","a,#0x00");
2339 outAcc(IC_RESULT(ic));
2343 /*-----------------------------------------------------------------*/
2344 /* genPlus - generates code for addition */
2345 /*-----------------------------------------------------------------*/
2346 static void genPlus (iCode *ic)
2348 int size, offset = 0;
2350 /* special cases :- */
2352 aopOp (IC_LEFT(ic),ic,FALSE);
2353 aopOp (IC_RIGHT(ic),ic,FALSE);
2354 aopOp (IC_RESULT(ic),ic,TRUE);
2356 /* if literal, literal on the right or
2357 if left requires ACC or right is already
2359 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2360 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2361 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2362 operand *t = IC_RIGHT(ic);
2363 IC_RIGHT(ic) = IC_LEFT(ic);
2367 /* if both left & right are in bit
2369 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2370 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2375 /* if left in bit space & right literal */
2376 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2377 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2378 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2379 /* if result in bit space */
2380 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2381 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
2382 emitcode("cpl","c");
2383 outBitC(IC_RESULT(ic));
2385 size = getDataSize(IC_RESULT(ic));
2387 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2388 emitcode("addc","a,#00");
2389 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2395 /* if I can do an increment instead
2396 of add then GOOD for ME */
2397 if (genPlusIncr (ic) == TRUE)
2400 size = getDataSize(IC_RESULT(ic));
2403 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2404 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2406 emitcode("add","a,%s",
2407 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2409 emitcode("addc","a,%s",
2410 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2412 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2414 emitcode("add","a,%s",
2415 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2417 emitcode("addc","a,%s",
2418 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2420 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2423 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2424 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2425 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2426 aopPut(AOP(IC_RESULT(ic)),
2427 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2430 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2431 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
2432 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2433 aopPut(AOP(IC_RESULT(ic)),
2434 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2437 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2438 AOP_SIZE(IC_LEFT(ic)) < 3 &&
2439 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
2440 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2441 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2443 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2444 aopPut(AOP(IC_RESULT(ic)),buffer,2);
2447 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2448 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2449 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2452 /*-----------------------------------------------------------------*/
2453 /* genMinusDec :- does subtraction with deccrement if possible */
2454 /*-----------------------------------------------------------------*/
2455 static bool genMinusDec (iCode *ic)
2457 unsigned int icount ;
2458 unsigned int size = getDataSize(IC_RESULT(ic));
2460 /* will try to generate an increment */
2461 /* if the right side is not a literal
2463 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2466 /* if the literal value of the right hand side
2467 is greater than 4 then it is not worth it */
2468 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2471 size = getDataSize(IC_RESULT(ic));
2472 /* if decrement 16 bits in register */
2473 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2476 symbol *tlbl = newiTempLabel(NULL);
2477 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2478 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2479 IS_AOP_PREG(IC_RESULT(ic)))
2480 emitcode("cjne","%s,#0xff,%05d$"
2481 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2484 emitcode("mov","a,#0xff");
2485 emitcode("cjne","a,%s,%05d$"
2486 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2489 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2491 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2492 IS_AOP_PREG(IC_RESULT(ic)))
2493 emitcode("cjne","%s,#0xff,%05d$"
2494 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2497 emitcode("cjne","a,%s,%05d$"
2498 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2501 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2502 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2503 IS_AOP_PREG(IC_RESULT(ic)))
2504 emitcode("cjne","%s,#0xff,%05d$"
2505 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2508 emitcode("cjne","a,%s,%05d$"
2509 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2512 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2514 emitcode("","%05d$:",tlbl->key+100);
2518 /* if the sizes are greater than 1 then we cannot */
2519 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2520 AOP_SIZE(IC_LEFT(ic)) > 1 )
2523 /* we can if the aops of the left & result match or
2524 if they are in registers and the registers are the
2526 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2529 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2537 /*-----------------------------------------------------------------*/
2538 /* addSign - complete with sign */
2539 /*-----------------------------------------------------------------*/
2540 static void addSign(operand *result, int offset, int sign)
2542 int size = (getDataSize(result) - offset);
2545 emitcode("rlc","a");
2546 emitcode("subb","a,acc");
2548 aopPut(AOP(result),"a",offset++);
2551 aopPut(AOP(result),zero,offset++);
2555 /*-----------------------------------------------------------------*/
2556 /* genMinusBits - generates code for subtraction of two bits */
2557 /*-----------------------------------------------------------------*/
2558 static void genMinusBits (iCode *ic)
2560 symbol *lbl = newiTempLabel(NULL);
2561 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2562 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2563 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2564 emitcode("cpl","c");
2565 emitcode("","%05d$:",(lbl->key+100));
2566 outBitC(IC_RESULT(ic));
2569 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2570 emitcode("subb","a,acc");
2571 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
2572 emitcode("inc","a");
2573 emitcode("","%05d$:",(lbl->key+100));
2574 aopPut(AOP(IC_RESULT(ic)),"a",0);
2575 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
2579 /*-----------------------------------------------------------------*/
2580 /* genMinus - generates code for subtraction */
2581 /*-----------------------------------------------------------------*/
2582 static void genMinus (iCode *ic)
2584 int size, offset = 0;
2585 unsigned long lit = 0L;
2587 aopOp (IC_LEFT(ic),ic,FALSE);
2588 aopOp (IC_RIGHT(ic),ic,FALSE);
2589 aopOp (IC_RESULT(ic),ic,TRUE);
2591 /* special cases :- */
2592 /* if both left & right are in bit space */
2593 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2594 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2599 /* if I can do an decrement instead
2600 of subtract then GOOD for ME */
2601 if (genMinusDec (ic) == TRUE)
2604 size = getDataSize(IC_RESULT(ic));
2606 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
2610 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2614 /* if literal, add a,#-lit, else normal subb */
2616 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2617 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2618 emitcode("subb","a,%s",
2619 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2621 /* first add without previous c */
2623 emitcode("add","a,#0x%02x",
2624 (unsigned int)(lit & 0x0FFL));
2626 emitcode("addc","a,#0x%02x",
2627 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
2629 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2632 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2633 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2634 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2635 aopPut(AOP(IC_RESULT(ic)),
2636 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2639 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2640 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
2641 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2642 aopPut(AOP(IC_RESULT(ic)),
2643 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2646 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2647 AOP_SIZE(IC_LEFT(ic)) < 3 &&
2648 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
2649 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2650 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2652 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2653 aopPut(AOP(IC_RESULT(ic)),buffer,2);
2656 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2657 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2658 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2662 /*-----------------------------------------------------------------*/
2663 /* genMultbits :- multiplication of bits */
2664 /*-----------------------------------------------------------------*/
2665 static void genMultbits (operand *left,
2669 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2670 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
2675 /*-----------------------------------------------------------------*/
2676 /* genMultOneByte : 8 bit multiplication & division */
2677 /*-----------------------------------------------------------------*/
2678 static void genMultOneByte (operand *left,
2682 link *opetype = operandType(result);
2687 /* (if two literals, the value is computed before) */
2688 /* if one literal, literal on the right */
2689 if (AOP_TYPE(left) == AOP_LIT){
2695 size = AOP_SIZE(result);
2696 /* signed or unsigned */
2697 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2698 l = aopGet(AOP(left),0,FALSE,FALSE);
2700 emitcode("mul","ab");
2701 /* if result size = 1, mul signed = mul unsigned */
2702 aopPut(AOP(result),"a",0);
2704 if (SPEC_USIGN(opetype)){
2705 aopPut(AOP(result),"b",1);
2707 /* for filling the MSBs */
2708 emitcode("clr","a");
2711 emitcode("mov","a,b");
2713 /* adjust the MSB if left or right neg */
2715 /* if one literal */
2716 if (AOP_TYPE(right) == AOP_LIT){
2717 /* AND literal negative */
2718 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
2719 /* adjust MSB (c==0 after mul) */
2720 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2724 lbl = newiTempLabel(NULL);
2725 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2726 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
2727 emitcode("","%05d$:",(lbl->key+100));
2728 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2729 lbl = newiTempLabel(NULL);
2730 emitcode("jc","%05d$",(lbl->key+100));
2731 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2732 emitcode("","%05d$:",(lbl->key+100));
2735 lbl = newiTempLabel(NULL);
2736 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
2737 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
2738 emitcode("","%05d$:",(lbl->key+100));
2739 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
2740 lbl = newiTempLabel(NULL);
2741 emitcode("jc","%05d$",(lbl->key+100));
2742 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
2743 emitcode("","%05d$:",(lbl->key+100));
2745 aopPut(AOP(result),"a",1);
2748 emitcode("rlc","a");
2749 emitcode("subb","a,acc");
2756 aopPut(AOP(result),"a",offset++);
2760 /*-----------------------------------------------------------------*/
2761 /* genMult - generates code for multiplication */
2762 /*-----------------------------------------------------------------*/
2763 static void genMult (iCode *ic)
2765 operand *left = IC_LEFT(ic);
2766 operand *right = IC_RIGHT(ic);
2767 operand *result= IC_RESULT(ic);
2769 /* assign the amsops */
2770 aopOp (left,ic,FALSE);
2771 aopOp (right,ic,FALSE);
2772 aopOp (result,ic,TRUE);
2774 /* special cases first */
2776 if (AOP_TYPE(left) == AOP_CRY &&
2777 AOP_TYPE(right)== AOP_CRY) {
2778 genMultbits(left,right,result);
2782 /* if both are of size == 1 */
2783 if (AOP_SIZE(left) == 1 &&
2784 AOP_SIZE(right) == 1 ) {
2785 genMultOneByte(left,right,result);
2789 /* should have been converted to function call */
2793 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2794 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2795 freeAsmop(result,NULL,ic,TRUE);
2798 /*-----------------------------------------------------------------*/
2799 /* genDivbits :- division of bits */
2800 /*-----------------------------------------------------------------*/
2801 static void genDivbits (operand *left,
2808 /* the result must be bit */
2809 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
2810 l = aopGet(AOP(left),0,FALSE,FALSE);
2814 emitcode("div","ab");
2815 emitcode("rrc","a");
2816 aopPut(AOP(result),"c",0);
2819 /*-----------------------------------------------------------------*/
2820 /* genDivOneByte : 8 bit division */
2821 /*-----------------------------------------------------------------*/
2822 static void genDivOneByte (operand *left,
2826 link *opetype = operandType(result);
2831 size = AOP_SIZE(result) - 1;
2833 /* signed or unsigned */
2834 if (SPEC_USIGN(opetype)) {
2835 /* unsigned is easy */
2836 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2837 l = aopGet(AOP(left),0,FALSE,FALSE);
2839 emitcode("div","ab");
2840 aopPut(AOP(result),"a",0);
2842 aopPut(AOP(result),zero,offset++);
2846 /* signed is a little bit more difficult */
2848 /* save the signs of the operands */
2849 l = aopGet(AOP(left),0,FALSE,FALSE);
2851 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
2852 emitcode("push","acc"); /* save it on the stack */
2854 /* now sign adjust for both left & right */
2855 l = aopGet(AOP(right),0,FALSE,FALSE);
2857 lbl = newiTempLabel(NULL);
2858 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
2859 emitcode("cpl","a");
2860 emitcode("inc","a");
2861 emitcode("","%05d$:",(lbl->key+100));
2862 emitcode("mov","b,a");
2864 /* sign adjust left side */
2865 l = aopGet(AOP(left),0,FALSE,FALSE);
2868 lbl = newiTempLabel(NULL);
2869 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
2870 emitcode("cpl","a");
2871 emitcode("inc","a");
2872 emitcode("","%05d$:",(lbl->key+100));
2874 /* now the division */
2875 emitcode("div","ab");
2876 /* we are interested in the lower order
2878 emitcode("mov","b,a");
2879 lbl = newiTempLabel(NULL);
2880 emitcode("pop","acc");
2881 /* if there was an over flow we don't
2882 adjust the sign of the result */
2883 emitcode("jb","ov,%05d$",(lbl->key+100));
2884 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
2886 emitcode("clr","a");
2887 emitcode("subb","a,b");
2888 emitcode("mov","b,a");
2889 emitcode("","%05d$:",(lbl->key+100));
2891 /* now we are done */
2892 aopPut(AOP(result),"b",0);
2894 emitcode("mov","c,b.7");
2895 emitcode("subb","a,acc");
2898 aopPut(AOP(result),"a",offset++);
2902 /*-----------------------------------------------------------------*/
2903 /* genDiv - generates code for division */
2904 /*-----------------------------------------------------------------*/
2905 static void genDiv (iCode *ic)
2907 operand *left = IC_LEFT(ic);
2908 operand *right = IC_RIGHT(ic);
2909 operand *result= IC_RESULT(ic);
2911 /* assign the amsops */
2912 aopOp (left,ic,FALSE);
2913 aopOp (right,ic,FALSE);
2914 aopOp (result,ic,TRUE);
2916 /* special cases first */
2918 if (AOP_TYPE(left) == AOP_CRY &&
2919 AOP_TYPE(right)== AOP_CRY) {
2920 genDivbits(left,right,result);
2924 /* if both are of size == 1 */
2925 if (AOP_SIZE(left) == 1 &&
2926 AOP_SIZE(right) == 1 ) {
2927 genDivOneByte(left,right,result);
2931 /* should have been converted to function call */
2934 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2935 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2936 freeAsmop(result,NULL,ic,TRUE);
2939 /*-----------------------------------------------------------------*/
2940 /* genModbits :- modulus of bits */
2941 /*-----------------------------------------------------------------*/
2942 static void genModbits (operand *left,
2949 /* the result must be bit */
2950 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
2951 l = aopGet(AOP(left),0,FALSE,FALSE);
2955 emitcode("div","ab");
2956 emitcode("mov","a,b");
2957 emitcode("rrc","a");
2958 aopPut(AOP(result),"c",0);
2961 /*-----------------------------------------------------------------*/
2962 /* genModOneByte : 8 bit modulus */
2963 /*-----------------------------------------------------------------*/
2964 static void genModOneByte (operand *left,
2968 link *opetype = operandType(result);
2972 /* signed or unsigned */
2973 if (SPEC_USIGN(opetype)) {
2974 /* unsigned is easy */
2975 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2976 l = aopGet(AOP(left),0,FALSE,FALSE);
2978 emitcode("div","ab");
2979 aopPut(AOP(result),"b",0);
2983 /* signed is a little bit more difficult */
2985 /* save the signs of the operands */
2986 l = aopGet(AOP(left),0,FALSE,FALSE);
2989 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2990 emitcode("push","acc"); /* save it on the stack */
2992 /* now sign adjust for both left & right */
2993 l = aopGet(AOP(right),0,FALSE,FALSE);
2996 lbl = newiTempLabel(NULL);
2997 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
2998 emitcode("cpl","a");
2999 emitcode("inc","a");
3000 emitcode("","%05d$:",(lbl->key+100));
3001 emitcode("mov","b,a");
3003 /* sign adjust left side */
3004 l = aopGet(AOP(left),0,FALSE,FALSE);
3007 lbl = newiTempLabel(NULL);
3008 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3009 emitcode("cpl","a");
3010 emitcode("inc","a");
3011 emitcode("","%05d$:",(lbl->key+100));
3013 /* now the multiplication */
3014 emitcode("div","ab");
3015 /* we are interested in the lower order
3017 lbl = newiTempLabel(NULL);
3018 emitcode("pop","acc");
3019 /* if there was an over flow we don't
3020 adjust the sign of the result */
3021 emitcode("jb","ov,%05d$",(lbl->key+100));
3022 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3024 emitcode("clr","a");
3025 emitcode("subb","a,b");
3026 emitcode("mov","b,a");
3027 emitcode("","%05d$:",(lbl->key+100));
3029 /* now we are done */
3030 aopPut(AOP(result),"b",0);
3034 /*-----------------------------------------------------------------*/
3035 /* genMod - generates code for division */
3036 /*-----------------------------------------------------------------*/
3037 static void genMod (iCode *ic)
3039 operand *left = IC_LEFT(ic);
3040 operand *right = IC_RIGHT(ic);
3041 operand *result= IC_RESULT(ic);
3043 /* assign the amsops */
3044 aopOp (left,ic,FALSE);
3045 aopOp (right,ic,FALSE);
3046 aopOp (result,ic,TRUE);
3048 /* special cases first */
3050 if (AOP_TYPE(left) == AOP_CRY &&
3051 AOP_TYPE(right)== AOP_CRY) {
3052 genModbits(left,right,result);
3056 /* if both are of size == 1 */
3057 if (AOP_SIZE(left) == 1 &&
3058 AOP_SIZE(right) == 1 ) {
3059 genModOneByte(left,right,result);
3063 /* should have been converted to function call */
3067 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3068 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3069 freeAsmop(result,NULL,ic,TRUE);
3072 /*-----------------------------------------------------------------*/
3073 /* genIfxJump :- will create a jump depending on the ifx */
3074 /*-----------------------------------------------------------------*/
3075 static void genIfxJump (iCode *ic, char *jval)
3078 symbol *tlbl = newiTempLabel(NULL);
3081 /* if true label then we jump if condition
3083 if ( IC_TRUE(ic) ) {
3085 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3086 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3089 /* false label is present */
3090 jlbl = IC_FALSE(ic) ;
3091 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3092 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3094 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3095 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3097 emitcode(inst,"%05d$",tlbl->key+100);
3098 emitcode("ljmp","%05d$",jlbl->key+100);
3099 emitcode("","%05d$:",tlbl->key+100);
3101 /* mark the icode as generated */
3105 /*-----------------------------------------------------------------*/
3106 /* genCmp :- greater or less than comparison */
3107 /*-----------------------------------------------------------------*/
3108 static void genCmp (operand *left,operand *right,
3109 operand *result, iCode *ifx, int sign)
3111 int size, offset = 0 ;
3112 unsigned long lit = 0L;
3114 /* if left & right are bit variables */
3115 if (AOP_TYPE(left) == AOP_CRY &&
3116 AOP_TYPE(right) == AOP_CRY ) {
3117 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3118 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3120 /* subtract right from left if at the
3121 end the carry flag is set then we know that
3122 left is greater than right */
3123 size = max(AOP_SIZE(left),AOP_SIZE(right));
3125 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3126 if((size == 1) && !sign &&
3127 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3128 symbol *lbl = newiTempLabel(NULL);
3129 emitcode("cjne","%s,%s,%05d$",
3130 aopGet(AOP(left),offset,FALSE,FALSE),
3131 aopGet(AOP(right),offset,FALSE,FALSE),
3133 emitcode("","%05d$:",lbl->key+100);
3135 if(AOP_TYPE(right) == AOP_LIT){
3136 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3137 /* optimize if(x < 0) or if(x >= 0) */
3143 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE));
3144 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3145 genIfxJump (ifx,"acc.7");
3149 emitcode("rlc","a");
3156 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3157 if (sign && size == 0) {
3158 emitcode("xrl","a,#0x80");
3159 if (AOP_TYPE(right) == AOP_LIT){
3160 unsigned long lit = (unsigned long)
3161 floatFromVal(AOP(right)->aopu.aop_lit);
3162 emitcode("subb","a,#0x%02x",
3163 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3165 emitcode("mov","b,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3166 emitcode("xrl","b,#0x80");
3167 emitcode("subb","a,b");
3170 emitcode("subb","a,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3176 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3179 /* if the result is used in the next
3180 ifx conditional branch then generate
3181 code a little differently */
3183 genIfxJump (ifx,"c");
3186 /* leave the result in acc */
3190 /*-----------------------------------------------------------------*/
3191 /* genCmpGt :- greater than comparison */
3192 /*-----------------------------------------------------------------*/
3193 static void genCmpGt (iCode *ic, iCode *ifx)
3195 operand *left, *right, *result;
3196 link *letype , *retype;
3200 right= IC_RIGHT(ic);
3201 result = IC_RESULT(ic);
3203 letype = getSpec(operandType(left));
3204 retype =getSpec(operandType(right));
3205 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3206 /* assign the amsops */
3207 aopOp (left,ic,FALSE);
3208 aopOp (right,ic,FALSE);
3209 aopOp (result,ic,TRUE);
3211 genCmp(right, left, result, ifx, sign);
3213 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3214 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3215 freeAsmop(result,NULL,ic,TRUE);
3218 /*-----------------------------------------------------------------*/
3219 /* genCmpLt - less than comparisons */
3220 /*-----------------------------------------------------------------*/
3221 static void genCmpLt (iCode *ic, iCode *ifx)
3223 operand *left, *right, *result;
3224 link *letype , *retype;
3228 right= IC_RIGHT(ic);
3229 result = IC_RESULT(ic);
3231 letype = getSpec(operandType(left));
3232 retype =getSpec(operandType(right));
3233 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3235 /* assign the amsops */
3236 aopOp (left,ic,FALSE);
3237 aopOp (right,ic,FALSE);
3238 aopOp (result,ic,TRUE);
3240 genCmp(left, right, result, ifx, sign);
3242 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3243 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3244 freeAsmop(result,NULL,ic,TRUE);
3247 /*-----------------------------------------------------------------*/
3248 /* gencjneshort - compare and jump if not equal */
3249 /*-----------------------------------------------------------------*/
3250 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3252 int size = max(AOP_SIZE(left),AOP_SIZE(right));
3254 unsigned long lit = 0L;
3256 /* if the left side is a literal or
3257 if the right is in a pointer register and left
3259 if ((AOP_TYPE(left) == AOP_LIT) ||
3260 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3265 if(AOP_TYPE(right) == AOP_LIT)
3266 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3268 /* if the right side is a literal then anything goes */
3269 if (AOP_TYPE(right) == AOP_LIT &&
3270 AOP_TYPE(left) != AOP_DIR ) {
3272 emitcode("cjne","%s,%s,%05d$",
3273 aopGet(AOP(left),offset,FALSE,FALSE),
3274 aopGet(AOP(right),offset,FALSE,FALSE),
3280 /* if the right side is in a register or in direct space or
3281 if the left is a pointer register & right is not */
3282 else if (AOP_TYPE(right) == AOP_REG ||
3283 AOP_TYPE(right) == AOP_DIR ||
3284 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3285 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3287 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3288 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3289 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
3290 emitcode("jnz","%05d$",lbl->key+100);
3292 emitcode("cjne","a,%s,%05d$",
3293 aopGet(AOP(right),offset,FALSE,TRUE),
3298 /* right is a pointer reg need both a & b */
3300 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
3302 emitcode("mov","b,%s",l);
3303 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3304 emitcode("cjne","a,b,%05d$",lbl->key+100);
3310 /*-----------------------------------------------------------------*/
3311 /* gencjne - compare and jump if not equal */
3312 /*-----------------------------------------------------------------*/
3313 static void gencjne(operand *left, operand *right, symbol *lbl)
3315 symbol *tlbl = newiTempLabel(NULL);
3317 gencjneshort(left, right, lbl);
3319 emitcode("mov","a,%s",one);
3320 emitcode("sjmp","%05d$",tlbl->key+100);
3321 emitcode("","%05d$:",lbl->key+100);
3322 emitcode("clr","a");
3323 emitcode("","%05d$:",tlbl->key+100);
3326 /*-----------------------------------------------------------------*/
3327 /* genCmpEq - generates code for equal to */
3328 /*-----------------------------------------------------------------*/
3329 static void genCmpEq (iCode *ic, iCode *ifx)
3331 operand *left, *right, *result;
3333 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3334 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3335 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3337 /* if literal, literal on the right or
3338 if the right is in a pointer register and left
3340 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
3341 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3342 operand *t = IC_RIGHT(ic);
3343 IC_RIGHT(ic) = IC_LEFT(ic);
3347 if(ifx && !AOP_SIZE(result)){
3349 /* if they are both bit variables */
3350 if (AOP_TYPE(left) == AOP_CRY &&
3351 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3352 if(AOP_TYPE(right) == AOP_LIT){
3353 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3355 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3356 emitcode("cpl","c");
3357 } else if(lit == 1L) {
3358 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3360 emitcode("clr","c");
3362 /* AOP_TYPE(right) == AOP_CRY */
3364 symbol *lbl = newiTempLabel(NULL);
3365 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3366 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3367 emitcode("cpl","c");
3368 emitcode("","%05d$:",(lbl->key+100));
3370 /* if true label then we jump if condition
3372 tlbl = newiTempLabel(NULL);
3373 if ( IC_TRUE(ifx) ) {
3374 emitcode("jnc","%05d$",tlbl->key+100);
3375 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3377 emitcode("jc","%05d$",tlbl->key+100);
3378 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3380 emitcode("","%05d$:",tlbl->key+100);
3382 tlbl = newiTempLabel(NULL);
3383 gencjneshort(left, right, tlbl);
3384 if ( IC_TRUE(ifx) ) {
3385 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3386 emitcode("","%05d$:",tlbl->key+100);
3388 symbol *lbl = newiTempLabel(NULL);
3389 emitcode("sjmp","%05d$",lbl->key+100);
3390 emitcode("","%05d$:",tlbl->key+100);
3391 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3392 emitcode("","%05d$:",lbl->key+100);
3395 /* mark the icode as generated */
3400 /* if they are both bit variables */
3401 if (AOP_TYPE(left) == AOP_CRY &&
3402 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3403 if(AOP_TYPE(right) == AOP_LIT){
3404 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3406 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3407 emitcode("cpl","c");
3408 } else if(lit == 1L) {
3409 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3411 emitcode("clr","c");
3413 /* AOP_TYPE(right) == AOP_CRY */
3415 symbol *lbl = newiTempLabel(NULL);
3416 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3417 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3418 emitcode("cpl","c");
3419 emitcode("","%05d$:",(lbl->key+100));
3422 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
3427 genIfxJump (ifx,"c");
3430 /* if the result is used in an arithmetic operation
3431 then put the result in place */
3434 gencjne(left,right,newiTempLabel(NULL));
3435 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3436 aopPut(AOP(result),"a",0);
3440 genIfxJump (ifx,"a");
3443 /* if the result is used in an arithmetic operation
3444 then put the result in place */
3445 if (AOP_TYPE(result) != AOP_CRY)
3447 /* leave the result in acc */
3451 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3452 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3453 freeAsmop(result,NULL,ic,TRUE);
3456 /*-----------------------------------------------------------------*/
3457 /* ifxForOp - returns the icode containing the ifx for operand */
3458 /*-----------------------------------------------------------------*/
3459 static iCode *ifxForOp ( operand *op, iCode *ic )
3461 /* if true symbol then needs to be assigned */
3462 if (IS_TRUE_SYMOP(op))
3465 /* if this has register type condition and
3466 the next instruction is ifx with the same operand
3467 and live to of the operand is upto the ifx only then */
3469 ic->next->op == IFX &&
3470 IC_COND(ic->next)->key == op->key &&
3471 OP_SYMBOL(op)->liveTo <= ic->next->seq )
3476 /*-----------------------------------------------------------------*/
3477 /* genAndOp - for && operation */
3478 /*-----------------------------------------------------------------*/
3479 static void genAndOp (iCode *ic)
3481 operand *left,*right, *result;
3484 /* note here that && operations that are in an
3485 if statement are taken away by backPatchLabels
3486 only those used in arthmetic operations remain */
3487 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3488 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3489 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3491 /* if both are bit variables */
3492 if (AOP_TYPE(left) == AOP_CRY &&
3493 AOP_TYPE(right) == AOP_CRY ) {
3494 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3495 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3498 tlbl = newiTempLabel(NULL);
3500 emitcode("jz","%05d$",tlbl->key+100);
3502 emitcode("","%05d$:",tlbl->key+100);
3506 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3507 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3508 freeAsmop(result,NULL,ic,TRUE);
3512 /*-----------------------------------------------------------------*/
3513 /* genOrOp - for || operation */
3514 /*-----------------------------------------------------------------*/
3515 static void genOrOp (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("orl","c,%s",AOP(right)->aopu.aop_dir);
3534 tlbl = newiTempLabel(NULL);
3536 emitcode("jnz","%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);
3547 /*-----------------------------------------------------------------*/
3548 /* isLiteralBit - test if lit == 2^n */
3549 /*-----------------------------------------------------------------*/
3550 static int isLiteralBit(unsigned long lit)
3552 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
3553 0x100L,0x200L,0x400L,0x800L,
3554 0x1000L,0x2000L,0x4000L,0x8000L,
3555 0x10000L,0x20000L,0x40000L,0x80000L,
3556 0x100000L,0x200000L,0x400000L,0x800000L,
3557 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
3558 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
3561 for(idx = 0; idx < 32; idx++)
3567 /*-----------------------------------------------------------------*/
3568 /* continueIfTrue - */
3569 /*-----------------------------------------------------------------*/
3570 static void continueIfTrue (iCode *ic)
3573 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3577 /*-----------------------------------------------------------------*/
3579 /*-----------------------------------------------------------------*/
3580 static void jumpIfTrue (iCode *ic)
3583 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3587 /*-----------------------------------------------------------------*/
3588 /* jmpTrueOrFalse - */
3589 /*-----------------------------------------------------------------*/
3590 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
3592 // ugly but optimized by peephole
3594 symbol *nlbl = newiTempLabel(NULL);
3595 emitcode("sjmp","%05d$",nlbl->key+100);
3596 emitcode("","%05d$:",tlbl->key+100);
3597 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3598 emitcode("","%05d$:",nlbl->key+100);
3601 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3602 emitcode("","%05d$:",tlbl->key+100);
3607 /*-----------------------------------------------------------------*/
3608 /* genAnd - code for and */
3609 /*-----------------------------------------------------------------*/
3610 static void genAnd (iCode *ic, iCode *ifx)
3612 operand *left, *right, *result;
3614 unsigned long lit = 0L;
3618 aopOp((left = IC_LEFT(ic)),ic,FALSE);
3619 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3620 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3623 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3625 AOP_TYPE(left), AOP_TYPE(right));
3626 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3628 AOP_SIZE(left), AOP_SIZE(right));
3631 /* if left is a literal & right is not then exchange them */
3632 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3633 AOP_NEEDSACC(left)) {
3634 operand *tmp = right ;
3639 /* if result = right then exchange them */
3640 if(sameRegs(AOP(result),AOP(right))){
3641 operand *tmp = right ;
3646 /* if right is bit then exchange them */
3647 if (AOP_TYPE(right) == AOP_CRY &&
3648 AOP_TYPE(left) != AOP_CRY){
3649 operand *tmp = right ;
3653 if(AOP_TYPE(right) == AOP_LIT)
3654 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3656 size = AOP_SIZE(result);
3659 // result = bit & yy;
3660 if (AOP_TYPE(left) == AOP_CRY){
3661 // c = bit & literal;
3662 if(AOP_TYPE(right) == AOP_LIT){
3664 if(size && sameRegs(AOP(result),AOP(left)))
3667 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3670 if(size && (AOP_TYPE(result) == AOP_CRY)){
3671 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
3674 if((AOP_TYPE(result) == AOP_CRY) && ifx){
3678 emitcode("clr","c");
3681 if (AOP_TYPE(right) == AOP_CRY){
3683 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3684 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3687 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
3689 emitcode("rrc","a");
3690 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3698 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
3699 genIfxJump(ifx, "c");
3703 // if(val & 0xZZ) - size = 0, ifx != FALSE -
3704 // bit = val & 0xZZ - size = 1, ifx = FALSE -
3705 if((AOP_TYPE(right) == AOP_LIT) &&
3706 (AOP_TYPE(result) == AOP_CRY) &&
3707 (AOP_TYPE(left) != AOP_CRY)){
3708 int posbit = isLiteralBit(lit);
3712 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
3715 emitcode("mov","c,acc.%d",posbit&0x07);
3719 sprintf(buffer,"acc.%d",posbit&0x07);
3720 genIfxJump(ifx, buffer);
3725 symbol *tlbl = newiTempLabel(NULL);
3726 int sizel = AOP_SIZE(left);
3728 emitcode("setb","c");
3730 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
3731 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
3733 if((posbit = isLiteralBit(bytelit)) != 0)
3734 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
3736 if(bytelit != 0x0FFL)
3737 emitcode("anl","a,%s",
3738 aopGet(AOP(right),offset,FALSE,TRUE));
3739 emitcode("jnz","%05d$",tlbl->key+100);
3744 // bit = left & literal
3746 emitcode("clr","c");
3747 emitcode("","%05d$:",tlbl->key+100);
3749 // if(left & literal)
3752 jmpTrueOrFalse(ifx, tlbl);
3760 /* if left is same as result */
3761 if(sameRegs(AOP(result),AOP(left))){
3762 for(;size--; offset++) {
3763 if(AOP_TYPE(right) == AOP_LIT){
3764 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
3768 aopPut(AOP(result),zero,offset);
3770 if (IS_AOP_PREG(result)) {
3771 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3772 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
3773 aopPut(AOP(result),"a",offset);
3775 emitcode("anl","%s,%s",
3776 aopGet(AOP(left),offset,FALSE,TRUE),
3777 aopGet(AOP(right),offset,FALSE,FALSE));
3779 if (AOP_TYPE(left) == AOP_ACC)
3780 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
3782 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3783 if (IS_AOP_PREG(result)) {
3784 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
3785 aopPut(AOP(result),"a",offset);
3788 emitcode("anl","%s,a",
3789 aopGet(AOP(left),offset,FALSE,TRUE));
3794 // left & result in different registers
3795 if(AOP_TYPE(result) == AOP_CRY){
3797 // if(size), result in bit
3798 // if(!size && ifx), conditional oper: if(left & right)
3799 symbol *tlbl = newiTempLabel(NULL);
3800 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
3802 emitcode("setb","c");
3804 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3805 emitcode("anl","a,%s",
3806 aopGet(AOP(left),offset,FALSE,FALSE));
3807 emitcode("jnz","%05d$",tlbl->key+100);
3812 emitcode("","%05d$:",tlbl->key+100);
3815 jmpTrueOrFalse(ifx, tlbl);
3817 for(;(size--);offset++) {
3819 // result = left & right
3820 if(AOP_TYPE(right) == AOP_LIT){
3821 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
3823 aopGet(AOP(left),offset,FALSE,FALSE),
3826 } else if(bytelit == 0){
3827 aopPut(AOP(result),zero,offset);
3831 // faster than result <- left, anl result,right
3832 // and better if result is SFR
3833 if (AOP_TYPE(left) == AOP_ACC)
3834 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
3836 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3837 emitcode("anl","a,%s",
3838 aopGet(AOP(left),offset,FALSE,FALSE));
3840 aopPut(AOP(result),"a",offset);
3846 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3847 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3848 freeAsmop(result,NULL,ic,TRUE);
3851 /*-----------------------------------------------------------------*/
3852 /* genOr - code for or */
3853 /*-----------------------------------------------------------------*/
3854 static void genOr (iCode *ic, iCode *ifx)
3856 operand *left, *right, *result;
3858 unsigned long lit = 0L;
3860 aopOp((left = IC_LEFT(ic)),ic,FALSE);
3861 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3862 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3865 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3867 AOP_TYPE(left), AOP_TYPE(right));
3868 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3870 AOP_SIZE(left), AOP_SIZE(right));
3873 /* if left is a literal & right is not then exchange them */
3874 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3875 AOP_NEEDSACC(left)) {
3876 operand *tmp = right ;
3881 /* if result = right then exchange them */
3882 if(sameRegs(AOP(result),AOP(right))){
3883 operand *tmp = right ;
3888 /* if right is bit then exchange them */
3889 if (AOP_TYPE(right) == AOP_CRY &&
3890 AOP_TYPE(left) != AOP_CRY){
3891 operand *tmp = right ;
3895 if(AOP_TYPE(right) == AOP_LIT)
3896 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3898 size = AOP_SIZE(result);
3902 if (AOP_TYPE(left) == AOP_CRY){
3903 if(AOP_TYPE(right) == AOP_LIT){
3904 // c = bit & literal;
3906 // lit != 0 => result = 1
3907 if(AOP_TYPE(result) == AOP_CRY){
3909 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
3911 continueIfTrue(ifx);
3914 emitcode("setb","c");
3916 // lit == 0 => result = left
3917 if(size && sameRegs(AOP(result),AOP(left)))
3919 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3922 if (AOP_TYPE(right) == AOP_CRY){
3924 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3925 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
3929 symbol *tlbl = newiTempLabel(NULL);
3930 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
3931 emitcode("setb","c");
3932 emitcode("jb","%s,%05d$",
3933 AOP(left)->aopu.aop_dir,tlbl->key+100);
3935 emitcode("jnz","%05d$",tlbl->key+100);
3936 if((AOP_TYPE(result) == AOP_CRY) && ifx){
3937 jmpTrueOrFalse(ifx, tlbl);
3941 emitcode("","%05d$:",tlbl->key+100);
3950 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
3951 genIfxJump(ifx, "c");
3955 // if(val | 0xZZ) - size = 0, ifx != FALSE -
3956 // bit = val | 0xZZ - size = 1, ifx = FALSE -
3957 if((AOP_TYPE(right) == AOP_LIT) &&
3958 (AOP_TYPE(result) == AOP_CRY) &&
3959 (AOP_TYPE(left) != AOP_CRY)){
3963 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
3965 continueIfTrue(ifx);
3968 // lit = 0, result = boolean(left)
3970 emitcode("setb","c");
3973 symbol *tlbl = newiTempLabel(NULL);
3974 emitcode("jnz","%05d$",tlbl->key+100);
3976 emitcode("","%05d$:",tlbl->key+100);
3978 genIfxJump (ifx,"a");
3986 /* if left is same as result */
3987 if(sameRegs(AOP(result),AOP(left))){
3988 for(;size--; offset++) {
3989 if(AOP_TYPE(right) == AOP_LIT){
3990 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
3993 if (IS_AOP_PREG(left)) {
3994 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3995 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
3996 aopPut(AOP(result),"a",offset);
3998 emitcode("orl","%s,%s",
3999 aopGet(AOP(left),offset,FALSE,TRUE),
4000 aopGet(AOP(right),offset,FALSE,FALSE));
4002 if (AOP_TYPE(left) == AOP_ACC)
4003 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4005 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4006 if (IS_AOP_PREG(left)) {
4007 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4008 aopPut(AOP(result),"a",offset);
4010 emitcode("orl","%s,a",
4011 aopGet(AOP(left),offset,FALSE,TRUE));
4016 // left & result in different registers
4017 if(AOP_TYPE(result) == AOP_CRY){
4019 // if(size), result in bit
4020 // if(!size && ifx), conditional oper: if(left | right)
4021 symbol *tlbl = newiTempLabel(NULL);
4022 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4024 emitcode("setb","c");
4026 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4027 emitcode("orl","a,%s",
4028 aopGet(AOP(left),offset,FALSE,FALSE));
4029 emitcode("jnz","%05d$",tlbl->key+100);
4034 emitcode("","%05d$:",tlbl->key+100);
4037 jmpTrueOrFalse(ifx, tlbl);
4038 } else for(;(size--);offset++){
4040 // result = left & right
4041 if(AOP_TYPE(right) == AOP_LIT){
4042 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4044 aopGet(AOP(left),offset,FALSE,FALSE),
4049 // faster than result <- left, anl result,right
4050 // and better if result is SFR
4051 if (AOP_TYPE(left) == AOP_ACC)
4052 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4054 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4055 emitcode("orl","a,%s",
4056 aopGet(AOP(left),offset,FALSE,FALSE));
4058 aopPut(AOP(result),"a",offset);
4063 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4064 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4065 freeAsmop(result,NULL,ic,TRUE);
4068 /*-----------------------------------------------------------------*/
4069 /* genXor - code for xclusive or */
4070 /*-----------------------------------------------------------------*/
4071 static void genXor (iCode *ic, iCode *ifx)
4073 operand *left, *right, *result;
4075 unsigned long lit = 0L;
4077 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4078 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4079 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4082 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4084 AOP_TYPE(left), AOP_TYPE(right));
4085 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4087 AOP_SIZE(left), AOP_SIZE(right));
4090 /* if left is a literal & right is not ||
4091 if left needs acc & right does not */
4092 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4093 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4094 operand *tmp = right ;
4099 /* if result = right then exchange them */
4100 if(sameRegs(AOP(result),AOP(right))){
4101 operand *tmp = right ;
4106 /* if right is bit then exchange them */
4107 if (AOP_TYPE(right) == AOP_CRY &&
4108 AOP_TYPE(left) != AOP_CRY){
4109 operand *tmp = right ;
4113 if(AOP_TYPE(right) == AOP_LIT)
4114 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4116 size = AOP_SIZE(result);
4120 if (AOP_TYPE(left) == AOP_CRY){
4121 if(AOP_TYPE(right) == AOP_LIT){
4122 // c = bit & literal;
4124 // lit>>1 != 0 => result = 1
4125 if(AOP_TYPE(result) == AOP_CRY){
4127 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4129 continueIfTrue(ifx);
4132 emitcode("setb","c");
4136 // lit == 0, result = left
4137 if(size && sameRegs(AOP(result),AOP(left)))
4139 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4141 // lit == 1, result = not(left)
4142 if(size && sameRegs(AOP(result),AOP(left))){
4143 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4146 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4147 emitcode("cpl","c");
4154 symbol *tlbl = newiTempLabel(NULL);
4155 if (AOP_TYPE(right) == AOP_CRY){
4157 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4160 int sizer = AOP_SIZE(right);
4162 // if val>>1 != 0, result = 1
4163 emitcode("setb","c");
4165 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
4167 // test the msb of the lsb
4168 emitcode("anl","a,#0xfe");
4169 emitcode("jnz","%05d$",tlbl->key+100);
4173 emitcode("rrc","a");
4175 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4176 emitcode("cpl","c");
4177 emitcode("","%05d$:",(tlbl->key+100));
4184 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4185 genIfxJump(ifx, "c");
4189 if(sameRegs(AOP(result),AOP(left))){
4190 /* if left is same as result */
4191 for(;size--; offset++) {
4192 if(AOP_TYPE(right) == AOP_LIT){
4193 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4196 if (IS_AOP_PREG(left)) {
4197 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4198 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4199 aopPut(AOP(result),"a",offset);
4201 emitcode("xrl","%s,%s",
4202 aopGet(AOP(left),offset,FALSE,TRUE),
4203 aopGet(AOP(right),offset,FALSE,FALSE));
4205 if (AOP_TYPE(left) == AOP_ACC)
4206 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4208 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4209 if (IS_AOP_PREG(left)) {
4210 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4211 aopPut(AOP(result),"a",offset);
4213 emitcode("xrl","%s,a",
4214 aopGet(AOP(left),offset,FALSE,TRUE));
4219 // left & result in different registers
4220 if(AOP_TYPE(result) == AOP_CRY){
4222 // if(size), result in bit
4223 // if(!size && ifx), conditional oper: if(left ^ right)
4224 symbol *tlbl = newiTempLabel(NULL);
4225 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4227 emitcode("setb","c");
4229 if((AOP_TYPE(right) == AOP_LIT) &&
4230 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4231 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4233 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4234 emitcode("xrl","a,%s",
4235 aopGet(AOP(left),offset,FALSE,FALSE));
4237 emitcode("jnz","%05d$",tlbl->key+100);
4242 emitcode("","%05d$:",tlbl->key+100);
4245 jmpTrueOrFalse(ifx, tlbl);
4246 } else for(;(size--);offset++){
4248 // result = left & right
4249 if(AOP_TYPE(right) == AOP_LIT){
4250 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4252 aopGet(AOP(left),offset,FALSE,FALSE),
4257 // faster than result <- left, anl result,right
4258 // and better if result is SFR
4259 if (AOP_TYPE(left) == AOP_ACC)
4260 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4262 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4263 emitcode("xrl","a,%s",
4264 aopGet(AOP(left),offset,FALSE,TRUE));
4266 aopPut(AOP(result),"a",offset);
4271 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4272 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4273 freeAsmop(result,NULL,ic,TRUE);
4276 /*-----------------------------------------------------------------*/
4277 /* genInline - write the inline code out */
4278 /*-----------------------------------------------------------------*/
4279 static void genInline (iCode *ic)
4281 char buffer[MAX_INLINEASM];
4285 _G.inLine += (!options.asmpeep);
4286 strcpy(buffer,IC_INLINE(ic));
4288 /* emit each line as a code */
4307 /* emitcode("",buffer); */
4308 _G.inLine -= (!options.asmpeep);
4311 /*-----------------------------------------------------------------*/
4312 /* genRRC - rotate right with carry */
4313 /*-----------------------------------------------------------------*/
4314 static void genRRC (iCode *ic)
4316 operand *left , *result ;
4317 int size, offset = 0;
4320 /* rotate right with carry */
4322 result=IC_RESULT(ic);
4323 aopOp (left,ic,FALSE);
4324 aopOp (result,ic,FALSE);
4326 /* move it to the result */
4327 size = AOP_SIZE(result);
4331 l = aopGet(AOP(left),offset,FALSE,FALSE);
4333 emitcode("rrc","a");
4334 if (AOP_SIZE(result) > 1)
4335 aopPut(AOP(result),"a",offset--);
4337 /* now we need to put the carry into the
4338 highest order byte of the result */
4339 if (AOP_SIZE(result) > 1) {
4340 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
4343 emitcode("mov","acc.7,c");
4344 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
4345 freeAsmop(left,NULL,ic,TRUE);
4346 freeAsmop(result,NULL,ic,TRUE);
4349 /*-----------------------------------------------------------------*/
4350 /* genRLC - generate code for rotate left with carry */
4351 /*-----------------------------------------------------------------*/
4352 static void genRLC (iCode *ic)
4354 operand *left , *result ;
4355 int size, offset = 0;
4358 /* rotate right with carry */
4360 result=IC_RESULT(ic);
4361 aopOp (left,ic,FALSE);
4362 aopOp (result,ic,FALSE);
4364 /* move it to the result */
4365 size = AOP_SIZE(result);
4368 l = aopGet(AOP(left),offset,FALSE,FALSE);
4370 emitcode("add","a,acc");
4371 if (AOP_SIZE(result) > 1)
4372 aopPut(AOP(result),"a",offset++);
4374 l = aopGet(AOP(left),offset,FALSE,FALSE);
4376 emitcode("rlc","a");
4377 if (AOP_SIZE(result) > 1)
4378 aopPut(AOP(result),"a",offset++);
4381 /* now we need to put the carry into the
4382 highest order byte of the result */
4383 if (AOP_SIZE(result) > 1) {
4384 l = aopGet(AOP(result),0,FALSE,FALSE);
4387 emitcode("mov","acc.0,c");
4388 aopPut(AOP(result),"a",0);
4389 freeAsmop(left,NULL,ic,TRUE);
4390 freeAsmop(result,NULL,ic,TRUE);
4393 /*-----------------------------------------------------------------*/
4394 /* genGetHbit - generates code get highest order bit */
4395 /*-----------------------------------------------------------------*/
4396 static void genGetHbit (iCode *ic)
4398 operand *left, *result;
4400 result=IC_RESULT(ic);
4401 aopOp (left,ic,FALSE);
4402 aopOp (result,ic,FALSE);
4404 /* get the highest order byte into a */
4405 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
4406 if(AOP_TYPE(result) == AOP_CRY){
4407 emitcode("rlc","a");
4412 emitcode("anl","a,#0x01");
4417 freeAsmop(left,NULL,ic,TRUE);
4418 freeAsmop(result,NULL,ic,TRUE);
4421 /*-----------------------------------------------------------------*/
4422 /* AccRol - rotate left accumulator by known count */
4423 /*-----------------------------------------------------------------*/
4424 static void AccRol (int shCount)
4426 shCount &= 0x0007; // shCount : 0..7
4438 emitcode("swap","a");
4442 emitcode("swap","a");
4445 emitcode("swap","a");
4458 /*-----------------------------------------------------------------*/
4459 /* AccLsh - left shift accumulator by known count */
4460 /*-----------------------------------------------------------------*/
4461 static void AccLsh (int shCount)
4465 emitcode("add","a,acc");
4468 emitcode("add","a,acc");
4469 emitcode("add","a,acc");
4471 /* rotate left accumulator */
4473 /* and kill the lower order bits */
4474 emitcode("anl","a,#0x%02x", SLMask[shCount]);
4479 /*-----------------------------------------------------------------*/
4480 /* AccRsh - right shift accumulator by known count */
4481 /*-----------------------------------------------------------------*/
4482 static void AccRsh (int shCount)
4487 emitcode("rrc","a");
4489 /* rotate right accumulator */
4490 AccRol(8 - shCount);
4491 /* and kill the higher order bits */
4492 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4497 /*-----------------------------------------------------------------*/
4498 /* AccSRsh - signed right shift accumulator by known count */
4499 /*-----------------------------------------------------------------*/
4500 static void AccSRsh (int shCount)
4505 emitcode("mov","c,acc.7");
4506 emitcode("rrc","a");
4507 } else if(shCount == 2){
4508 emitcode("mov","c,acc.7");
4509 emitcode("rrc","a");
4510 emitcode("mov","c,acc.7");
4511 emitcode("rrc","a");
4513 tlbl = newiTempLabel(NULL);
4514 /* rotate right accumulator */
4515 AccRol(8 - shCount);
4516 /* and kill the higher order bits */
4517 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4518 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4519 emitcode("orl","a,#0x%02x",
4520 (unsigned char)~SRMask[shCount]);
4521 emitcode("","%05d$:",tlbl->key+100);
4526 /*-----------------------------------------------------------------*/
4527 /* shiftR1Left2Result - shift right one byte from left to result */
4528 /*-----------------------------------------------------------------*/
4529 static void shiftR1Left2Result (operand *left, int offl,
4530 operand *result, int offr,
4531 int shCount, int sign)
4533 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4534 /* shift right accumulator */
4539 aopPut(AOP(result),"a",offr);
4542 /*-----------------------------------------------------------------*/
4543 /* shiftL1Left2Result - shift left one byte from left to result */
4544 /*-----------------------------------------------------------------*/
4545 static void shiftL1Left2Result (operand *left, int offl,
4546 operand *result, int offr, int shCount)
4549 l = aopGet(AOP(left),offl,FALSE,FALSE);
4551 /* shift left accumulator */
4553 aopPut(AOP(result),"a",offr);
4556 /*-----------------------------------------------------------------*/
4557 /* movLeft2Result - move byte from left to result */
4558 /*-----------------------------------------------------------------*/
4559 static void movLeft2Result (operand *left, int offl,
4560 operand *result, int offr, int sign)
4563 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
4564 l = aopGet(AOP(left),offl,FALSE,FALSE);
4566 if (*l == '@' && (IS_AOP_PREG(result))) {
4567 emitcode("mov","a,%s",l);
4568 aopPut(AOP(result),"a",offr);
4571 aopPut(AOP(result),l,offr);
4573 /* MSB sign in acc.7 ! */
4574 if(getDataSize(left) == offl+1){
4575 emitcode("mov","a,%s",l);
4576 aopPut(AOP(result),"a",offr);
4583 /*-----------------------------------------------------------------*/
4584 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
4585 /*-----------------------------------------------------------------*/
4586 static void AccAXRrl1 (char *x)
4588 emitcode("rrc","a");
4589 emitcode("xch","a,%s", x);
4590 emitcode("rrc","a");
4591 emitcode("xch","a,%s", x);
4594 /*-----------------------------------------------------------------*/
4595 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
4596 /*-----------------------------------------------------------------*/
4597 static void AccAXLrl1 (char *x)
4599 emitcode("xch","a,%s",x);
4600 emitcode("rlc","a");
4601 emitcode("xch","a,%s",x);
4602 emitcode("rlc","a");
4605 /*-----------------------------------------------------------------*/
4606 /* AccAXLsh1 - left shift a:x<-0 by 1 */
4607 /*-----------------------------------------------------------------*/
4608 static void AccAXLsh1 (char *x)
4610 emitcode("xch","a,%s",x);
4611 emitcode("add","a,acc");
4612 emitcode("xch","a,%s",x);
4613 emitcode("rlc","a");
4616 /*-----------------------------------------------------------------*/
4617 /* AccAXLsh - left shift a:x by known count (0..7) */
4618 /*-----------------------------------------------------------------*/
4619 static void AccAXLsh (char *x, int shCount)
4633 case 5 : // AAAAABBB:CCCCCDDD
4634 AccRol(shCount); // BBBAAAAA:CCCCCDDD
4635 emitcode("anl","a,#0x%02x",
4636 SLMask[shCount]); // BBB00000:CCCCCDDD
4637 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
4638 AccRol(shCount); // DDDCCCCC:BBB00000
4639 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
4640 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
4641 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
4642 emitcode("anl","a,#0x%02x",
4643 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
4644 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
4645 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
4647 case 6 : // AAAAAABB:CCCCCCDD
4648 emitcode("anl","a,#0x%02x",
4649 SRMask[shCount]); // 000000BB:CCCCCCDD
4650 emitcode("mov","c,acc.0"); // c = B
4651 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
4652 AccAXRrl1(x); // BCCCCCCD:D000000B
4653 AccAXRrl1(x); // BBCCCCCC:DD000000
4655 case 7 : // a:x <<= 7
4656 emitcode("anl","a,#0x%02x",
4657 SRMask[shCount]); // 0000000B:CCCCCCCD
4658 emitcode("mov","c,acc.0"); // c = B
4659 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
4660 AccAXRrl1(x); // BCCCCCCC:D0000000
4667 /*-----------------------------------------------------------------*/
4668 /* AccAXRsh - right shift a:x known count (0..7) */
4669 /*-----------------------------------------------------------------*/
4670 static void AccAXRsh (char *x, int shCount)
4677 AccAXRrl1(x); // 0->a:x
4681 AccAXRrl1(x); // 0->a:x
4683 AccAXRrl1(x); // 0->a:x
4687 case 5 : // AAAAABBB:CCCCCDDD = a:x
4688 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
4689 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
4690 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
4691 emitcode("anl","a,#0x%02x",
4692 SRMask[shCount]); // 000CCCCC:BBBAAAAA
4693 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
4694 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
4695 emitcode("anl","a,#0x%02x",
4696 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
4697 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
4698 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
4699 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
4701 case 6 : // AABBBBBB:CCDDDDDD
4702 emitcode("mov","c,acc.7");
4703 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
4704 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
4705 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
4706 emitcode("anl","a,#0x%02x",
4707 SRMask[shCount]); // 000000AA:BBBBBBCC
4709 case 7 : // ABBBBBBB:CDDDDDDD
4710 emitcode("mov","c,acc.7"); // c = A
4711 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
4712 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
4713 emitcode("anl","a,#0x%02x",
4714 SRMask[shCount]); // 0000000A:BBBBBBBC
4721 /*-----------------------------------------------------------------*/
4722 /* AccAXRshS - right shift signed a:x known count (0..7) */
4723 /*-----------------------------------------------------------------*/
4724 static void AccAXRshS (char *x, int shCount)
4731 emitcode("mov","c,acc.7");
4732 AccAXRrl1(x); // s->a:x
4735 emitcode("mov","c,acc.7");
4736 AccAXRrl1(x); // s->a:x
4737 emitcode("mov","c,acc.7");
4738 AccAXRrl1(x); // s->a:x
4742 case 5 : // AAAAABBB:CCCCCDDD = a:x
4743 tlbl = newiTempLabel(NULL);
4744 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
4745 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
4746 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
4747 emitcode("anl","a,#0x%02x",
4748 SRMask[shCount]); // 000CCCCC:BBBAAAAA
4749 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
4750 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
4751 emitcode("anl","a,#0x%02x",
4752 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
4753 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
4754 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
4755 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
4756 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4757 emitcode("orl","a,#0x%02x",
4758 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
4759 emitcode("","%05d$:",tlbl->key+100);
4760 break; // SSSSAAAA:BBBCCCCC
4761 case 6 : // AABBBBBB:CCDDDDDD
4762 tlbl = newiTempLabel(NULL);
4763 emitcode("mov","c,acc.7");
4764 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
4765 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
4766 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
4767 emitcode("anl","a,#0x%02x",
4768 SRMask[shCount]); // 000000AA:BBBBBBCC
4769 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4770 emitcode("orl","a,#0x%02x",
4771 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
4772 emitcode("","%05d$:",tlbl->key+100);
4774 case 7 : // ABBBBBBB:CDDDDDDD
4775 tlbl = newiTempLabel(NULL);
4776 emitcode("mov","c,acc.7"); // c = A
4777 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
4778 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
4779 emitcode("anl","a,#0x%02x",
4780 SRMask[shCount]); // 0000000A:BBBBBBBC
4781 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4782 emitcode("orl","a,#0x%02x",
4783 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
4784 emitcode("","%05d$:",tlbl->key+100);
4791 /*-----------------------------------------------------------------*/
4792 /* shiftL2Left2Result - shift left two bytes from left to result */
4793 /*-----------------------------------------------------------------*/
4794 static void shiftL2Left2Result (operand *left, int offl,
4795 operand *result, int offr, int shCount)
4797 if(sameRegs(AOP(result), AOP(left)) &&
4798 ((offl + MSB16) == offr)){
4799 /* don't crash result[offr] */
4800 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4801 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4803 movLeft2Result(left,offl, result, offr, 0);
4804 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4806 /* ax << shCount (x = lsb(result))*/
4807 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
4808 aopPut(AOP(result),"a",offr+MSB16);
4812 /*-----------------------------------------------------------------*/
4813 /* shiftR2Left2Result - shift right two bytes from left to result */
4814 /*-----------------------------------------------------------------*/
4815 static void shiftR2Left2Result (operand *left, int offl,
4816 operand *result, int offr,
4817 int shCount, int sign)
4819 if(sameRegs(AOP(result), AOP(left)) &&
4820 ((offl + MSB16) == offr)){
4821 /* don't crash result[offr] */
4822 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4823 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4825 movLeft2Result(left,offl, result, offr, 0);
4826 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4828 /* a:x >> shCount (x = lsb(result))*/
4830 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
4832 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
4833 if(getDataSize(result) > 1)
4834 aopPut(AOP(result),"a",offr+MSB16);
4837 /*-----------------------------------------------------------------*/
4838 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
4839 /*-----------------------------------------------------------------*/
4840 static void shiftLLeftOrResult (operand *left, int offl,
4841 operand *result, int offr, int shCount)
4843 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4844 /* shift left accumulator */
4846 /* or with result */
4847 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
4848 /* back to result */
4849 aopPut(AOP(result),"a",offr);
4852 /*-----------------------------------------------------------------*/
4853 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
4854 /*-----------------------------------------------------------------*/
4855 static void shiftRLeftOrResult (operand *left, int offl,
4856 operand *result, int offr, int shCount)
4858 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4859 /* shift right accumulator */
4861 /* or with result */
4862 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
4863 /* back to result */
4864 aopPut(AOP(result),"a",offr);
4867 /*-----------------------------------------------------------------*/
4868 /* genlshOne - left shift a one byte quantity by known count */
4869 /*-----------------------------------------------------------------*/
4870 static void genlshOne (operand *result, operand *left, int shCount)
4872 shiftL1Left2Result(left, LSB, result, LSB, shCount);
4875 /*-----------------------------------------------------------------*/
4876 /* genlshTwo - left shift two bytes by known amount != 0 */
4877 /*-----------------------------------------------------------------*/
4878 static void genlshTwo (operand *result,operand *left, int shCount)
4880 int size = AOP_SIZE(result);
4885 /* if shCount >= 8 */
4891 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
4893 movLeft2Result(left, LSB, result, MSB16, 0);
4895 aopPut(AOP(result),zero,LSB);
4898 /* 1 <= shCount <= 7 */
4901 shiftL1Left2Result(left, LSB, result, LSB, shCount);
4903 shiftL2Left2Result(left, LSB, result, LSB, shCount);
4907 /*-----------------------------------------------------------------*/
4908 /* shiftLLong - shift left one long from left to result */
4909 /* offl = LSB or MSB16 */
4910 /*-----------------------------------------------------------------*/
4911 static void shiftLLong (operand *left, operand *result, int offr )
4914 int size = AOP_SIZE(result);
4916 if(size >= LSB+offr){
4917 l = aopGet(AOP(left),LSB,FALSE,FALSE);
4919 emitcode("add","a,acc");
4920 if (sameRegs(AOP(left),AOP(result)) &&
4921 size >= MSB16+offr && offr != LSB )
4922 emitcode("xch","a,%s",
4923 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
4925 aopPut(AOP(result),"a",LSB+offr);
4928 if(size >= MSB16+offr){
4929 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
4930 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
4933 emitcode("rlc","a");
4934 if (sameRegs(AOP(left),AOP(result)) &&
4935 size >= MSB24+offr && offr != LSB)
4936 emitcode("xch","a,%s",
4937 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
4939 aopPut(AOP(result),"a",MSB16+offr);
4942 if(size >= MSB24+offr){
4943 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
4944 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
4947 emitcode("rlc","a");
4948 if (sameRegs(AOP(left),AOP(result)) &&
4949 size >= MSB32+offr && offr != LSB )
4950 emitcode("xch","a,%s",
4951 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
4953 aopPut(AOP(result),"a",MSB24+offr);
4956 if(size > MSB32+offr){
4957 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
4958 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
4961 emitcode("rlc","a");
4962 aopPut(AOP(result),"a",MSB32+offr);
4965 aopPut(AOP(result),zero,LSB);
4968 /*-----------------------------------------------------------------*/
4969 /* genlshFour - shift four byte by a known amount != 0 */
4970 /*-----------------------------------------------------------------*/
4971 static void genlshFour (operand *result, operand *left, int shCount)
4975 size = AOP_SIZE(result);
4977 /* if shifting more that 3 bytes */
4978 if (shCount >= 24 ) {
4981 /* lowest order of left goes to the highest
4982 order of the destination */
4983 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
4985 movLeft2Result(left, LSB, result, MSB32, 0);
4986 aopPut(AOP(result),zero,LSB);
4987 aopPut(AOP(result),zero,MSB16);
4988 aopPut(AOP(result),zero,MSB32);
4992 /* more than two bytes */
4993 else if ( shCount >= 16 ) {
4994 /* lower order two bytes goes to higher order two bytes */
4996 /* if some more remaining */
4998 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5000 movLeft2Result(left, MSB16, result, MSB32, 0);
5001 movLeft2Result(left, LSB, result, MSB24, 0);
5003 aopPut(AOP(result),zero,MSB16);
5004 aopPut(AOP(result),zero,LSB);
5008 /* if more than 1 byte */
5009 else if ( shCount >= 8 ) {
5010 /* lower order three bytes goes to higher order three bytes */
5014 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5016 movLeft2Result(left, LSB, result, MSB16, 0);
5018 else{ /* size = 4 */
5020 movLeft2Result(left, MSB24, result, MSB32, 0);
5021 movLeft2Result(left, MSB16, result, MSB24, 0);
5022 movLeft2Result(left, LSB, result, MSB16, 0);
5023 aopPut(AOP(result),zero,LSB);
5025 else if(shCount == 1)
5026 shiftLLong(left, result, MSB16);
5028 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5029 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5030 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5031 aopPut(AOP(result),zero,LSB);
5036 /* 1 <= shCount <= 7 */
5037 else if(shCount <= 2){
5038 shiftLLong(left, result, LSB);
5040 shiftLLong(result, result, LSB);
5042 /* 3 <= shCount <= 7, optimize */
5044 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5045 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5046 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5050 /*-----------------------------------------------------------------*/
5051 /* genLeftShiftLiteral - left shifting by known count */
5052 /*-----------------------------------------------------------------*/
5053 static void genLeftShiftLiteral (operand *left,
5058 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5061 freeAsmop(right,NULL,ic,TRUE);
5063 aopOp(left,ic,FALSE);
5064 aopOp(result,ic,FALSE);
5066 size = getSize(operandType(result));
5069 emitcode("; shift left ","result %d, left %d",size,
5073 /* I suppose that the left size >= result size */
5076 movLeft2Result(left, size, result, size, 0);
5080 else if(shCount >= (size * 8))
5082 aopPut(AOP(result),zero,size);
5086 genlshOne (result,left,shCount);
5091 genlshTwo (result,left,shCount);
5095 genlshFour (result,left,shCount);
5099 freeAsmop(left,NULL,ic,TRUE);
5100 freeAsmop(result,NULL,ic,TRUE);
5103 /*-----------------------------------------------------------------*/
5104 /* genLeftShift - generates code for left shifting */
5105 /*-----------------------------------------------------------------*/
5106 static void genLeftShift (iCode *ic)
5108 operand *left,*right, *result;
5111 symbol *tlbl , *tlbl1;
5113 right = IC_RIGHT(ic);
5115 result = IC_RESULT(ic);
5117 aopOp(right,ic,FALSE);
5119 /* if the shift count is known then do it
5120 as efficiently as possible */
5121 if (AOP_TYPE(right) == AOP_LIT) {
5122 genLeftShiftLiteral (left,right,result,ic);
5126 /* shift count is unknown then we have to form
5127 a loop get the loop count in B : Note: we take
5128 only the lower order byte since shifting
5129 more that 32 bits make no sense anyway, ( the
5130 largest size of an object can be only 32 bits ) */
5132 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5133 emitcode("inc","b");
5134 freeAsmop (right,NULL,ic,TRUE);
5135 aopOp(left,ic,FALSE);
5136 aopOp(result,ic,FALSE);
5138 /* now move the left to the result if they are not the
5140 if (!sameRegs(AOP(left),AOP(result)) &&
5141 AOP_SIZE(result) > 1) {
5143 size = AOP_SIZE(result);
5146 l = aopGet(AOP(left),offset,FALSE,TRUE);
5147 if (*l == '@' && (IS_AOP_PREG(result))) {
5149 emitcode("mov","a,%s",l);
5150 aopPut(AOP(result),"a",offset);
5152 aopPut(AOP(result),l,offset);
5157 tlbl = newiTempLabel(NULL);
5158 size = AOP_SIZE(result);
5160 tlbl1 = newiTempLabel(NULL);
5162 /* if it is only one byte then */
5164 symbol *tlbl1 = newiTempLabel(NULL);
5166 l = aopGet(AOP(left),0,FALSE,FALSE);
5168 emitcode("sjmp","%05d$",tlbl1->key+100);
5169 emitcode("","%05d$:",tlbl->key+100);
5170 emitcode("add","a,acc");
5171 emitcode("","%05d$:",tlbl1->key+100);
5172 emitcode("djnz","b,%05d$",tlbl->key+100);
5173 aopPut(AOP(result),"a",0);
5177 reAdjustPreg(AOP(result));
5179 emitcode("sjmp","%05d$",tlbl1->key+100);
5180 emitcode("","%05d$:",tlbl->key+100);
5181 l = aopGet(AOP(result),offset,FALSE,FALSE);
5183 emitcode("add","a,acc");
5184 aopPut(AOP(result),"a",offset++);
5186 l = aopGet(AOP(result),offset,FALSE,FALSE);
5188 emitcode("rlc","a");
5189 aopPut(AOP(result),"a",offset++);
5191 reAdjustPreg(AOP(result));
5193 emitcode("","%05d$:",tlbl1->key+100);
5194 emitcode("djnz","b,%05d$",tlbl->key+100);
5196 freeAsmop(left,NULL,ic,TRUE);
5197 freeAsmop(result,NULL,ic,TRUE);
5200 /*-----------------------------------------------------------------*/
5201 /* genrshOne - right shift a one byte quantity by known count */
5202 /*-----------------------------------------------------------------*/
5203 static void genrshOne (operand *result, operand *left,
5204 int shCount, int sign)
5206 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
5209 /*-----------------------------------------------------------------*/
5210 /* genrshTwo - right shift two bytes by known amount != 0 */
5211 /*-----------------------------------------------------------------*/
5212 static void genrshTwo (operand *result,operand *left,
5213 int shCount, int sign)
5215 /* if shCount >= 8 */
5219 shiftR1Left2Result(left, MSB16, result, LSB,
5222 movLeft2Result(left, MSB16, result, LSB, sign);
5223 addSign(result, MSB16, sign);
5226 /* 1 <= shCount <= 7 */
5228 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
5231 /*-----------------------------------------------------------------*/
5232 /* shiftRLong - shift right one long from left to result */
5233 /* offl = LSB or MSB16 */
5234 /*-----------------------------------------------------------------*/
5235 static void shiftRLong (operand *left, int offl,
5236 operand *result, int sign)
5239 emitcode("clr","c");
5240 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
5242 emitcode("mov","c,acc.7");
5243 emitcode("rrc","a");
5244 aopPut(AOP(result),"a",MSB32-offl);
5246 /* add sign of "a" */
5247 addSign(result, MSB32, sign);
5249 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
5250 emitcode("rrc","a");
5251 aopPut(AOP(result),"a",MSB24-offl);
5253 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
5254 emitcode("rrc","a");
5255 aopPut(AOP(result),"a",MSB16-offl);
5258 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
5259 emitcode("rrc","a");
5260 aopPut(AOP(result),"a",LSB);
5264 /*-----------------------------------------------------------------*/
5265 /* genrshFour - shift four byte by a known amount != 0 */
5266 /*-----------------------------------------------------------------*/
5267 static void genrshFour (operand *result, operand *left,
5268 int shCount, int sign)
5270 /* if shifting more that 3 bytes */
5271 if(shCount >= 24 ) {
5274 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
5276 movLeft2Result(left, MSB32, result, LSB, sign);
5277 addSign(result, MSB16, sign);
5279 else if(shCount >= 16){
5282 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
5284 movLeft2Result(left, MSB24, result, LSB, 0);
5285 movLeft2Result(left, MSB32, result, MSB16, sign);
5287 addSign(result, MSB24, sign);
5289 else if(shCount >= 8){
5292 shiftRLong(left, MSB16, result, sign);
5293 else if(shCount == 0){
5294 movLeft2Result(left, MSB16, result, LSB, 0);
5295 movLeft2Result(left, MSB24, result, MSB16, 0);
5296 movLeft2Result(left, MSB32, result, MSB24, sign);
5297 addSign(result, MSB32, sign);
5300 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
5301 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
5302 /* the last shift is signed */
5303 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
5304 addSign(result, MSB32, sign);
5307 else{ /* 1 <= shCount <= 7 */
5309 shiftRLong(left, LSB, result, sign);
5311 shiftRLong(result, LSB, result, sign);
5314 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
5315 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
5316 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
5321 /*-----------------------------------------------------------------*/
5322 /* genRightShiftLiteral - right shifting by known count */
5323 /*-----------------------------------------------------------------*/
5324 static void genRightShiftLiteral (operand *left,
5330 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5333 freeAsmop(right,NULL,ic,TRUE);
5335 aopOp(left,ic,FALSE);
5336 aopOp(result,ic,FALSE);
5339 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
5343 size = getDataSize(left);
5344 /* test the LEFT size !!! */
5346 /* I suppose that the left size >= result size */
5348 size = getDataSize(result);
5350 movLeft2Result(left, size, result, size, 0);
5353 else if(shCount >= (size * 8)){
5355 /* get sign in acc.7 */
5356 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
5357 addSign(result, LSB, sign);
5361 genrshOne (result,left,shCount,sign);
5365 genrshTwo (result,left,shCount,sign);
5369 genrshFour (result,left,shCount,sign);
5375 freeAsmop(left,NULL,ic,TRUE);
5376 freeAsmop(result,NULL,ic,TRUE);
5380 /*-----------------------------------------------------------------*/
5381 /* genSignedRightShift - right shift of signed number */
5382 /*-----------------------------------------------------------------*/
5383 static void genSignedRightShift (iCode *ic)
5385 operand *right, *left, *result;
5388 symbol *tlbl, *tlbl1 ;
5390 /* we do it the hard way put the shift count in b
5391 and loop thru preserving the sign */
5393 right = IC_RIGHT(ic);
5395 result = IC_RESULT(ic);
5397 aopOp(right,ic,FALSE);
5400 if ( AOP_TYPE(right) == AOP_LIT) {
5401 genRightShiftLiteral (left,right,result,ic,1);
5404 /* shift count is unknown then we have to form
5405 a loop get the loop count in B : Note: we take
5406 only the lower order byte since shifting
5407 more that 32 bits make no sense anyway, ( the
5408 largest size of an object can be only 32 bits ) */
5410 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5411 emitcode("inc","b");
5412 freeAsmop (right,NULL,ic,TRUE);
5413 aopOp(left,ic,FALSE);
5414 aopOp(result,ic,FALSE);
5416 /* now move the left to the result if they are not the
5418 if (!sameRegs(AOP(left),AOP(result)) &&
5419 AOP_SIZE(result) > 1) {
5421 size = AOP_SIZE(result);
5424 l = aopGet(AOP(left),offset,FALSE,TRUE);
5425 if (*l == '@' && IS_AOP_PREG(result)) {
5427 emitcode("mov","a,%s",l);
5428 aopPut(AOP(result),"a",offset);
5430 aopPut(AOP(result),l,offset);
5435 /* mov the highest order bit to OVR */
5436 tlbl = newiTempLabel(NULL);
5437 tlbl1= newiTempLabel(NULL);
5439 size = AOP_SIZE(result);
5441 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
5442 emitcode("rlc","a");
5443 emitcode("mov","ov,c");
5444 /* if it is only one byte then */
5446 l = aopGet(AOP(left),0,FALSE,FALSE);
5448 emitcode("sjmp","%05d$",tlbl1->key+100);
5449 emitcode("","%05d$:",tlbl->key+100);
5450 emitcode("mov","c,ov");
5451 emitcode("rrc","a");
5452 emitcode("","%05d$:",tlbl1->key+100);
5453 emitcode("djnz","b,%05d$",tlbl->key+100);
5454 aopPut(AOP(result),"a",0);
5458 reAdjustPreg(AOP(result));
5459 emitcode("sjmp","%05d$",tlbl1->key+100);
5460 emitcode("","%05d$:",tlbl->key+100);
5461 emitcode("mov","c,ov");
5463 l = aopGet(AOP(result),offset,FALSE,FALSE);
5465 emitcode("rrc","a");
5466 aopPut(AOP(result),"a",offset--);
5468 reAdjustPreg(AOP(result));
5469 emitcode("","%05d$:",tlbl1->key+100);
5470 emitcode("djnz","b,%05d$",tlbl->key+100);
5473 freeAsmop(left,NULL,ic,TRUE);
5474 freeAsmop(result,NULL,ic,TRUE);
5477 /*-----------------------------------------------------------------*/
5478 /* genRightShift - generate code for right shifting */
5479 /*-----------------------------------------------------------------*/
5480 static void genRightShift (iCode *ic)
5482 operand *right, *left, *result;
5486 symbol *tlbl, *tlbl1 ;
5488 /* if signed then we do it the hard way preserve the
5489 sign bit moving it inwards */
5490 retype = getSpec(operandType(IC_RESULT(ic)));
5492 if (!SPEC_USIGN(retype)) {
5493 genSignedRightShift (ic);
5497 /* signed & unsigned types are treated the same : i.e. the
5498 signed is NOT propagated inwards : quoting from the
5499 ANSI - standard : "for E1 >> E2, is equivalent to division
5500 by 2**E2 if unsigned or if it has a non-negative value,
5501 otherwise the result is implementation defined ", MY definition
5502 is that the sign does not get propagated */
5504 right = IC_RIGHT(ic);
5506 result = IC_RESULT(ic);
5508 aopOp(right,ic,FALSE);
5510 /* if the shift count is known then do it
5511 as efficiently as possible */
5512 if (AOP_TYPE(right) == AOP_LIT) {
5513 genRightShiftLiteral (left,right,result,ic, 0);
5517 /* shift count is unknown then we have to form
5518 a loop get the loop count in B : Note: we take
5519 only the lower order byte since shifting
5520 more that 32 bits make no sense anyway, ( the
5521 largest size of an object can be only 32 bits ) */
5523 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5524 emitcode("inc","b");
5525 freeAsmop (right,NULL,ic,TRUE);
5526 aopOp(left,ic,FALSE);
5527 aopOp(result,ic,FALSE);
5529 /* now move the left to the result if they are not the
5531 if (!sameRegs(AOP(left),AOP(result)) &&
5532 AOP_SIZE(result) > 1) {
5534 size = AOP_SIZE(result);
5537 l = aopGet(AOP(left),offset,FALSE,TRUE);
5538 if (*l == '@' && IS_AOP_PREG(result)) {
5540 emitcode("mov","a,%s",l);
5541 aopPut(AOP(result),"a",offset);
5543 aopPut(AOP(result),l,offset);
5548 tlbl = newiTempLabel(NULL);
5549 tlbl1= newiTempLabel(NULL);
5550 size = AOP_SIZE(result);
5553 /* if it is only one byte then */
5555 l = aopGet(AOP(left),0,FALSE,FALSE);
5557 emitcode("sjmp","%05d$",tlbl1->key+100);
5558 emitcode("","%05d$:",tlbl->key+100);
5560 emitcode("rrc","a");
5561 emitcode("","%05d$:",tlbl1->key+100);
5562 emitcode("djnz","b,%05d$",tlbl->key+100);
5563 aopPut(AOP(result),"a",0);
5567 reAdjustPreg(AOP(result));
5568 emitcode("sjmp","%05d$",tlbl1->key+100);
5569 emitcode("","%05d$:",tlbl->key+100);
5572 l = aopGet(AOP(result),offset,FALSE,FALSE);
5574 emitcode("rrc","a");
5575 aopPut(AOP(result),"a",offset--);
5577 reAdjustPreg(AOP(result));
5579 emitcode("","%05d$:",tlbl1->key+100);
5580 emitcode("djnz","b,%05d$",tlbl->key+100);
5583 freeAsmop(left,NULL,ic,TRUE);
5584 freeAsmop(result,NULL,ic,TRUE);
5587 /*-----------------------------------------------------------------*/
5588 /* genUnpackBits - generates code for unpacking bits */
5589 /*-----------------------------------------------------------------*/
5590 static void genUnpackBits (operand *result, char *rname, int ptype)
5597 etype = getSpec(operandType(result));
5599 /* read the first byte */
5604 emitcode("mov","a,@%s",rname);
5608 emitcode("movx","a,@%s",rname);
5612 emitcode("movx","a,@dptr");
5616 emitcode("clr","a");
5617 emitcode("movc","a","@a+dptr");
5621 emitcode("lcall","__gptrget");
5625 /* if we have bitdisplacement then it fits */
5626 /* into this byte completely or if length is */
5627 /* less than a byte */
5628 if ((shCnt = SPEC_BSTR(etype)) ||
5629 (SPEC_BLEN(etype) <= 8)) {
5631 /* shift right acc */
5634 emitcode("anl","a,#0x%02x",
5635 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
5636 aopPut(AOP(result),"a",offset);
5640 /* bit field did not fit in a byte */
5641 rlen = SPEC_BLEN(etype) - 8;
5642 aopPut(AOP(result),"a",offset++);
5649 emitcode("inc","%s",rname);
5650 emitcode("mov","a,@%s",rname);
5654 emitcode("inc","%s",rname);
5655 emitcode("movx","a,@%s",rname);
5659 emitcode("inc","dptr");
5660 emitcode("movx","a,@dptr");
5664 emitcode("clr","a");
5665 emitcode("inc","dptr");
5666 emitcode("movc","a","@a+dptr");
5670 emitcode("inc","dptr");
5671 emitcode("lcall","__gptrget");
5676 /* if we are done */
5680 aopPut(AOP(result),"a",offset++);
5685 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
5686 aopPut(AOP(result),"a",offset);
5693 /*-----------------------------------------------------------------*/
5694 /* genDataPointerGet - generates code when ptr offset is known */
5695 /*-----------------------------------------------------------------*/
5696 static void genDataPointerGet (operand *left,
5702 int size , offset = 0;
5703 aopOp(result,ic,TRUE);
5705 /* get the string representation of the name */
5706 l = aopGet(AOP(left),0,FALSE,TRUE);
5707 size = AOP_SIZE(result);
5710 sprintf(buffer,"(%s + %d)",l+1,offset);
5712 sprintf(buffer,"%s",l+1);
5713 aopPut(AOP(result),buffer,offset++);
5716 freeAsmop(left,NULL,ic,TRUE);
5717 freeAsmop(result,NULL,ic,TRUE);
5720 /*-----------------------------------------------------------------*/
5721 /* genNearPointerGet - emitcode for near pointer fetch */
5722 /*-----------------------------------------------------------------*/
5723 static void genNearPointerGet (operand *left,
5730 link *rtype, *retype;
5731 link *ltype = operandType(left);
5734 rtype = operandType(result);
5735 retype= getSpec(rtype);
5737 aopOp(left,ic,FALSE);
5739 /* if left is rematerialisable and
5740 result is not bit variable type and
5741 the left is pointer to data space i.e
5742 lower 128 bytes of space */
5743 if (AOP_TYPE(left) == AOP_IMMD &&
5744 !IS_BITVAR(retype) &&
5745 DCL_TYPE(ltype) == POINTER) {
5746 genDataPointerGet (left,result,ic);
5750 /* if the value is already in a pointer register
5751 then don't need anything more */
5752 if (!AOP_INPREG(AOP(left))) {
5753 /* otherwise get a free pointer register */
5755 preg = getFreePtr(ic,&aop,FALSE);
5756 emitcode("mov","%s,%s",
5758 aopGet(AOP(left),0,FALSE,TRUE));
5759 rname = preg->name ;
5761 rname = aopGet(AOP(left),0,FALSE,FALSE);
5763 freeAsmop(left,NULL,ic,TRUE);
5764 aopOp (result,ic,FALSE);
5766 /* if bitfield then unpack the bits */
5767 if (IS_BITVAR(retype))
5768 genUnpackBits (result,rname,POINTER);
5770 /* we have can just get the values */
5771 int size = AOP_SIZE(result);
5775 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
5777 emitcode("mov","a,@%s",rname);
5778 aopPut(AOP(result),"a",offset);
5780 sprintf(buffer,"@%s",rname);
5781 aopPut(AOP(result),buffer,offset);
5785 emitcode("inc","%s",rname);
5789 /* now some housekeeping stuff */
5791 /* we had to allocate for this iCode */
5792 freeAsmop(NULL,aop,ic,TRUE);
5794 /* we did not allocate which means left
5795 already in a pointer register, then
5796 if size > 0 && this could be used again
5797 we have to point it back to where it
5799 if (AOP_SIZE(result) > 1 &&
5800 !OP_SYMBOL(left)->remat &&
5801 ( OP_SYMBOL(left)->liveTo > ic->seq ||
5803 int size = AOP_SIZE(result) - 1;
5805 emitcode("dec","%s",rname);
5810 freeAsmop(result,NULL,ic,TRUE);
5814 /*-----------------------------------------------------------------*/
5815 /* genPagedPointerGet - emitcode for paged pointer fetch */
5816 /*-----------------------------------------------------------------*/
5817 static void genPagedPointerGet (operand *left,
5824 link *rtype, *retype;
5826 rtype = operandType(result);
5827 retype= getSpec(rtype);
5829 aopOp(left,ic,FALSE);
5831 /* if the value is already in a pointer register
5832 then don't need anything more */
5833 if (!AOP_INPREG(AOP(left))) {
5834 /* otherwise get a free pointer register */
5836 preg = getFreePtr(ic,&aop,FALSE);
5837 emitcode("mov","%s,%s",
5839 aopGet(AOP(left),0,FALSE,TRUE));
5840 rname = preg->name ;
5842 rname = aopGet(AOP(left),0,FALSE,FALSE);
5844 freeAsmop(left,NULL,ic,TRUE);
5845 aopOp (result,ic,FALSE);
5847 /* if bitfield then unpack the bits */
5848 if (IS_BITVAR(retype))
5849 genUnpackBits (result,rname,PPOINTER);
5851 /* we have can just get the values */
5852 int size = AOP_SIZE(result);
5857 emitcode("movx","a,@%s",rname);
5858 aopPut(AOP(result),"a",offset);
5863 emitcode("inc","%s",rname);
5867 /* now some housekeeping stuff */
5869 /* we had to allocate for this iCode */
5870 freeAsmop(NULL,aop,ic,TRUE);
5872 /* we did not allocate which means left
5873 already in a pointer register, then
5874 if size > 0 && this could be used again
5875 we have to point it back to where it
5877 if (AOP_SIZE(result) > 1 &&
5878 !OP_SYMBOL(left)->remat &&
5879 ( OP_SYMBOL(left)->liveTo > ic->seq ||
5881 int size = AOP_SIZE(result) - 1;
5883 emitcode("dec","%s",rname);
5888 freeAsmop(result,NULL,ic,TRUE);
5893 /*-----------------------------------------------------------------*/
5894 /* genFarPointerGet - gget value from far space */
5895 /*-----------------------------------------------------------------*/
5896 static void genFarPointerGet (operand *left,
5897 operand *result, iCode *ic)
5900 link *retype = getSpec(operandType(result));
5902 aopOp(left,ic,FALSE);
5904 /* if the operand is already in dptr
5905 then we do nothing else we move the value to dptr */
5906 if (AOP_TYPE(left) != AOP_STR) {
5907 /* if this is remateriazable */
5908 if (AOP_TYPE(left) == AOP_IMMD)
5909 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
5910 else { /* we need to get it byte by byte */
5911 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
5912 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
5915 /* so dptr know contains the address */
5916 freeAsmop(left,NULL,ic,TRUE);
5917 aopOp(result,ic,FALSE);
5919 /* if bit then unpack */
5920 if (IS_BITVAR(retype))
5921 genUnpackBits(result,"dptr",FPOINTER);
5923 size = AOP_SIZE(result);
5927 emitcode("movx","a,@dptr");
5928 aopPut(AOP(result),"a",offset++);
5930 emitcode("inc","dptr");
5934 freeAsmop(result,NULL,ic,TRUE);
5937 /*-----------------------------------------------------------------*/
5938 /* emitcodePointerGet - gget value from code space */
5939 /*-----------------------------------------------------------------*/
5940 static void emitcodePointerGet (operand *left,
5941 operand *result, iCode *ic)
5944 link *retype = getSpec(operandType(result));
5946 aopOp(left,ic,FALSE);
5948 /* if the operand is already in dptr
5949 then we do nothing else we move the value to dptr */
5950 if (AOP_TYPE(left) != AOP_STR) {
5951 /* if this is remateriazable */
5952 if (AOP_TYPE(left) == AOP_IMMD)
5953 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
5954 else { /* we need to get it byte by byte */
5955 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
5956 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
5959 /* so dptr know contains the address */
5960 freeAsmop(left,NULL,ic,TRUE);
5961 aopOp(result,ic,FALSE);
5963 /* if bit then unpack */
5964 if (IS_BITVAR(retype))
5965 genUnpackBits(result,"dptr",CPOINTER);
5967 size = AOP_SIZE(result);
5971 emitcode("clr","a");
5972 emitcode("movc","a,@a+dptr");
5973 aopPut(AOP(result),"a",offset++);
5975 emitcode("inc","dptr");
5979 freeAsmop(result,NULL,ic,TRUE);
5982 /*-----------------------------------------------------------------*/
5983 /* genGenPointerGet - gget value from generic pointer space */
5984 /*-----------------------------------------------------------------*/
5985 static void genGenPointerGet (operand *left,
5986 operand *result, iCode *ic)
5989 link *retype = getSpec(operandType(result));
5991 aopOp(left,ic,FALSE);
5993 /* if the operand is already in dptr
5994 then we do nothing else we move the value to dptr */
5995 if (AOP_TYPE(left) != AOP_STR) {
5996 /* if this is remateriazable */
5997 if (AOP_TYPE(left) == AOP_IMMD) {
5998 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
5999 emitcode("mov","b,#%d",pointerCode(retype));
6001 else { /* we need to get it byte by byte */
6002 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6003 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6004 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
6007 /* so dptr know contains the address */
6008 freeAsmop(left,NULL,ic,TRUE);
6009 aopOp(result,ic,FALSE);
6011 /* if bit then unpack */
6012 if (IS_BITVAR(retype))
6013 genUnpackBits(result,"dptr",GPOINTER);
6015 size = AOP_SIZE(result);
6019 emitcode("lcall","__gptrget");
6020 aopPut(AOP(result),"a",offset++);
6022 emitcode("inc","dptr");
6026 freeAsmop(result,NULL,ic,TRUE);
6029 /*-----------------------------------------------------------------*/
6030 /* genPointerGet - generate code for pointer get */
6031 /*-----------------------------------------------------------------*/
6032 static void genPointerGet (iCode *ic)
6034 operand *left, *result ;
6039 result = IC_RESULT(ic) ;
6041 /* depending on the type of pointer we need to
6042 move it to the correct pointer register */
6043 type = operandType(left);
6044 etype = getSpec(type);
6045 /* if left is of type of pointer then it is simple */
6046 if (IS_PTR(type) && !IS_FUNC(type->next))
6047 p_type = DCL_TYPE(type);
6050 /* we have to go by the storage class */
6051 if (SPEC_OCLS(etype)->codesp ) {
6055 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
6058 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
6061 if (SPEC_OCLS(etype) == idata )
6067 /* now that we have the pointer type we assign
6068 the pointer values */
6073 genNearPointerGet (left,result,ic);
6077 genPagedPointerGet(left,result,ic);
6081 genFarPointerGet (left,result,ic);
6085 emitcodePointerGet (left,result,ic);
6089 genGenPointerGet (left,result,ic);
6095 /*-----------------------------------------------------------------*/
6096 /* genPackBits - generates code for packed bit storage */
6097 /*-----------------------------------------------------------------*/
6098 static void genPackBits (link *etype ,
6100 char *rname, int p_type)
6108 blen = SPEC_BLEN(etype);
6109 bstr = SPEC_BSTR(etype);
6111 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6114 /* if the bit lenth is less than or */
6115 /* it exactly fits a byte then */
6116 if (SPEC_BLEN(etype) <= 8 ) {
6117 shCount = SPEC_BSTR(etype) ;
6119 /* shift left acc */
6122 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6127 emitcode ("mov","b,a");
6128 emitcode("mov","a,@%s",rname);
6132 emitcode ("mov","b,a");
6133 emitcode("movx","a,@dptr");
6137 emitcode ("push","b");
6138 emitcode ("push","acc");
6139 emitcode ("lcall","__gptrget");
6140 emitcode ("pop","b");
6144 emitcode ("anl","a,#0x%02x",(unsigned char)
6145 ((unsigned char)(0xFF << (blen+bstr)) |
6146 (unsigned char)(0xFF >> (8-bstr)) ) );
6147 emitcode ("orl","a,b");
6148 if (p_type == GPOINTER)
6149 emitcode("pop","b");
6155 emitcode("mov","@%s,a",rname);
6159 emitcode("movx","@dptr,a");
6163 emitcode("lcall","__gptrput");
6168 if ( SPEC_BLEN(etype) <= 8 )
6171 emitcode("inc","%s",rname);
6172 rLen = SPEC_BLEN(etype) ;
6174 /* now generate for lengths greater than one byte */
6177 l = aopGet(AOP(right),offset++,FALSE,TRUE);
6187 emitcode("mov","@%s,a",rname);
6189 emitcode("mov","@%s,%s",rname,l);
6194 emitcode("movx","@dptr,a");
6199 emitcode("lcall","__gptrput");
6202 emitcode ("inc","%s",rname);
6207 /* last last was not complete */
6209 /* save the byte & read byte */
6212 emitcode ("mov","b,a");
6213 emitcode("mov","a,@%s",rname);
6217 emitcode ("mov","b,a");
6218 emitcode("movx","a,@dptr");
6222 emitcode ("push","b");
6223 emitcode ("push","acc");
6224 emitcode ("lcall","__gptrget");
6225 emitcode ("pop","b");
6229 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
6230 emitcode ("orl","a,b");
6233 if (p_type == GPOINTER)
6234 emitcode("pop","b");
6239 emitcode("mov","@%s,a",rname);
6243 emitcode("movx","@dptr,a");
6247 emitcode("lcall","__gptrput");
6251 /*-----------------------------------------------------------------*/
6252 /* genDataPointerSet - remat pointer to data space */
6253 /*-----------------------------------------------------------------*/
6254 static void genDataPointerSet(operand *right,
6258 int size, offset = 0 ;
6259 char *l, buffer[256];
6261 aopOp(right,ic,FALSE);
6263 l = aopGet(AOP(result),0,FALSE,TRUE);
6264 size = AOP_SIZE(right);
6267 sprintf(buffer,"(%s + %d)",l+1,offset);
6269 sprintf(buffer,"%s",l+1);
6270 emitcode("mov","%s,%s",buffer,
6271 aopGet(AOP(right),offset++,FALSE,FALSE));
6274 freeAsmop(right,NULL,ic,TRUE);
6275 freeAsmop(result,NULL,ic,TRUE);
6278 /*-----------------------------------------------------------------*/
6279 /* genNearPointerSet - emitcode for near pointer put */
6280 /*-----------------------------------------------------------------*/
6281 static void genNearPointerSet (operand *right,
6289 link *ptype = operandType(result);
6291 retype= getSpec(operandType(right));
6293 aopOp(result,ic,FALSE);
6295 /* if the result is rematerializable &
6296 in data space & not a bit variable */
6297 if (AOP_TYPE(result) == AOP_IMMD &&
6298 DCL_TYPE(ptype) == POINTER &&
6299 !IS_BITVAR(retype)) {
6300 genDataPointerSet (right,result,ic);
6304 /* if the value is already in a pointer register
6305 then don't need anything more */
6306 if (!AOP_INPREG(AOP(result))) {
6307 /* otherwise get a free pointer register */
6309 preg = getFreePtr(ic,&aop,FALSE);
6310 emitcode("mov","%s,%s",
6312 aopGet(AOP(result),0,FALSE,TRUE));
6313 rname = preg->name ;
6315 rname = aopGet(AOP(result),0,FALSE,FALSE);
6317 freeAsmop(result,NULL,ic,TRUE);
6318 aopOp (right,ic,FALSE);
6320 /* if bitfield then unpack the bits */
6321 if (IS_BITVAR(retype))
6322 genPackBits (retype,right,rname,POINTER);
6324 /* we have can just get the values */
6325 int size = AOP_SIZE(right);
6329 l = aopGet(AOP(right),offset,FALSE,TRUE);
6332 emitcode("mov","@%s,a",rname);
6334 emitcode("mov","@%s,%s",rname,l);
6336 emitcode("inc","%s",rname);
6341 /* now some housekeeping stuff */
6343 /* we had to allocate for this iCode */
6344 freeAsmop(NULL,aop,ic,TRUE);
6346 /* we did not allocate which means left
6347 already in a pointer register, then
6348 if size > 0 && this could be used again
6349 we have to point it back to where it
6351 if (AOP_SIZE(right) > 1 &&
6352 !OP_SYMBOL(result)->remat &&
6353 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6355 int size = AOP_SIZE(right) - 1;
6357 emitcode("dec","%s",rname);
6362 freeAsmop(right,NULL,ic,TRUE);
6367 /*-----------------------------------------------------------------*/
6368 /* genPagedPointerSet - emitcode for Paged pointer put */
6369 /*-----------------------------------------------------------------*/
6370 static void genPagedPointerSet (operand *right,
6379 retype= getSpec(operandType(right));
6381 aopOp(result,ic,FALSE);
6383 /* if the value is already in a pointer register
6384 then don't need anything more */
6385 if (!AOP_INPREG(AOP(result))) {
6386 /* otherwise get a free pointer register */
6388 preg = getFreePtr(ic,&aop,FALSE);
6389 emitcode("mov","%s,%s",
6391 aopGet(AOP(result),0,FALSE,TRUE));
6392 rname = preg->name ;
6394 rname = aopGet(AOP(result),0,FALSE,FALSE);
6396 freeAsmop(result,NULL,ic,TRUE);
6397 aopOp (right,ic,FALSE);
6399 /* if bitfield then unpack the bits */
6400 if (IS_BITVAR(retype))
6401 genPackBits (retype,right,rname,PPOINTER);
6403 /* we have can just get the values */
6404 int size = AOP_SIZE(right);
6408 l = aopGet(AOP(right),offset,FALSE,TRUE);
6411 emitcode("movx","@%s,a",rname);
6414 emitcode("inc","%s",rname);
6420 /* now some housekeeping stuff */
6422 /* we had to allocate for this iCode */
6423 freeAsmop(NULL,aop,ic,TRUE);
6425 /* we did not allocate which means left
6426 already in a pointer register, then
6427 if size > 0 && this could be used again
6428 we have to point it back to where it
6430 if (AOP_SIZE(right) > 1 &&
6431 !OP_SYMBOL(result)->remat &&
6432 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6434 int size = AOP_SIZE(right) - 1;
6436 emitcode("dec","%s",rname);
6441 freeAsmop(right,NULL,ic,TRUE);
6446 /*-----------------------------------------------------------------*/
6447 /* genFarPointerSet - set value from far space */
6448 /*-----------------------------------------------------------------*/
6449 static void genFarPointerSet (operand *right,
6450 operand *result, iCode *ic)
6453 link *retype = getSpec(operandType(right));
6455 aopOp(result,ic,FALSE);
6457 /* if the operand is already in dptr
6458 then we do nothing else we move the value to dptr */
6459 if (AOP_TYPE(result) != AOP_STR) {
6460 /* if this is remateriazable */
6461 if (AOP_TYPE(result) == AOP_IMMD)
6462 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6463 else { /* we need to get it byte by byte */
6464 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6465 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6468 /* so dptr know contains the address */
6469 freeAsmop(result,NULL,ic,TRUE);
6470 aopOp(right,ic,FALSE);
6472 /* if bit then unpack */
6473 if (IS_BITVAR(retype))
6474 genPackBits(retype,right,"dptr",FPOINTER);
6476 size = AOP_SIZE(right);
6480 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6482 emitcode("movx","@dptr,a");
6484 emitcode("inc","dptr");
6488 freeAsmop(right,NULL,ic,TRUE);
6491 /*-----------------------------------------------------------------*/
6492 /* genGenPointerSet - set value from generic pointer space */
6493 /*-----------------------------------------------------------------*/
6494 static void genGenPointerSet (operand *right,
6495 operand *result, iCode *ic)
6498 link *retype = getSpec(operandType(right));
6500 aopOp(result,ic,FALSE);
6502 /* if the operand is already in dptr
6503 then we do nothing else we move the value to dptr */
6504 if (AOP_TYPE(result) != AOP_STR) {
6505 /* if this is remateriazable */
6506 if (AOP_TYPE(result) == AOP_IMMD) {
6507 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6508 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
6510 else { /* we need to get it byte by byte */
6511 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6512 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6513 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
6516 /* so dptr know contains the address */
6517 freeAsmop(result,NULL,ic,TRUE);
6518 aopOp(right,ic,FALSE);
6520 /* if bit then unpack */
6521 if (IS_BITVAR(retype))
6522 genPackBits(retype,right,"dptr",GPOINTER);
6524 size = AOP_SIZE(right);
6528 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6530 emitcode("lcall","__gptrput");
6532 emitcode("inc","dptr");
6536 freeAsmop(right,NULL,ic,TRUE);
6539 /*-----------------------------------------------------------------*/
6540 /* genPointerSet - stores the value into a pointer location */
6541 /*-----------------------------------------------------------------*/
6542 static void genPointerSet (iCode *ic)
6544 operand *right, *result ;
6548 right = IC_RIGHT(ic);
6549 result = IC_RESULT(ic) ;
6551 /* depending on the type of pointer we need to
6552 move it to the correct pointer register */
6553 type = operandType(result);
6554 etype = getSpec(type);
6555 /* if left is of type of pointer then it is simple */
6556 if (IS_PTR(type) && !IS_FUNC(type->next)) {
6557 p_type = DCL_TYPE(type);
6561 /* we have to go by the storage class */
6562 if (SPEC_OCLS(etype)->codesp ) {
6566 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
6569 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
6572 if (SPEC_OCLS(etype) == idata )
6578 /* now that we have the pointer type we assign
6579 the pointer values */
6584 genNearPointerSet (right,result,ic);
6588 genPagedPointerSet (right,result,ic);
6592 genFarPointerSet (right,result,ic);
6596 genGenPointerSet (right,result,ic);
6602 /*-----------------------------------------------------------------*/
6603 /* genIfx - generate code for Ifx statement */
6604 /*-----------------------------------------------------------------*/
6605 static void genIfx (iCode *ic, iCode *popIc)
6607 operand *cond = IC_COND(ic);
6610 aopOp(cond,ic,FALSE);
6612 /* get the value into acc */
6613 if (AOP_TYPE(cond) != AOP_CRY)
6617 /* the result is now in the accumulator */
6618 freeAsmop(cond,NULL,ic,TRUE);
6620 /* if there was something to be popped then do it */
6624 /* if the condition is a bit variable */
6625 if (isbit && IS_ITEMP(cond) &&
6627 genIfxJump(ic,SPIL_LOC(cond)->rname);
6629 if (isbit && !IS_ITEMP(cond))
6630 genIfxJump(ic,OP_SYMBOL(cond)->rname);
6637 /*-----------------------------------------------------------------*/
6638 /* genAddrOf - generates code for address of */
6639 /*-----------------------------------------------------------------*/
6640 static void genAddrOf (iCode *ic)
6642 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
6645 aopOp(IC_RESULT(ic),ic,FALSE);
6647 /* if the operand is on the stack then we
6648 need to get the stack offset of this
6651 /* if it has an offset then we need to compute
6654 emitcode("mov","a,_bp");
6655 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
6656 aopPut(AOP(IC_RESULT(ic)),"a",0);
6658 /* we can just move _bp */
6659 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
6660 /* fill the result with zero */
6661 size = AOP_SIZE(IC_RESULT(ic)) - 1;
6664 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
6669 /* object not on stack then we need the name */
6670 size = AOP_SIZE(IC_RESULT(ic));
6674 char s[SDCC_NAME_MAX];
6676 sprintf(s,"#(%s >> %d)",
6680 sprintf(s,"#%s",sym->rname);
6681 aopPut(AOP(IC_RESULT(ic)),s,offset++);
6685 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
6689 /*-----------------------------------------------------------------*/
6690 /* genFarFarAssign - assignment when both are in far space */
6691 /*-----------------------------------------------------------------*/
6692 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
6694 int size = AOP_SIZE(right);
6697 /* first push the right side on to the stack */
6699 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6701 emitcode ("push","acc");
6704 freeAsmop(right,NULL,ic,FALSE);
6705 /* now assign DPTR to result */
6706 aopOp(result,ic,FALSE);
6707 size = AOP_SIZE(result);
6709 emitcode ("pop","acc");
6710 aopPut(AOP(result),"a",--offset);
6712 freeAsmop(result,NULL,ic,FALSE);
6716 /*-----------------------------------------------------------------*/
6717 /* genAssign - generate code for assignment */
6718 /*-----------------------------------------------------------------*/
6719 static void genAssign (iCode *ic)
6721 operand *result, *right;
6723 unsigned long lit = 0L;
6725 result = IC_RESULT(ic);
6726 right = IC_RIGHT(ic) ;
6728 /* if they are the same */
6729 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
6732 aopOp(right,ic,FALSE);
6734 /* special case both in far space */
6735 if (AOP_TYPE(right) == AOP_DPTR &&
6736 IS_TRUE_SYMOP(result) &&
6737 isOperandInFarSpace(result)) {
6739 genFarFarAssign (result,right,ic);
6743 aopOp(result,ic,TRUE);
6745 /* if they are the same registers */
6746 if (sameRegs(AOP(right),AOP(result)))
6749 /* if the result is a bit */
6750 if (AOP_TYPE(result) == AOP_CRY) {
6752 /* if the right size is a literal then
6753 we know what the value is */
6754 if (AOP_TYPE(right) == AOP_LIT) {
6755 if (((int) operandLitValue(right)))
6756 aopPut(AOP(result),one,0);
6758 aopPut(AOP(result),zero,0);
6762 /* the right is also a bit variable */
6763 if (AOP_TYPE(right) == AOP_CRY) {
6764 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6765 aopPut(AOP(result),"c",0);
6771 aopPut(AOP(result),"a",0);
6775 /* bit variables done */
6777 size = AOP_SIZE(result);
6779 if(AOP_TYPE(right) == AOP_LIT)
6780 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6782 (AOP_TYPE(result) != AOP_REG) &&
6783 (AOP_TYPE(right) == AOP_LIT) &&
6784 !IS_FLOAT(operandType(right)) &&
6786 emitcode("clr","a");
6788 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
6789 aopPut(AOP(result),"a",size);
6792 aopGet(AOP(right),size,FALSE,FALSE),
6798 aopGet(AOP(right),offset,FALSE,FALSE),
6805 freeAsmop (right,NULL,ic,FALSE);
6806 freeAsmop (result,NULL,ic,TRUE);
6809 /*-----------------------------------------------------------------*/
6810 /* genJumpTab - genrates code for jump table */
6811 /*-----------------------------------------------------------------*/
6812 static void genJumpTab (iCode *ic)
6817 aopOp(IC_JTCOND(ic),ic,FALSE);
6818 /* get the condition into accumulator */
6819 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
6821 /* multiply by three */
6822 emitcode("add","a,acc");
6823 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
6824 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
6826 jtab = newiTempLabel(NULL);
6827 emitcode("mov","dptr,#%05d$",jtab->key+100);
6828 emitcode("jmp","@a+dptr");
6829 emitcode("","%05d$:",jtab->key+100);
6830 /* now generate the jump labels */
6831 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
6832 jtab = setNextItem(IC_JTLABELS(ic)))
6833 emitcode("ljmp","%05d$",jtab->key+100);
6837 /*-----------------------------------------------------------------*/
6838 /* genCast - gen code for casting */
6839 /*-----------------------------------------------------------------*/
6840 static void genCast (iCode *ic)
6842 operand *result = IC_RESULT(ic);
6843 link *ctype = operandType(IC_LEFT(ic));
6844 operand *right = IC_RIGHT(ic);
6847 /* if they are equivalent then do nothing */
6848 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
6851 aopOp(right,ic,FALSE) ;
6852 aopOp(result,ic,FALSE);
6854 /* if the result is a bit */
6855 if (AOP_TYPE(result) == AOP_CRY) {
6856 /* if the right size is a literal then
6857 we know what the value is */
6858 if (AOP_TYPE(right) == AOP_LIT) {
6859 if (((int) operandLitValue(right)))
6860 aopPut(AOP(result),one,0);
6862 aopPut(AOP(result),zero,0);
6867 /* the right is also a bit variable */
6868 if (AOP_TYPE(right) == AOP_CRY) {
6869 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6870 aopPut(AOP(result),"c",0);
6876 aopPut(AOP(result),"a",0);
6880 /* if they are the same size : or less */
6881 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
6883 /* if they are in the same place */
6884 if (sameRegs(AOP(right),AOP(result)))
6887 /* if they in different places then copy */
6888 size = AOP_SIZE(result);
6892 aopGet(AOP(right),offset,FALSE,FALSE),
6900 /* if the result is of type pointer */
6901 if (IS_PTR(ctype)) {
6904 link *type = operandType(right);
6905 link *etype = getSpec(type);
6907 /* pointer to generic pointer */
6908 if (IS_GENPTR(ctype)) {
6912 p_type = DCL_TYPE(type);
6914 /* we have to go by the storage class */
6915 if (SPEC_OCLS(etype)->codesp )
6918 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
6921 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
6924 if (SPEC_OCLS(etype) == idata )
6930 /* the first two bytes are known */
6935 aopGet(AOP(right),offset,FALSE,FALSE),
6939 /* the last byte depending on type */
6956 /* this should never happen */
6957 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
6958 "got unknown pointer type");
6961 aopPut(AOP(result),l,2);
6965 /* just copy the pointers */
6966 size = AOP_SIZE(result);
6970 aopGet(AOP(right),offset,FALSE,FALSE),
6977 /* so we now know that the size of destination is greater
6978 than the size of the source */
6979 /* we move to result for the size of source */
6980 size = AOP_SIZE(right);
6984 aopGet(AOP(right),offset,FALSE,FALSE),
6989 /* now depending on the sign of the destination */
6990 size = AOP_SIZE(result) - AOP_SIZE(right);
6991 /* if unsigned or not an integral type */
6992 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
6994 aopPut(AOP(result),zero,offset++);
6996 /* we need to extend the sign :{ */
6997 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
7000 emitcode("rlc","a");
7001 emitcode("subb","a,acc");
7003 aopPut(AOP(result),"a",offset++);
7006 /* we are done hurray !!!! */
7009 freeAsmop(right,NULL,ic,TRUE);
7010 freeAsmop(result,NULL,ic,TRUE);
7014 /*-----------------------------------------------------------------*/
7015 /* genDjnz - generate decrement & jump if not zero instrucion */
7016 /*-----------------------------------------------------------------*/
7017 static int genDjnz (iCode *ic, iCode *ifx)
7023 /* if the if condition has a false label
7024 then we cannot save */
7028 /* if the minus is not of the form
7030 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
7031 !IS_OP_LITERAL(IC_RIGHT(ic)))
7034 if (operandLitValue(IC_RIGHT(ic)) != 1)
7037 /* if the size of this greater than one then no
7039 if (getSize(operandType(IC_RESULT(ic))) > 1)
7042 /* otherwise we can save BIG */
7043 lbl = newiTempLabel(NULL);
7044 lbl1= newiTempLabel(NULL);
7046 aopOp(IC_RESULT(ic),ic,FALSE);
7048 if (IS_AOP_PREG(IC_RESULT(ic))) {
7049 emitcode("dec","%s",
7050 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7051 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7052 emitcode("jnz","%05d$",lbl->key+100);
7054 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
7057 emitcode ("sjmp","%05d$",lbl1->key+100);
7058 emitcode ("","%05d$:",lbl->key+100);
7059 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
7060 emitcode ("","%05d$:",lbl1->key+100);
7062 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7067 /*-----------------------------------------------------------------*/
7068 /* genReceive - generate code for a receive iCode */
7069 /*-----------------------------------------------------------------*/
7070 static void genReceive (iCode *ic)
7072 if (isOperandInFarSpace(IC_RESULT(ic)) &&
7073 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
7074 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
7076 int size = getSize(operandType(IC_RESULT(ic)));
7077 int offset = 4 - size;
7079 emitcode ("push","%s", (strcmp(fReturn[3 - offset],"a") ?
7080 fReturn[3 - offset] : "acc"));
7083 aopOp(IC_RESULT(ic),ic,FALSE);
7084 size = AOP_SIZE(IC_RESULT(ic));
7087 emitcode ("pop","acc");
7088 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
7093 aopOp(IC_RESULT(ic),ic,FALSE);
7095 assignResultValue(IC_RESULT(ic));
7098 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7101 /*-----------------------------------------------------------------*/
7102 /* gen51Code - generate code for 8051 based controllers */
7103 /*-----------------------------------------------------------------*/
7104 void gen51Code (iCode *lic)
7109 lineHead = lineCurr = NULL;
7111 /* if debug information required */
7112 /* if (options.debug && currFunc) { */
7114 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
7116 if (IS_STATIC(currFunc->etype))
7117 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
7119 emitcode("","G$%s$0$0 ==.",currFunc->name);
7122 /* stack pointer name */
7123 if (options.useXstack)
7129 for (ic = lic ; ic ; ic = ic->next ) {
7131 if ( cln != ic->lineno ) {
7132 if ( options.debug ) {
7134 emitcode("","C$%s$%d$%d$%d ==.",
7135 ic->filename,ic->lineno,
7136 ic->level,ic->block);
7139 emitcode(";","%s %d",ic->filename,ic->lineno);
7142 /* if the result is marked as
7143 spilt and rematerializable or code for
7144 this has already been generated then
7146 if (resultRemat(ic) || ic->generated )
7149 /* depending on the operation */
7168 /* IPOP happens only when trying to restore a
7169 spilt live range, if there is an ifx statement
7170 following this pop then the if statement might
7171 be using some of the registers being popped which
7172 would destory the contents of the register so
7173 we need to check for this condition and handle it */
7175 ic->next->op == IFX &&
7176 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
7177 genIfx (ic->next,ic);
7195 genEndFunction (ic);
7215 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
7232 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
7236 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
7243 /* note these two are xlated by algebraic equivalence
7244 during parsing SDCC.y */
7245 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7246 "got '>=' or '<=' shouldn't have come here");
7250 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
7262 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
7266 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
7270 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
7297 case GET_VALUE_AT_ADDRESS:
7302 if (POINTER_SET(ic))
7329 addSet(&_G.sendSet,ic);
7334 /* piCode(ic,stdout); */
7340 /* now we are ready to call the
7341 peep hole optimizer */
7342 if (!options.nopeep)
7343 peepHole (&lineHead);
7345 /* now do the actual printing */
7346 printLine (lineHead,codeOutFile);