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);
4172 emitcode("rrc","a");
4174 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4175 emitcode("cpl","c");
4176 emitcode("","%05d$:",(tlbl->key+100));
4183 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4184 genIfxJump(ifx, "c");
4188 if(sameRegs(AOP(result),AOP(left))){
4189 /* if left is same as result */
4190 for(;size--; offset++) {
4191 if(AOP_TYPE(right) == AOP_LIT){
4192 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4195 if (IS_AOP_PREG(left)) {
4196 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4197 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4198 aopPut(AOP(result),"a",offset);
4200 emitcode("xrl","%s,%s",
4201 aopGet(AOP(left),offset,FALSE,TRUE),
4202 aopGet(AOP(right),offset,FALSE,FALSE));
4204 if (AOP_TYPE(left) == AOP_ACC)
4205 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4207 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4208 if (IS_AOP_PREG(left)) {
4209 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4210 aopPut(AOP(result),"a",offset);
4212 emitcode("xrl","%s,a",
4213 aopGet(AOP(left),offset,FALSE,TRUE));
4218 // left & result in different registers
4219 if(AOP_TYPE(result) == AOP_CRY){
4221 // if(size), result in bit
4222 // if(!size && ifx), conditional oper: if(left ^ right)
4223 symbol *tlbl = newiTempLabel(NULL);
4224 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4226 emitcode("setb","c");
4228 if((AOP_TYPE(right) == AOP_LIT) &&
4229 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4230 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4232 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4233 emitcode("xrl","a,%s",
4234 aopGet(AOP(left),offset,FALSE,FALSE));
4236 emitcode("jnz","%05d$",tlbl->key+100);
4241 emitcode("","%05d$:",tlbl->key+100);
4244 jmpTrueOrFalse(ifx, tlbl);
4245 } else for(;(size--);offset++){
4247 // result = left & right
4248 if(AOP_TYPE(right) == AOP_LIT){
4249 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4251 aopGet(AOP(left),offset,FALSE,FALSE),
4256 // faster than result <- left, anl result,right
4257 // and better if result is SFR
4258 if (AOP_TYPE(left) == AOP_ACC)
4259 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4261 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4262 emitcode("xrl","a,%s",
4263 aopGet(AOP(left),offset,FALSE,TRUE));
4265 aopPut(AOP(result),"a",offset);
4270 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4271 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4272 freeAsmop(result,NULL,ic,TRUE);
4275 /*-----------------------------------------------------------------*/
4276 /* genInline - write the inline code out */
4277 /*-----------------------------------------------------------------*/
4278 static void genInline (iCode *ic)
4280 char buffer[MAX_INLINEASM];
4284 _G.inLine += (!options.asmpeep);
4285 strcpy(buffer,IC_INLINE(ic));
4287 /* emit each line as a code */
4306 /* emitcode("",buffer); */
4307 _G.inLine -= (!options.asmpeep);
4310 /*-----------------------------------------------------------------*/
4311 /* genRRC - rotate right with carry */
4312 /*-----------------------------------------------------------------*/
4313 static void genRRC (iCode *ic)
4315 operand *left , *result ;
4316 int size, offset = 0;
4319 /* rotate right with carry */
4321 result=IC_RESULT(ic);
4322 aopOp (left,ic,FALSE);
4323 aopOp (result,ic,FALSE);
4325 /* move it to the result */
4326 size = AOP_SIZE(result);
4330 l = aopGet(AOP(left),offset,FALSE,FALSE);
4332 emitcode("rrc","a");
4333 if (AOP_SIZE(result) > 1)
4334 aopPut(AOP(result),"a",offset--);
4336 /* now we need to put the carry into the
4337 highest order byte of the result */
4338 if (AOP_SIZE(result) > 1) {
4339 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
4342 emitcode("mov","acc.7,c");
4343 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
4344 freeAsmop(left,NULL,ic,TRUE);
4345 freeAsmop(result,NULL,ic,TRUE);
4348 /*-----------------------------------------------------------------*/
4349 /* genRLC - generate code for rotate left with carry */
4350 /*-----------------------------------------------------------------*/
4351 static void genRLC (iCode *ic)
4353 operand *left , *result ;
4354 int size, offset = 0;
4357 /* rotate right with carry */
4359 result=IC_RESULT(ic);
4360 aopOp (left,ic,FALSE);
4361 aopOp (result,ic,FALSE);
4363 /* move it to the result */
4364 size = AOP_SIZE(result);
4367 l = aopGet(AOP(left),offset,FALSE,FALSE);
4369 emitcode("add","a,acc");
4370 if (AOP_SIZE(result) > 1)
4371 aopPut(AOP(result),"a",offset++);
4373 l = aopGet(AOP(left),offset,FALSE,FALSE);
4375 emitcode("rlc","a");
4376 if (AOP_SIZE(result) > 1)
4377 aopPut(AOP(result),"a",offset++);
4380 /* now we need to put the carry into the
4381 highest order byte of the result */
4382 if (AOP_SIZE(result) > 1) {
4383 l = aopGet(AOP(result),0,FALSE,FALSE);
4386 emitcode("mov","acc.0,c");
4387 aopPut(AOP(result),"a",0);
4388 freeAsmop(left,NULL,ic,TRUE);
4389 freeAsmop(result,NULL,ic,TRUE);
4392 /*-----------------------------------------------------------------*/
4393 /* genGetHbit - generates code get highest order bit */
4394 /*-----------------------------------------------------------------*/
4395 static void genGetHbit (iCode *ic)
4397 operand *left, *result;
4399 result=IC_RESULT(ic);
4400 aopOp (left,ic,FALSE);
4401 aopOp (result,ic,FALSE);
4403 /* get the highest order byte into a */
4404 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
4405 if(AOP_TYPE(result) == AOP_CRY){
4406 emitcode("rlc","a");
4411 emitcode("anl","a,#0x01");
4416 freeAsmop(left,NULL,ic,TRUE);
4417 freeAsmop(result,NULL,ic,TRUE);
4420 /*-----------------------------------------------------------------*/
4421 /* AccRol - rotate left accumulator by known count */
4422 /*-----------------------------------------------------------------*/
4423 static void AccRol (int shCount)
4425 shCount &= 0x0007; // shCount : 0..7
4437 emitcode("swap","a");
4441 emitcode("swap","a");
4444 emitcode("swap","a");
4457 /*-----------------------------------------------------------------*/
4458 /* AccLsh - left shift accumulator by known count */
4459 /*-----------------------------------------------------------------*/
4460 static void AccLsh (int shCount)
4464 emitcode("add","a,acc");
4467 emitcode("add","a,acc");
4468 emitcode("add","a,acc");
4470 /* rotate left accumulator */
4472 /* and kill the lower order bits */
4473 emitcode("anl","a,#0x%02x", SLMask[shCount]);
4478 /*-----------------------------------------------------------------*/
4479 /* AccRsh - right shift accumulator by known count */
4480 /*-----------------------------------------------------------------*/
4481 static void AccRsh (int shCount)
4486 emitcode("rrc","a");
4488 /* rotate right accumulator */
4489 AccRol(8 - shCount);
4490 /* and kill the higher order bits */
4491 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4496 /*-----------------------------------------------------------------*/
4497 /* AccSRsh - signed right shift accumulator by known count */
4498 /*-----------------------------------------------------------------*/
4499 static void AccSRsh (int shCount)
4504 emitcode("mov","c,acc.7");
4505 emitcode("rrc","a");
4506 } else if(shCount == 2){
4507 emitcode("mov","c,acc.7");
4508 emitcode("rrc","a");
4509 emitcode("mov","c,acc.7");
4510 emitcode("rrc","a");
4512 tlbl = newiTempLabel(NULL);
4513 /* rotate right accumulator */
4514 AccRol(8 - shCount);
4515 /* and kill the higher order bits */
4516 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4517 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4518 emitcode("orl","a,#0x%02x",
4519 (unsigned char)~SRMask[shCount]);
4520 emitcode("","%05d$:",tlbl->key+100);
4525 /*-----------------------------------------------------------------*/
4526 /* shiftR1Left2Result - shift right one byte from left to result */
4527 /*-----------------------------------------------------------------*/
4528 static void shiftR1Left2Result (operand *left, int offl,
4529 operand *result, int offr,
4530 int shCount, int sign)
4532 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4533 /* shift right accumulator */
4538 aopPut(AOP(result),"a",offr);
4541 /*-----------------------------------------------------------------*/
4542 /* shiftL1Left2Result - shift left one byte from left to result */
4543 /*-----------------------------------------------------------------*/
4544 static void shiftL1Left2Result (operand *left, int offl,
4545 operand *result, int offr, int shCount)
4548 l = aopGet(AOP(left),offl,FALSE,FALSE);
4550 /* shift left accumulator */
4552 aopPut(AOP(result),"a",offr);
4555 /*-----------------------------------------------------------------*/
4556 /* movLeft2Result - move byte from left to result */
4557 /*-----------------------------------------------------------------*/
4558 static void movLeft2Result (operand *left, int offl,
4559 operand *result, int offr, int sign)
4562 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
4563 l = aopGet(AOP(left),offl,FALSE,FALSE);
4565 if (*l == '@' && (IS_AOP_PREG(result))) {
4566 emitcode("mov","a,%s",l);
4567 aopPut(AOP(result),"a",offr);
4570 aopPut(AOP(result),l,offr);
4572 /* MSB sign in acc.7 ! */
4573 if(getDataSize(left) == offl+1){
4574 emitcode("mov","a,%s",l);
4575 aopPut(AOP(result),"a",offr);
4582 /*-----------------------------------------------------------------*/
4583 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
4584 /*-----------------------------------------------------------------*/
4585 static void AccAXRrl1 (char *x)
4587 emitcode("rrc","a");
4588 emitcode("xch","a,%s", x);
4589 emitcode("rrc","a");
4590 emitcode("xch","a,%s", x);
4593 /*-----------------------------------------------------------------*/
4594 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
4595 /*-----------------------------------------------------------------*/
4596 static void AccAXLrl1 (char *x)
4598 emitcode("xch","a,%s",x);
4599 emitcode("rlc","a");
4600 emitcode("xch","a,%s",x);
4601 emitcode("rlc","a");
4604 /*-----------------------------------------------------------------*/
4605 /* AccAXLsh1 - left shift a:x<-0 by 1 */
4606 /*-----------------------------------------------------------------*/
4607 static void AccAXLsh1 (char *x)
4609 emitcode("xch","a,%s",x);
4610 emitcode("add","a,acc");
4611 emitcode("xch","a,%s",x);
4612 emitcode("rlc","a");
4615 /*-----------------------------------------------------------------*/
4616 /* AccAXLsh - left shift a:x by known count (0..7) */
4617 /*-----------------------------------------------------------------*/
4618 static void AccAXLsh (char *x, int shCount)
4632 case 5 : // AAAAABBB:CCCCCDDD
4633 AccRol(shCount); // BBBAAAAA:CCCCCDDD
4634 emitcode("anl","a,#0x%02x",
4635 SLMask[shCount]); // BBB00000:CCCCCDDD
4636 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
4637 AccRol(shCount); // DDDCCCCC:BBB00000
4638 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
4639 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
4640 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
4641 emitcode("anl","a,#0x%02x",
4642 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
4643 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
4644 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
4646 case 6 : // AAAAAABB:CCCCCCDD
4647 emitcode("anl","a,#0x%02x",
4648 SRMask[shCount]); // 000000BB:CCCCCCDD
4649 emitcode("mov","c,acc.0"); // c = B
4650 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
4651 AccAXRrl1(x); // BCCCCCCD:D000000B
4652 AccAXRrl1(x); // BBCCCCCC:DD000000
4654 case 7 : // a:x <<= 7
4655 emitcode("anl","a,#0x%02x",
4656 SRMask[shCount]); // 0000000B:CCCCCCCD
4657 emitcode("mov","c,acc.0"); // c = B
4658 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
4659 AccAXRrl1(x); // BCCCCCCC:D0000000
4666 /*-----------------------------------------------------------------*/
4667 /* AccAXRsh - right shift a:x known count (0..7) */
4668 /*-----------------------------------------------------------------*/
4669 static void AccAXRsh (char *x, int shCount)
4676 AccAXRrl1(x); // 0->a:x
4680 AccAXRrl1(x); // 0->a:x
4682 AccAXRrl1(x); // 0->a:x
4686 case 5 : // AAAAABBB:CCCCCDDD = a:x
4687 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
4688 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
4689 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
4690 emitcode("anl","a,#0x%02x",
4691 SRMask[shCount]); // 000CCCCC:BBBAAAAA
4692 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
4693 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
4694 emitcode("anl","a,#0x%02x",
4695 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
4696 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
4697 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
4698 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
4700 case 6 : // AABBBBBB:CCDDDDDD
4701 emitcode("mov","c,acc.7");
4702 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
4703 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
4704 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
4705 emitcode("anl","a,#0x%02x",
4706 SRMask[shCount]); // 000000AA:BBBBBBCC
4708 case 7 : // ABBBBBBB:CDDDDDDD
4709 emitcode("mov","c,acc.7"); // c = A
4710 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
4711 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
4712 emitcode("anl","a,#0x%02x",
4713 SRMask[shCount]); // 0000000A:BBBBBBBC
4720 /*-----------------------------------------------------------------*/
4721 /* AccAXRshS - right shift signed a:x known count (0..7) */
4722 /*-----------------------------------------------------------------*/
4723 static void AccAXRshS (char *x, int shCount)
4730 emitcode("mov","c,acc.7");
4731 AccAXRrl1(x); // s->a:x
4734 emitcode("mov","c,acc.7");
4735 AccAXRrl1(x); // s->a:x
4736 emitcode("mov","c,acc.7");
4737 AccAXRrl1(x); // s->a:x
4741 case 5 : // AAAAABBB:CCCCCDDD = a:x
4742 tlbl = newiTempLabel(NULL);
4743 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
4744 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
4745 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
4746 emitcode("anl","a,#0x%02x",
4747 SRMask[shCount]); // 000CCCCC:BBBAAAAA
4748 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
4749 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
4750 emitcode("anl","a,#0x%02x",
4751 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
4752 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
4753 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
4754 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
4755 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4756 emitcode("orl","a,#0x%02x",
4757 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
4758 emitcode("","%05d$:",tlbl->key+100);
4759 break; // SSSSAAAA:BBBCCCCC
4760 case 6 : // AABBBBBB:CCDDDDDD
4761 tlbl = newiTempLabel(NULL);
4762 emitcode("mov","c,acc.7");
4763 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
4764 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
4765 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
4766 emitcode("anl","a,#0x%02x",
4767 SRMask[shCount]); // 000000AA:BBBBBBCC
4768 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4769 emitcode("orl","a,#0x%02x",
4770 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
4771 emitcode("","%05d$:",tlbl->key+100);
4773 case 7 : // ABBBBBBB:CDDDDDDD
4774 tlbl = newiTempLabel(NULL);
4775 emitcode("mov","c,acc.7"); // c = A
4776 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
4777 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
4778 emitcode("anl","a,#0x%02x",
4779 SRMask[shCount]); // 0000000A:BBBBBBBC
4780 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4781 emitcode("orl","a,#0x%02x",
4782 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
4783 emitcode("","%05d$:",tlbl->key+100);
4790 /*-----------------------------------------------------------------*/
4791 /* shiftL2Left2Result - shift left two bytes from left to result */
4792 /*-----------------------------------------------------------------*/
4793 static void shiftL2Left2Result (operand *left, int offl,
4794 operand *result, int offr, int shCount)
4796 if(sameRegs(AOP(result), AOP(left)) &&
4797 ((offl + MSB16) == offr)){
4798 /* don't crash result[offr] */
4799 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4800 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4802 movLeft2Result(left,offl, result, offr, 0);
4803 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4805 /* ax << shCount (x = lsb(result))*/
4806 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
4807 aopPut(AOP(result),"a",offr+MSB16);
4811 /*-----------------------------------------------------------------*/
4812 /* shiftR2Left2Result - shift right two bytes from left to result */
4813 /*-----------------------------------------------------------------*/
4814 static void shiftR2Left2Result (operand *left, int offl,
4815 operand *result, int offr,
4816 int shCount, int sign)
4818 if(sameRegs(AOP(result), AOP(left)) &&
4819 ((offl + MSB16) == offr)){
4820 /* don't crash result[offr] */
4821 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4822 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4824 movLeft2Result(left,offl, result, offr, 0);
4825 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4827 /* a:x >> shCount (x = lsb(result))*/
4829 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
4831 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
4832 if(getDataSize(result) > 1)
4833 aopPut(AOP(result),"a",offr+MSB16);
4836 /*-----------------------------------------------------------------*/
4837 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
4838 /*-----------------------------------------------------------------*/
4839 static void shiftLLeftOrResult (operand *left, int offl,
4840 operand *result, int offr, int shCount)
4842 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4843 /* shift left accumulator */
4845 /* or with result */
4846 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
4847 /* back to result */
4848 aopPut(AOP(result),"a",offr);
4851 /*-----------------------------------------------------------------*/
4852 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
4853 /*-----------------------------------------------------------------*/
4854 static void shiftRLeftOrResult (operand *left, int offl,
4855 operand *result, int offr, int shCount)
4857 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4858 /* shift right accumulator */
4860 /* or with result */
4861 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
4862 /* back to result */
4863 aopPut(AOP(result),"a",offr);
4866 /*-----------------------------------------------------------------*/
4867 /* genlshOne - left shift a one byte quantity by known count */
4868 /*-----------------------------------------------------------------*/
4869 static void genlshOne (operand *result, operand *left, int shCount)
4871 shiftL1Left2Result(left, LSB, result, LSB, shCount);
4874 /*-----------------------------------------------------------------*/
4875 /* genlshTwo - left shift two bytes by known amount != 0 */
4876 /*-----------------------------------------------------------------*/
4877 static void genlshTwo (operand *result,operand *left, int shCount)
4879 int size = AOP_SIZE(result);
4884 /* if shCount >= 8 */
4890 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
4892 movLeft2Result(left, LSB, result, MSB16, 0);
4894 aopPut(AOP(result),zero,LSB);
4897 /* 1 <= shCount <= 7 */
4900 shiftL1Left2Result(left, LSB, result, LSB, shCount);
4902 shiftL2Left2Result(left, LSB, result, LSB, shCount);
4906 /*-----------------------------------------------------------------*/
4907 /* shiftLLong - shift left one long from left to result */
4908 /* offl = LSB or MSB16 */
4909 /*-----------------------------------------------------------------*/
4910 static void shiftLLong (operand *left, operand *result, int offr )
4913 int size = AOP_SIZE(result);
4915 if(size >= LSB+offr){
4916 l = aopGet(AOP(left),LSB,FALSE,FALSE);
4918 emitcode("add","a,acc");
4919 if (sameRegs(AOP(left),AOP(result)) &&
4920 size >= MSB16+offr && offr != LSB )
4921 emitcode("xch","a,%s",
4922 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
4924 aopPut(AOP(result),"a",LSB+offr);
4927 if(size >= MSB16+offr){
4928 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
4929 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
4932 emitcode("rlc","a");
4933 if (sameRegs(AOP(left),AOP(result)) &&
4934 size >= MSB24+offr && offr != LSB)
4935 emitcode("xch","a,%s",
4936 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
4938 aopPut(AOP(result),"a",MSB16+offr);
4941 if(size >= MSB24+offr){
4942 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
4943 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
4946 emitcode("rlc","a");
4947 if (sameRegs(AOP(left),AOP(result)) &&
4948 size >= MSB32+offr && offr != LSB )
4949 emitcode("xch","a,%s",
4950 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
4952 aopPut(AOP(result),"a",MSB24+offr);
4955 if(size > MSB32+offr){
4956 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
4957 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
4960 emitcode("rlc","a");
4961 aopPut(AOP(result),"a",MSB32+offr);
4964 aopPut(AOP(result),zero,LSB);
4967 /*-----------------------------------------------------------------*/
4968 /* genlshFour - shift four byte by a known amount != 0 */
4969 /*-----------------------------------------------------------------*/
4970 static void genlshFour (operand *result, operand *left, int shCount)
4974 size = AOP_SIZE(result);
4976 /* if shifting more that 3 bytes */
4977 if (shCount >= 24 ) {
4980 /* lowest order of left goes to the highest
4981 order of the destination */
4982 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
4984 movLeft2Result(left, LSB, result, MSB32, 0);
4985 aopPut(AOP(result),zero,LSB);
4986 aopPut(AOP(result),zero,MSB16);
4987 aopPut(AOP(result),zero,MSB32);
4991 /* more than two bytes */
4992 else if ( shCount >= 16 ) {
4993 /* lower order two bytes goes to higher order two bytes */
4995 /* if some more remaining */
4997 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
4999 movLeft2Result(left, MSB16, result, MSB32, 0);
5000 movLeft2Result(left, LSB, result, MSB24, 0);
5002 aopPut(AOP(result),zero,MSB16);
5003 aopPut(AOP(result),zero,LSB);
5007 /* if more than 1 byte */
5008 else if ( shCount >= 8 ) {
5009 /* lower order three bytes goes to higher order three bytes */
5013 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5015 movLeft2Result(left, LSB, result, MSB16, 0);
5017 else{ /* size = 4 */
5019 movLeft2Result(left, MSB24, result, MSB32, 0);
5020 movLeft2Result(left, MSB16, result, MSB24, 0);
5021 movLeft2Result(left, LSB, result, MSB16, 0);
5022 aopPut(AOP(result),zero,LSB);
5024 else if(shCount == 1)
5025 shiftLLong(left, result, MSB16);
5027 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5028 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5029 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5030 aopPut(AOP(result),zero,LSB);
5035 /* 1 <= shCount <= 7 */
5036 else if(shCount <= 2){
5037 shiftLLong(left, result, LSB);
5039 shiftLLong(result, result, LSB);
5041 /* 3 <= shCount <= 7, optimize */
5043 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5044 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5045 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5049 /*-----------------------------------------------------------------*/
5050 /* genLeftShiftLiteral - left shifting by known count */
5051 /*-----------------------------------------------------------------*/
5052 static void genLeftShiftLiteral (operand *left,
5057 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5060 freeAsmop(right,NULL,ic,TRUE);
5062 aopOp(left,ic,FALSE);
5063 aopOp(result,ic,FALSE);
5065 size = getSize(operandType(result));
5068 emitcode("; shift left ","result %d, left %d",size,
5072 /* I suppose that the left size >= result size */
5075 movLeft2Result(left, size, result, size, 0);
5079 else if(shCount >= (size * 8))
5081 aopPut(AOP(result),zero,size);
5085 genlshOne (result,left,shCount);
5090 genlshTwo (result,left,shCount);
5094 genlshFour (result,left,shCount);
5098 freeAsmop(left,NULL,ic,TRUE);
5099 freeAsmop(result,NULL,ic,TRUE);
5102 /*-----------------------------------------------------------------*/
5103 /* genLeftShift - generates code for left shifting */
5104 /*-----------------------------------------------------------------*/
5105 static void genLeftShift (iCode *ic)
5107 operand *left,*right, *result;
5110 symbol *tlbl , *tlbl1;
5112 right = IC_RIGHT(ic);
5114 result = IC_RESULT(ic);
5116 aopOp(right,ic,FALSE);
5118 /* if the shift count is known then do it
5119 as efficiently as possible */
5120 if (AOP_TYPE(right) == AOP_LIT) {
5121 genLeftShiftLiteral (left,right,result,ic);
5125 /* shift count is unknown then we have to form
5126 a loop get the loop count in B : Note: we take
5127 only the lower order byte since shifting
5128 more that 32 bits make no sense anyway, ( the
5129 largest size of an object can be only 32 bits ) */
5131 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5132 emitcode("inc","b");
5133 freeAsmop (right,NULL,ic,TRUE);
5134 aopOp(left,ic,FALSE);
5135 aopOp(result,ic,FALSE);
5137 /* now move the left to the result if they are not the
5139 if (!sameRegs(AOP(left),AOP(result)) &&
5140 AOP_SIZE(result) > 1) {
5142 size = AOP_SIZE(result);
5145 l = aopGet(AOP(left),offset,FALSE,TRUE);
5146 if (*l == '@' && (IS_AOP_PREG(result))) {
5148 emitcode("mov","a,%s",l);
5149 aopPut(AOP(result),"a",offset);
5151 aopPut(AOP(result),l,offset);
5156 tlbl = newiTempLabel(NULL);
5157 size = AOP_SIZE(result);
5159 tlbl1 = newiTempLabel(NULL);
5161 /* if it is only one byte then */
5163 symbol *tlbl1 = newiTempLabel(NULL);
5165 l = aopGet(AOP(left),0,FALSE,FALSE);
5167 emitcode("sjmp","%05d$",tlbl1->key+100);
5168 emitcode("","%05d$:",tlbl->key+100);
5169 emitcode("add","a,acc");
5170 emitcode("","%05d$:",tlbl1->key+100);
5171 emitcode("djnz","b,%05d$",tlbl->key+100);
5172 aopPut(AOP(result),"a",0);
5176 reAdjustPreg(AOP(result));
5178 emitcode("sjmp","%05d$",tlbl1->key+100);
5179 emitcode("","%05d$:",tlbl->key+100);
5180 l = aopGet(AOP(result),offset,FALSE,FALSE);
5182 emitcode("add","a,acc");
5183 aopPut(AOP(result),"a",offset++);
5185 l = aopGet(AOP(result),offset,FALSE,FALSE);
5187 emitcode("rlc","a");
5188 aopPut(AOP(result),"a",offset++);
5190 reAdjustPreg(AOP(result));
5192 emitcode("","%05d$:",tlbl1->key+100);
5193 emitcode("djnz","b,%05d$",tlbl->key+100);
5195 freeAsmop(left,NULL,ic,TRUE);
5196 freeAsmop(result,NULL,ic,TRUE);
5199 /*-----------------------------------------------------------------*/
5200 /* genrshOne - right shift a one byte quantity by known count */
5201 /*-----------------------------------------------------------------*/
5202 static void genrshOne (operand *result, operand *left,
5203 int shCount, int sign)
5205 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
5208 /*-----------------------------------------------------------------*/
5209 /* genrshTwo - right shift two bytes by known amount != 0 */
5210 /*-----------------------------------------------------------------*/
5211 static void genrshTwo (operand *result,operand *left,
5212 int shCount, int sign)
5214 /* if shCount >= 8 */
5218 shiftR1Left2Result(left, MSB16, result, LSB,
5221 movLeft2Result(left, MSB16, result, LSB, sign);
5222 addSign(result, MSB16, sign);
5225 /* 1 <= shCount <= 7 */
5227 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
5230 /*-----------------------------------------------------------------*/
5231 /* shiftRLong - shift right one long from left to result */
5232 /* offl = LSB or MSB16 */
5233 /*-----------------------------------------------------------------*/
5234 static void shiftRLong (operand *left, int offl,
5235 operand *result, int sign)
5238 emitcode("clr","c");
5239 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
5241 emitcode("mov","c,acc.7");
5242 emitcode("rrc","a");
5243 aopPut(AOP(result),"a",MSB32-offl);
5245 /* add sign of "a" */
5246 addSign(result, MSB32, sign);
5248 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
5249 emitcode("rrc","a");
5250 aopPut(AOP(result),"a",MSB24-offl);
5252 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
5253 emitcode("rrc","a");
5254 aopPut(AOP(result),"a",MSB16-offl);
5257 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
5258 emitcode("rrc","a");
5259 aopPut(AOP(result),"a",LSB);
5263 /*-----------------------------------------------------------------*/
5264 /* genrshFour - shift four byte by a known amount != 0 */
5265 /*-----------------------------------------------------------------*/
5266 static void genrshFour (operand *result, operand *left,
5267 int shCount, int sign)
5269 /* if shifting more that 3 bytes */
5270 if(shCount >= 24 ) {
5273 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
5275 movLeft2Result(left, MSB32, result, LSB, sign);
5276 addSign(result, MSB16, sign);
5278 else if(shCount >= 16){
5281 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
5283 movLeft2Result(left, MSB24, result, LSB, 0);
5284 movLeft2Result(left, MSB32, result, MSB16, sign);
5286 addSign(result, MSB24, sign);
5288 else if(shCount >= 8){
5291 shiftRLong(left, MSB16, result, sign);
5292 else if(shCount == 0){
5293 movLeft2Result(left, MSB16, result, LSB, 0);
5294 movLeft2Result(left, MSB24, result, MSB16, 0);
5295 movLeft2Result(left, MSB32, result, MSB24, sign);
5296 addSign(result, MSB32, sign);
5299 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
5300 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
5301 /* the last shift is signed */
5302 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
5303 addSign(result, MSB32, sign);
5306 else{ /* 1 <= shCount <= 7 */
5308 shiftRLong(left, LSB, result, sign);
5310 shiftRLong(result, LSB, result, sign);
5313 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
5314 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
5315 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
5320 /*-----------------------------------------------------------------*/
5321 /* genRightShiftLiteral - right shifting by known count */
5322 /*-----------------------------------------------------------------*/
5323 static void genRightShiftLiteral (operand *left,
5329 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5332 freeAsmop(right,NULL,ic,TRUE);
5334 aopOp(left,ic,FALSE);
5335 aopOp(result,ic,FALSE);
5338 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
5342 size = getDataSize(left);
5343 /* test the LEFT size !!! */
5345 /* I suppose that the left size >= result size */
5347 size = getDataSize(result);
5349 movLeft2Result(left, size, result, size, 0);
5352 else if(shCount >= (size * 8)){
5354 /* get sign in acc.7 */
5355 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
5356 addSign(result, LSB, sign);
5360 genrshOne (result,left,shCount,sign);
5364 genrshTwo (result,left,shCount,sign);
5368 genrshFour (result,left,shCount,sign);
5374 freeAsmop(left,NULL,ic,TRUE);
5375 freeAsmop(result,NULL,ic,TRUE);
5379 /*-----------------------------------------------------------------*/
5380 /* genSignedRightShift - right shift of signed number */
5381 /*-----------------------------------------------------------------*/
5382 static void genSignedRightShift (iCode *ic)
5384 operand *right, *left, *result;
5387 symbol *tlbl, *tlbl1 ;
5389 /* we do it the hard way put the shift count in b
5390 and loop thru preserving the sign */
5392 right = IC_RIGHT(ic);
5394 result = IC_RESULT(ic);
5396 aopOp(right,ic,FALSE);
5399 if ( AOP_TYPE(right) == AOP_LIT) {
5400 genRightShiftLiteral (left,right,result,ic,1);
5403 /* shift count is unknown then we have to form
5404 a loop get the loop count in B : Note: we take
5405 only the lower order byte since shifting
5406 more that 32 bits make no sense anyway, ( the
5407 largest size of an object can be only 32 bits ) */
5409 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5410 emitcode("inc","b");
5411 freeAsmop (right,NULL,ic,TRUE);
5412 aopOp(left,ic,FALSE);
5413 aopOp(result,ic,FALSE);
5415 /* now move the left to the result if they are not the
5417 if (!sameRegs(AOP(left),AOP(result)) &&
5418 AOP_SIZE(result) > 1) {
5420 size = AOP_SIZE(result);
5423 l = aopGet(AOP(left),offset,FALSE,TRUE);
5424 if (*l == '@' && IS_AOP_PREG(result)) {
5426 emitcode("mov","a,%s",l);
5427 aopPut(AOP(result),"a",offset);
5429 aopPut(AOP(result),l,offset);
5434 /* mov the highest order bit to OVR */
5435 tlbl = newiTempLabel(NULL);
5436 tlbl1= newiTempLabel(NULL);
5438 size = AOP_SIZE(result);
5440 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
5441 emitcode("rlc","a");
5442 emitcode("mov","ov,c");
5443 /* if it is only one byte then */
5445 l = aopGet(AOP(left),0,FALSE,FALSE);
5447 emitcode("sjmp","%05d$",tlbl1->key+100);
5448 emitcode("","%05d$:",tlbl->key+100);
5449 emitcode("mov","c,ov");
5450 emitcode("rrc","a");
5451 emitcode("","%05d$:",tlbl1->key+100);
5452 emitcode("djnz","b,%05d$",tlbl->key+100);
5453 aopPut(AOP(result),"a",0);
5457 reAdjustPreg(AOP(result));
5458 emitcode("sjmp","%05d$",tlbl1->key+100);
5459 emitcode("","%05d$:",tlbl->key+100);
5460 emitcode("mov","c,ov");
5462 l = aopGet(AOP(result),offset,FALSE,FALSE);
5464 emitcode("rrc","a");
5465 aopPut(AOP(result),"a",offset--);
5467 reAdjustPreg(AOP(result));
5468 emitcode("","%05d$:",tlbl1->key+100);
5469 emitcode("djnz","b,%05d$",tlbl->key+100);
5472 freeAsmop(left,NULL,ic,TRUE);
5473 freeAsmop(result,NULL,ic,TRUE);
5476 /*-----------------------------------------------------------------*/
5477 /* genRightShift - generate code for right shifting */
5478 /*-----------------------------------------------------------------*/
5479 static void genRightShift (iCode *ic)
5481 operand *right, *left, *result;
5485 symbol *tlbl, *tlbl1 ;
5487 /* if signed then we do it the hard way preserve the
5488 sign bit moving it inwards */
5489 retype = getSpec(operandType(IC_RESULT(ic)));
5491 if (!SPEC_USIGN(retype)) {
5492 genSignedRightShift (ic);
5496 /* signed & unsigned types are treated the same : i.e. the
5497 signed is NOT propagated inwards : quoting from the
5498 ANSI - standard : "for E1 >> E2, is equivalent to division
5499 by 2**E2 if unsigned or if it has a non-negative value,
5500 otherwise the result is implementation defined ", MY definition
5501 is that the sign does not get propagated */
5503 right = IC_RIGHT(ic);
5505 result = IC_RESULT(ic);
5507 aopOp(right,ic,FALSE);
5509 /* if the shift count is known then do it
5510 as efficiently as possible */
5511 if (AOP_TYPE(right) == AOP_LIT) {
5512 genRightShiftLiteral (left,right,result,ic, 0);
5516 /* shift count is unknown then we have to form
5517 a loop get the loop count in B : Note: we take
5518 only the lower order byte since shifting
5519 more that 32 bits make no sense anyway, ( the
5520 largest size of an object can be only 32 bits ) */
5522 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5523 emitcode("inc","b");
5524 freeAsmop (right,NULL,ic,TRUE);
5525 aopOp(left,ic,FALSE);
5526 aopOp(result,ic,FALSE);
5528 /* now move the left to the result if they are not the
5530 if (!sameRegs(AOP(left),AOP(result)) &&
5531 AOP_SIZE(result) > 1) {
5533 size = AOP_SIZE(result);
5536 l = aopGet(AOP(left),offset,FALSE,TRUE);
5537 if (*l == '@' && IS_AOP_PREG(result)) {
5539 emitcode("mov","a,%s",l);
5540 aopPut(AOP(result),"a",offset);
5542 aopPut(AOP(result),l,offset);
5547 tlbl = newiTempLabel(NULL);
5548 tlbl1= newiTempLabel(NULL);
5549 size = AOP_SIZE(result);
5552 /* if it is only one byte then */
5554 l = aopGet(AOP(left),0,FALSE,FALSE);
5556 emitcode("sjmp","%05d$",tlbl1->key+100);
5557 emitcode("","%05d$:",tlbl->key+100);
5559 emitcode("rrc","a");
5560 emitcode("","%05d$:",tlbl1->key+100);
5561 emitcode("djnz","b,%05d$",tlbl->key+100);
5562 aopPut(AOP(result),"a",0);
5566 reAdjustPreg(AOP(result));
5567 emitcode("sjmp","%05d$",tlbl1->key+100);
5568 emitcode("","%05d$:",tlbl->key+100);
5571 l = aopGet(AOP(result),offset,FALSE,FALSE);
5573 emitcode("rrc","a");
5574 aopPut(AOP(result),"a",offset--);
5576 reAdjustPreg(AOP(result));
5578 emitcode("","%05d$:",tlbl1->key+100);
5579 emitcode("djnz","b,%05d$",tlbl->key+100);
5582 freeAsmop(left,NULL,ic,TRUE);
5583 freeAsmop(result,NULL,ic,TRUE);
5586 /*-----------------------------------------------------------------*/
5587 /* genUnpackBits - generates code for unpacking bits */
5588 /*-----------------------------------------------------------------*/
5589 static void genUnpackBits (operand *result, char *rname, int ptype)
5596 etype = getSpec(operandType(result));
5598 /* read the first byte */
5603 emitcode("mov","a,@%s",rname);
5607 emitcode("movx","a,@%s",rname);
5611 emitcode("movx","a,@dptr");
5615 emitcode("clr","a");
5616 emitcode("movc","a","@a+dptr");
5620 emitcode("lcall","__gptrget");
5624 /* if we have bitdisplacement then it fits */
5625 /* into this byte completely or if length is */
5626 /* less than a byte */
5627 if ((shCnt = SPEC_BSTR(etype)) ||
5628 (SPEC_BLEN(etype) <= 8)) {
5630 /* shift right acc */
5633 emitcode("anl","a,#0x%02x",
5634 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
5635 aopPut(AOP(result),"a",offset);
5639 /* bit field did not fit in a byte */
5640 rlen = SPEC_BLEN(etype) - 8;
5641 aopPut(AOP(result),"a",offset++);
5648 emitcode("inc","%s",rname);
5649 emitcode("mov","a,@%s",rname);
5653 emitcode("inc","%s",rname);
5654 emitcode("movx","a,@%s",rname);
5658 emitcode("inc","dptr");
5659 emitcode("movx","a,@dptr");
5663 emitcode("clr","a");
5664 emitcode("inc","dptr");
5665 emitcode("movc","a","@a+dptr");
5669 emitcode("inc","dptr");
5670 emitcode("lcall","__gptrget");
5675 /* if we are done */
5679 aopPut(AOP(result),"a",offset++);
5684 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
5685 aopPut(AOP(result),"a",offset);
5692 /*-----------------------------------------------------------------*/
5693 /* genDataPointerGet - generates code when ptr offset is known */
5694 /*-----------------------------------------------------------------*/
5695 static void genDataPointerGet (operand *left,
5701 int size , offset = 0;
5702 aopOp(result,ic,TRUE);
5704 /* get the string representation of the name */
5705 l = aopGet(AOP(left),0,FALSE,TRUE);
5706 size = AOP_SIZE(result);
5709 sprintf(buffer,"(%s + %d)",l+1,offset);
5711 sprintf(buffer,"%s",l+1);
5712 aopPut(AOP(result),buffer,offset++);
5715 freeAsmop(left,NULL,ic,TRUE);
5716 freeAsmop(result,NULL,ic,TRUE);
5719 /*-----------------------------------------------------------------*/
5720 /* genNearPointerGet - emitcode for near pointer fetch */
5721 /*-----------------------------------------------------------------*/
5722 static void genNearPointerGet (operand *left,
5729 link *rtype, *retype;
5730 link *ltype = operandType(left);
5733 rtype = operandType(result);
5734 retype= getSpec(rtype);
5736 aopOp(left,ic,FALSE);
5738 /* if left is rematerialisable and
5739 result is not bit variable type and
5740 the left is pointer to data space i.e
5741 lower 128 bytes of space */
5742 if (AOP_TYPE(left) == AOP_IMMD &&
5743 !IS_BITVAR(retype) &&
5744 DCL_TYPE(ltype) == POINTER) {
5745 genDataPointerGet (left,result,ic);
5749 /* if the value is already in a pointer register
5750 then don't need anything more */
5751 if (!AOP_INPREG(AOP(left))) {
5752 /* otherwise get a free pointer register */
5754 preg = getFreePtr(ic,&aop,FALSE);
5755 emitcode("mov","%s,%s",
5757 aopGet(AOP(left),0,FALSE,TRUE));
5758 rname = preg->name ;
5760 rname = aopGet(AOP(left),0,FALSE,FALSE);
5762 freeAsmop(left,NULL,ic,TRUE);
5763 aopOp (result,ic,FALSE);
5765 /* if bitfield then unpack the bits */
5766 if (IS_BITVAR(retype))
5767 genUnpackBits (result,rname,POINTER);
5769 /* we have can just get the values */
5770 int size = AOP_SIZE(result);
5774 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
5776 emitcode("mov","a,@%s",rname);
5777 aopPut(AOP(result),"a",offset);
5779 sprintf(buffer,"@%s",rname);
5780 aopPut(AOP(result),buffer,offset);
5784 emitcode("inc","%s",rname);
5788 /* now some housekeeping stuff */
5790 /* we had to allocate for this iCode */
5791 freeAsmop(NULL,aop,ic,TRUE);
5793 /* we did not allocate which means left
5794 already in a pointer register, then
5795 if size > 0 && this could be used again
5796 we have to point it back to where it
5798 if (AOP_SIZE(result) > 1 &&
5799 !OP_SYMBOL(left)->remat &&
5800 ( OP_SYMBOL(left)->liveTo > ic->seq ||
5802 int size = AOP_SIZE(result) - 1;
5804 emitcode("dec","%s",rname);
5809 freeAsmop(result,NULL,ic,TRUE);
5813 /*-----------------------------------------------------------------*/
5814 /* genPagedPointerGet - emitcode for paged pointer fetch */
5815 /*-----------------------------------------------------------------*/
5816 static void genPagedPointerGet (operand *left,
5823 link *rtype, *retype;
5825 rtype = operandType(result);
5826 retype= getSpec(rtype);
5828 aopOp(left,ic,FALSE);
5830 /* if the value is already in a pointer register
5831 then don't need anything more */
5832 if (!AOP_INPREG(AOP(left))) {
5833 /* otherwise get a free pointer register */
5835 preg = getFreePtr(ic,&aop,FALSE);
5836 emitcode("mov","%s,%s",
5838 aopGet(AOP(left),0,FALSE,TRUE));
5839 rname = preg->name ;
5841 rname = aopGet(AOP(left),0,FALSE,FALSE);
5843 freeAsmop(left,NULL,ic,TRUE);
5844 aopOp (result,ic,FALSE);
5846 /* if bitfield then unpack the bits */
5847 if (IS_BITVAR(retype))
5848 genUnpackBits (result,rname,PPOINTER);
5850 /* we have can just get the values */
5851 int size = AOP_SIZE(result);
5856 emitcode("movx","a,@%s",rname);
5857 aopPut(AOP(result),"a",offset);
5862 emitcode("inc","%s",rname);
5866 /* now some housekeeping stuff */
5868 /* we had to allocate for this iCode */
5869 freeAsmop(NULL,aop,ic,TRUE);
5871 /* we did not allocate which means left
5872 already in a pointer register, then
5873 if size > 0 && this could be used again
5874 we have to point it back to where it
5876 if (AOP_SIZE(result) > 1 &&
5877 !OP_SYMBOL(left)->remat &&
5878 ( OP_SYMBOL(left)->liveTo > ic->seq ||
5880 int size = AOP_SIZE(result) - 1;
5882 emitcode("dec","%s",rname);
5887 freeAsmop(result,NULL,ic,TRUE);
5892 /*-----------------------------------------------------------------*/
5893 /* genFarPointerGet - gget value from far space */
5894 /*-----------------------------------------------------------------*/
5895 static void genFarPointerGet (operand *left,
5896 operand *result, iCode *ic)
5899 link *retype = getSpec(operandType(result));
5901 aopOp(left,ic,FALSE);
5903 /* if the operand is already in dptr
5904 then we do nothing else we move the value to dptr */
5905 if (AOP_TYPE(left) != AOP_STR) {
5906 /* if this is remateriazable */
5907 if (AOP_TYPE(left) == AOP_IMMD)
5908 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
5909 else { /* we need to get it byte by byte */
5910 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
5911 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
5914 /* so dptr know contains the address */
5915 freeAsmop(left,NULL,ic,TRUE);
5916 aopOp(result,ic,FALSE);
5918 /* if bit then unpack */
5919 if (IS_BITVAR(retype))
5920 genUnpackBits(result,"dptr",FPOINTER);
5922 size = AOP_SIZE(result);
5926 emitcode("movx","a,@dptr");
5927 aopPut(AOP(result),"a",offset++);
5929 emitcode("inc","dptr");
5933 freeAsmop(result,NULL,ic,TRUE);
5936 /*-----------------------------------------------------------------*/
5937 /* emitcodePointerGet - gget value from code space */
5938 /*-----------------------------------------------------------------*/
5939 static void emitcodePointerGet (operand *left,
5940 operand *result, iCode *ic)
5943 link *retype = getSpec(operandType(result));
5945 aopOp(left,ic,FALSE);
5947 /* if the operand is already in dptr
5948 then we do nothing else we move the value to dptr */
5949 if (AOP_TYPE(left) != AOP_STR) {
5950 /* if this is remateriazable */
5951 if (AOP_TYPE(left) == AOP_IMMD)
5952 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
5953 else { /* we need to get it byte by byte */
5954 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
5955 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
5958 /* so dptr know contains the address */
5959 freeAsmop(left,NULL,ic,TRUE);
5960 aopOp(result,ic,FALSE);
5962 /* if bit then unpack */
5963 if (IS_BITVAR(retype))
5964 genUnpackBits(result,"dptr",CPOINTER);
5966 size = AOP_SIZE(result);
5970 emitcode("clr","a");
5971 emitcode("movc","a,@a+dptr");
5972 aopPut(AOP(result),"a",offset++);
5974 emitcode("inc","dptr");
5978 freeAsmop(result,NULL,ic,TRUE);
5981 /*-----------------------------------------------------------------*/
5982 /* genGenPointerGet - gget value from generic pointer space */
5983 /*-----------------------------------------------------------------*/
5984 static void genGenPointerGet (operand *left,
5985 operand *result, iCode *ic)
5988 link *retype = getSpec(operandType(result));
5990 aopOp(left,ic,FALSE);
5992 /* if the operand is already in dptr
5993 then we do nothing else we move the value to dptr */
5994 if (AOP_TYPE(left) != AOP_STR) {
5995 /* if this is remateriazable */
5996 if (AOP_TYPE(left) == AOP_IMMD) {
5997 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
5998 emitcode("mov","b,#%d",pointerCode(retype));
6000 else { /* we need to get it byte by byte */
6001 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6002 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6003 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
6006 /* so dptr know contains the address */
6007 freeAsmop(left,NULL,ic,TRUE);
6008 aopOp(result,ic,FALSE);
6010 /* if bit then unpack */
6011 if (IS_BITVAR(retype))
6012 genUnpackBits(result,"dptr",GPOINTER);
6014 size = AOP_SIZE(result);
6018 emitcode("lcall","__gptrget");
6019 aopPut(AOP(result),"a",offset++);
6021 emitcode("inc","dptr");
6025 freeAsmop(result,NULL,ic,TRUE);
6028 /*-----------------------------------------------------------------*/
6029 /* genPointerGet - generate code for pointer get */
6030 /*-----------------------------------------------------------------*/
6031 static void genPointerGet (iCode *ic)
6033 operand *left, *result ;
6038 result = IC_RESULT(ic) ;
6040 /* depending on the type of pointer we need to
6041 move it to the correct pointer register */
6042 type = operandType(left);
6043 etype = getSpec(type);
6044 /* if left is of type of pointer then it is simple */
6045 if (IS_PTR(type) && !IS_FUNC(type->next))
6046 p_type = DCL_TYPE(type);
6049 /* we have to go by the storage class */
6050 if (SPEC_OCLS(etype)->codesp ) {
6054 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
6057 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
6060 if (SPEC_OCLS(etype) == idata )
6066 /* now that we have the pointer type we assign
6067 the pointer values */
6072 genNearPointerGet (left,result,ic);
6076 genPagedPointerGet(left,result,ic);
6080 genFarPointerGet (left,result,ic);
6084 emitcodePointerGet (left,result,ic);
6088 genGenPointerGet (left,result,ic);
6094 /*-----------------------------------------------------------------*/
6095 /* genPackBits - generates code for packed bit storage */
6096 /*-----------------------------------------------------------------*/
6097 static void genPackBits (link *etype ,
6099 char *rname, int p_type)
6107 blen = SPEC_BLEN(etype);
6108 bstr = SPEC_BSTR(etype);
6110 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6113 /* if the bit lenth is less than or */
6114 /* it exactly fits a byte then */
6115 if (SPEC_BLEN(etype) <= 8 ) {
6116 shCount = SPEC_BSTR(etype) ;
6118 /* shift left acc */
6121 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6126 emitcode ("mov","b,a");
6127 emitcode("mov","a,@%s",rname);
6131 emitcode ("mov","b,a");
6132 emitcode("movx","a,@dptr");
6136 emitcode ("push","b");
6137 emitcode ("push","acc");
6138 emitcode ("lcall","__gptrget");
6139 emitcode ("pop","b");
6143 emitcode ("anl","a,#0x%02x",(unsigned char)
6144 ((unsigned char)(0xFF << (blen+bstr)) |
6145 (unsigned char)(0xFF >> (8-bstr)) ) );
6146 emitcode ("orl","a,b");
6147 if (p_type == GPOINTER)
6148 emitcode("pop","b");
6154 emitcode("mov","@%s,a",rname);
6158 emitcode("movx","@dptr,a");
6162 emitcode("lcall","__gptrput");
6167 if ( SPEC_BLEN(etype) <= 8 )
6170 emitcode("inc","%s",rname);
6171 rLen = SPEC_BLEN(etype) ;
6173 /* now generate for lengths greater than one byte */
6176 l = aopGet(AOP(right),offset++,FALSE,TRUE);
6186 emitcode("mov","@%s,a",rname);
6188 emitcode("mov","@%s,%s",rname,l);
6193 emitcode("movx","@dptr,a");
6198 emitcode("lcall","__gptrput");
6201 emitcode ("inc","%s",rname);
6206 /* last last was not complete */
6208 /* save the byte & read byte */
6211 emitcode ("mov","b,a");
6212 emitcode("mov","a,@%s",rname);
6216 emitcode ("mov","b,a");
6217 emitcode("movx","a,@dptr");
6221 emitcode ("push","b");
6222 emitcode ("push","acc");
6223 emitcode ("lcall","__gptrget");
6224 emitcode ("pop","b");
6228 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
6229 emitcode ("orl","a,b");
6232 if (p_type == GPOINTER)
6233 emitcode("pop","b");
6238 emitcode("mov","@%s,a",rname);
6242 emitcode("movx","@dptr,a");
6246 emitcode("lcall","__gptrput");
6250 /*-----------------------------------------------------------------*/
6251 /* genDataPointerSet - remat pointer to data space */
6252 /*-----------------------------------------------------------------*/
6253 static void genDataPointerSet(operand *right,
6257 int size, offset = 0 ;
6258 char *l, buffer[256];
6260 aopOp(right,ic,FALSE);
6262 l = aopGet(AOP(result),0,FALSE,TRUE);
6263 size = AOP_SIZE(right);
6266 sprintf(buffer,"(%s + %d)",l+1,offset);
6268 sprintf(buffer,"%s",l+1);
6269 emitcode("mov","%s,%s",buffer,
6270 aopGet(AOP(right),offset++,FALSE,FALSE));
6273 freeAsmop(right,NULL,ic,TRUE);
6274 freeAsmop(result,NULL,ic,TRUE);
6277 /*-----------------------------------------------------------------*/
6278 /* genNearPointerSet - emitcode for near pointer put */
6279 /*-----------------------------------------------------------------*/
6280 static void genNearPointerSet (operand *right,
6288 link *ptype = operandType(result);
6290 retype= getSpec(operandType(right));
6292 aopOp(result,ic,FALSE);
6294 /* if the result is rematerializable &
6295 in data space & not a bit variable */
6296 if (AOP_TYPE(result) == AOP_IMMD &&
6297 DCL_TYPE(ptype) == POINTER &&
6298 !IS_BITVAR(retype)) {
6299 genDataPointerSet (right,result,ic);
6303 /* if the value is already in a pointer register
6304 then don't need anything more */
6305 if (!AOP_INPREG(AOP(result))) {
6306 /* otherwise get a free pointer register */
6308 preg = getFreePtr(ic,&aop,FALSE);
6309 emitcode("mov","%s,%s",
6311 aopGet(AOP(result),0,FALSE,TRUE));
6312 rname = preg->name ;
6314 rname = aopGet(AOP(result),0,FALSE,FALSE);
6316 freeAsmop(result,NULL,ic,TRUE);
6317 aopOp (right,ic,FALSE);
6319 /* if bitfield then unpack the bits */
6320 if (IS_BITVAR(retype))
6321 genPackBits (retype,right,rname,POINTER);
6323 /* we have can just get the values */
6324 int size = AOP_SIZE(right);
6328 l = aopGet(AOP(right),offset,FALSE,TRUE);
6331 emitcode("mov","@%s,a",rname);
6333 emitcode("mov","@%s,%s",rname,l);
6335 emitcode("inc","%s",rname);
6340 /* now some housekeeping stuff */
6342 /* we had to allocate for this iCode */
6343 freeAsmop(NULL,aop,ic,TRUE);
6345 /* we did not allocate which means left
6346 already in a pointer register, then
6347 if size > 0 && this could be used again
6348 we have to point it back to where it
6350 if (AOP_SIZE(right) > 1 &&
6351 !OP_SYMBOL(result)->remat &&
6352 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6354 int size = AOP_SIZE(right) - 1;
6356 emitcode("dec","%s",rname);
6361 freeAsmop(right,NULL,ic,TRUE);
6366 /*-----------------------------------------------------------------*/
6367 /* genPagedPointerSet - emitcode for Paged pointer put */
6368 /*-----------------------------------------------------------------*/
6369 static void genPagedPointerSet (operand *right,
6378 retype= getSpec(operandType(right));
6380 aopOp(result,ic,FALSE);
6382 /* if the value is already in a pointer register
6383 then don't need anything more */
6384 if (!AOP_INPREG(AOP(result))) {
6385 /* otherwise get a free pointer register */
6387 preg = getFreePtr(ic,&aop,FALSE);
6388 emitcode("mov","%s,%s",
6390 aopGet(AOP(result),0,FALSE,TRUE));
6391 rname = preg->name ;
6393 rname = aopGet(AOP(result),0,FALSE,FALSE);
6395 freeAsmop(result,NULL,ic,TRUE);
6396 aopOp (right,ic,FALSE);
6398 /* if bitfield then unpack the bits */
6399 if (IS_BITVAR(retype))
6400 genPackBits (retype,right,rname,PPOINTER);
6402 /* we have can just get the values */
6403 int size = AOP_SIZE(right);
6407 l = aopGet(AOP(right),offset,FALSE,TRUE);
6410 emitcode("movx","@%s,a",rname);
6413 emitcode("inc","%s",rname);
6419 /* now some housekeeping stuff */
6421 /* we had to allocate for this iCode */
6422 freeAsmop(NULL,aop,ic,TRUE);
6424 /* we did not allocate which means left
6425 already in a pointer register, then
6426 if size > 0 && this could be used again
6427 we have to point it back to where it
6429 if (AOP_SIZE(right) > 1 &&
6430 !OP_SYMBOL(result)->remat &&
6431 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6433 int size = AOP_SIZE(right) - 1;
6435 emitcode("dec","%s",rname);
6440 freeAsmop(right,NULL,ic,TRUE);
6445 /*-----------------------------------------------------------------*/
6446 /* genFarPointerSet - set value from far space */
6447 /*-----------------------------------------------------------------*/
6448 static void genFarPointerSet (operand *right,
6449 operand *result, iCode *ic)
6452 link *retype = getSpec(operandType(right));
6454 aopOp(result,ic,FALSE);
6456 /* if the operand is already in dptr
6457 then we do nothing else we move the value to dptr */
6458 if (AOP_TYPE(result) != AOP_STR) {
6459 /* if this is remateriazable */
6460 if (AOP_TYPE(result) == AOP_IMMD)
6461 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6462 else { /* we need to get it byte by byte */
6463 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6464 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6467 /* so dptr know contains the address */
6468 freeAsmop(result,NULL,ic,TRUE);
6469 aopOp(right,ic,FALSE);
6471 /* if bit then unpack */
6472 if (IS_BITVAR(retype))
6473 genPackBits(retype,right,"dptr",FPOINTER);
6475 size = AOP_SIZE(right);
6479 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6481 emitcode("movx","@dptr,a");
6483 emitcode("inc","dptr");
6487 freeAsmop(right,NULL,ic,TRUE);
6490 /*-----------------------------------------------------------------*/
6491 /* genGenPointerSet - set value from generic pointer space */
6492 /*-----------------------------------------------------------------*/
6493 static void genGenPointerSet (operand *right,
6494 operand *result, iCode *ic)
6497 link *retype = getSpec(operandType(right));
6499 aopOp(result,ic,FALSE);
6501 /* if the operand is already in dptr
6502 then we do nothing else we move the value to dptr */
6503 if (AOP_TYPE(result) != AOP_STR) {
6504 /* if this is remateriazable */
6505 if (AOP_TYPE(result) == AOP_IMMD) {
6506 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6507 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
6509 else { /* we need to get it byte by byte */
6510 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6511 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6512 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
6515 /* so dptr know contains the address */
6516 freeAsmop(result,NULL,ic,TRUE);
6517 aopOp(right,ic,FALSE);
6519 /* if bit then unpack */
6520 if (IS_BITVAR(retype))
6521 genPackBits(retype,right,"dptr",GPOINTER);
6523 size = AOP_SIZE(right);
6527 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6529 emitcode("lcall","__gptrput");
6531 emitcode("inc","dptr");
6535 freeAsmop(right,NULL,ic,TRUE);
6538 /*-----------------------------------------------------------------*/
6539 /* genPointerSet - stores the value into a pointer location */
6540 /*-----------------------------------------------------------------*/
6541 static void genPointerSet (iCode *ic)
6543 operand *right, *result ;
6547 right = IC_RIGHT(ic);
6548 result = IC_RESULT(ic) ;
6550 /* depending on the type of pointer we need to
6551 move it to the correct pointer register */
6552 type = operandType(result);
6553 etype = getSpec(type);
6554 /* if left is of type of pointer then it is simple */
6555 if (IS_PTR(type) && !IS_FUNC(type->next)) {
6556 p_type = DCL_TYPE(type);
6560 /* we have to go by the storage class */
6561 if (SPEC_OCLS(etype)->codesp ) {
6565 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
6568 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
6571 if (SPEC_OCLS(etype) == idata )
6577 /* now that we have the pointer type we assign
6578 the pointer values */
6583 genNearPointerSet (right,result,ic);
6587 genPagedPointerSet (right,result,ic);
6591 genFarPointerSet (right,result,ic);
6595 genGenPointerSet (right,result,ic);
6601 /*-----------------------------------------------------------------*/
6602 /* genIfx - generate code for Ifx statement */
6603 /*-----------------------------------------------------------------*/
6604 static void genIfx (iCode *ic, iCode *popIc)
6606 operand *cond = IC_COND(ic);
6609 aopOp(cond,ic,FALSE);
6611 /* get the value into acc */
6612 if (AOP_TYPE(cond) != AOP_CRY)
6616 /* the result is now in the accumulator */
6617 freeAsmop(cond,NULL,ic,TRUE);
6619 /* if there was something to be popped then do it */
6623 /* if the condition is a bit variable */
6624 if (isbit && IS_ITEMP(cond) &&
6626 genIfxJump(ic,SPIL_LOC(cond)->rname);
6628 if (isbit && !IS_ITEMP(cond))
6629 genIfxJump(ic,OP_SYMBOL(cond)->rname);
6636 /*-----------------------------------------------------------------*/
6637 /* genAddrOf - generates code for address of */
6638 /*-----------------------------------------------------------------*/
6639 static void genAddrOf (iCode *ic)
6641 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
6644 aopOp(IC_RESULT(ic),ic,FALSE);
6646 /* if the operand is on the stack then we
6647 need to get the stack offset of this
6650 /* if it has an offset then we need to compute
6653 emitcode("mov","a,_bp");
6654 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
6655 aopPut(AOP(IC_RESULT(ic)),"a",0);
6657 /* we can just move _bp */
6658 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
6659 /* fill the result with zero */
6660 size = AOP_SIZE(IC_RESULT(ic)) - 1;
6663 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
6668 /* object not on stack then we need the name */
6669 size = AOP_SIZE(IC_RESULT(ic));
6673 char s[SDCC_NAME_MAX];
6675 sprintf(s,"#(%s >> %d)",
6679 sprintf(s,"#%s",sym->rname);
6680 aopPut(AOP(IC_RESULT(ic)),s,offset++);
6684 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
6688 /*-----------------------------------------------------------------*/
6689 /* genFarFarAssign - assignment when both are in far space */
6690 /*-----------------------------------------------------------------*/
6691 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
6693 int size = AOP_SIZE(right);
6696 /* first push the right side on to the stack */
6698 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6700 emitcode ("push","acc");
6703 freeAsmop(right,NULL,ic,FALSE);
6704 /* now assign DPTR to result */
6705 aopOp(result,ic,FALSE);
6706 size = AOP_SIZE(result);
6708 emitcode ("pop","acc");
6709 aopPut(AOP(result),"a",--offset);
6711 freeAsmop(result,NULL,ic,FALSE);
6715 /*-----------------------------------------------------------------*/
6716 /* genAssign - generate code for assignment */
6717 /*-----------------------------------------------------------------*/
6718 static void genAssign (iCode *ic)
6720 operand *result, *right;
6722 unsigned long lit = 0L;
6724 result = IC_RESULT(ic);
6725 right = IC_RIGHT(ic) ;
6727 /* if they are the same */
6728 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
6731 aopOp(right,ic,FALSE);
6733 /* special case both in far space */
6734 if (AOP_TYPE(right) == AOP_DPTR &&
6735 IS_TRUE_SYMOP(result) &&
6736 isOperandInFarSpace(result)) {
6738 genFarFarAssign (result,right,ic);
6742 aopOp(result,ic,TRUE);
6744 /* if they are the same registers */
6745 if (sameRegs(AOP(right),AOP(result)))
6748 /* if the result is a bit */
6749 if (AOP_TYPE(result) == AOP_CRY) {
6751 /* if the right size is a literal then
6752 we know what the value is */
6753 if (AOP_TYPE(right) == AOP_LIT) {
6754 if (((int) operandLitValue(right)))
6755 aopPut(AOP(result),one,0);
6757 aopPut(AOP(result),zero,0);
6761 /* the right is also a bit variable */
6762 if (AOP_TYPE(right) == AOP_CRY) {
6763 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6764 aopPut(AOP(result),"c",0);
6770 aopPut(AOP(result),"a",0);
6774 /* bit variables done */
6776 size = AOP_SIZE(result);
6778 if(AOP_TYPE(right) == AOP_LIT)
6779 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6781 (AOP_TYPE(result) != AOP_REG) &&
6782 (AOP_TYPE(right) == AOP_LIT) &&
6783 !IS_FLOAT(operandType(right)) &&
6785 emitcode("clr","a");
6787 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
6788 aopPut(AOP(result),"a",size);
6791 aopGet(AOP(right),size,FALSE,FALSE),
6797 aopGet(AOP(right),offset,FALSE,FALSE),
6804 freeAsmop (right,NULL,ic,FALSE);
6805 freeAsmop (result,NULL,ic,TRUE);
6808 /*-----------------------------------------------------------------*/
6809 /* genJumpTab - genrates code for jump table */
6810 /*-----------------------------------------------------------------*/
6811 static void genJumpTab (iCode *ic)
6816 aopOp(IC_JTCOND(ic),ic,FALSE);
6817 /* get the condition into accumulator */
6818 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
6820 /* multiply by three */
6821 emitcode("add","a,acc");
6822 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
6823 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
6825 jtab = newiTempLabel(NULL);
6826 emitcode("mov","dptr,#%05d$",jtab->key+100);
6827 emitcode("jmp","@a+dptr");
6828 emitcode("","%05d$:",jtab->key+100);
6829 /* now generate the jump labels */
6830 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
6831 jtab = setNextItem(IC_JTLABELS(ic)))
6832 emitcode("ljmp","%05d$",jtab->key+100);
6836 /*-----------------------------------------------------------------*/
6837 /* genCast - gen code for casting */
6838 /*-----------------------------------------------------------------*/
6839 static void genCast (iCode *ic)
6841 operand *result = IC_RESULT(ic);
6842 link *ctype = operandType(IC_LEFT(ic));
6843 operand *right = IC_RIGHT(ic);
6846 /* if they are equivalent then do nothing */
6847 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
6850 aopOp(right,ic,FALSE) ;
6851 aopOp(result,ic,FALSE);
6853 /* if the result is a bit */
6854 if (AOP_TYPE(result) == AOP_CRY) {
6855 /* if the right size is a literal then
6856 we know what the value is */
6857 if (AOP_TYPE(right) == AOP_LIT) {
6858 if (((int) operandLitValue(right)))
6859 aopPut(AOP(result),one,0);
6861 aopPut(AOP(result),zero,0);
6866 /* the right is also a bit variable */
6867 if (AOP_TYPE(right) == AOP_CRY) {
6868 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6869 aopPut(AOP(result),"c",0);
6875 aopPut(AOP(result),"a",0);
6879 /* if they are the same size : or less */
6880 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
6882 /* if they are in the same place */
6883 if (sameRegs(AOP(right),AOP(result)))
6886 /* if they in different places then copy */
6887 size = AOP_SIZE(result);
6891 aopGet(AOP(right),offset,FALSE,FALSE),
6899 /* if the result is of type pointer */
6900 if (IS_PTR(ctype)) {
6903 link *type = operandType(right);
6904 link *etype = getSpec(type);
6906 /* pointer to generic pointer */
6907 if (IS_GENPTR(ctype)) {
6911 p_type = DCL_TYPE(type);
6913 /* we have to go by the storage class */
6914 if (SPEC_OCLS(etype)->codesp )
6917 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
6920 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
6923 if (SPEC_OCLS(etype) == idata )
6929 /* the first two bytes are known */
6934 aopGet(AOP(right),offset,FALSE,FALSE),
6938 /* the last byte depending on type */
6955 /* this should never happen */
6956 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
6957 "got unknown pointer type");
6960 aopPut(AOP(result),l,2);
6964 /* just copy the pointers */
6965 size = AOP_SIZE(result);
6969 aopGet(AOP(right),offset,FALSE,FALSE),
6976 /* so we now know that the size of destination is greater
6977 than the size of the source */
6978 /* we move to result for the size of source */
6979 size = AOP_SIZE(right);
6983 aopGet(AOP(right),offset,FALSE,FALSE),
6988 /* now depending on the sign of the destination */
6989 size = AOP_SIZE(result) - AOP_SIZE(right);
6990 /* if unsigned or not an integral type */
6991 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
6993 aopPut(AOP(result),zero,offset++);
6995 /* we need to extend the sign :{ */
6996 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
6999 emitcode("rlc","a");
7000 emitcode("subb","a,acc");
7002 aopPut(AOP(result),"a",offset++);
7005 /* we are done hurray !!!! */
7008 freeAsmop(right,NULL,ic,TRUE);
7009 freeAsmop(result,NULL,ic,TRUE);
7013 /*-----------------------------------------------------------------*/
7014 /* genDjnz - generate decrement & jump if not zero instrucion */
7015 /*-----------------------------------------------------------------*/
7016 static int genDjnz (iCode *ic, iCode *ifx)
7022 /* if the if condition has a false label
7023 then we cannot save */
7027 /* if the minus is not of the form
7029 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
7030 !IS_OP_LITERAL(IC_RIGHT(ic)))
7033 if (operandLitValue(IC_RIGHT(ic)) != 1)
7036 /* if the size of this greater than one then no
7038 if (getSize(operandType(IC_RESULT(ic))) > 1)
7041 /* otherwise we can save BIG */
7042 lbl = newiTempLabel(NULL);
7043 lbl1= newiTempLabel(NULL);
7045 aopOp(IC_RESULT(ic),ic,FALSE);
7047 if (IS_AOP_PREG(IC_RESULT(ic))) {
7048 emitcode("dec","%s",
7049 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7050 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7051 emitcode("jnz","%05d$",lbl->key+100);
7053 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
7056 emitcode ("sjmp","%05d$",lbl1->key+100);
7057 emitcode ("","%05d$:",lbl->key+100);
7058 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
7059 emitcode ("","%05d$:",lbl1->key+100);
7061 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7066 /*-----------------------------------------------------------------*/
7067 /* genReceive - generate code for a receive iCode */
7068 /*-----------------------------------------------------------------*/
7069 static void genReceive (iCode *ic)
7071 if (isOperandInFarSpace(IC_RESULT(ic)) &&
7072 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
7073 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
7075 int size = getSize(operandType(IC_RESULT(ic)));
7076 int offset = 4 - size;
7078 emitcode ("push","%s", (strcmp(fReturn[3 - offset],"a") ?
7079 fReturn[3 - offset] : "acc"));
7082 aopOp(IC_RESULT(ic),ic,FALSE);
7083 size = AOP_SIZE(IC_RESULT(ic));
7086 emitcode ("pop","acc");
7087 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
7092 aopOp(IC_RESULT(ic),ic,FALSE);
7094 assignResultValue(IC_RESULT(ic));
7097 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7100 /*-----------------------------------------------------------------*/
7101 /* gen51Code - generate code for 8051 based controllers */
7102 /*-----------------------------------------------------------------*/
7103 void gen51Code (iCode *lic)
7108 lineHead = lineCurr = NULL;
7110 /* if debug information required */
7111 /* if (options.debug && currFunc) { */
7113 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
7115 if (IS_STATIC(currFunc->etype))
7116 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
7118 emitcode("","G$%s$0$0 ==.",currFunc->name);
7121 /* stack pointer name */
7122 if (options.useXstack)
7128 for (ic = lic ; ic ; ic = ic->next ) {
7130 if ( cln != ic->lineno ) {
7131 if ( options.debug ) {
7133 emitcode("","C$%s$%d$%d$%d ==.",
7134 ic->filename,ic->lineno,
7135 ic->level,ic->block);
7138 emitcode(";","%s %d",ic->filename,ic->lineno);
7141 /* if the result is marked as
7142 spilt and rematerializable or code for
7143 this has already been generated then
7145 if (resultRemat(ic) || ic->generated )
7148 /* depending on the operation */
7167 /* IPOP happens only when trying to restore a
7168 spilt live range, if there is an ifx statement
7169 following this pop then the if statement might
7170 be using some of the registers being popped which
7171 would destory the contents of the register so
7172 we need to check for this condition and handle it */
7174 ic->next->op == IFX &&
7175 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
7176 genIfx (ic->next,ic);
7194 genEndFunction (ic);
7214 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
7231 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
7235 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
7242 /* note these two are xlated by algebraic equivalence
7243 during parsing SDCC.y */
7244 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7245 "got '>=' or '<=' shouldn't have come here");
7249 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
7261 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
7265 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
7269 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
7296 case GET_VALUE_AT_ADDRESS:
7301 if (POINTER_SET(ic))
7328 addSet(&_G.sendSet,ic);
7333 /* piCode(ic,stdout); */
7339 /* now we are ready to call the
7340 peep hole optimizer */
7341 if (!options.nopeep)
7342 peepHole (&lineHead);
7344 /* now do the actual printing */
7345 printLine (lineHead,codeOutFile);