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)))
152 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
153 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
155 /* if no usage of r0 then return it */
156 if (!r0iu && !r0ou) {
157 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
158 (*aopp)->type = AOP_R0;
160 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R0_IDX);
163 /* if no usage of r1 then return it */
164 if (!r1iu && !r1ou) {
165 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
166 (*aopp)->type = AOP_R1;
168 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R1_IDX);
171 /* now we know they both have usage */
172 /* if r0 not used in this instruction */
174 /* push it if not already pushed */
176 emitcode ("push","%s",
177 mcs51_regWithIdx(R0_IDX)->dname);
181 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
182 (*aopp)->type = AOP_R0;
184 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R0_IDX);
187 /* if r1 not used then */
190 /* push it if not already pushed */
192 emitcode ("push","%s",
193 mcs51_regWithIdx(R1_IDX)->dname);
197 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
198 (*aopp)->type = AOP_R1;
199 return mcs51_regWithIdx(R1_IDX);
203 /* I said end of world but not quite end of world yet */
204 /* if this is a result then we can push it on the stack*/
206 (*aopp)->type = AOP_STK;
211 /* other wise this is true end of the world */
212 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
213 "getFreePtr should never reach here");
217 /*-----------------------------------------------------------------*/
218 /* newAsmop - creates a new asmOp */
219 /*-----------------------------------------------------------------*/
220 static asmop *newAsmop (short type)
224 ALLOC(aop,sizeof(asmop));
229 /*-----------------------------------------------------------------*/
230 /* pointerCode - returns the code for a pointer type */
231 /*-----------------------------------------------------------------*/
232 static int pointerCode (link *etype)
235 if (SPEC_OCLS(etype)->codesp ) {
239 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
242 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
245 if (SPEC_OCLS(etype) == idata )
252 /*-----------------------------------------------------------------*/
253 /* aopForSym - for a true symbol */
254 /*-----------------------------------------------------------------*/
255 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
258 memmap *space= SPEC_OCLS(sym->etype);
260 /* if already has one */
264 /* assign depending on the storage class */
265 /* if it is on the stack or indirectly addressable */
266 /* space we need to assign either r0 or r1 to it */
267 if (sym->onStack || sym->iaccess) {
268 sym->aop = aop = newAsmop(0);
269 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
270 aop->size = getSize(sym->type);
272 /* now assign the address of the variable to
273 the pointer register */
274 if (aop->type != AOP_STK) {
279 emitcode("push","acc");
281 emitcode("mov","a,_bp");
282 emitcode("add","a,#0x%02x",
284 ((char)(sym->stack - _G.nRegsSaved )) :
285 ((char)sym->stack)) & 0xff);
286 emitcode("mov","%s,a",
287 aop->aopu.aop_ptr->name);
290 emitcode("pop","acc");
293 emitcode("mov","%s,#%s",
294 aop->aopu.aop_ptr->name,
296 aop->paged = space->paged;
298 aop->aopu.aop_stk = sym->stack;
302 /* if in bit space */
303 if (IN_BITSPACE(space)) {
304 sym->aop = aop = newAsmop (AOP_CRY);
305 aop->aopu.aop_dir = sym->rname ;
306 aop->size = getSize(sym->type);
309 /* if it is in direct space */
310 if (IN_DIRSPACE(space)) {
311 sym->aop = aop = newAsmop (AOP_DIR);
312 aop->aopu.aop_dir = sym->rname ;
313 aop->size = getSize(sym->type);
317 /* special case for a function */
318 if (IS_FUNC(sym->type)) {
319 sym->aop = aop = newAsmop(AOP_IMMD);
320 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
321 strcpy(aop->aopu.aop_immd,sym->rname);
322 aop->size = FPTRSIZE;
326 /* only remaining is far space */
327 /* in which case DPTR gets the address */
328 sym->aop = aop = newAsmop(AOP_DPTR);
329 emitcode ("mov","dptr,#%s", sym->rname);
330 aop->size = getSize(sym->type);
332 /* if it is in code space */
333 if (IN_CODESPACE(space))
339 /*-----------------------------------------------------------------*/
340 /* aopForRemat - rematerialzes an object */
341 /*-----------------------------------------------------------------*/
342 static asmop *aopForRemat (symbol *sym)
345 iCode *ic = sym->rematiCode;
346 asmop *aop = newAsmop(AOP_IMMD);
350 /* if plus or minus print the right hand side */
351 if (ic->op == '+' || ic->op == '-') {
352 sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
355 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
359 /* we reached the end */
360 sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
364 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
365 strcpy(aop->aopu.aop_immd,buffer);
369 /*-----------------------------------------------------------------*/
370 /* regsInCommon - two operands have some registers in common */
371 /*-----------------------------------------------------------------*/
372 static bool regsInCommon (operand *op1, operand *op2)
377 /* if they have registers in common */
378 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
381 sym1 = OP_SYMBOL(op1);
382 sym2 = OP_SYMBOL(op2);
384 if (sym1->nRegs == 0 || sym2->nRegs == 0)
387 for (i = 0 ; i < sym1->nRegs ; i++) {
392 for (j = 0 ; j < sym2->nRegs ;j++ ) {
396 if (sym2->regs[j] == sym1->regs[i])
404 /*-----------------------------------------------------------------*/
405 /* operandsEqu - equivalent */
406 /*-----------------------------------------------------------------*/
407 static bool operandsEqu ( operand *op1, operand *op2)
411 /* if they not symbols */
412 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
415 sym1 = OP_SYMBOL(op1);
416 sym2 = OP_SYMBOL(op2);
418 /* if both are itemps & one is spilt
419 and the other is not then false */
420 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
421 sym1->isspilt != sym2->isspilt )
424 /* if they are the same */
428 if (strcmp(sym1->rname,sym2->rname) == 0)
432 /* if left is a tmp & right is not */
436 (sym1->usl.spillLoc == sym2))
443 (sym2->usl.spillLoc == sym1))
449 /*-----------------------------------------------------------------*/
450 /* sameRegs - two asmops have the same registers */
451 /*-----------------------------------------------------------------*/
452 static bool sameRegs (asmop *aop1, asmop *aop2 )
459 if (aop1->type != AOP_REG ||
460 aop2->type != AOP_REG )
463 if (aop1->size != aop2->size )
466 for (i = 0 ; i < aop1->size ; i++ )
467 if (aop1->aopu.aop_reg[i] !=
468 aop2->aopu.aop_reg[i] )
474 /*-----------------------------------------------------------------*/
475 /* aopOp - allocates an asmop for an operand : */
476 /*-----------------------------------------------------------------*/
477 static void aopOp (operand *op, iCode *ic, bool result)
486 /* if this a literal */
487 if (IS_OP_LITERAL(op)) {
488 op->aop = aop = newAsmop(AOP_LIT);
489 aop->aopu.aop_lit = op->operand.valOperand;
490 aop->size = getSize(operandType(op));
494 /* if already has a asmop then continue */
498 /* if the underlying symbol has a aop */
499 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
500 op->aop = OP_SYMBOL(op)->aop;
504 /* if this is a true symbol */
505 if (IS_TRUE_SYMOP(op)) {
506 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
510 /* this is a temporary : this has
516 e) can be a return use only */
521 /* if the type is a conditional */
522 if (sym->regType == REG_CND) {
523 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
528 /* if it is spilt then two situations
530 b) has a spill location */
531 if (sym->isspilt || sym->nRegs == 0) {
533 /* rematerialize it NOW */
535 sym->aop = op->aop = aop =
537 aop->size = getSize(sym->type);
543 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
544 aop->size = getSize(sym->type);
545 for ( i = 0 ; i < 2 ; i++ )
546 aop->aopu.aop_str[i] = accUse[i];
552 aop = op->aop = sym->aop = newAsmop(AOP_STR);
553 aop->size = getSize(sym->type);
554 for ( i = 0 ; i < 4 ; i++ )
555 aop->aopu.aop_str[i] = fReturn[i];
559 /* else spill location */
560 sym->aop = op->aop = aop =
561 aopForSym(ic,sym->usl.spillLoc,result);
562 aop->size = getSize(sym->type);
566 /* must be in a register */
567 sym->aop = op->aop = aop = newAsmop(AOP_REG);
568 aop->size = sym->nRegs;
569 for ( i = 0 ; i < sym->nRegs ;i++)
570 aop->aopu.aop_reg[i] = sym->regs[i];
573 /*-----------------------------------------------------------------*/
574 /* freeAsmop - free up the asmop given to an operand */
575 /*----------------------------------------------------------------*/
576 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
593 /* depending on the asmop type only three cases need work AOP_RO
594 , AOP_R1 && AOP_STK */
599 emitcode ("pop","ar0");
603 bitVectUnSetBit(ic->rUsed,R0_IDX);
609 emitcode ("pop","ar1");
613 bitVectUnSetBit(ic->rUsed,R1_IDX);
619 int stk = aop->aopu.aop_stk + aop->size;
620 bitVectUnSetBit(ic->rUsed,R0_IDX);
621 bitVectUnSetBit(ic->rUsed,R1_IDX);
623 getFreePtr(ic,&aop,FALSE);
625 emitcode ("mov","a,_bp");
626 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
627 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
629 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
632 emitcode("pop","acc");
633 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
635 emitcode("dec","%s",aop->aopu.aop_ptr->name);
638 freeAsmop(op,NULL,ic,TRUE);
640 emitcode("pop","ar0");
645 emitcode("pop","ar1");
652 /* all other cases just dealloc */
656 OP_SYMBOL(op)->aop = NULL;
657 /* if the symbol has a spill */
659 SPIL_LOC(op)->aop = NULL;
664 /*-----------------------------------------------------------------*/
665 /* aopGet - for fetching value of the aop */
666 /*-----------------------------------------------------------------*/
667 static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
672 /* offset is greater than
674 if (offset > (aop->size - 1) &&
675 aop->type != AOP_LIT)
678 /* depending on type */
683 /* if we need to increment it */
684 while (offset > aop->coff) {
685 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
689 while (offset < aop->coff) {
690 emitcode("dec","%s",aop->aopu.aop_ptr->name);
696 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
697 return (dname ? "acc" : "a");
699 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
700 ALLOC_ATOMIC(rs,strlen(s)+1);
705 while (offset > aop->coff) {
706 emitcode ("inc","dptr");
710 while (offset < aop->coff) {
711 emitcode("lcall","__decdptr");
718 emitcode("movc","a,@a+dptr");
721 emitcode("movx","a,@dptr");
722 return (dname ? "acc" : "a");
727 sprintf (s,"#(%s)",aop->aopu.aop_immd);
730 sprintf(s,"#(%s >> %d)",
736 ALLOC_ATOMIC(rs,strlen(s)+1);
742 sprintf(s,"(%s + %d)",
746 sprintf(s,"%s",aop->aopu.aop_dir);
747 ALLOC_ATOMIC(rs,strlen(s)+1);
753 return aop->aopu.aop_reg[offset]->dname;
755 return aop->aopu.aop_reg[offset]->name;
759 emitcode("mov","c,%s",aop->aopu.aop_dir);
760 emitcode("rlc","a") ;
761 return (dname ? "acc" : "a");
764 if (!offset && dname)
766 return aop->aopu.aop_str[offset];
769 return aopLiteral (aop->aopu.aop_lit,offset);
773 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
777 return aop->aopu.aop_str[offset];
781 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
782 "aopget got unsupported aop->type");
785 /*-----------------------------------------------------------------*/
786 /* aopPut - puts a string for a aop */
787 /*-----------------------------------------------------------------*/
788 static void aopPut (asmop *aop, char *s, int offset)
793 if (aop->size && offset > ( aop->size - 1)) {
794 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
795 "aopPut got offset > aop->size");
799 /* will assign value to value */
800 /* depending on where it is ofcourse */
804 sprintf(d,"(%s + %d)",
805 aop->aopu.aop_dir,offset);
807 sprintf(d,"%s",aop->aopu.aop_dir);
810 emitcode("mov","%s,%s",d,s);
815 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
816 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
818 strcmp(s,"r0") == 0 ||
819 strcmp(s,"r1") == 0 ||
820 strcmp(s,"r2") == 0 ||
821 strcmp(s,"r3") == 0 ||
822 strcmp(s,"r4") == 0 ||
823 strcmp(s,"r5") == 0 ||
824 strcmp(s,"r6") == 0 ||
825 strcmp(s,"r7") == 0 )
826 emitcode("mov","%s,%s",
827 aop->aopu.aop_reg[offset]->dname,s);
829 emitcode("mov","%s,%s",
830 aop->aopu.aop_reg[offset]->name,s);
836 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
837 "aopPut writting to code space");
841 while (offset > aop->coff) {
843 emitcode ("inc","dptr");
846 while (offset < aop->coff) {
848 emitcode("lcall","__decdptr");
853 /* if not in accumulater */
856 emitcode ("movx","@dptr,a");
861 while (offset > aop->coff) {
863 emitcode("inc","%s",aop->aopu.aop_ptr->name);
865 while (offset < aop->coff) {
867 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
873 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
878 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
880 if (strcmp(s,"r0") == 0 ||
881 strcmp(s,"r1") == 0 ||
882 strcmp(s,"r2") == 0 ||
883 strcmp(s,"r3") == 0 ||
884 strcmp(s,"r4") == 0 ||
885 strcmp(s,"r5") == 0 ||
886 strcmp(s,"r6") == 0 ||
887 strcmp(s,"r7") == 0 ) {
889 sprintf(buffer,"a%s",s);
890 emitcode("mov","@%s,%s",
891 aop->aopu.aop_ptr->name,buffer);
893 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
898 if (strcmp(s,"a") == 0)
899 emitcode("push","acc");
901 emitcode("push","%s",s);
906 /* if bit variable */
907 if (!aop->aopu.aop_dir) {
912 emitcode("clr","%s",aop->aopu.aop_dir);
915 emitcode("setb","%s",aop->aopu.aop_dir);
918 emitcode("mov","%s,c",aop->aopu.aop_dir);
920 lbl = newiTempLabel(NULL);
925 emitcode("cjne","a,#0x01,%05d$",lbl->key+100);
926 emitcode("","%05d$:",lbl->key+100);
928 emitcode("mov","%s,c",aop->aopu.aop_dir);
935 if (strcmp(aop->aopu.aop_str[offset],s))
936 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
941 if (!offset && (strcmp(s,"acc") == 0))
944 if (strcmp(aop->aopu.aop_str[offset],s))
945 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
949 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
950 "aopPut got unsupported aop->type");
958 /*-----------------------------------------------------------------*/
959 /* pointToEnd :- points to the last byte of the operand */
960 /*-----------------------------------------------------------------*/
961 static void pointToEnd (asmop *aop)
967 aop->coff = count = (aop->size - 1);
972 emitcode("inc","%s",aop->aopu.aop_ptr->name);
976 emitcode("inc","dptr");
983 /*-----------------------------------------------------------------*/
984 /* reAdjustPreg - points a register back to where it should */
985 /*-----------------------------------------------------------------*/
986 static void reAdjustPreg (asmop *aop)
991 if ((size = aop->size) <= 1)
998 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1002 emitcode("lcall","__decdptr");
1009 #define AOP(op) op->aop
1010 #define AOP_TYPE(op) AOP(op)->type
1011 #define AOP_SIZE(op) AOP(op)->size
1012 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1013 AOP_TYPE(x) == AOP_R0))
1015 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1016 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1018 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1019 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1020 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1022 /*-----------------------------------------------------------------*/
1023 /* genNotFloat - generates not for float operations */
1024 /*-----------------------------------------------------------------*/
1025 static void genNotFloat (operand *op, operand *res)
1031 /* we will put 127 in the first byte of
1033 aopPut(AOP(res),"#127",0);
1034 size = AOP_SIZE(op) - 1;
1037 l = aopGet(op->aop,offset++,FALSE,FALSE);
1041 emitcode("orl","a,%s",
1043 offset++,FALSE,FALSE));
1045 tlbl = newiTempLabel(NULL);
1047 tlbl = newiTempLabel(NULL);
1048 aopPut(res->aop,one,1);
1049 emitcode("jz","%05d$",(tlbl->key+100));
1050 aopPut(res->aop,zero,1);
1051 emitcode("","%05d$:",(tlbl->key+100));
1053 size = res->aop->size - 2;
1055 /* put zeros in the rest */
1057 aopPut(res->aop,zero,offset++);
1060 /*-----------------------------------------------------------------*/
1061 /* getDataSize - get the operand data size */
1062 /*-----------------------------------------------------------------*/
1063 static int getDataSize(operand *op)
1066 size = AOP_SIZE(op);
1073 /*-----------------------------------------------------------------*/
1074 /* outAcc - output Acc */
1075 /*-----------------------------------------------------------------*/
1076 static void outAcc(operand *result)
1079 size = getDataSize(result);
1081 aopPut(AOP(result),"a",0);
1084 /* unsigned or positive */
1086 aopPut(AOP(result),zero,offset++);
1091 /*-----------------------------------------------------------------*/
1092 /* outBitC - output a bit C */
1093 /*-----------------------------------------------------------------*/
1094 static void outBitC(operand *result)
1096 /* if the result is bit */
1097 if (AOP_TYPE(result) == AOP_CRY)
1098 aopPut(AOP(result),"c",0);
1100 emitcode("clr","a");
1101 emitcode("rlc","a");
1106 /*-----------------------------------------------------------------*/
1107 /* toBoolean - emit code for orl a,operator(sizeop) */
1108 /*-----------------------------------------------------------------*/
1109 static void toBoolean(operand *oper)
1111 int size = AOP_SIZE(oper) - 1;
1113 MOVA(aopGet(AOP(oper),0,FALSE,FALSE));
1115 emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE));
1119 /*-----------------------------------------------------------------*/
1120 /* genNot - generate code for ! operation */
1121 /*-----------------------------------------------------------------*/
1122 static void genNot (iCode *ic)
1125 link *optype = operandType(IC_LEFT(ic));
1127 /* assign asmOps to operand & result */
1128 aopOp (IC_LEFT(ic),ic,FALSE);
1129 aopOp (IC_RESULT(ic),ic,TRUE);
1131 /* if in bit space then a special case */
1132 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1133 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1134 emitcode("cpl","c");
1135 outBitC(IC_RESULT(ic));
1139 /* if type float then do float */
1140 if (IS_FLOAT(optype)) {
1141 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1145 toBoolean(IC_LEFT(ic));
1147 tlbl = newiTempLabel(NULL);
1148 emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1149 emitcode("","%05d$:",tlbl->key+100);
1150 outBitC(IC_RESULT(ic));
1153 /* release the aops */
1154 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1155 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1159 /*-----------------------------------------------------------------*/
1160 /* genCpl - generate code for complement */
1161 /*-----------------------------------------------------------------*/
1162 static void genCpl (iCode *ic)
1168 /* assign asmOps to operand & result */
1169 aopOp (IC_LEFT(ic),ic,FALSE);
1170 aopOp (IC_RESULT(ic),ic,TRUE);
1172 /* if both are in bit space then
1174 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1175 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1177 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1178 emitcode("cpl","c");
1179 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1183 size = AOP_SIZE(IC_RESULT(ic));
1185 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1187 emitcode("cpl","a");
1188 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1193 /* release the aops */
1194 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1195 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1198 /*-----------------------------------------------------------------*/
1199 /* genUminusFloat - unary minus for floating points */
1200 /*-----------------------------------------------------------------*/
1201 static void genUminusFloat(operand *op,operand *result)
1203 int size ,offset =0 ;
1205 /* for this we just need to flip the
1206 first it then copy the rest in place */
1207 size = AOP_SIZE(op) - 1;
1208 l = aopGet(AOP(op),3,FALSE,FALSE);
1212 emitcode("cpl","acc.7");
1213 aopPut(AOP(result),"a",3);
1217 aopGet(AOP(op),offset,FALSE,FALSE),
1223 /*-----------------------------------------------------------------*/
1224 /* genUminus - unary minus code generation */
1225 /*-----------------------------------------------------------------*/
1226 static void genUminus (iCode *ic)
1229 link *optype, *rtype;
1233 aopOp(IC_LEFT(ic),ic,FALSE);
1234 aopOp(IC_RESULT(ic),ic,TRUE);
1236 /* if both in bit space then special
1238 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1239 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1241 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1242 emitcode("cpl","c");
1243 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1247 optype = operandType(IC_LEFT(ic));
1248 rtype = operandType(IC_RESULT(ic));
1250 /* if float then do float stuff */
1251 if (IS_FLOAT(optype)) {
1252 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1256 /* otherwise subtract from zero */
1257 size = AOP_SIZE(IC_LEFT(ic));
1261 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1262 if (!strcmp(l,"a")) {
1263 emitcode("cpl","a");
1264 emitcode("inc","a");
1266 emitcode("clr","a");
1267 emitcode("subb","a,%s",l);
1269 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1272 /* if any remaining bytes in the result */
1273 /* we just need to propagate the sign */
1274 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1275 emitcode("rlc","a");
1276 emitcode("subb","a,acc");
1278 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1282 /* release the aops */
1283 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1284 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1287 /*-----------------------------------------------------------------*/
1288 /* saveRegisters - will look for a call and save the registers */
1289 /*-----------------------------------------------------------------*/
1290 static void saveRegisters(iCode *lic)
1298 for (ic = lic ; ic ; ic = ic->next)
1299 if (ic->op == CALL || ic->op == PCALL)
1303 fprintf(stderr,"found parameter push with no function call\n");
1307 /* if the registers have been saved already then
1309 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1312 /* find the registers in use at this time
1313 and push them away to safety */
1314 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1318 if (options.useXstack) {
1319 if (bitVectBitValue(rsave,R0_IDX))
1320 emitcode("mov","b,r0");
1321 emitcode("mov","r0,%s",spname);
1322 for (i = 0 ; i < mcs51_nRegs ; i++) {
1323 if (bitVectBitValue(rsave,i)) {
1325 emitcode("mov","a,b");
1327 emitcode("mov","a,%s",mcs51_regWithIdx(i)->name);
1328 emitcode("movx","@r0,a");
1329 emitcode("inc","r0");
1332 emitcode("mov","%s,r0",spname);
1333 if (bitVectBitValue(rsave,R0_IDX))
1334 emitcode("mov","r0,b");
1336 for (i = 0 ; i < mcs51_nRegs ; i++) {
1337 if (bitVectBitValue(rsave,i))
1338 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
1341 detype = getSpec(operandType(IC_LEFT(ic)));
1343 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1344 IS_ISR(currFunc->etype) &&
1347 saverbank(SPEC_BANK(detype),ic,TRUE);
1350 /*-----------------------------------------------------------------*/
1351 /* unsaveRegisters - pop the pushed registers */
1352 /*-----------------------------------------------------------------*/
1353 static void unsaveRegisters (iCode *ic)
1357 /* find the registers in use at this time
1358 and push them away to safety */
1359 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1362 if (options.useXstack) {
1363 emitcode("mov","r0,%s",spname);
1364 for (i = mcs51_nRegs ; i >= 0 ; i--) {
1365 if (bitVectBitValue(rsave,i)) {
1366 emitcode("dec","r0");
1367 emitcode("movx","a,@r0");
1369 emitcode("mov","b,a");
1371 emitcode("mov","%s,a",mcs51_regWithIdx(i)->name);
1375 emitcode("mov","%s,r0",spname);
1376 if (bitVectBitValue(rsave,R0_IDX))
1377 emitcode("mov","r0,b");
1379 for (i = mcs51_nRegs ; i >= 0 ; i--) {
1380 if (bitVectBitValue(rsave,i))
1381 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
1387 /*-----------------------------------------------------------------*/
1389 /*-----------------------------------------------------------------*/
1390 static void pushSide(operand * oper, int size)
1394 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1395 if (AOP_TYPE(oper) != AOP_REG &&
1396 AOP_TYPE(oper) != AOP_DIR &&
1398 emitcode("mov","a,%s",l);
1399 emitcode("push","acc");
1401 emitcode("push","%s",l);
1405 /*-----------------------------------------------------------------*/
1406 /* assignResultValue - */
1407 /*-----------------------------------------------------------------*/
1408 static void assignResultValue(operand * oper)
1411 int size = AOP_SIZE(oper);
1413 aopPut(AOP(oper),fReturn[offset],offset);
1419 /*-----------------------------------------------------------------*/
1420 /* genXpush - pushes onto the external stack */
1421 /*-----------------------------------------------------------------*/
1422 static void genXpush (iCode *ic)
1424 asmop *aop = newAsmop(0);
1426 int size,offset = 0;
1428 aopOp(IC_LEFT(ic),ic,FALSE);
1429 r = getFreePtr(ic,&aop,FALSE);
1432 emitcode("mov","%s,_spx",r->name);
1434 size = AOP_SIZE(IC_LEFT(ic));
1437 char *l = aopGet(AOP(IC_LEFT(ic)),
1438 offset++,FALSE,FALSE);
1440 emitcode("movx","@%s,a",r->name);
1441 emitcode("inc","%s",r->name);
1446 emitcode("mov","_spx,%s",r->name);
1448 freeAsmop(NULL,aop,ic,TRUE);
1449 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1452 /*-----------------------------------------------------------------*/
1453 /* genIpush - genrate code for pushing this gets a little complex */
1454 /*-----------------------------------------------------------------*/
1455 static void genIpush (iCode *ic)
1457 int size, offset = 0 ;
1461 /* if this is not a parm push : ie. it is spill push
1462 and spill push is always done on the local stack */
1463 if (!ic->parmPush) {
1465 /* and the item is spilt then do nothing */
1466 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1469 aopOp(IC_LEFT(ic),ic,FALSE);
1470 size = AOP_SIZE(IC_LEFT(ic));
1471 /* push it on the stack */
1473 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1478 emitcode("push","%s",l);
1483 /* this is a paramter push: in this case we call
1484 the routine to find the call and save those
1485 registers that need to be saved */
1488 /* if use external stack then call the external
1489 stack pushing routine */
1490 if (options.useXstack) {
1495 /* then do the push */
1496 aopOp(IC_LEFT(ic),ic,FALSE);
1499 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1500 size = AOP_SIZE(IC_LEFT(ic));
1503 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1504 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1505 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1507 emitcode("mov","a,%s",l);
1508 emitcode("push","acc");
1510 emitcode("push","%s",l);
1513 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1516 /*-----------------------------------------------------------------*/
1517 /* genIpop - recover the registers: can happen only for spilling */
1518 /*-----------------------------------------------------------------*/
1519 static void genIpop (iCode *ic)
1524 /* if the temp was not pushed then */
1525 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1528 aopOp(IC_LEFT(ic),ic,FALSE);
1529 size = AOP_SIZE(IC_LEFT(ic));
1532 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1535 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1538 /*-----------------------------------------------------------------*/
1539 /* unsaverbank - restores the resgister bank from stack */
1540 /*-----------------------------------------------------------------*/
1541 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1548 if (options.useXstack) {
1550 r = getFreePtr(ic,&aop,FALSE);
1553 emitcode("mov","%s,_spx",r->name);
1554 emitcode("movx","a,@%s",r->name);
1555 emitcode("mov","psw,a");
1556 emitcode("dec","%s",r->name);
1559 emitcode ("pop","psw");
1562 for (i = (mcs51_nRegs - 1) ; i >= 0 ;i--) {
1563 if (options.useXstack) {
1564 emitcode("movx","a,@%s",r->name);
1565 emitcode("mov","(%s+%d),a",
1566 regs8051[i].base,8*bank+regs8051[i].offset);
1567 emitcode("dec","%s",r->name);
1570 emitcode("pop","(%s+%d)",
1571 regs8051[i].base,8*bank+regs8051[i].offset);
1574 if (options.useXstack) {
1576 emitcode("mov","_spx,%s",r->name);
1577 freeAsmop(NULL,aop,ic,TRUE);
1582 /*-----------------------------------------------------------------*/
1583 /* saverbank - saves an entire register bank on the stack */
1584 /*-----------------------------------------------------------------*/
1585 static void saverbank (int bank, iCode *ic, bool pushPsw)
1591 if (options.useXstack) {
1594 r = getFreePtr(ic,&aop,FALSE);
1595 emitcode("mov","%s,_spx",r->name);
1599 for (i = 0 ; i < mcs51_nRegs ;i++) {
1600 if (options.useXstack) {
1601 emitcode("inc","%s",r->name);
1602 emitcode("mov","a,(%s+%d)",
1603 regs8051[i].base,8*bank+regs8051[i].offset);
1604 emitcode("movx","@%s,a",r->name);
1606 emitcode("push","(%s+%d)",
1607 regs8051[i].base,8*bank+regs8051[i].offset);
1611 if (options.useXstack) {
1612 emitcode("mov","a,psw");
1613 emitcode("movx","@%s,a",r->name);
1614 emitcode("inc","%s",r->name);
1615 emitcode("mov","_spx,%s",r->name);
1616 freeAsmop (NULL,aop,ic,TRUE);
1619 emitcode("push","psw");
1621 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1627 /*-----------------------------------------------------------------*/
1628 /* genCall - generates a call statement */
1629 /*-----------------------------------------------------------------*/
1630 static void genCall (iCode *ic)
1634 /* if caller saves & we have not saved then */
1638 /* if we are calling a function that is not using
1639 the same register bank then we need to save the
1640 destination registers on the stack */
1641 detype = getSpec(operandType(IC_LEFT(ic)));
1643 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1644 IS_ISR(currFunc->etype) &&
1647 saverbank(SPEC_BANK(detype),ic,TRUE);
1649 /* if send set is not empty the assign */
1653 for (sic = setFirstItem(_G.sendSet) ; sic ;
1654 sic = setNextItem(_G.sendSet)) {
1655 int size, offset = 0;
1656 aopOp(IC_LEFT(sic),sic,FALSE);
1657 size = AOP_SIZE(IC_LEFT(sic));
1659 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1661 if (strcmp(l,fReturn[offset]))
1662 emitcode("mov","%s,%s",
1667 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1672 emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1673 OP_SYMBOL(IC_LEFT(ic))->rname :
1674 OP_SYMBOL(IC_LEFT(ic))->name));
1676 /* if we need assign a result value */
1677 if ((IS_ITEMP(IC_RESULT(ic)) &&
1678 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1679 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1680 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1683 aopOp(IC_RESULT(ic),ic,FALSE);
1686 assignResultValue(IC_RESULT(ic));
1688 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1691 /* adjust the stack for parameters if
1693 if (IC_LEFT(ic)->parmBytes) {
1695 if (IC_LEFT(ic)->parmBytes > 3) {
1696 emitcode("mov","a,%s",spname);
1697 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1698 emitcode("mov","%s,a",spname);
1700 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1701 emitcode("dec","%s",spname);
1705 /* if register bank was saved then pop them */
1707 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1709 /* if we hade saved some registers then unsave them */
1710 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1711 unsaveRegisters (ic);
1716 /*-----------------------------------------------------------------*/
1717 /* genPcall - generates a call by pointer statement */
1718 /*-----------------------------------------------------------------*/
1719 static void genPcall (iCode *ic)
1722 symbol *rlbl = newiTempLabel(NULL);
1725 /* if caller saves & we have not saved then */
1729 /* if we are calling a function that is not using
1730 the same register bank then we need to save the
1731 destination registers on the stack */
1732 detype = getSpec(operandType(IC_LEFT(ic)));
1734 IS_ISR(currFunc->etype) &&
1735 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
1736 saverbank(SPEC_BANK(detype),ic,TRUE);
1739 /* push the return address on to the stack */
1740 emitcode("mov","a,#%05d$",(rlbl->key+100));
1741 emitcode("push","acc");
1742 emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
1743 emitcode("push","acc");
1745 if (options.model == MODEL_FLAT24)
1747 emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
1748 emitcode("push","acc");
1751 /* now push the calling address */
1752 aopOp(IC_LEFT(ic),ic,FALSE);
1754 pushSide(IC_LEFT(ic), FPTRSIZE);
1756 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1758 /* if send set is not empty the assign */
1762 for (sic = setFirstItem(_G.sendSet) ; sic ;
1763 sic = setNextItem(_G.sendSet)) {
1764 int size, offset = 0;
1765 aopOp(IC_LEFT(sic),sic,FALSE);
1766 size = AOP_SIZE(IC_LEFT(sic));
1768 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1770 if (strcmp(l,fReturn[offset]))
1771 emitcode("mov","%s,%s",
1776 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1782 emitcode("","%05d$:",(rlbl->key+100));
1785 /* if we need assign a result value */
1786 if ((IS_ITEMP(IC_RESULT(ic)) &&
1787 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1788 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
1789 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1792 aopOp(IC_RESULT(ic),ic,FALSE);
1795 assignResultValue(IC_RESULT(ic));
1797 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1800 /* adjust the stack for parameters if
1802 if (IC_LEFT(ic)->parmBytes) {
1804 if (IC_LEFT(ic)->parmBytes > 3) {
1805 emitcode("mov","a,%s",spname);
1806 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1807 emitcode("mov","%s,a",spname);
1809 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1810 emitcode("dec","%s",spname);
1814 /* if register bank was saved then unsave them */
1816 (SPEC_BANK(currFunc->etype) !=
1818 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1820 /* if we hade saved some registers then
1823 unsaveRegisters (ic);
1827 /*-----------------------------------------------------------------*/
1828 /* resultRemat - result is rematerializable */
1829 /*-----------------------------------------------------------------*/
1830 static int resultRemat (iCode *ic)
1832 if (SKIP_IC(ic) || ic->op == IFX)
1835 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1836 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1837 if (sym->remat && !POINTER_SET(ic))
1844 /*-----------------------------------------------------------------*/
1845 /* inExcludeList - return 1 if the string is in exclude Reg list */
1846 /*-----------------------------------------------------------------*/
1847 static bool inExcludeList(char *s)
1851 if (options.excludeRegs[i] &&
1852 strcasecmp(options.excludeRegs[i],"none") == 0)
1855 for ( i = 0 ; options.excludeRegs[i]; i++) {
1856 if (options.excludeRegs[i] &&
1857 strcasecmp(s,options.excludeRegs[i]) == 0)
1863 /*-----------------------------------------------------------------*/
1864 /* genFunction - generated code for function entry */
1865 /*-----------------------------------------------------------------*/
1866 static void genFunction (iCode *ic)
1872 /* create the function header */
1873 emitcode(";","-----------------------------------------");
1874 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1875 emitcode(";","-----------------------------------------");
1877 emitcode("","%s:",sym->rname);
1878 fetype = getSpec(operandType(IC_LEFT(ic)));
1880 /* if critical function then turn interrupts off */
1881 if (SPEC_CRTCL(fetype))
1882 emitcode("clr","ea");
1884 /* here we need to generate the equates for the
1885 register bank if required */
1886 if (SPEC_BANK(fetype) != rbank) {
1889 rbank = SPEC_BANK(fetype);
1890 for ( i = 0 ; i < mcs51_nRegs ; i++ ) {
1891 if (strcmp(regs8051[i].base,"0") == 0)
1892 emitcode("","%s = 0x%02x",
1894 8*rbank+regs8051[i].offset);
1896 emitcode ("","%s = %s + 0x%02x",
1899 8*rbank+regs8051[i].offset);
1903 /* if this is an interrupt service routine then
1904 save acc, b, dpl, dph */
1905 if (IS_ISR(sym->etype)) {
1907 if (!inExcludeList("acc"))
1908 emitcode ("push","acc");
1909 if (!inExcludeList("b"))
1910 emitcode ("push","b");
1911 if (!inExcludeList("dpl"))
1912 emitcode ("push","dpl");
1913 if (!inExcludeList("dph"))
1914 emitcode ("push","dph");
1915 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
1916 emitcode ("push", "dpx");
1917 /* if this isr has no bank i.e. is going to
1918 run with bank 0 , then we need to save more
1920 if (!SPEC_BANK(sym->etype)) {
1922 /* if this function does not call any other
1923 function then we can be economical and
1924 save only those registers that are used */
1925 if (! sym->hasFcall) {
1928 /* if any registers used */
1929 if (sym->regsUsed) {
1930 /* save the registers used */
1931 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
1932 if (bitVectBitValue(sym->regsUsed,i) ||
1933 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
1934 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
1939 /* this function has a function call cannot
1940 determines register usage so we will have the
1942 saverbank(0,ic,FALSE);
1946 /* if callee-save to be used for this function
1947 then save the registers being used in this function */
1948 if (sym->calleeSave) {
1951 /* if any registers used */
1952 if (sym->regsUsed) {
1953 /* save the registers used */
1954 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
1955 if (bitVectBitValue(sym->regsUsed,i) ||
1956 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
1957 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
1965 /* set the register bank to the desired value */
1966 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
1967 emitcode("push","psw");
1968 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
1971 if (IS_RENT(sym->etype) || options.stackAuto) {
1973 if (options.useXstack) {
1974 emitcode("mov","r0,%s",spname);
1975 emitcode("mov","a,_bp");
1976 emitcode("movx","@r0,a");
1977 emitcode("inc","%s",spname);
1980 /* set up the stack */
1981 emitcode ("push","_bp"); /* save the callers stack */
1982 emitcode ("mov","_bp,%s",spname);
1985 /* adjust the stack for the function */
1990 werror(W_STACK_OVERFLOW,sym->name);
1992 if (i > 3 && sym->recvSize < 4) {
1994 emitcode ("mov","a,sp");
1995 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
1996 emitcode ("mov","sp,a");
2001 emitcode("inc","sp");
2006 emitcode ("mov","a,_spx");
2007 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2008 emitcode ("mov","_spx,a");
2013 /*-----------------------------------------------------------------*/
2014 /* genEndFunction - generates epilogue for functions */
2015 /*-----------------------------------------------------------------*/
2016 static void genEndFunction (iCode *ic)
2018 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2020 if (IS_RENT(sym->etype) || options.stackAuto)
2021 emitcode ("mov","%s,_bp",spname);
2023 /* if use external stack but some variables were
2024 added to the local stack then decrement the
2026 if (options.useXstack && sym->stack) {
2027 emitcode("mov","a,sp");
2028 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2029 emitcode("mov","sp,a");
2033 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2034 if (options.useXstack) {
2035 emitcode("mov","r0,%s",spname);
2036 emitcode("movx","a,@r0");
2037 emitcode("mov","_bp,a");
2038 emitcode("dec","%s",spname);
2041 emitcode ("pop","_bp");
2044 /* restore the register bank */
2045 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2046 emitcode ("pop","psw");
2048 if (IS_ISR(sym->etype)) {
2050 /* now we need to restore the registers */
2051 /* if this isr has no bank i.e. is going to
2052 run with bank 0 , then we need to save more
2054 if (!SPEC_BANK(sym->etype)) {
2056 /* if this function does not call any other
2057 function then we can be economical and
2058 save only those registers that are used */
2059 if (! sym->hasFcall) {
2062 /* if any registers used */
2063 if (sym->regsUsed) {
2064 /* save the registers used */
2065 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2066 if (bitVectBitValue(sym->regsUsed,i) ||
2067 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2068 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
2073 /* this function has a function call cannot
2074 determines register usage so we will have the
2076 unsaverbank(0,ic,FALSE);
2080 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2081 emitcode ("pop", "dpx");
2082 if (!inExcludeList("dph"))
2083 emitcode ("pop","dph");
2084 if (!inExcludeList("dpl"))
2085 emitcode ("pop","dpl");
2086 if (!inExcludeList("b"))
2087 emitcode ("pop","b");
2088 if (!inExcludeList("acc"))
2089 emitcode ("pop","acc");
2091 if (SPEC_CRTCL(sym->etype))
2092 emitcode("setb","ea");
2094 /* if debug then send end of function */
2095 /* if (options.debug && currFunc) { */
2098 emitcode("","C$%s$%d$%d$%d ==.",
2099 ic->filename,currFunc->lastLine,
2100 ic->level,ic->block);
2101 if (IS_STATIC(currFunc->etype))
2102 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2104 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2108 emitcode ("reti","");
2111 if (SPEC_CRTCL(sym->etype))
2112 emitcode("setb","ea");
2114 if (sym->calleeSave) {
2117 /* if any registers used */
2118 if (sym->regsUsed) {
2119 /* save the registers used */
2120 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2121 if (bitVectBitValue(sym->regsUsed,i) ||
2122 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2123 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
2129 /* if debug then send end of function */
2130 /* if (options.debug && currFunc) { */
2133 emitcode("","C$%s$%d$%d$%d ==.",
2134 ic->filename,currFunc->lastLine,
2135 ic->level,ic->block);
2136 if (IS_STATIC(currFunc->etype))
2137 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2139 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2143 emitcode ("ret","");
2148 /*-----------------------------------------------------------------*/
2149 /* genRet - generate code for return statement */
2150 /*-----------------------------------------------------------------*/
2151 static void genRet (iCode *ic)
2153 int size,offset = 0 , pushed = 0;
2155 /* if we have no return value then
2156 just generate the "ret" */
2160 /* we have something to return then
2161 move the return value into place */
2162 aopOp(IC_LEFT(ic),ic,FALSE);
2163 size = AOP_SIZE(IC_LEFT(ic));
2167 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2168 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2170 emitcode("push","%s",l);
2173 l = aopGet(AOP(IC_LEFT(ic)),offset,
2175 if (strcmp(fReturn[offset],l))
2176 emitcode("mov","%s,%s",fReturn[offset++],l);
2183 if (strcmp(fReturn[pushed],"a"))
2184 emitcode("pop",fReturn[pushed]);
2186 emitcode("pop","acc");
2189 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2192 /* generate a jump to the return label
2193 if the next is not the return statement */
2194 if (!(ic->next && ic->next->op == LABEL &&
2195 IC_LABEL(ic->next) == returnLabel))
2197 emitcode("ljmp","%05d$",(returnLabel->key+100));
2201 /*-----------------------------------------------------------------*/
2202 /* genLabel - generates a label */
2203 /*-----------------------------------------------------------------*/
2204 static void genLabel (iCode *ic)
2206 /* special case never generate */
2207 if (IC_LABEL(ic) == entryLabel)
2210 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2213 /*-----------------------------------------------------------------*/
2214 /* genGoto - generates a ljmp */
2215 /*-----------------------------------------------------------------*/
2216 static void genGoto (iCode *ic)
2218 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2221 /*-----------------------------------------------------------------*/
2222 /* genPlusIncr :- does addition with increment if possible */
2223 /*-----------------------------------------------------------------*/
2224 static bool genPlusIncr (iCode *ic)
2226 unsigned int icount ;
2227 unsigned int size = getDataSize(IC_RESULT(ic));
2229 /* will try to generate an increment */
2230 /* if the right side is not a literal
2232 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2235 /* if the literal value of the right hand side
2236 is greater than 4 then it is not worth it */
2237 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2240 /* if increment 16 bits in register */
2241 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2244 symbol *tlbl = newiTempLabel(NULL);
2245 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2246 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2247 IS_AOP_PREG(IC_RESULT(ic)))
2248 emitcode("cjne","%s,#0x00,%05d$"
2249 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2252 emitcode("clr","a");
2253 emitcode("cjne","a,%s,%05d$"
2254 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2258 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,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)),MSB16,FALSE,FALSE)
2266 emitcode("cjne","a,%s,%05d$"
2267 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2270 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2271 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2272 IS_AOP_PREG(IC_RESULT(ic)))
2273 emitcode("cjne","%s,#0x00,%05d$"
2274 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2277 emitcode("cjne","a,%s,%05d$"
2278 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2281 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2283 emitcode("","%05d$:",tlbl->key+100);
2287 /* if the sizes are greater than 1 then we cannot */
2288 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2289 AOP_SIZE(IC_LEFT(ic)) > 1 )
2292 /* we can if the aops of the left & result match or
2293 if they are in registers and the registers are the
2295 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2298 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2299 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2300 aopPut(AOP(IC_RESULT(ic)),"a",0);
2304 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2313 /*-----------------------------------------------------------------*/
2314 /* outBitAcc - output a bit in acc */
2315 /*-----------------------------------------------------------------*/
2316 static void outBitAcc(operand *result)
2318 symbol *tlbl = newiTempLabel(NULL);
2319 /* if the result is a bit */
2320 if (AOP_TYPE(result) == AOP_CRY){
2321 aopPut(AOP(result),"a",0);
2324 emitcode("jz","%05d$",tlbl->key+100);
2325 emitcode("mov","a,%s",one);
2326 emitcode("","%05d$:",tlbl->key+100);
2331 /*-----------------------------------------------------------------*/
2332 /* genPlusBits - generates code for addition of two bits */
2333 /*-----------------------------------------------------------------*/
2334 static void genPlusBits (iCode *ic)
2336 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2337 symbol *lbl = newiTempLabel(NULL);
2338 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2339 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2340 emitcode("cpl","c");
2341 emitcode("","%05d$:",(lbl->key+100));
2342 outBitC(IC_RESULT(ic));
2345 emitcode("clr","a");
2346 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2347 emitcode("rlc","a");
2348 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2349 emitcode("addc","a,#0x00");
2350 outAcc(IC_RESULT(ic));
2354 /*-----------------------------------------------------------------*/
2355 /* genPlus - generates code for addition */
2356 /*-----------------------------------------------------------------*/
2357 static void genPlus (iCode *ic)
2359 int size, offset = 0;
2361 /* special cases :- */
2363 aopOp (IC_LEFT(ic),ic,FALSE);
2364 aopOp (IC_RIGHT(ic),ic,FALSE);
2365 aopOp (IC_RESULT(ic),ic,TRUE);
2367 /* if literal, literal on the right or
2368 if left requires ACC or right is already
2370 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2371 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2372 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2373 operand *t = IC_RIGHT(ic);
2374 IC_RIGHT(ic) = IC_LEFT(ic);
2378 /* if both left & right are in bit
2380 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2381 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2386 /* if left in bit space & right literal */
2387 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2388 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2389 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2390 /* if result in bit space */
2391 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2392 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
2393 emitcode("cpl","c");
2394 outBitC(IC_RESULT(ic));
2396 size = getDataSize(IC_RESULT(ic));
2398 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2399 emitcode("addc","a,#00");
2400 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2406 /* if I can do an increment instead
2407 of add then GOOD for ME */
2408 if (genPlusIncr (ic) == TRUE)
2411 size = getDataSize(IC_RESULT(ic));
2414 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2415 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2417 emitcode("add","a,%s",
2418 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2420 emitcode("addc","a,%s",
2421 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2423 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2425 emitcode("add","a,%s",
2426 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2428 emitcode("addc","a,%s",
2429 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2431 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2434 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2435 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2436 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2437 aopPut(AOP(IC_RESULT(ic)),
2438 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2441 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2442 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
2443 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2444 aopPut(AOP(IC_RESULT(ic)),
2445 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2448 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2449 AOP_SIZE(IC_LEFT(ic)) < 3 &&
2450 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
2451 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2452 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2454 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2455 aopPut(AOP(IC_RESULT(ic)),buffer,2);
2458 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2459 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2460 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2463 /*-----------------------------------------------------------------*/
2464 /* genMinusDec :- does subtraction with deccrement if possible */
2465 /*-----------------------------------------------------------------*/
2466 static bool genMinusDec (iCode *ic)
2468 unsigned int icount ;
2469 unsigned int size = getDataSize(IC_RESULT(ic));
2471 /* will try to generate an increment */
2472 /* if the right side is not a literal
2474 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2477 /* if the literal value of the right hand side
2478 is greater than 4 then it is not worth it */
2479 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2482 size = getDataSize(IC_RESULT(ic));
2483 /* if decrement 16 bits in register */
2484 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2487 symbol *tlbl = newiTempLabel(NULL);
2488 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2489 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2490 IS_AOP_PREG(IC_RESULT(ic)))
2491 emitcode("cjne","%s,#0xff,%05d$"
2492 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2495 emitcode("mov","a,#0xff");
2496 emitcode("cjne","a,%s,%05d$"
2497 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2500 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,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)),MSB16,FALSE,FALSE)
2508 emitcode("cjne","a,%s,%05d$"
2509 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2512 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2513 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2514 IS_AOP_PREG(IC_RESULT(ic)))
2515 emitcode("cjne","%s,#0xff,%05d$"
2516 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2519 emitcode("cjne","a,%s,%05d$"
2520 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2523 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2525 emitcode("","%05d$:",tlbl->key+100);
2529 /* if the sizes are greater than 1 then we cannot */
2530 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2531 AOP_SIZE(IC_LEFT(ic)) > 1 )
2534 /* we can if the aops of the left & result match or
2535 if they are in registers and the registers are the
2537 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2540 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2548 /*-----------------------------------------------------------------*/
2549 /* addSign - complete with sign */
2550 /*-----------------------------------------------------------------*/
2551 static void addSign(operand *result, int offset, int sign)
2553 int size = (getDataSize(result) - offset);
2556 emitcode("rlc","a");
2557 emitcode("subb","a,acc");
2559 aopPut(AOP(result),"a",offset++);
2562 aopPut(AOP(result),zero,offset++);
2566 /*-----------------------------------------------------------------*/
2567 /* genMinusBits - generates code for subtraction of two bits */
2568 /*-----------------------------------------------------------------*/
2569 static void genMinusBits (iCode *ic)
2571 symbol *lbl = newiTempLabel(NULL);
2572 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2573 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2574 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2575 emitcode("cpl","c");
2576 emitcode("","%05d$:",(lbl->key+100));
2577 outBitC(IC_RESULT(ic));
2580 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2581 emitcode("subb","a,acc");
2582 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
2583 emitcode("inc","a");
2584 emitcode("","%05d$:",(lbl->key+100));
2585 aopPut(AOP(IC_RESULT(ic)),"a",0);
2586 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
2590 /*-----------------------------------------------------------------*/
2591 /* genMinus - generates code for subtraction */
2592 /*-----------------------------------------------------------------*/
2593 static void genMinus (iCode *ic)
2595 int size, offset = 0;
2596 unsigned long lit = 0L;
2598 aopOp (IC_LEFT(ic),ic,FALSE);
2599 aopOp (IC_RIGHT(ic),ic,FALSE);
2600 aopOp (IC_RESULT(ic),ic,TRUE);
2602 /* special cases :- */
2603 /* if both left & right are in bit space */
2604 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2605 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2610 /* if I can do an decrement instead
2611 of subtract then GOOD for ME */
2612 if (genMinusDec (ic) == TRUE)
2615 size = getDataSize(IC_RESULT(ic));
2617 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
2621 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2625 /* if literal, add a,#-lit, else normal subb */
2627 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2628 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2629 emitcode("subb","a,%s",
2630 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2632 /* first add without previous c */
2634 emitcode("add","a,#0x%02x",
2635 (unsigned int)(lit & 0x0FFL));
2637 emitcode("addc","a,#0x%02x",
2638 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
2640 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2643 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2644 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2645 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2646 aopPut(AOP(IC_RESULT(ic)),
2647 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2650 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2651 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
2652 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2653 aopPut(AOP(IC_RESULT(ic)),
2654 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2657 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2658 AOP_SIZE(IC_LEFT(ic)) < 3 &&
2659 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
2660 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2661 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2663 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2664 aopPut(AOP(IC_RESULT(ic)),buffer,2);
2667 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2668 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2669 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2673 /*-----------------------------------------------------------------*/
2674 /* genMultbits :- multiplication of bits */
2675 /*-----------------------------------------------------------------*/
2676 static void genMultbits (operand *left,
2680 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2681 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
2686 /*-----------------------------------------------------------------*/
2687 /* genMultOneByte : 8 bit multiplication & division */
2688 /*-----------------------------------------------------------------*/
2689 static void genMultOneByte (operand *left,
2693 link *opetype = operandType(result);
2698 /* (if two literals, the value is computed before) */
2699 /* if one literal, literal on the right */
2700 if (AOP_TYPE(left) == AOP_LIT){
2706 size = AOP_SIZE(result);
2707 /* signed or unsigned */
2708 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2709 l = aopGet(AOP(left),0,FALSE,FALSE);
2711 emitcode("mul","ab");
2712 /* if result size = 1, mul signed = mul unsigned */
2713 aopPut(AOP(result),"a",0);
2715 if (SPEC_USIGN(opetype)){
2716 aopPut(AOP(result),"b",1);
2718 /* for filling the MSBs */
2719 emitcode("clr","a");
2722 emitcode("mov","a,b");
2724 /* adjust the MSB if left or right neg */
2726 /* if one literal */
2727 if (AOP_TYPE(right) == AOP_LIT){
2728 /* AND literal negative */
2729 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
2730 /* adjust MSB (c==0 after mul) */
2731 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2735 lbl = newiTempLabel(NULL);
2736 emitcode("xch","a,%s",aopGet(AOP(right),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(right),0,FALSE,FALSE));
2740 lbl = newiTempLabel(NULL);
2741 emitcode("jc","%05d$",(lbl->key+100));
2742 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2743 emitcode("","%05d$:",(lbl->key+100));
2746 lbl = newiTempLabel(NULL);
2747 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
2748 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
2749 emitcode("","%05d$:",(lbl->key+100));
2750 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
2751 lbl = newiTempLabel(NULL);
2752 emitcode("jc","%05d$",(lbl->key+100));
2753 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
2754 emitcode("","%05d$:",(lbl->key+100));
2756 aopPut(AOP(result),"a",1);
2759 emitcode("rlc","a");
2760 emitcode("subb","a,acc");
2767 aopPut(AOP(result),"a",offset++);
2771 /*-----------------------------------------------------------------*/
2772 /* genMult - generates code for multiplication */
2773 /*-----------------------------------------------------------------*/
2774 static void genMult (iCode *ic)
2776 operand *left = IC_LEFT(ic);
2777 operand *right = IC_RIGHT(ic);
2778 operand *result= IC_RESULT(ic);
2780 /* assign the amsops */
2781 aopOp (left,ic,FALSE);
2782 aopOp (right,ic,FALSE);
2783 aopOp (result,ic,TRUE);
2785 /* special cases first */
2787 if (AOP_TYPE(left) == AOP_CRY &&
2788 AOP_TYPE(right)== AOP_CRY) {
2789 genMultbits(left,right,result);
2793 /* if both are of size == 1 */
2794 if (AOP_SIZE(left) == 1 &&
2795 AOP_SIZE(right) == 1 ) {
2796 genMultOneByte(left,right,result);
2800 /* should have been converted to function call */
2804 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2805 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2806 freeAsmop(result,NULL,ic,TRUE);
2809 /*-----------------------------------------------------------------*/
2810 /* genDivbits :- division of bits */
2811 /*-----------------------------------------------------------------*/
2812 static void genDivbits (operand *left,
2819 /* the result must be bit */
2820 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
2821 l = aopGet(AOP(left),0,FALSE,FALSE);
2825 emitcode("div","ab");
2826 emitcode("rrc","a");
2827 aopPut(AOP(result),"c",0);
2830 /*-----------------------------------------------------------------*/
2831 /* genDivOneByte : 8 bit division */
2832 /*-----------------------------------------------------------------*/
2833 static void genDivOneByte (operand *left,
2837 link *opetype = operandType(result);
2842 size = AOP_SIZE(result) - 1;
2844 /* signed or unsigned */
2845 if (SPEC_USIGN(opetype)) {
2846 /* unsigned is easy */
2847 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2848 l = aopGet(AOP(left),0,FALSE,FALSE);
2850 emitcode("div","ab");
2851 aopPut(AOP(result),"a",0);
2853 aopPut(AOP(result),zero,offset++);
2857 /* signed is a little bit more difficult */
2859 /* save the signs of the operands */
2860 l = aopGet(AOP(left),0,FALSE,FALSE);
2862 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
2863 emitcode("push","acc"); /* save it on the stack */
2865 /* now sign adjust for both left & right */
2866 l = aopGet(AOP(right),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));
2873 emitcode("mov","b,a");
2875 /* sign adjust left side */
2876 l = aopGet(AOP(left),0,FALSE,FALSE);
2879 lbl = newiTempLabel(NULL);
2880 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
2881 emitcode("cpl","a");
2882 emitcode("inc","a");
2883 emitcode("","%05d$:",(lbl->key+100));
2885 /* now the division */
2886 emitcode("div","ab");
2887 /* we are interested in the lower order
2889 emitcode("mov","b,a");
2890 lbl = newiTempLabel(NULL);
2891 emitcode("pop","acc");
2892 /* if there was an over flow we don't
2893 adjust the sign of the result */
2894 emitcode("jb","ov,%05d$",(lbl->key+100));
2895 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
2897 emitcode("clr","a");
2898 emitcode("subb","a,b");
2899 emitcode("mov","b,a");
2900 emitcode("","%05d$:",(lbl->key+100));
2902 /* now we are done */
2903 aopPut(AOP(result),"b",0);
2905 emitcode("mov","c,b.7");
2906 emitcode("subb","a,acc");
2909 aopPut(AOP(result),"a",offset++);
2913 /*-----------------------------------------------------------------*/
2914 /* genDiv - generates code for division */
2915 /*-----------------------------------------------------------------*/
2916 static void genDiv (iCode *ic)
2918 operand *left = IC_LEFT(ic);
2919 operand *right = IC_RIGHT(ic);
2920 operand *result= IC_RESULT(ic);
2922 /* assign the amsops */
2923 aopOp (left,ic,FALSE);
2924 aopOp (right,ic,FALSE);
2925 aopOp (result,ic,TRUE);
2927 /* special cases first */
2929 if (AOP_TYPE(left) == AOP_CRY &&
2930 AOP_TYPE(right)== AOP_CRY) {
2931 genDivbits(left,right,result);
2935 /* if both are of size == 1 */
2936 if (AOP_SIZE(left) == 1 &&
2937 AOP_SIZE(right) == 1 ) {
2938 genDivOneByte(left,right,result);
2942 /* should have been converted to function call */
2945 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2946 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2947 freeAsmop(result,NULL,ic,TRUE);
2950 /*-----------------------------------------------------------------*/
2951 /* genModbits :- modulus of bits */
2952 /*-----------------------------------------------------------------*/
2953 static void genModbits (operand *left,
2960 /* the result must be bit */
2961 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
2962 l = aopGet(AOP(left),0,FALSE,FALSE);
2966 emitcode("div","ab");
2967 emitcode("mov","a,b");
2968 emitcode("rrc","a");
2969 aopPut(AOP(result),"c",0);
2972 /*-----------------------------------------------------------------*/
2973 /* genModOneByte : 8 bit modulus */
2974 /*-----------------------------------------------------------------*/
2975 static void genModOneByte (operand *left,
2979 link *opetype = operandType(result);
2983 /* signed or unsigned */
2984 if (SPEC_USIGN(opetype)) {
2985 /* unsigned is easy */
2986 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2987 l = aopGet(AOP(left),0,FALSE,FALSE);
2989 emitcode("div","ab");
2990 aopPut(AOP(result),"b",0);
2994 /* signed is a little bit more difficult */
2996 /* save the signs of the operands */
2997 l = aopGet(AOP(left),0,FALSE,FALSE);
3000 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3001 emitcode("push","acc"); /* save it on the stack */
3003 /* now sign adjust for both left & right */
3004 l = aopGet(AOP(right),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));
3012 emitcode("mov","b,a");
3014 /* sign adjust left side */
3015 l = aopGet(AOP(left),0,FALSE,FALSE);
3018 lbl = newiTempLabel(NULL);
3019 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3020 emitcode("cpl","a");
3021 emitcode("inc","a");
3022 emitcode("","%05d$:",(lbl->key+100));
3024 /* now the multiplication */
3025 emitcode("div","ab");
3026 /* we are interested in the lower order
3028 lbl = newiTempLabel(NULL);
3029 emitcode("pop","acc");
3030 /* if there was an over flow we don't
3031 adjust the sign of the result */
3032 emitcode("jb","ov,%05d$",(lbl->key+100));
3033 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3035 emitcode("clr","a");
3036 emitcode("subb","a,b");
3037 emitcode("mov","b,a");
3038 emitcode("","%05d$:",(lbl->key+100));
3040 /* now we are done */
3041 aopPut(AOP(result),"b",0);
3045 /*-----------------------------------------------------------------*/
3046 /* genMod - generates code for division */
3047 /*-----------------------------------------------------------------*/
3048 static void genMod (iCode *ic)
3050 operand *left = IC_LEFT(ic);
3051 operand *right = IC_RIGHT(ic);
3052 operand *result= IC_RESULT(ic);
3054 /* assign the amsops */
3055 aopOp (left,ic,FALSE);
3056 aopOp (right,ic,FALSE);
3057 aopOp (result,ic,TRUE);
3059 /* special cases first */
3061 if (AOP_TYPE(left) == AOP_CRY &&
3062 AOP_TYPE(right)== AOP_CRY) {
3063 genModbits(left,right,result);
3067 /* if both are of size == 1 */
3068 if (AOP_SIZE(left) == 1 &&
3069 AOP_SIZE(right) == 1 ) {
3070 genModOneByte(left,right,result);
3074 /* should have been converted to function call */
3078 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3079 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3080 freeAsmop(result,NULL,ic,TRUE);
3083 /*-----------------------------------------------------------------*/
3084 /* genIfxJump :- will create a jump depending on the ifx */
3085 /*-----------------------------------------------------------------*/
3086 static void genIfxJump (iCode *ic, char *jval)
3089 symbol *tlbl = newiTempLabel(NULL);
3092 /* if true label then we jump if condition
3094 if ( IC_TRUE(ic) ) {
3096 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3097 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3100 /* false label is present */
3101 jlbl = IC_FALSE(ic) ;
3102 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3103 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3105 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3106 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3108 emitcode(inst,"%05d$",tlbl->key+100);
3109 emitcode("ljmp","%05d$",jlbl->key+100);
3110 emitcode("","%05d$:",tlbl->key+100);
3112 /* mark the icode as generated */
3116 /*-----------------------------------------------------------------*/
3117 /* genCmp :- greater or less than comparison */
3118 /*-----------------------------------------------------------------*/
3119 static void genCmp (operand *left,operand *right,
3120 operand *result, iCode *ifx, int sign)
3122 int size, offset = 0 ;
3123 unsigned long lit = 0L;
3125 /* if left & right are bit variables */
3126 if (AOP_TYPE(left) == AOP_CRY &&
3127 AOP_TYPE(right) == AOP_CRY ) {
3128 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3129 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3131 /* subtract right from left if at the
3132 end the carry flag is set then we know that
3133 left is greater than right */
3134 size = max(AOP_SIZE(left),AOP_SIZE(right));
3136 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3137 if((size == 1) && !sign &&
3138 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3139 symbol *lbl = newiTempLabel(NULL);
3140 emitcode("cjne","%s,%s,%05d$",
3141 aopGet(AOP(left),offset,FALSE,FALSE),
3142 aopGet(AOP(right),offset,FALSE,FALSE),
3144 emitcode("","%05d$:",lbl->key+100);
3146 if(AOP_TYPE(right) == AOP_LIT){
3147 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3148 /* optimize if(x < 0) or if(x >= 0) */
3154 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE));
3155 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3156 genIfxJump (ifx,"acc.7");
3160 emitcode("rlc","a");
3167 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3168 if (sign && size == 0) {
3169 emitcode("xrl","a,#0x80");
3170 if (AOP_TYPE(right) == AOP_LIT){
3171 unsigned long lit = (unsigned long)
3172 floatFromVal(AOP(right)->aopu.aop_lit);
3173 emitcode("subb","a,#0x%02x",
3174 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3176 emitcode("mov","b,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3177 emitcode("xrl","b,#0x80");
3178 emitcode("subb","a,b");
3181 emitcode("subb","a,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3187 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3190 /* if the result is used in the next
3191 ifx conditional branch then generate
3192 code a little differently */
3194 genIfxJump (ifx,"c");
3197 /* leave the result in acc */
3201 /*-----------------------------------------------------------------*/
3202 /* genCmpGt :- greater than comparison */
3203 /*-----------------------------------------------------------------*/
3204 static void genCmpGt (iCode *ic, iCode *ifx)
3206 operand *left, *right, *result;
3207 link *letype , *retype;
3211 right= IC_RIGHT(ic);
3212 result = IC_RESULT(ic);
3214 letype = getSpec(operandType(left));
3215 retype =getSpec(operandType(right));
3216 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3217 /* assign the amsops */
3218 aopOp (left,ic,FALSE);
3219 aopOp (right,ic,FALSE);
3220 aopOp (result,ic,TRUE);
3222 genCmp(right, left, result, ifx, sign);
3224 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3225 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3226 freeAsmop(result,NULL,ic,TRUE);
3229 /*-----------------------------------------------------------------*/
3230 /* genCmpLt - less than comparisons */
3231 /*-----------------------------------------------------------------*/
3232 static void genCmpLt (iCode *ic, iCode *ifx)
3234 operand *left, *right, *result;
3235 link *letype , *retype;
3239 right= IC_RIGHT(ic);
3240 result = IC_RESULT(ic);
3242 letype = getSpec(operandType(left));
3243 retype =getSpec(operandType(right));
3244 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3246 /* assign the amsops */
3247 aopOp (left,ic,FALSE);
3248 aopOp (right,ic,FALSE);
3249 aopOp (result,ic,TRUE);
3251 genCmp(left, right, result, ifx, sign);
3253 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3254 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3255 freeAsmop(result,NULL,ic,TRUE);
3258 /*-----------------------------------------------------------------*/
3259 /* gencjneshort - compare and jump if not equal */
3260 /*-----------------------------------------------------------------*/
3261 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3263 int size = max(AOP_SIZE(left),AOP_SIZE(right));
3265 unsigned long lit = 0L;
3267 /* if the left side is a literal or
3268 if the right is in a pointer register and left
3270 if ((AOP_TYPE(left) == AOP_LIT) ||
3271 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3276 if(AOP_TYPE(right) == AOP_LIT)
3277 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3279 /* if the right side is a literal then anything goes */
3280 if (AOP_TYPE(right) == AOP_LIT &&
3281 AOP_TYPE(left) != AOP_DIR ) {
3283 emitcode("cjne","%s,%s,%05d$",
3284 aopGet(AOP(left),offset,FALSE,FALSE),
3285 aopGet(AOP(right),offset,FALSE,FALSE),
3291 /* if the right side is in a register or in direct space or
3292 if the left is a pointer register & right is not */
3293 else if (AOP_TYPE(right) == AOP_REG ||
3294 AOP_TYPE(right) == AOP_DIR ||
3295 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3296 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3298 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3299 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3300 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
3301 emitcode("jnz","%05d$",lbl->key+100);
3303 emitcode("cjne","a,%s,%05d$",
3304 aopGet(AOP(right),offset,FALSE,TRUE),
3309 /* right is a pointer reg need both a & b */
3311 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
3313 emitcode("mov","b,%s",l);
3314 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3315 emitcode("cjne","a,b,%05d$",lbl->key+100);
3321 /*-----------------------------------------------------------------*/
3322 /* gencjne - compare and jump if not equal */
3323 /*-----------------------------------------------------------------*/
3324 static void gencjne(operand *left, operand *right, symbol *lbl)
3326 symbol *tlbl = newiTempLabel(NULL);
3328 gencjneshort(left, right, lbl);
3330 emitcode("mov","a,%s",one);
3331 emitcode("sjmp","%05d$",tlbl->key+100);
3332 emitcode("","%05d$:",lbl->key+100);
3333 emitcode("clr","a");
3334 emitcode("","%05d$:",tlbl->key+100);
3337 /*-----------------------------------------------------------------*/
3338 /* genCmpEq - generates code for equal to */
3339 /*-----------------------------------------------------------------*/
3340 static void genCmpEq (iCode *ic, iCode *ifx)
3342 operand *left, *right, *result;
3344 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3345 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3346 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3348 /* if literal, literal on the right or
3349 if the right is in a pointer register and left
3351 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
3352 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3353 operand *t = IC_RIGHT(ic);
3354 IC_RIGHT(ic) = IC_LEFT(ic);
3358 if(ifx && !AOP_SIZE(result)){
3360 /* if they are both bit variables */
3361 if (AOP_TYPE(left) == AOP_CRY &&
3362 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3363 if(AOP_TYPE(right) == AOP_LIT){
3364 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3366 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3367 emitcode("cpl","c");
3368 } else if(lit == 1L) {
3369 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3371 emitcode("clr","c");
3373 /* AOP_TYPE(right) == AOP_CRY */
3375 symbol *lbl = newiTempLabel(NULL);
3376 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3377 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3378 emitcode("cpl","c");
3379 emitcode("","%05d$:",(lbl->key+100));
3381 /* if true label then we jump if condition
3383 tlbl = newiTempLabel(NULL);
3384 if ( IC_TRUE(ifx) ) {
3385 emitcode("jnc","%05d$",tlbl->key+100);
3386 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3388 emitcode("jc","%05d$",tlbl->key+100);
3389 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3391 emitcode("","%05d$:",tlbl->key+100);
3393 tlbl = newiTempLabel(NULL);
3394 gencjneshort(left, right, tlbl);
3395 if ( IC_TRUE(ifx) ) {
3396 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3397 emitcode("","%05d$:",tlbl->key+100);
3399 symbol *lbl = newiTempLabel(NULL);
3400 emitcode("sjmp","%05d$",lbl->key+100);
3401 emitcode("","%05d$:",tlbl->key+100);
3402 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3403 emitcode("","%05d$:",lbl->key+100);
3406 /* mark the icode as generated */
3411 /* if they are both bit variables */
3412 if (AOP_TYPE(left) == AOP_CRY &&
3413 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3414 if(AOP_TYPE(right) == AOP_LIT){
3415 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3417 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3418 emitcode("cpl","c");
3419 } else if(lit == 1L) {
3420 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3422 emitcode("clr","c");
3424 /* AOP_TYPE(right) == AOP_CRY */
3426 symbol *lbl = newiTempLabel(NULL);
3427 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3428 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3429 emitcode("cpl","c");
3430 emitcode("","%05d$:",(lbl->key+100));
3433 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
3438 genIfxJump (ifx,"c");
3441 /* if the result is used in an arithmetic operation
3442 then put the result in place */
3445 gencjne(left,right,newiTempLabel(NULL));
3446 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3447 aopPut(AOP(result),"a",0);
3451 genIfxJump (ifx,"a");
3454 /* if the result is used in an arithmetic operation
3455 then put the result in place */
3456 if (AOP_TYPE(result) != AOP_CRY)
3458 /* leave the result in acc */
3462 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3463 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3464 freeAsmop(result,NULL,ic,TRUE);
3467 /*-----------------------------------------------------------------*/
3468 /* ifxForOp - returns the icode containing the ifx for operand */
3469 /*-----------------------------------------------------------------*/
3470 static iCode *ifxForOp ( operand *op, iCode *ic )
3472 /* if true symbol then needs to be assigned */
3473 if (IS_TRUE_SYMOP(op))
3476 /* if this has register type condition and
3477 the next instruction is ifx with the same operand
3478 and live to of the operand is upto the ifx only then */
3480 ic->next->op == IFX &&
3481 IC_COND(ic->next)->key == op->key &&
3482 OP_SYMBOL(op)->liveTo <= ic->next->seq )
3487 /*-----------------------------------------------------------------*/
3488 /* genAndOp - for && operation */
3489 /*-----------------------------------------------------------------*/
3490 static void genAndOp (iCode *ic)
3492 operand *left,*right, *result;
3495 /* note here that && operations that are in an
3496 if statement are taken away by backPatchLabels
3497 only those used in arthmetic operations remain */
3498 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3499 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3500 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3502 /* if both are bit variables */
3503 if (AOP_TYPE(left) == AOP_CRY &&
3504 AOP_TYPE(right) == AOP_CRY ) {
3505 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3506 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3509 tlbl = newiTempLabel(NULL);
3511 emitcode("jz","%05d$",tlbl->key+100);
3513 emitcode("","%05d$:",tlbl->key+100);
3517 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3518 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3519 freeAsmop(result,NULL,ic,TRUE);
3523 /*-----------------------------------------------------------------*/
3524 /* genOrOp - for || operation */
3525 /*-----------------------------------------------------------------*/
3526 static void genOrOp (iCode *ic)
3528 operand *left,*right, *result;
3531 /* note here that || operations that are in an
3532 if statement are taken away by backPatchLabels
3533 only those used in arthmetic operations remain */
3534 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3535 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3536 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3538 /* if both are bit variables */
3539 if (AOP_TYPE(left) == AOP_CRY &&
3540 AOP_TYPE(right) == AOP_CRY ) {
3541 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3542 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
3545 tlbl = newiTempLabel(NULL);
3547 emitcode("jnz","%05d$",tlbl->key+100);
3549 emitcode("","%05d$:",tlbl->key+100);
3553 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3554 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3555 freeAsmop(result,NULL,ic,TRUE);
3558 /*-----------------------------------------------------------------*/
3559 /* isLiteralBit - test if lit == 2^n */
3560 /*-----------------------------------------------------------------*/
3561 static int isLiteralBit(unsigned long lit)
3563 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
3564 0x100L,0x200L,0x400L,0x800L,
3565 0x1000L,0x2000L,0x4000L,0x8000L,
3566 0x10000L,0x20000L,0x40000L,0x80000L,
3567 0x100000L,0x200000L,0x400000L,0x800000L,
3568 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
3569 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
3572 for(idx = 0; idx < 32; idx++)
3578 /*-----------------------------------------------------------------*/
3579 /* continueIfTrue - */
3580 /*-----------------------------------------------------------------*/
3581 static void continueIfTrue (iCode *ic)
3584 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3588 /*-----------------------------------------------------------------*/
3590 /*-----------------------------------------------------------------*/
3591 static void jumpIfTrue (iCode *ic)
3594 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3598 /*-----------------------------------------------------------------*/
3599 /* jmpTrueOrFalse - */
3600 /*-----------------------------------------------------------------*/
3601 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
3603 // ugly but optimized by peephole
3605 symbol *nlbl = newiTempLabel(NULL);
3606 emitcode("sjmp","%05d$",nlbl->key+100);
3607 emitcode("","%05d$:",tlbl->key+100);
3608 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3609 emitcode("","%05d$:",nlbl->key+100);
3612 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3613 emitcode("","%05d$:",tlbl->key+100);
3618 /*-----------------------------------------------------------------*/
3619 /* genAnd - code for and */
3620 /*-----------------------------------------------------------------*/
3621 static void genAnd (iCode *ic, iCode *ifx)
3623 operand *left, *right, *result;
3625 unsigned long lit = 0L;
3629 aopOp((left = IC_LEFT(ic)),ic,FALSE);
3630 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3631 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3634 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3636 AOP_TYPE(left), AOP_TYPE(right));
3637 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3639 AOP_SIZE(left), AOP_SIZE(right));
3642 /* if left is a literal & right is not then exchange them */
3643 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3644 AOP_NEEDSACC(left)) {
3645 operand *tmp = right ;
3650 /* if result = right then exchange them */
3651 if(sameRegs(AOP(result),AOP(right))){
3652 operand *tmp = right ;
3657 /* if right is bit then exchange them */
3658 if (AOP_TYPE(right) == AOP_CRY &&
3659 AOP_TYPE(left) != AOP_CRY){
3660 operand *tmp = right ;
3664 if(AOP_TYPE(right) == AOP_LIT)
3665 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3667 size = AOP_SIZE(result);
3670 // result = bit & yy;
3671 if (AOP_TYPE(left) == AOP_CRY){
3672 // c = bit & literal;
3673 if(AOP_TYPE(right) == AOP_LIT){
3675 if(size && sameRegs(AOP(result),AOP(left)))
3678 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3681 if(size && (AOP_TYPE(result) == AOP_CRY)){
3682 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
3685 if((AOP_TYPE(result) == AOP_CRY) && ifx){
3689 emitcode("clr","c");
3692 if (AOP_TYPE(right) == AOP_CRY){
3694 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3695 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3698 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
3700 emitcode("rrc","a");
3701 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3709 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
3710 genIfxJump(ifx, "c");
3714 // if(val & 0xZZ) - size = 0, ifx != FALSE -
3715 // bit = val & 0xZZ - size = 1, ifx = FALSE -
3716 if((AOP_TYPE(right) == AOP_LIT) &&
3717 (AOP_TYPE(result) == AOP_CRY) &&
3718 (AOP_TYPE(left) != AOP_CRY)){
3719 int posbit = isLiteralBit(lit);
3723 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
3726 emitcode("mov","c,acc.%d",posbit&0x07);
3730 sprintf(buffer,"acc.%d",posbit&0x07);
3731 genIfxJump(ifx, buffer);
3736 symbol *tlbl = newiTempLabel(NULL);
3737 int sizel = AOP_SIZE(left);
3739 emitcode("setb","c");
3741 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
3742 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
3744 if((posbit = isLiteralBit(bytelit)) != 0)
3745 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
3747 if(bytelit != 0x0FFL)
3748 emitcode("anl","a,%s",
3749 aopGet(AOP(right),offset,FALSE,TRUE));
3750 emitcode("jnz","%05d$",tlbl->key+100);
3755 // bit = left & literal
3757 emitcode("clr","c");
3758 emitcode("","%05d$:",tlbl->key+100);
3760 // if(left & literal)
3763 jmpTrueOrFalse(ifx, tlbl);
3771 /* if left is same as result */
3772 if(sameRegs(AOP(result),AOP(left))){
3773 for(;size--; offset++) {
3774 if(AOP_TYPE(right) == AOP_LIT){
3775 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
3779 aopPut(AOP(result),zero,offset);
3781 if (IS_AOP_PREG(result)) {
3782 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3783 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
3784 aopPut(AOP(result),"a",offset);
3786 emitcode("anl","%s,%s",
3787 aopGet(AOP(left),offset,FALSE,TRUE),
3788 aopGet(AOP(right),offset,FALSE,FALSE));
3790 if (AOP_TYPE(left) == AOP_ACC)
3791 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
3793 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3794 if (IS_AOP_PREG(result)) {
3795 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
3796 aopPut(AOP(result),"a",offset);
3799 emitcode("anl","%s,a",
3800 aopGet(AOP(left),offset,FALSE,TRUE));
3805 // left & result in different registers
3806 if(AOP_TYPE(result) == AOP_CRY){
3808 // if(size), result in bit
3809 // if(!size && ifx), conditional oper: if(left & right)
3810 symbol *tlbl = newiTempLabel(NULL);
3811 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
3813 emitcode("setb","c");
3815 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3816 emitcode("anl","a,%s",
3817 aopGet(AOP(left),offset,FALSE,FALSE));
3818 emitcode("jnz","%05d$",tlbl->key+100);
3823 emitcode("","%05d$:",tlbl->key+100);
3826 jmpTrueOrFalse(ifx, tlbl);
3828 for(;(size--);offset++) {
3830 // result = left & right
3831 if(AOP_TYPE(right) == AOP_LIT){
3832 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
3834 aopGet(AOP(left),offset,FALSE,FALSE),
3837 } else if(bytelit == 0){
3838 aopPut(AOP(result),zero,offset);
3842 // faster than result <- left, anl result,right
3843 // and better if result is SFR
3844 if (AOP_TYPE(left) == AOP_ACC)
3845 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
3847 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3848 emitcode("anl","a,%s",
3849 aopGet(AOP(left),offset,FALSE,FALSE));
3851 aopPut(AOP(result),"a",offset);
3857 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3858 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3859 freeAsmop(result,NULL,ic,TRUE);
3862 /*-----------------------------------------------------------------*/
3863 /* genOr - code for or */
3864 /*-----------------------------------------------------------------*/
3865 static void genOr (iCode *ic, iCode *ifx)
3867 operand *left, *right, *result;
3869 unsigned long lit = 0L;
3871 aopOp((left = IC_LEFT(ic)),ic,FALSE);
3872 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3873 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3876 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3878 AOP_TYPE(left), AOP_TYPE(right));
3879 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3881 AOP_SIZE(left), AOP_SIZE(right));
3884 /* if left is a literal & right is not then exchange them */
3885 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3886 AOP_NEEDSACC(left)) {
3887 operand *tmp = right ;
3892 /* if result = right then exchange them */
3893 if(sameRegs(AOP(result),AOP(right))){
3894 operand *tmp = right ;
3899 /* if right is bit then exchange them */
3900 if (AOP_TYPE(right) == AOP_CRY &&
3901 AOP_TYPE(left) != AOP_CRY){
3902 operand *tmp = right ;
3906 if(AOP_TYPE(right) == AOP_LIT)
3907 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3909 size = AOP_SIZE(result);
3913 if (AOP_TYPE(left) == AOP_CRY){
3914 if(AOP_TYPE(right) == AOP_LIT){
3915 // c = bit & literal;
3917 // lit != 0 => result = 1
3918 if(AOP_TYPE(result) == AOP_CRY){
3920 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
3922 continueIfTrue(ifx);
3925 emitcode("setb","c");
3927 // lit == 0 => result = left
3928 if(size && sameRegs(AOP(result),AOP(left)))
3930 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3933 if (AOP_TYPE(right) == AOP_CRY){
3935 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3936 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
3940 symbol *tlbl = newiTempLabel(NULL);
3941 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
3942 emitcode("setb","c");
3943 emitcode("jb","%s,%05d$",
3944 AOP(left)->aopu.aop_dir,tlbl->key+100);
3946 emitcode("jnz","%05d$",tlbl->key+100);
3947 if((AOP_TYPE(result) == AOP_CRY) && ifx){
3948 jmpTrueOrFalse(ifx, tlbl);
3952 emitcode("","%05d$:",tlbl->key+100);
3961 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
3962 genIfxJump(ifx, "c");
3966 // if(val | 0xZZ) - size = 0, ifx != FALSE -
3967 // bit = val | 0xZZ - size = 1, ifx = FALSE -
3968 if((AOP_TYPE(right) == AOP_LIT) &&
3969 (AOP_TYPE(result) == AOP_CRY) &&
3970 (AOP_TYPE(left) != AOP_CRY)){
3974 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
3976 continueIfTrue(ifx);
3979 // lit = 0, result = boolean(left)
3981 emitcode("setb","c");
3984 symbol *tlbl = newiTempLabel(NULL);
3985 emitcode("jnz","%05d$",tlbl->key+100);
3987 emitcode("","%05d$:",tlbl->key+100);
3989 genIfxJump (ifx,"a");
3997 /* if left is same as result */
3998 if(sameRegs(AOP(result),AOP(left))){
3999 for(;size--; offset++) {
4000 if(AOP_TYPE(right) == AOP_LIT){
4001 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4004 if (IS_AOP_PREG(left)) {
4005 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4006 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4007 aopPut(AOP(result),"a",offset);
4009 emitcode("orl","%s,%s",
4010 aopGet(AOP(left),offset,FALSE,TRUE),
4011 aopGet(AOP(right),offset,FALSE,FALSE));
4013 if (AOP_TYPE(left) == AOP_ACC)
4014 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4016 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4017 if (IS_AOP_PREG(left)) {
4018 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4019 aopPut(AOP(result),"a",offset);
4021 emitcode("orl","%s,a",
4022 aopGet(AOP(left),offset,FALSE,TRUE));
4027 // left & result in different registers
4028 if(AOP_TYPE(result) == AOP_CRY){
4030 // if(size), result in bit
4031 // if(!size && ifx), conditional oper: if(left | right)
4032 symbol *tlbl = newiTempLabel(NULL);
4033 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4035 emitcode("setb","c");
4037 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4038 emitcode("orl","a,%s",
4039 aopGet(AOP(left),offset,FALSE,FALSE));
4040 emitcode("jnz","%05d$",tlbl->key+100);
4045 emitcode("","%05d$:",tlbl->key+100);
4048 jmpTrueOrFalse(ifx, tlbl);
4049 } else for(;(size--);offset++){
4051 // result = left & right
4052 if(AOP_TYPE(right) == AOP_LIT){
4053 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4055 aopGet(AOP(left),offset,FALSE,FALSE),
4060 // faster than result <- left, anl result,right
4061 // and better if result is SFR
4062 if (AOP_TYPE(left) == AOP_ACC)
4063 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4065 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4066 emitcode("orl","a,%s",
4067 aopGet(AOP(left),offset,FALSE,FALSE));
4069 aopPut(AOP(result),"a",offset);
4074 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4075 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4076 freeAsmop(result,NULL,ic,TRUE);
4079 /*-----------------------------------------------------------------*/
4080 /* genXor - code for xclusive or */
4081 /*-----------------------------------------------------------------*/
4082 static void genXor (iCode *ic, iCode *ifx)
4084 operand *left, *right, *result;
4086 unsigned long lit = 0L;
4088 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4089 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4090 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4093 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4095 AOP_TYPE(left), AOP_TYPE(right));
4096 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4098 AOP_SIZE(left), AOP_SIZE(right));
4101 /* if left is a literal & right is not ||
4102 if left needs acc & right does not */
4103 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4104 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4105 operand *tmp = right ;
4110 /* if result = right then exchange them */
4111 if(sameRegs(AOP(result),AOP(right))){
4112 operand *tmp = right ;
4117 /* if right is bit then exchange them */
4118 if (AOP_TYPE(right) == AOP_CRY &&
4119 AOP_TYPE(left) != AOP_CRY){
4120 operand *tmp = right ;
4124 if(AOP_TYPE(right) == AOP_LIT)
4125 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4127 size = AOP_SIZE(result);
4131 if (AOP_TYPE(left) == AOP_CRY){
4132 if(AOP_TYPE(right) == AOP_LIT){
4133 // c = bit & literal;
4135 // lit>>1 != 0 => result = 1
4136 if(AOP_TYPE(result) == AOP_CRY){
4138 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4140 continueIfTrue(ifx);
4143 emitcode("setb","c");
4147 // lit == 0, result = left
4148 if(size && sameRegs(AOP(result),AOP(left)))
4150 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4152 // lit == 1, result = not(left)
4153 if(size && sameRegs(AOP(result),AOP(left))){
4154 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4157 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4158 emitcode("cpl","c");
4165 symbol *tlbl = newiTempLabel(NULL);
4166 if (AOP_TYPE(right) == AOP_CRY){
4168 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4171 int sizer = AOP_SIZE(right);
4173 // if val>>1 != 0, result = 1
4174 emitcode("setb","c");
4176 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
4178 // test the msb of the lsb
4179 emitcode("anl","a,#0xfe");
4180 emitcode("jnz","%05d$",tlbl->key+100);
4184 emitcode("rrc","a");
4186 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4187 emitcode("cpl","c");
4188 emitcode("","%05d$:",(tlbl->key+100));
4195 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4196 genIfxJump(ifx, "c");
4200 if(sameRegs(AOP(result),AOP(left))){
4201 /* if left is same as result */
4202 for(;size--; offset++) {
4203 if(AOP_TYPE(right) == AOP_LIT){
4204 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4207 if (IS_AOP_PREG(left)) {
4208 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4209 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4210 aopPut(AOP(result),"a",offset);
4212 emitcode("xrl","%s,%s",
4213 aopGet(AOP(left),offset,FALSE,TRUE),
4214 aopGet(AOP(right),offset,FALSE,FALSE));
4216 if (AOP_TYPE(left) == AOP_ACC)
4217 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4219 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4220 if (IS_AOP_PREG(left)) {
4221 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4222 aopPut(AOP(result),"a",offset);
4224 emitcode("xrl","%s,a",
4225 aopGet(AOP(left),offset,FALSE,TRUE));
4230 // left & result in different registers
4231 if(AOP_TYPE(result) == AOP_CRY){
4233 // if(size), result in bit
4234 // if(!size && ifx), conditional oper: if(left ^ right)
4235 symbol *tlbl = newiTempLabel(NULL);
4236 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4238 emitcode("setb","c");
4240 if((AOP_TYPE(right) == AOP_LIT) &&
4241 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4242 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4244 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4245 emitcode("xrl","a,%s",
4246 aopGet(AOP(left),offset,FALSE,FALSE));
4248 emitcode("jnz","%05d$",tlbl->key+100);
4253 emitcode("","%05d$:",tlbl->key+100);
4256 jmpTrueOrFalse(ifx, tlbl);
4257 } else for(;(size--);offset++){
4259 // result = left & right
4260 if(AOP_TYPE(right) == AOP_LIT){
4261 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4263 aopGet(AOP(left),offset,FALSE,FALSE),
4268 // faster than result <- left, anl result,right
4269 // and better if result is SFR
4270 if (AOP_TYPE(left) == AOP_ACC)
4271 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4273 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4274 emitcode("xrl","a,%s",
4275 aopGet(AOP(left),offset,FALSE,TRUE));
4277 aopPut(AOP(result),"a",offset);
4282 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4283 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4284 freeAsmop(result,NULL,ic,TRUE);
4287 /*-----------------------------------------------------------------*/
4288 /* genInline - write the inline code out */
4289 /*-----------------------------------------------------------------*/
4290 static void genInline (iCode *ic)
4292 char buffer[MAX_INLINEASM];
4296 _G.inLine += (!options.asmpeep);
4297 strcpy(buffer,IC_INLINE(ic));
4299 /* emit each line as a code */
4318 /* emitcode("",buffer); */
4319 _G.inLine -= (!options.asmpeep);
4322 /*-----------------------------------------------------------------*/
4323 /* genRRC - rotate right with carry */
4324 /*-----------------------------------------------------------------*/
4325 static void genRRC (iCode *ic)
4327 operand *left , *result ;
4328 int size, offset = 0;
4331 /* rotate right with carry */
4333 result=IC_RESULT(ic);
4334 aopOp (left,ic,FALSE);
4335 aopOp (result,ic,FALSE);
4337 /* move it to the result */
4338 size = AOP_SIZE(result);
4342 l = aopGet(AOP(left),offset,FALSE,FALSE);
4344 emitcode("rrc","a");
4345 if (AOP_SIZE(result) > 1)
4346 aopPut(AOP(result),"a",offset--);
4348 /* now we need to put the carry into the
4349 highest order byte of the result */
4350 if (AOP_SIZE(result) > 1) {
4351 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
4354 emitcode("mov","acc.7,c");
4355 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
4356 freeAsmop(left,NULL,ic,TRUE);
4357 freeAsmop(result,NULL,ic,TRUE);
4360 /*-----------------------------------------------------------------*/
4361 /* genRLC - generate code for rotate left with carry */
4362 /*-----------------------------------------------------------------*/
4363 static void genRLC (iCode *ic)
4365 operand *left , *result ;
4366 int size, offset = 0;
4369 /* rotate right with carry */
4371 result=IC_RESULT(ic);
4372 aopOp (left,ic,FALSE);
4373 aopOp (result,ic,FALSE);
4375 /* move it to the result */
4376 size = AOP_SIZE(result);
4379 l = aopGet(AOP(left),offset,FALSE,FALSE);
4381 emitcode("add","a,acc");
4382 if (AOP_SIZE(result) > 1)
4383 aopPut(AOP(result),"a",offset++);
4385 l = aopGet(AOP(left),offset,FALSE,FALSE);
4387 emitcode("rlc","a");
4388 if (AOP_SIZE(result) > 1)
4389 aopPut(AOP(result),"a",offset++);
4392 /* now we need to put the carry into the
4393 highest order byte of the result */
4394 if (AOP_SIZE(result) > 1) {
4395 l = aopGet(AOP(result),0,FALSE,FALSE);
4398 emitcode("mov","acc.0,c");
4399 aopPut(AOP(result),"a",0);
4400 freeAsmop(left,NULL,ic,TRUE);
4401 freeAsmop(result,NULL,ic,TRUE);
4404 /*-----------------------------------------------------------------*/
4405 /* genGetHbit - generates code get highest order bit */
4406 /*-----------------------------------------------------------------*/
4407 static void genGetHbit (iCode *ic)
4409 operand *left, *result;
4411 result=IC_RESULT(ic);
4412 aopOp (left,ic,FALSE);
4413 aopOp (result,ic,FALSE);
4415 /* get the highest order byte into a */
4416 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
4417 if(AOP_TYPE(result) == AOP_CRY){
4418 emitcode("rlc","a");
4423 emitcode("anl","a,#0x01");
4428 freeAsmop(left,NULL,ic,TRUE);
4429 freeAsmop(result,NULL,ic,TRUE);
4432 /*-----------------------------------------------------------------*/
4433 /* AccRol - rotate left accumulator by known count */
4434 /*-----------------------------------------------------------------*/
4435 static void AccRol (int shCount)
4437 shCount &= 0x0007; // shCount : 0..7
4449 emitcode("swap","a");
4453 emitcode("swap","a");
4456 emitcode("swap","a");
4469 /*-----------------------------------------------------------------*/
4470 /* AccLsh - left shift accumulator by known count */
4471 /*-----------------------------------------------------------------*/
4472 static void AccLsh (int shCount)
4476 emitcode("add","a,acc");
4479 emitcode("add","a,acc");
4480 emitcode("add","a,acc");
4482 /* rotate left accumulator */
4484 /* and kill the lower order bits */
4485 emitcode("anl","a,#0x%02x", SLMask[shCount]);
4490 /*-----------------------------------------------------------------*/
4491 /* AccRsh - right shift accumulator by known count */
4492 /*-----------------------------------------------------------------*/
4493 static void AccRsh (int shCount)
4498 emitcode("rrc","a");
4500 /* rotate right accumulator */
4501 AccRol(8 - shCount);
4502 /* and kill the higher order bits */
4503 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4508 /*-----------------------------------------------------------------*/
4509 /* AccSRsh - signed right shift accumulator by known count */
4510 /*-----------------------------------------------------------------*/
4511 static void AccSRsh (int shCount)
4516 emitcode("mov","c,acc.7");
4517 emitcode("rrc","a");
4518 } else if(shCount == 2){
4519 emitcode("mov","c,acc.7");
4520 emitcode("rrc","a");
4521 emitcode("mov","c,acc.7");
4522 emitcode("rrc","a");
4524 tlbl = newiTempLabel(NULL);
4525 /* rotate right accumulator */
4526 AccRol(8 - shCount);
4527 /* and kill the higher order bits */
4528 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4529 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4530 emitcode("orl","a,#0x%02x",
4531 (unsigned char)~SRMask[shCount]);
4532 emitcode("","%05d$:",tlbl->key+100);
4537 /*-----------------------------------------------------------------*/
4538 /* shiftR1Left2Result - shift right one byte from left to result */
4539 /*-----------------------------------------------------------------*/
4540 static void shiftR1Left2Result (operand *left, int offl,
4541 operand *result, int offr,
4542 int shCount, int sign)
4544 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4545 /* shift right accumulator */
4550 aopPut(AOP(result),"a",offr);
4553 /*-----------------------------------------------------------------*/
4554 /* shiftL1Left2Result - shift left one byte from left to result */
4555 /*-----------------------------------------------------------------*/
4556 static void shiftL1Left2Result (operand *left, int offl,
4557 operand *result, int offr, int shCount)
4560 l = aopGet(AOP(left),offl,FALSE,FALSE);
4562 /* shift left accumulator */
4564 aopPut(AOP(result),"a",offr);
4567 /*-----------------------------------------------------------------*/
4568 /* movLeft2Result - move byte from left to result */
4569 /*-----------------------------------------------------------------*/
4570 static void movLeft2Result (operand *left, int offl,
4571 operand *result, int offr, int sign)
4574 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
4575 l = aopGet(AOP(left),offl,FALSE,FALSE);
4577 if (*l == '@' && (IS_AOP_PREG(result))) {
4578 emitcode("mov","a,%s",l);
4579 aopPut(AOP(result),"a",offr);
4582 aopPut(AOP(result),l,offr);
4584 /* MSB sign in acc.7 ! */
4585 if(getDataSize(left) == offl+1){
4586 emitcode("mov","a,%s",l);
4587 aopPut(AOP(result),"a",offr);
4594 /*-----------------------------------------------------------------*/
4595 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
4596 /*-----------------------------------------------------------------*/
4597 static void AccAXRrl1 (char *x)
4599 emitcode("rrc","a");
4600 emitcode("xch","a,%s", x);
4601 emitcode("rrc","a");
4602 emitcode("xch","a,%s", x);
4605 /*-----------------------------------------------------------------*/
4606 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
4607 /*-----------------------------------------------------------------*/
4608 static void AccAXLrl1 (char *x)
4610 emitcode("xch","a,%s",x);
4611 emitcode("rlc","a");
4612 emitcode("xch","a,%s",x);
4613 emitcode("rlc","a");
4616 /*-----------------------------------------------------------------*/
4617 /* AccAXLsh1 - left shift a:x<-0 by 1 */
4618 /*-----------------------------------------------------------------*/
4619 static void AccAXLsh1 (char *x)
4621 emitcode("xch","a,%s",x);
4622 emitcode("add","a,acc");
4623 emitcode("xch","a,%s",x);
4624 emitcode("rlc","a");
4627 /*-----------------------------------------------------------------*/
4628 /* AccAXLsh - left shift a:x by known count (0..7) */
4629 /*-----------------------------------------------------------------*/
4630 static void AccAXLsh (char *x, int shCount)
4644 case 5 : // AAAAABBB:CCCCCDDD
4645 AccRol(shCount); // BBBAAAAA:CCCCCDDD
4646 emitcode("anl","a,#0x%02x",
4647 SLMask[shCount]); // BBB00000:CCCCCDDD
4648 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
4649 AccRol(shCount); // DDDCCCCC:BBB00000
4650 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
4651 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
4652 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
4653 emitcode("anl","a,#0x%02x",
4654 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
4655 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
4656 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
4658 case 6 : // AAAAAABB:CCCCCCDD
4659 emitcode("anl","a,#0x%02x",
4660 SRMask[shCount]); // 000000BB:CCCCCCDD
4661 emitcode("mov","c,acc.0"); // c = B
4662 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
4663 AccAXRrl1(x); // BCCCCCCD:D000000B
4664 AccAXRrl1(x); // BBCCCCCC:DD000000
4666 case 7 : // a:x <<= 7
4667 emitcode("anl","a,#0x%02x",
4668 SRMask[shCount]); // 0000000B:CCCCCCCD
4669 emitcode("mov","c,acc.0"); // c = B
4670 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
4671 AccAXRrl1(x); // BCCCCCCC:D0000000
4678 /*-----------------------------------------------------------------*/
4679 /* AccAXRsh - right shift a:x known count (0..7) */
4680 /*-----------------------------------------------------------------*/
4681 static void AccAXRsh (char *x, int shCount)
4688 AccAXRrl1(x); // 0->a:x
4692 AccAXRrl1(x); // 0->a:x
4694 AccAXRrl1(x); // 0->a:x
4698 case 5 : // AAAAABBB:CCCCCDDD = a:x
4699 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
4700 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
4701 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
4702 emitcode("anl","a,#0x%02x",
4703 SRMask[shCount]); // 000CCCCC:BBBAAAAA
4704 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
4705 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
4706 emitcode("anl","a,#0x%02x",
4707 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
4708 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
4709 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
4710 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
4712 case 6 : // AABBBBBB:CCDDDDDD
4713 emitcode("mov","c,acc.7");
4714 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
4715 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
4716 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
4717 emitcode("anl","a,#0x%02x",
4718 SRMask[shCount]); // 000000AA:BBBBBBCC
4720 case 7 : // ABBBBBBB:CDDDDDDD
4721 emitcode("mov","c,acc.7"); // c = A
4722 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
4723 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
4724 emitcode("anl","a,#0x%02x",
4725 SRMask[shCount]); // 0000000A:BBBBBBBC
4732 /*-----------------------------------------------------------------*/
4733 /* AccAXRshS - right shift signed a:x known count (0..7) */
4734 /*-----------------------------------------------------------------*/
4735 static void AccAXRshS (char *x, int shCount)
4742 emitcode("mov","c,acc.7");
4743 AccAXRrl1(x); // s->a:x
4746 emitcode("mov","c,acc.7");
4747 AccAXRrl1(x); // s->a:x
4748 emitcode("mov","c,acc.7");
4749 AccAXRrl1(x); // s->a:x
4753 case 5 : // AAAAABBB:CCCCCDDD = a:x
4754 tlbl = newiTempLabel(NULL);
4755 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
4756 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
4757 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
4758 emitcode("anl","a,#0x%02x",
4759 SRMask[shCount]); // 000CCCCC:BBBAAAAA
4760 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
4761 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
4762 emitcode("anl","a,#0x%02x",
4763 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
4764 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
4765 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
4766 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
4767 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4768 emitcode("orl","a,#0x%02x",
4769 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
4770 emitcode("","%05d$:",tlbl->key+100);
4771 break; // SSSSAAAA:BBBCCCCC
4772 case 6 : // AABBBBBB:CCDDDDDD
4773 tlbl = newiTempLabel(NULL);
4774 emitcode("mov","c,acc.7");
4775 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
4776 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
4777 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
4778 emitcode("anl","a,#0x%02x",
4779 SRMask[shCount]); // 000000AA:BBBBBBCC
4780 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4781 emitcode("orl","a,#0x%02x",
4782 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
4783 emitcode("","%05d$:",tlbl->key+100);
4785 case 7 : // ABBBBBBB:CDDDDDDD
4786 tlbl = newiTempLabel(NULL);
4787 emitcode("mov","c,acc.7"); // c = A
4788 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
4789 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
4790 emitcode("anl","a,#0x%02x",
4791 SRMask[shCount]); // 0000000A:BBBBBBBC
4792 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4793 emitcode("orl","a,#0x%02x",
4794 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
4795 emitcode("","%05d$:",tlbl->key+100);
4802 /*-----------------------------------------------------------------*/
4803 /* shiftL2Left2Result - shift left two bytes from left to result */
4804 /*-----------------------------------------------------------------*/
4805 static void shiftL2Left2Result (operand *left, int offl,
4806 operand *result, int offr, int shCount)
4808 if(sameRegs(AOP(result), AOP(left)) &&
4809 ((offl + MSB16) == offr)){
4810 /* don't crash result[offr] */
4811 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4812 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4814 movLeft2Result(left,offl, result, offr, 0);
4815 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4817 /* ax << shCount (x = lsb(result))*/
4818 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
4819 aopPut(AOP(result),"a",offr+MSB16);
4823 /*-----------------------------------------------------------------*/
4824 /* shiftR2Left2Result - shift right two bytes from left to result */
4825 /*-----------------------------------------------------------------*/
4826 static void shiftR2Left2Result (operand *left, int offl,
4827 operand *result, int offr,
4828 int shCount, int sign)
4830 if(sameRegs(AOP(result), AOP(left)) &&
4831 ((offl + MSB16) == offr)){
4832 /* don't crash result[offr] */
4833 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4834 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4836 movLeft2Result(left,offl, result, offr, 0);
4837 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4839 /* a:x >> shCount (x = lsb(result))*/
4841 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
4843 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
4844 if(getDataSize(result) > 1)
4845 aopPut(AOP(result),"a",offr+MSB16);
4848 /*-----------------------------------------------------------------*/
4849 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
4850 /*-----------------------------------------------------------------*/
4851 static void shiftLLeftOrResult (operand *left, int offl,
4852 operand *result, int offr, int shCount)
4854 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4855 /* shift left accumulator */
4857 /* or with result */
4858 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
4859 /* back to result */
4860 aopPut(AOP(result),"a",offr);
4863 /*-----------------------------------------------------------------*/
4864 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
4865 /*-----------------------------------------------------------------*/
4866 static void shiftRLeftOrResult (operand *left, int offl,
4867 operand *result, int offr, int shCount)
4869 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4870 /* shift right accumulator */
4872 /* or with result */
4873 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
4874 /* back to result */
4875 aopPut(AOP(result),"a",offr);
4878 /*-----------------------------------------------------------------*/
4879 /* genlshOne - left shift a one byte quantity by known count */
4880 /*-----------------------------------------------------------------*/
4881 static void genlshOne (operand *result, operand *left, int shCount)
4883 shiftL1Left2Result(left, LSB, result, LSB, shCount);
4886 /*-----------------------------------------------------------------*/
4887 /* genlshTwo - left shift two bytes by known amount != 0 */
4888 /*-----------------------------------------------------------------*/
4889 static void genlshTwo (operand *result,operand *left, int shCount)
4891 int size = AOP_SIZE(result);
4896 /* if shCount >= 8 */
4902 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
4904 movLeft2Result(left, LSB, result, MSB16, 0);
4906 aopPut(AOP(result),zero,LSB);
4909 /* 1 <= shCount <= 7 */
4912 shiftL1Left2Result(left, LSB, result, LSB, shCount);
4914 shiftL2Left2Result(left, LSB, result, LSB, shCount);
4918 /*-----------------------------------------------------------------*/
4919 /* shiftLLong - shift left one long from left to result */
4920 /* offl = LSB or MSB16 */
4921 /*-----------------------------------------------------------------*/
4922 static void shiftLLong (operand *left, operand *result, int offr )
4925 int size = AOP_SIZE(result);
4927 if(size >= LSB+offr){
4928 l = aopGet(AOP(left),LSB,FALSE,FALSE);
4930 emitcode("add","a,acc");
4931 if (sameRegs(AOP(left),AOP(result)) &&
4932 size >= MSB16+offr && offr != LSB )
4933 emitcode("xch","a,%s",
4934 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
4936 aopPut(AOP(result),"a",LSB+offr);
4939 if(size >= MSB16+offr){
4940 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
4941 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
4944 emitcode("rlc","a");
4945 if (sameRegs(AOP(left),AOP(result)) &&
4946 size >= MSB24+offr && offr != LSB)
4947 emitcode("xch","a,%s",
4948 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
4950 aopPut(AOP(result),"a",MSB16+offr);
4953 if(size >= MSB24+offr){
4954 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
4955 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
4958 emitcode("rlc","a");
4959 if (sameRegs(AOP(left),AOP(result)) &&
4960 size >= MSB32+offr && offr != LSB )
4961 emitcode("xch","a,%s",
4962 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
4964 aopPut(AOP(result),"a",MSB24+offr);
4967 if(size > MSB32+offr){
4968 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
4969 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
4972 emitcode("rlc","a");
4973 aopPut(AOP(result),"a",MSB32+offr);
4976 aopPut(AOP(result),zero,LSB);
4979 /*-----------------------------------------------------------------*/
4980 /* genlshFour - shift four byte by a known amount != 0 */
4981 /*-----------------------------------------------------------------*/
4982 static void genlshFour (operand *result, operand *left, int shCount)
4986 size = AOP_SIZE(result);
4988 /* if shifting more that 3 bytes */
4989 if (shCount >= 24 ) {
4992 /* lowest order of left goes to the highest
4993 order of the destination */
4994 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
4996 movLeft2Result(left, LSB, result, MSB32, 0);
4997 aopPut(AOP(result),zero,LSB);
4998 aopPut(AOP(result),zero,MSB16);
4999 aopPut(AOP(result),zero,MSB32);
5003 /* more than two bytes */
5004 else if ( shCount >= 16 ) {
5005 /* lower order two bytes goes to higher order two bytes */
5007 /* if some more remaining */
5009 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5011 movLeft2Result(left, MSB16, result, MSB32, 0);
5012 movLeft2Result(left, LSB, result, MSB24, 0);
5014 aopPut(AOP(result),zero,MSB16);
5015 aopPut(AOP(result),zero,LSB);
5019 /* if more than 1 byte */
5020 else if ( shCount >= 8 ) {
5021 /* lower order three bytes goes to higher order three bytes */
5025 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5027 movLeft2Result(left, LSB, result, MSB16, 0);
5029 else{ /* size = 4 */
5031 movLeft2Result(left, MSB24, result, MSB32, 0);
5032 movLeft2Result(left, MSB16, result, MSB24, 0);
5033 movLeft2Result(left, LSB, result, MSB16, 0);
5034 aopPut(AOP(result),zero,LSB);
5036 else if(shCount == 1)
5037 shiftLLong(left, result, MSB16);
5039 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5040 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5041 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5042 aopPut(AOP(result),zero,LSB);
5047 /* 1 <= shCount <= 7 */
5048 else if(shCount <= 2){
5049 shiftLLong(left, result, LSB);
5051 shiftLLong(result, result, LSB);
5053 /* 3 <= shCount <= 7, optimize */
5055 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5056 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5057 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5061 /*-----------------------------------------------------------------*/
5062 /* genLeftShiftLiteral - left shifting by known count */
5063 /*-----------------------------------------------------------------*/
5064 static void genLeftShiftLiteral (operand *left,
5069 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5072 freeAsmop(right,NULL,ic,TRUE);
5074 aopOp(left,ic,FALSE);
5075 aopOp(result,ic,FALSE);
5077 size = getSize(operandType(result));
5080 emitcode("; shift left ","result %d, left %d",size,
5084 /* I suppose that the left size >= result size */
5087 movLeft2Result(left, size, result, size, 0);
5091 else if(shCount >= (size * 8))
5093 aopPut(AOP(result),zero,size);
5097 genlshOne (result,left,shCount);
5102 genlshTwo (result,left,shCount);
5106 genlshFour (result,left,shCount);
5110 freeAsmop(left,NULL,ic,TRUE);
5111 freeAsmop(result,NULL,ic,TRUE);
5114 /*-----------------------------------------------------------------*/
5115 /* genLeftShift - generates code for left shifting */
5116 /*-----------------------------------------------------------------*/
5117 static void genLeftShift (iCode *ic)
5119 operand *left,*right, *result;
5122 symbol *tlbl , *tlbl1;
5124 right = IC_RIGHT(ic);
5126 result = IC_RESULT(ic);
5128 aopOp(right,ic,FALSE);
5130 /* if the shift count is known then do it
5131 as efficiently as possible */
5132 if (AOP_TYPE(right) == AOP_LIT) {
5133 genLeftShiftLiteral (left,right,result,ic);
5137 /* shift count is unknown then we have to form
5138 a loop get the loop count in B : Note: we take
5139 only the lower order byte since shifting
5140 more that 32 bits make no sense anyway, ( the
5141 largest size of an object can be only 32 bits ) */
5143 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5144 emitcode("inc","b");
5145 freeAsmop (right,NULL,ic,TRUE);
5146 aopOp(left,ic,FALSE);
5147 aopOp(result,ic,FALSE);
5149 /* now move the left to the result if they are not the
5151 if (!sameRegs(AOP(left),AOP(result)) &&
5152 AOP_SIZE(result) > 1) {
5154 size = AOP_SIZE(result);
5157 l = aopGet(AOP(left),offset,FALSE,TRUE);
5158 if (*l == '@' && (IS_AOP_PREG(result))) {
5160 emitcode("mov","a,%s",l);
5161 aopPut(AOP(result),"a",offset);
5163 aopPut(AOP(result),l,offset);
5168 tlbl = newiTempLabel(NULL);
5169 size = AOP_SIZE(result);
5171 tlbl1 = newiTempLabel(NULL);
5173 /* if it is only one byte then */
5175 symbol *tlbl1 = newiTempLabel(NULL);
5177 l = aopGet(AOP(left),0,FALSE,FALSE);
5179 emitcode("sjmp","%05d$",tlbl1->key+100);
5180 emitcode("","%05d$:",tlbl->key+100);
5181 emitcode("add","a,acc");
5182 emitcode("","%05d$:",tlbl1->key+100);
5183 emitcode("djnz","b,%05d$",tlbl->key+100);
5184 aopPut(AOP(result),"a",0);
5188 reAdjustPreg(AOP(result));
5190 emitcode("sjmp","%05d$",tlbl1->key+100);
5191 emitcode("","%05d$:",tlbl->key+100);
5192 l = aopGet(AOP(result),offset,FALSE,FALSE);
5194 emitcode("add","a,acc");
5195 aopPut(AOP(result),"a",offset++);
5197 l = aopGet(AOP(result),offset,FALSE,FALSE);
5199 emitcode("rlc","a");
5200 aopPut(AOP(result),"a",offset++);
5202 reAdjustPreg(AOP(result));
5204 emitcode("","%05d$:",tlbl1->key+100);
5205 emitcode("djnz","b,%05d$",tlbl->key+100);
5207 freeAsmop(left,NULL,ic,TRUE);
5208 freeAsmop(result,NULL,ic,TRUE);
5211 /*-----------------------------------------------------------------*/
5212 /* genrshOne - right shift a one byte quantity by known count */
5213 /*-----------------------------------------------------------------*/
5214 static void genrshOne (operand *result, operand *left,
5215 int shCount, int sign)
5217 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
5220 /*-----------------------------------------------------------------*/
5221 /* genrshTwo - right shift two bytes by known amount != 0 */
5222 /*-----------------------------------------------------------------*/
5223 static void genrshTwo (operand *result,operand *left,
5224 int shCount, int sign)
5226 /* if shCount >= 8 */
5230 shiftR1Left2Result(left, MSB16, result, LSB,
5233 movLeft2Result(left, MSB16, result, LSB, sign);
5234 addSign(result, MSB16, sign);
5237 /* 1 <= shCount <= 7 */
5239 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
5242 /*-----------------------------------------------------------------*/
5243 /* shiftRLong - shift right one long from left to result */
5244 /* offl = LSB or MSB16 */
5245 /*-----------------------------------------------------------------*/
5246 static void shiftRLong (operand *left, int offl,
5247 operand *result, int sign)
5250 emitcode("clr","c");
5251 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
5253 emitcode("mov","c,acc.7");
5254 emitcode("rrc","a");
5255 aopPut(AOP(result),"a",MSB32-offl);
5257 /* add sign of "a" */
5258 addSign(result, MSB32, sign);
5260 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
5261 emitcode("rrc","a");
5262 aopPut(AOP(result),"a",MSB24-offl);
5264 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
5265 emitcode("rrc","a");
5266 aopPut(AOP(result),"a",MSB16-offl);
5269 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
5270 emitcode("rrc","a");
5271 aopPut(AOP(result),"a",LSB);
5275 /*-----------------------------------------------------------------*/
5276 /* genrshFour - shift four byte by a known amount != 0 */
5277 /*-----------------------------------------------------------------*/
5278 static void genrshFour (operand *result, operand *left,
5279 int shCount, int sign)
5281 /* if shifting more that 3 bytes */
5282 if(shCount >= 24 ) {
5285 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
5287 movLeft2Result(left, MSB32, result, LSB, sign);
5288 addSign(result, MSB16, sign);
5290 else if(shCount >= 16){
5293 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
5295 movLeft2Result(left, MSB24, result, LSB, 0);
5296 movLeft2Result(left, MSB32, result, MSB16, sign);
5298 addSign(result, MSB24, sign);
5300 else if(shCount >= 8){
5303 shiftRLong(left, MSB16, result, sign);
5304 else if(shCount == 0){
5305 movLeft2Result(left, MSB16, result, LSB, 0);
5306 movLeft2Result(left, MSB24, result, MSB16, 0);
5307 movLeft2Result(left, MSB32, result, MSB24, sign);
5308 addSign(result, MSB32, sign);
5311 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
5312 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
5313 /* the last shift is signed */
5314 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
5315 addSign(result, MSB32, sign);
5318 else{ /* 1 <= shCount <= 7 */
5320 shiftRLong(left, LSB, result, sign);
5322 shiftRLong(result, LSB, result, sign);
5325 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
5326 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
5327 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
5332 /*-----------------------------------------------------------------*/
5333 /* genRightShiftLiteral - right shifting by known count */
5334 /*-----------------------------------------------------------------*/
5335 static void genRightShiftLiteral (operand *left,
5341 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5344 freeAsmop(right,NULL,ic,TRUE);
5346 aopOp(left,ic,FALSE);
5347 aopOp(result,ic,FALSE);
5350 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
5354 size = getDataSize(left);
5355 /* test the LEFT size !!! */
5357 /* I suppose that the left size >= result size */
5359 size = getDataSize(result);
5361 movLeft2Result(left, size, result, size, 0);
5364 else if(shCount >= (size * 8)){
5366 /* get sign in acc.7 */
5367 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
5368 addSign(result, LSB, sign);
5372 genrshOne (result,left,shCount,sign);
5376 genrshTwo (result,left,shCount,sign);
5380 genrshFour (result,left,shCount,sign);
5386 freeAsmop(left,NULL,ic,TRUE);
5387 freeAsmop(result,NULL,ic,TRUE);
5391 /*-----------------------------------------------------------------*/
5392 /* genSignedRightShift - right shift of signed number */
5393 /*-----------------------------------------------------------------*/
5394 static void genSignedRightShift (iCode *ic)
5396 operand *right, *left, *result;
5399 symbol *tlbl, *tlbl1 ;
5401 /* we do it the hard way put the shift count in b
5402 and loop thru preserving the sign */
5404 right = IC_RIGHT(ic);
5406 result = IC_RESULT(ic);
5408 aopOp(right,ic,FALSE);
5411 if ( AOP_TYPE(right) == AOP_LIT) {
5412 genRightShiftLiteral (left,right,result,ic,1);
5415 /* shift count is unknown then we have to form
5416 a loop get the loop count in B : Note: we take
5417 only the lower order byte since shifting
5418 more that 32 bits make no sense anyway, ( the
5419 largest size of an object can be only 32 bits ) */
5421 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5422 emitcode("inc","b");
5423 freeAsmop (right,NULL,ic,TRUE);
5424 aopOp(left,ic,FALSE);
5425 aopOp(result,ic,FALSE);
5427 /* now move the left to the result if they are not the
5429 if (!sameRegs(AOP(left),AOP(result)) &&
5430 AOP_SIZE(result) > 1) {
5432 size = AOP_SIZE(result);
5435 l = aopGet(AOP(left),offset,FALSE,TRUE);
5436 if (*l == '@' && IS_AOP_PREG(result)) {
5438 emitcode("mov","a,%s",l);
5439 aopPut(AOP(result),"a",offset);
5441 aopPut(AOP(result),l,offset);
5446 /* mov the highest order bit to OVR */
5447 tlbl = newiTempLabel(NULL);
5448 tlbl1= newiTempLabel(NULL);
5450 size = AOP_SIZE(result);
5452 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
5453 emitcode("rlc","a");
5454 emitcode("mov","ov,c");
5455 /* if it is only one byte then */
5457 l = aopGet(AOP(left),0,FALSE,FALSE);
5459 emitcode("sjmp","%05d$",tlbl1->key+100);
5460 emitcode("","%05d$:",tlbl->key+100);
5461 emitcode("mov","c,ov");
5462 emitcode("rrc","a");
5463 emitcode("","%05d$:",tlbl1->key+100);
5464 emitcode("djnz","b,%05d$",tlbl->key+100);
5465 aopPut(AOP(result),"a",0);
5469 reAdjustPreg(AOP(result));
5470 emitcode("sjmp","%05d$",tlbl1->key+100);
5471 emitcode("","%05d$:",tlbl->key+100);
5472 emitcode("mov","c,ov");
5474 l = aopGet(AOP(result),offset,FALSE,FALSE);
5476 emitcode("rrc","a");
5477 aopPut(AOP(result),"a",offset--);
5479 reAdjustPreg(AOP(result));
5480 emitcode("","%05d$:",tlbl1->key+100);
5481 emitcode("djnz","b,%05d$",tlbl->key+100);
5484 freeAsmop(left,NULL,ic,TRUE);
5485 freeAsmop(result,NULL,ic,TRUE);
5488 /*-----------------------------------------------------------------*/
5489 /* genRightShift - generate code for right shifting */
5490 /*-----------------------------------------------------------------*/
5491 static void genRightShift (iCode *ic)
5493 operand *right, *left, *result;
5497 symbol *tlbl, *tlbl1 ;
5499 /* if signed then we do it the hard way preserve the
5500 sign bit moving it inwards */
5501 retype = getSpec(operandType(IC_RESULT(ic)));
5503 if (!SPEC_USIGN(retype)) {
5504 genSignedRightShift (ic);
5508 /* signed & unsigned types are treated the same : i.e. the
5509 signed is NOT propagated inwards : quoting from the
5510 ANSI - standard : "for E1 >> E2, is equivalent to division
5511 by 2**E2 if unsigned or if it has a non-negative value,
5512 otherwise the result is implementation defined ", MY definition
5513 is that the sign does not get propagated */
5515 right = IC_RIGHT(ic);
5517 result = IC_RESULT(ic);
5519 aopOp(right,ic,FALSE);
5521 /* if the shift count is known then do it
5522 as efficiently as possible */
5523 if (AOP_TYPE(right) == AOP_LIT) {
5524 genRightShiftLiteral (left,right,result,ic, 0);
5528 /* shift count is unknown then we have to form
5529 a loop get the loop count in B : Note: we take
5530 only the lower order byte since shifting
5531 more that 32 bits make no sense anyway, ( the
5532 largest size of an object can be only 32 bits ) */
5534 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5535 emitcode("inc","b");
5536 freeAsmop (right,NULL,ic,TRUE);
5537 aopOp(left,ic,FALSE);
5538 aopOp(result,ic,FALSE);
5540 /* now move the left to the result if they are not the
5542 if (!sameRegs(AOP(left),AOP(result)) &&
5543 AOP_SIZE(result) > 1) {
5545 size = AOP_SIZE(result);
5548 l = aopGet(AOP(left),offset,FALSE,TRUE);
5549 if (*l == '@' && IS_AOP_PREG(result)) {
5551 emitcode("mov","a,%s",l);
5552 aopPut(AOP(result),"a",offset);
5554 aopPut(AOP(result),l,offset);
5559 tlbl = newiTempLabel(NULL);
5560 tlbl1= newiTempLabel(NULL);
5561 size = AOP_SIZE(result);
5564 /* if it is only one byte then */
5566 l = aopGet(AOP(left),0,FALSE,FALSE);
5568 emitcode("sjmp","%05d$",tlbl1->key+100);
5569 emitcode("","%05d$:",tlbl->key+100);
5571 emitcode("rrc","a");
5572 emitcode("","%05d$:",tlbl1->key+100);
5573 emitcode("djnz","b,%05d$",tlbl->key+100);
5574 aopPut(AOP(result),"a",0);
5578 reAdjustPreg(AOP(result));
5579 emitcode("sjmp","%05d$",tlbl1->key+100);
5580 emitcode("","%05d$:",tlbl->key+100);
5583 l = aopGet(AOP(result),offset,FALSE,FALSE);
5585 emitcode("rrc","a");
5586 aopPut(AOP(result),"a",offset--);
5588 reAdjustPreg(AOP(result));
5590 emitcode("","%05d$:",tlbl1->key+100);
5591 emitcode("djnz","b,%05d$",tlbl->key+100);
5594 freeAsmop(left,NULL,ic,TRUE);
5595 freeAsmop(result,NULL,ic,TRUE);
5598 /*-----------------------------------------------------------------*/
5599 /* genUnpackBits - generates code for unpacking bits */
5600 /*-----------------------------------------------------------------*/
5601 static void genUnpackBits (operand *result, char *rname, int ptype)
5608 etype = getSpec(operandType(result));
5610 /* read the first byte */
5615 emitcode("mov","a,@%s",rname);
5619 emitcode("movx","a,@%s",rname);
5623 emitcode("movx","a,@dptr");
5627 emitcode("clr","a");
5628 emitcode("movc","a","@a+dptr");
5632 emitcode("lcall","__gptrget");
5636 /* if we have bitdisplacement then it fits */
5637 /* into this byte completely or if length is */
5638 /* less than a byte */
5639 if ((shCnt = SPEC_BSTR(etype)) ||
5640 (SPEC_BLEN(etype) <= 8)) {
5642 /* shift right acc */
5645 emitcode("anl","a,#0x%02x",
5646 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
5647 aopPut(AOP(result),"a",offset);
5651 /* bit field did not fit in a byte */
5652 rlen = SPEC_BLEN(etype) - 8;
5653 aopPut(AOP(result),"a",offset++);
5660 emitcode("inc","%s",rname);
5661 emitcode("mov","a,@%s",rname);
5665 emitcode("inc","%s",rname);
5666 emitcode("movx","a,@%s",rname);
5670 emitcode("inc","dptr");
5671 emitcode("movx","a,@dptr");
5675 emitcode("clr","a");
5676 emitcode("inc","dptr");
5677 emitcode("movc","a","@a+dptr");
5681 emitcode("inc","dptr");
5682 emitcode("lcall","__gptrget");
5687 /* if we are done */
5691 aopPut(AOP(result),"a",offset++);
5696 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
5697 aopPut(AOP(result),"a",offset);
5704 /*-----------------------------------------------------------------*/
5705 /* genDataPointerGet - generates code when ptr offset is known */
5706 /*-----------------------------------------------------------------*/
5707 static void genDataPointerGet (operand *left,
5713 int size , offset = 0;
5714 aopOp(result,ic,TRUE);
5716 /* get the string representation of the name */
5717 l = aopGet(AOP(left),0,FALSE,TRUE);
5718 size = AOP_SIZE(result);
5721 sprintf(buffer,"(%s + %d)",l+1,offset);
5723 sprintf(buffer,"%s",l+1);
5724 aopPut(AOP(result),buffer,offset++);
5727 freeAsmop(left,NULL,ic,TRUE);
5728 freeAsmop(result,NULL,ic,TRUE);
5731 /*-----------------------------------------------------------------*/
5732 /* genNearPointerGet - emitcode for near pointer fetch */
5733 /*-----------------------------------------------------------------*/
5734 static void genNearPointerGet (operand *left,
5741 link *rtype, *retype;
5742 link *ltype = operandType(left);
5745 rtype = operandType(result);
5746 retype= getSpec(rtype);
5748 aopOp(left,ic,FALSE);
5750 /* if left is rematerialisable and
5751 result is not bit variable type and
5752 the left is pointer to data space i.e
5753 lower 128 bytes of space */
5754 if (AOP_TYPE(left) == AOP_IMMD &&
5755 !IS_BITVAR(retype) &&
5756 DCL_TYPE(ltype) == POINTER) {
5757 genDataPointerGet (left,result,ic);
5761 /* if the value is already in a pointer register
5762 then don't need anything more */
5763 if (!AOP_INPREG(AOP(left))) {
5764 /* otherwise get a free pointer register */
5766 preg = getFreePtr(ic,&aop,FALSE);
5767 emitcode("mov","%s,%s",
5769 aopGet(AOP(left),0,FALSE,TRUE));
5770 rname = preg->name ;
5772 rname = aopGet(AOP(left),0,FALSE,FALSE);
5774 freeAsmop(left,NULL,ic,TRUE);
5775 aopOp (result,ic,FALSE);
5777 /* if bitfield then unpack the bits */
5778 if (IS_BITVAR(retype))
5779 genUnpackBits (result,rname,POINTER);
5781 /* we have can just get the values */
5782 int size = AOP_SIZE(result);
5786 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
5788 emitcode("mov","a,@%s",rname);
5789 aopPut(AOP(result),"a",offset);
5791 sprintf(buffer,"@%s",rname);
5792 aopPut(AOP(result),buffer,offset);
5796 emitcode("inc","%s",rname);
5800 /* now some housekeeping stuff */
5802 /* we had to allocate for this iCode */
5803 freeAsmop(NULL,aop,ic,TRUE);
5805 /* we did not allocate which means left
5806 already in a pointer register, then
5807 if size > 0 && this could be used again
5808 we have to point it back to where it
5810 if (AOP_SIZE(result) > 1 &&
5811 !OP_SYMBOL(left)->remat &&
5812 ( OP_SYMBOL(left)->liveTo > ic->seq ||
5814 int size = AOP_SIZE(result) - 1;
5816 emitcode("dec","%s",rname);
5821 freeAsmop(result,NULL,ic,TRUE);
5825 /*-----------------------------------------------------------------*/
5826 /* genPagedPointerGet - emitcode for paged pointer fetch */
5827 /*-----------------------------------------------------------------*/
5828 static void genPagedPointerGet (operand *left,
5835 link *rtype, *retype;
5837 rtype = operandType(result);
5838 retype= getSpec(rtype);
5840 aopOp(left,ic,FALSE);
5842 /* if the value is already in a pointer register
5843 then don't need anything more */
5844 if (!AOP_INPREG(AOP(left))) {
5845 /* otherwise get a free pointer register */
5847 preg = getFreePtr(ic,&aop,FALSE);
5848 emitcode("mov","%s,%s",
5850 aopGet(AOP(left),0,FALSE,TRUE));
5851 rname = preg->name ;
5853 rname = aopGet(AOP(left),0,FALSE,FALSE);
5855 freeAsmop(left,NULL,ic,TRUE);
5856 aopOp (result,ic,FALSE);
5858 /* if bitfield then unpack the bits */
5859 if (IS_BITVAR(retype))
5860 genUnpackBits (result,rname,PPOINTER);
5862 /* we have can just get the values */
5863 int size = AOP_SIZE(result);
5868 emitcode("movx","a,@%s",rname);
5869 aopPut(AOP(result),"a",offset);
5874 emitcode("inc","%s",rname);
5878 /* now some housekeeping stuff */
5880 /* we had to allocate for this iCode */
5881 freeAsmop(NULL,aop,ic,TRUE);
5883 /* we did not allocate which means left
5884 already in a pointer register, then
5885 if size > 0 && this could be used again
5886 we have to point it back to where it
5888 if (AOP_SIZE(result) > 1 &&
5889 !OP_SYMBOL(left)->remat &&
5890 ( OP_SYMBOL(left)->liveTo > ic->seq ||
5892 int size = AOP_SIZE(result) - 1;
5894 emitcode("dec","%s",rname);
5899 freeAsmop(result,NULL,ic,TRUE);
5904 /*-----------------------------------------------------------------*/
5905 /* genFarPointerGet - gget value from far space */
5906 /*-----------------------------------------------------------------*/
5907 static void genFarPointerGet (operand *left,
5908 operand *result, iCode *ic)
5911 link *retype = getSpec(operandType(result));
5913 aopOp(left,ic,FALSE);
5915 /* if the operand is already in dptr
5916 then we do nothing else we move the value to dptr */
5917 if (AOP_TYPE(left) != AOP_STR) {
5918 /* if this is remateriazable */
5919 if (AOP_TYPE(left) == AOP_IMMD)
5920 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
5921 else { /* we need to get it byte by byte */
5922 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
5923 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
5924 if (options.model == MODEL_FLAT24)
5926 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
5930 /* so dptr know contains the address */
5931 freeAsmop(left,NULL,ic,TRUE);
5932 aopOp(result,ic,FALSE);
5934 /* if bit then unpack */
5935 if (IS_BITVAR(retype))
5936 genUnpackBits(result,"dptr",FPOINTER);
5938 size = AOP_SIZE(result);
5942 emitcode("movx","a,@dptr");
5943 aopPut(AOP(result),"a",offset++);
5945 emitcode("inc","dptr");
5949 freeAsmop(result,NULL,ic,TRUE);
5952 /*-----------------------------------------------------------------*/
5953 /* emitcodePointerGet - gget value from code space */
5954 /*-----------------------------------------------------------------*/
5955 static void emitcodePointerGet (operand *left,
5956 operand *result, iCode *ic)
5959 link *retype = getSpec(operandType(result));
5961 aopOp(left,ic,FALSE);
5963 /* if the operand is already in dptr
5964 then we do nothing else we move the value to dptr */
5965 if (AOP_TYPE(left) != AOP_STR) {
5966 /* if this is remateriazable */
5967 if (AOP_TYPE(left) == AOP_IMMD)
5968 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
5969 else { /* we need to get it byte by byte */
5970 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
5971 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
5972 if (options.model == MODEL_FLAT24)
5974 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
5978 /* so dptr know contains the address */
5979 freeAsmop(left,NULL,ic,TRUE);
5980 aopOp(result,ic,FALSE);
5982 /* if bit then unpack */
5983 if (IS_BITVAR(retype))
5984 genUnpackBits(result,"dptr",CPOINTER);
5986 size = AOP_SIZE(result);
5990 emitcode("clr","a");
5991 emitcode("movc","a,@a+dptr");
5992 aopPut(AOP(result),"a",offset++);
5994 emitcode("inc","dptr");
5998 freeAsmop(result,NULL,ic,TRUE);
6001 /*-----------------------------------------------------------------*/
6002 /* genGenPointerGet - gget value from generic pointer space */
6003 /*-----------------------------------------------------------------*/
6004 static void genGenPointerGet (operand *left,
6005 operand *result, iCode *ic)
6008 link *retype = getSpec(operandType(result));
6010 aopOp(left,ic,FALSE);
6012 /* if the operand is already in dptr
6013 then we do nothing else we move the value to dptr */
6014 if (AOP_TYPE(left) != AOP_STR) {
6015 /* if this is remateriazable */
6016 if (AOP_TYPE(left) == AOP_IMMD) {
6017 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6018 emitcode("mov","b,#%d",pointerCode(retype));
6020 else { /* we need to get it byte by byte */
6021 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6022 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6023 if (options.model == MODEL_FLAT24)
6025 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6026 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
6030 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
6034 /* so dptr know contains the address */
6035 freeAsmop(left,NULL,ic,TRUE);
6036 aopOp(result,ic,FALSE);
6038 /* if bit then unpack */
6039 if (IS_BITVAR(retype))
6040 genUnpackBits(result,"dptr",GPOINTER);
6042 size = AOP_SIZE(result);
6046 emitcode("lcall","__gptrget");
6047 aopPut(AOP(result),"a",offset++);
6049 emitcode("inc","dptr");
6053 freeAsmop(result,NULL,ic,TRUE);
6056 /*-----------------------------------------------------------------*/
6057 /* genPointerGet - generate code for pointer get */
6058 /*-----------------------------------------------------------------*/
6059 static void genPointerGet (iCode *ic)
6061 operand *left, *result ;
6066 result = IC_RESULT(ic) ;
6068 /* depending on the type of pointer we need to
6069 move it to the correct pointer register */
6070 type = operandType(left);
6071 etype = getSpec(type);
6072 /* if left is of type of pointer then it is simple */
6073 if (IS_PTR(type) && !IS_FUNC(type->next))
6074 p_type = DCL_TYPE(type);
6077 /* we have to go by the storage class */
6078 if (SPEC_OCLS(etype)->codesp ) {
6082 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
6085 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
6088 if (SPEC_OCLS(etype) == idata )
6094 /* now that we have the pointer type we assign
6095 the pointer values */
6100 genNearPointerGet (left,result,ic);
6104 genPagedPointerGet(left,result,ic);
6108 genFarPointerGet (left,result,ic);
6112 emitcodePointerGet (left,result,ic);
6116 genGenPointerGet (left,result,ic);
6122 /*-----------------------------------------------------------------*/
6123 /* genPackBits - generates code for packed bit storage */
6124 /*-----------------------------------------------------------------*/
6125 static void genPackBits (link *etype ,
6127 char *rname, int p_type)
6135 blen = SPEC_BLEN(etype);
6136 bstr = SPEC_BSTR(etype);
6138 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6141 /* if the bit lenth is less than or */
6142 /* it exactly fits a byte then */
6143 if (SPEC_BLEN(etype) <= 8 ) {
6144 shCount = SPEC_BSTR(etype) ;
6146 /* shift left acc */
6149 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6154 emitcode ("mov","b,a");
6155 emitcode("mov","a,@%s",rname);
6159 emitcode ("mov","b,a");
6160 emitcode("movx","a,@dptr");
6164 emitcode ("push","b");
6165 emitcode ("push","acc");
6166 emitcode ("lcall","__gptrget");
6167 emitcode ("pop","b");
6171 emitcode ("anl","a,#0x%02x",(unsigned char)
6172 ((unsigned char)(0xFF << (blen+bstr)) |
6173 (unsigned char)(0xFF >> (8-bstr)) ) );
6174 emitcode ("orl","a,b");
6175 if (p_type == GPOINTER)
6176 emitcode("pop","b");
6182 emitcode("mov","@%s,a",rname);
6186 emitcode("movx","@dptr,a");
6190 emitcode("lcall","__gptrput");
6195 if ( SPEC_BLEN(etype) <= 8 )
6198 emitcode("inc","%s",rname);
6199 rLen = SPEC_BLEN(etype) ;
6201 /* now generate for lengths greater than one byte */
6204 l = aopGet(AOP(right),offset++,FALSE,TRUE);
6214 emitcode("mov","@%s,a",rname);
6216 emitcode("mov","@%s,%s",rname,l);
6221 emitcode("movx","@dptr,a");
6226 emitcode("lcall","__gptrput");
6229 emitcode ("inc","%s",rname);
6234 /* last last was not complete */
6236 /* save the byte & read byte */
6239 emitcode ("mov","b,a");
6240 emitcode("mov","a,@%s",rname);
6244 emitcode ("mov","b,a");
6245 emitcode("movx","a,@dptr");
6249 emitcode ("push","b");
6250 emitcode ("push","acc");
6251 emitcode ("lcall","__gptrget");
6252 emitcode ("pop","b");
6256 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
6257 emitcode ("orl","a,b");
6260 if (p_type == GPOINTER)
6261 emitcode("pop","b");
6266 emitcode("mov","@%s,a",rname);
6270 emitcode("movx","@dptr,a");
6274 emitcode("lcall","__gptrput");
6278 /*-----------------------------------------------------------------*/
6279 /* genDataPointerSet - remat pointer to data space */
6280 /*-----------------------------------------------------------------*/
6281 static void genDataPointerSet(operand *right,
6285 int size, offset = 0 ;
6286 char *l, buffer[256];
6288 aopOp(right,ic,FALSE);
6290 l = aopGet(AOP(result),0,FALSE,TRUE);
6291 size = AOP_SIZE(right);
6294 sprintf(buffer,"(%s + %d)",l+1,offset);
6296 sprintf(buffer,"%s",l+1);
6297 emitcode("mov","%s,%s",buffer,
6298 aopGet(AOP(right),offset++,FALSE,FALSE));
6301 freeAsmop(right,NULL,ic,TRUE);
6302 freeAsmop(result,NULL,ic,TRUE);
6305 /*-----------------------------------------------------------------*/
6306 /* genNearPointerSet - emitcode for near pointer put */
6307 /*-----------------------------------------------------------------*/
6308 static void genNearPointerSet (operand *right,
6316 link *ptype = operandType(result);
6318 retype= getSpec(operandType(right));
6320 aopOp(result,ic,FALSE);
6322 /* if the result is rematerializable &
6323 in data space & not a bit variable */
6324 if (AOP_TYPE(result) == AOP_IMMD &&
6325 DCL_TYPE(ptype) == POINTER &&
6326 !IS_BITVAR(retype)) {
6327 genDataPointerSet (right,result,ic);
6331 /* if the value is already in a pointer register
6332 then don't need anything more */
6333 if (!AOP_INPREG(AOP(result))) {
6334 /* otherwise get a free pointer register */
6336 preg = getFreePtr(ic,&aop,FALSE);
6337 emitcode("mov","%s,%s",
6339 aopGet(AOP(result),0,FALSE,TRUE));
6340 rname = preg->name ;
6342 rname = aopGet(AOP(result),0,FALSE,FALSE);
6344 freeAsmop(result,NULL,ic,TRUE);
6345 aopOp (right,ic,FALSE);
6347 /* if bitfield then unpack the bits */
6348 if (IS_BITVAR(retype))
6349 genPackBits (retype,right,rname,POINTER);
6351 /* we have can just get the values */
6352 int size = AOP_SIZE(right);
6356 l = aopGet(AOP(right),offset,FALSE,TRUE);
6359 emitcode("mov","@%s,a",rname);
6361 emitcode("mov","@%s,%s",rname,l);
6363 emitcode("inc","%s",rname);
6368 /* now some housekeeping stuff */
6370 /* we had to allocate for this iCode */
6371 freeAsmop(NULL,aop,ic,TRUE);
6373 /* we did not allocate which means left
6374 already in a pointer register, then
6375 if size > 0 && this could be used again
6376 we have to point it back to where it
6378 if (AOP_SIZE(right) > 1 &&
6379 !OP_SYMBOL(result)->remat &&
6380 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6382 int size = AOP_SIZE(right) - 1;
6384 emitcode("dec","%s",rname);
6389 freeAsmop(right,NULL,ic,TRUE);
6394 /*-----------------------------------------------------------------*/
6395 /* genPagedPointerSet - emitcode for Paged pointer put */
6396 /*-----------------------------------------------------------------*/
6397 static void genPagedPointerSet (operand *right,
6406 retype= getSpec(operandType(right));
6408 aopOp(result,ic,FALSE);
6410 /* if the value is already in a pointer register
6411 then don't need anything more */
6412 if (!AOP_INPREG(AOP(result))) {
6413 /* otherwise get a free pointer register */
6415 preg = getFreePtr(ic,&aop,FALSE);
6416 emitcode("mov","%s,%s",
6418 aopGet(AOP(result),0,FALSE,TRUE));
6419 rname = preg->name ;
6421 rname = aopGet(AOP(result),0,FALSE,FALSE);
6423 freeAsmop(result,NULL,ic,TRUE);
6424 aopOp (right,ic,FALSE);
6426 /* if bitfield then unpack the bits */
6427 if (IS_BITVAR(retype))
6428 genPackBits (retype,right,rname,PPOINTER);
6430 /* we have can just get the values */
6431 int size = AOP_SIZE(right);
6435 l = aopGet(AOP(right),offset,FALSE,TRUE);
6438 emitcode("movx","@%s,a",rname);
6441 emitcode("inc","%s",rname);
6447 /* now some housekeeping stuff */
6449 /* we had to allocate for this iCode */
6450 freeAsmop(NULL,aop,ic,TRUE);
6452 /* we did not allocate which means left
6453 already in a pointer register, then
6454 if size > 0 && this could be used again
6455 we have to point it back to where it
6457 if (AOP_SIZE(right) > 1 &&
6458 !OP_SYMBOL(result)->remat &&
6459 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6461 int size = AOP_SIZE(right) - 1;
6463 emitcode("dec","%s",rname);
6468 freeAsmop(right,NULL,ic,TRUE);
6473 /*-----------------------------------------------------------------*/
6474 /* genFarPointerSet - set value from far space */
6475 /*-----------------------------------------------------------------*/
6476 static void genFarPointerSet (operand *right,
6477 operand *result, iCode *ic)
6480 link *retype = getSpec(operandType(right));
6482 aopOp(result,ic,FALSE);
6484 /* if the operand is already in dptr
6485 then we do nothing else we move the value to dptr */
6486 if (AOP_TYPE(result) != AOP_STR) {
6487 /* if this is remateriazable */
6488 if (AOP_TYPE(result) == AOP_IMMD)
6489 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6490 else { /* we need to get it byte by byte */
6491 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6492 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6493 if (options.model == MODEL_FLAT24)
6495 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6499 /* so dptr know contains the address */
6500 freeAsmop(result,NULL,ic,TRUE);
6501 aopOp(right,ic,FALSE);
6503 /* if bit then unpack */
6504 if (IS_BITVAR(retype))
6505 genPackBits(retype,right,"dptr",FPOINTER);
6507 size = AOP_SIZE(right);
6511 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6513 emitcode("movx","@dptr,a");
6515 emitcode("inc","dptr");
6519 freeAsmop(right,NULL,ic,TRUE);
6522 /*-----------------------------------------------------------------*/
6523 /* genGenPointerSet - set value from generic pointer space */
6524 /*-----------------------------------------------------------------*/
6525 static void genGenPointerSet (operand *right,
6526 operand *result, iCode *ic)
6529 link *retype = getSpec(operandType(right));
6531 aopOp(result,ic,FALSE);
6533 /* if the operand is already in dptr
6534 then we do nothing else we move the value to dptr */
6535 if (AOP_TYPE(result) != AOP_STR) {
6536 /* if this is remateriazable */
6537 if (AOP_TYPE(result) == AOP_IMMD) {
6538 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6539 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
6541 else { /* we need to get it byte by byte */
6542 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6543 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6544 if (options.model == MODEL_FLAT24)
6546 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6547 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
6551 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
6555 /* so dptr know contains the address */
6556 freeAsmop(result,NULL,ic,TRUE);
6557 aopOp(right,ic,FALSE);
6559 /* if bit then unpack */
6560 if (IS_BITVAR(retype))
6561 genPackBits(retype,right,"dptr",GPOINTER);
6563 size = AOP_SIZE(right);
6567 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6569 emitcode("lcall","__gptrput");
6571 emitcode("inc","dptr");
6575 freeAsmop(right,NULL,ic,TRUE);
6578 /*-----------------------------------------------------------------*/
6579 /* genPointerSet - stores the value into a pointer location */
6580 /*-----------------------------------------------------------------*/
6581 static void genPointerSet (iCode *ic)
6583 operand *right, *result ;
6587 right = IC_RIGHT(ic);
6588 result = IC_RESULT(ic) ;
6590 /* depending on the type of pointer we need to
6591 move it to the correct pointer register */
6592 type = operandType(result);
6593 etype = getSpec(type);
6594 /* if left is of type of pointer then it is simple */
6595 if (IS_PTR(type) && !IS_FUNC(type->next)) {
6596 p_type = DCL_TYPE(type);
6600 /* we have to go by the storage class */
6601 if (SPEC_OCLS(etype)->codesp ) {
6605 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
6608 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
6611 if (SPEC_OCLS(etype) == idata )
6617 /* now that we have the pointer type we assign
6618 the pointer values */
6623 genNearPointerSet (right,result,ic);
6627 genPagedPointerSet (right,result,ic);
6631 genFarPointerSet (right,result,ic);
6635 genGenPointerSet (right,result,ic);
6641 /*-----------------------------------------------------------------*/
6642 /* genIfx - generate code for Ifx statement */
6643 /*-----------------------------------------------------------------*/
6644 static void genIfx (iCode *ic, iCode *popIc)
6646 operand *cond = IC_COND(ic);
6649 aopOp(cond,ic,FALSE);
6651 /* get the value into acc */
6652 if (AOP_TYPE(cond) != AOP_CRY)
6656 /* the result is now in the accumulator */
6657 freeAsmop(cond,NULL,ic,TRUE);
6659 /* if there was something to be popped then do it */
6663 /* if the condition is a bit variable */
6664 if (isbit && IS_ITEMP(cond) &&
6666 genIfxJump(ic,SPIL_LOC(cond)->rname);
6668 if (isbit && !IS_ITEMP(cond))
6669 genIfxJump(ic,OP_SYMBOL(cond)->rname);
6676 /*-----------------------------------------------------------------*/
6677 /* genAddrOf - generates code for address of */
6678 /*-----------------------------------------------------------------*/
6679 static void genAddrOf (iCode *ic)
6681 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
6684 aopOp(IC_RESULT(ic),ic,FALSE);
6686 /* if the operand is on the stack then we
6687 need to get the stack offset of this
6690 /* if it has an offset then we need to compute
6693 emitcode("mov","a,_bp");
6694 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
6695 aopPut(AOP(IC_RESULT(ic)),"a",0);
6697 /* we can just move _bp */
6698 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
6699 /* fill the result with zero */
6700 size = AOP_SIZE(IC_RESULT(ic)) - 1;
6703 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
6708 /* object not on stack then we need the name */
6709 size = AOP_SIZE(IC_RESULT(ic));
6713 char s[SDCC_NAME_MAX];
6715 sprintf(s,"#(%s >> %d)",
6719 sprintf(s,"#%s",sym->rname);
6720 aopPut(AOP(IC_RESULT(ic)),s,offset++);
6724 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
6728 /*-----------------------------------------------------------------*/
6729 /* genFarFarAssign - assignment when both are in far space */
6730 /*-----------------------------------------------------------------*/
6731 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
6733 int size = AOP_SIZE(right);
6736 /* first push the right side on to the stack */
6738 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6740 emitcode ("push","acc");
6743 freeAsmop(right,NULL,ic,FALSE);
6744 /* now assign DPTR to result */
6745 aopOp(result,ic,FALSE);
6746 size = AOP_SIZE(result);
6748 emitcode ("pop","acc");
6749 aopPut(AOP(result),"a",--offset);
6751 freeAsmop(result,NULL,ic,FALSE);
6755 /*-----------------------------------------------------------------*/
6756 /* genAssign - generate code for assignment */
6757 /*-----------------------------------------------------------------*/
6758 static void genAssign (iCode *ic)
6760 operand *result, *right;
6762 unsigned long lit = 0L;
6764 result = IC_RESULT(ic);
6765 right = IC_RIGHT(ic) ;
6767 /* if they are the same */
6768 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
6771 aopOp(right,ic,FALSE);
6773 /* special case both in far space */
6774 if (AOP_TYPE(right) == AOP_DPTR &&
6775 IS_TRUE_SYMOP(result) &&
6776 isOperandInFarSpace(result)) {
6778 genFarFarAssign (result,right,ic);
6782 aopOp(result,ic,TRUE);
6784 /* if they are the same registers */
6785 if (sameRegs(AOP(right),AOP(result)))
6788 /* if the result is a bit */
6789 if (AOP_TYPE(result) == AOP_CRY) {
6791 /* if the right size is a literal then
6792 we know what the value is */
6793 if (AOP_TYPE(right) == AOP_LIT) {
6794 if (((int) operandLitValue(right)))
6795 aopPut(AOP(result),one,0);
6797 aopPut(AOP(result),zero,0);
6801 /* the right is also a bit variable */
6802 if (AOP_TYPE(right) == AOP_CRY) {
6803 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6804 aopPut(AOP(result),"c",0);
6810 aopPut(AOP(result),"a",0);
6814 /* bit variables done */
6816 size = AOP_SIZE(result);
6818 if(AOP_TYPE(right) == AOP_LIT)
6819 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6821 (AOP_TYPE(result) != AOP_REG) &&
6822 (AOP_TYPE(right) == AOP_LIT) &&
6823 !IS_FLOAT(operandType(right)) &&
6825 emitcode("clr","a");
6827 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
6828 aopPut(AOP(result),"a",size);
6831 aopGet(AOP(right),size,FALSE,FALSE),
6837 aopGet(AOP(right),offset,FALSE,FALSE),
6844 freeAsmop (right,NULL,ic,FALSE);
6845 freeAsmop (result,NULL,ic,TRUE);
6848 /*-----------------------------------------------------------------*/
6849 /* genJumpTab - genrates code for jump table */
6850 /*-----------------------------------------------------------------*/
6851 static void genJumpTab (iCode *ic)
6856 aopOp(IC_JTCOND(ic),ic,FALSE);
6857 /* get the condition into accumulator */
6858 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
6860 /* multiply by three */
6861 emitcode("add","a,acc");
6862 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
6863 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
6865 jtab = newiTempLabel(NULL);
6866 emitcode("mov","dptr,#%05d$",jtab->key+100);
6867 emitcode("jmp","@a+dptr");
6868 emitcode("","%05d$:",jtab->key+100);
6869 /* now generate the jump labels */
6870 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
6871 jtab = setNextItem(IC_JTLABELS(ic)))
6872 emitcode("ljmp","%05d$",jtab->key+100);
6876 /*-----------------------------------------------------------------*/
6877 /* genCast - gen code for casting */
6878 /*-----------------------------------------------------------------*/
6879 static void genCast (iCode *ic)
6881 operand *result = IC_RESULT(ic);
6882 link *ctype = operandType(IC_LEFT(ic));
6883 operand *right = IC_RIGHT(ic);
6886 /* if they are equivalent then do nothing */
6887 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
6890 aopOp(right,ic,FALSE) ;
6891 aopOp(result,ic,FALSE);
6893 /* if the result is a bit */
6894 if (AOP_TYPE(result) == AOP_CRY) {
6895 /* if the right size is a literal then
6896 we know what the value is */
6897 if (AOP_TYPE(right) == AOP_LIT) {
6898 if (((int) operandLitValue(right)))
6899 aopPut(AOP(result),one,0);
6901 aopPut(AOP(result),zero,0);
6906 /* the right is also a bit variable */
6907 if (AOP_TYPE(right) == AOP_CRY) {
6908 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6909 aopPut(AOP(result),"c",0);
6915 aopPut(AOP(result),"a",0);
6919 /* if they are the same size : or less */
6920 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
6922 /* if they are in the same place */
6923 if (sameRegs(AOP(right),AOP(result)))
6926 /* if they in different places then copy */
6927 size = AOP_SIZE(result);
6931 aopGet(AOP(right),offset,FALSE,FALSE),
6939 /* if the result is of type pointer */
6940 if (IS_PTR(ctype)) {
6943 link *type = operandType(right);
6944 link *etype = getSpec(type);
6946 /* pointer to generic pointer */
6947 if (IS_GENPTR(ctype)) {
6951 p_type = DCL_TYPE(type);
6953 /* we have to go by the storage class */
6954 if (SPEC_OCLS(etype)->codesp )
6957 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
6960 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
6963 if (SPEC_OCLS(etype) == idata )
6969 /* the first two bytes are known */
6970 size = GPTRSIZE - 1;
6974 aopGet(AOP(right),offset,FALSE,FALSE),
6978 /* the last byte depending on type */
6995 /* this should never happen */
6996 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
6997 "got unknown pointer type");
7000 aopPut(AOP(result),l, GPTRSIZE - 1);
7004 /* just copy the pointers */
7005 size = AOP_SIZE(result);
7009 aopGet(AOP(right),offset,FALSE,FALSE),
7016 /* so we now know that the size of destination is greater
7017 than the size of the source */
7018 /* we move to result for the size of source */
7019 size = AOP_SIZE(right);
7023 aopGet(AOP(right),offset,FALSE,FALSE),
7028 /* now depending on the sign of the destination */
7029 size = AOP_SIZE(result) - AOP_SIZE(right);
7030 /* if unsigned or not an integral type */
7031 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
7033 aopPut(AOP(result),zero,offset++);
7035 /* we need to extend the sign :{ */
7036 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
7039 emitcode("rlc","a");
7040 emitcode("subb","a,acc");
7042 aopPut(AOP(result),"a",offset++);
7045 /* we are done hurray !!!! */
7048 freeAsmop(right,NULL,ic,TRUE);
7049 freeAsmop(result,NULL,ic,TRUE);
7053 /*-----------------------------------------------------------------*/
7054 /* genDjnz - generate decrement & jump if not zero instrucion */
7055 /*-----------------------------------------------------------------*/
7056 static int genDjnz (iCode *ic, iCode *ifx)
7062 /* if the if condition has a false label
7063 then we cannot save */
7067 /* if the minus is not of the form
7069 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
7070 !IS_OP_LITERAL(IC_RIGHT(ic)))
7073 if (operandLitValue(IC_RIGHT(ic)) != 1)
7076 /* if the size of this greater than one then no
7078 if (getSize(operandType(IC_RESULT(ic))) > 1)
7081 /* otherwise we can save BIG */
7082 lbl = newiTempLabel(NULL);
7083 lbl1= newiTempLabel(NULL);
7085 aopOp(IC_RESULT(ic),ic,FALSE);
7087 if (IS_AOP_PREG(IC_RESULT(ic))) {
7088 emitcode("dec","%s",
7089 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7090 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7091 emitcode("jnz","%05d$",lbl->key+100);
7093 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
7096 emitcode ("sjmp","%05d$",lbl1->key+100);
7097 emitcode ("","%05d$:",lbl->key+100);
7098 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
7099 emitcode ("","%05d$:",lbl1->key+100);
7101 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7106 /*-----------------------------------------------------------------*/
7107 /* genReceive - generate code for a receive iCode */
7108 /*-----------------------------------------------------------------*/
7109 static void genReceive (iCode *ic)
7111 if (isOperandInFarSpace(IC_RESULT(ic)) &&
7112 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
7113 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
7115 int size = getSize(operandType(IC_RESULT(ic)));
7116 int offset = 4 - size;
7118 emitcode ("push","%s", (strcmp(fReturn[3 - offset],"a") ?
7119 fReturn[3 - offset] : "acc"));
7122 aopOp(IC_RESULT(ic),ic,FALSE);
7123 size = AOP_SIZE(IC_RESULT(ic));
7126 emitcode ("pop","acc");
7127 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
7132 aopOp(IC_RESULT(ic),ic,FALSE);
7134 assignResultValue(IC_RESULT(ic));
7137 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7140 /*-----------------------------------------------------------------*/
7141 /* gen51Code - generate code for 8051 based controllers */
7142 /*-----------------------------------------------------------------*/
7143 void gen51Code (iCode *lic)
7148 lineHead = lineCurr = NULL;
7150 /* if debug information required */
7151 /* if (options.debug && currFunc) { */
7153 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
7155 if (IS_STATIC(currFunc->etype))
7156 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
7158 emitcode("","G$%s$0$0 ==.",currFunc->name);
7161 /* stack pointer name */
7162 if (options.useXstack)
7168 for (ic = lic ; ic ; ic = ic->next ) {
7170 if ( cln != ic->lineno ) {
7171 if ( options.debug ) {
7173 emitcode("","C$%s$%d$%d$%d ==.",
7174 ic->filename,ic->lineno,
7175 ic->level,ic->block);
7178 emitcode(";","%s %d",ic->filename,ic->lineno);
7181 /* if the result is marked as
7182 spilt and rematerializable or code for
7183 this has already been generated then
7185 if (resultRemat(ic) || ic->generated )
7188 /* depending on the operation */
7207 /* IPOP happens only when trying to restore a
7208 spilt live range, if there is an ifx statement
7209 following this pop then the if statement might
7210 be using some of the registers being popped which
7211 would destory the contents of the register so
7212 we need to check for this condition and handle it */
7214 ic->next->op == IFX &&
7215 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
7216 genIfx (ic->next,ic);
7234 genEndFunction (ic);
7254 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
7271 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
7275 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
7282 /* note these two are xlated by algebraic equivalence
7283 during parsing SDCC.y */
7284 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7285 "got '>=' or '<=' shouldn't have come here");
7289 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
7301 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
7305 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
7309 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
7336 case GET_VALUE_AT_ADDRESS:
7341 if (POINTER_SET(ic))
7368 addSet(&_G.sendSet,ic);
7373 /* piCode(ic,stdout); */
7379 /* now we are ready to call the
7380 peep hole optimizer */
7381 if (!options.nopeep)
7382 peepHole (&lineHead);
7384 /* now do the actual printing */
7385 printLine (lineHead,codeOutFile);