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);
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 /* now push the calling address */
1746 aopOp(IC_LEFT(ic),ic,FALSE);
1748 pushSide(IC_LEFT(ic), 2);
1750 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1752 /* if send set is not empty the assign */
1756 for (sic = setFirstItem(_G.sendSet) ; sic ;
1757 sic = setNextItem(_G.sendSet)) {
1758 int size, offset = 0;
1759 aopOp(IC_LEFT(sic),sic,FALSE);
1760 size = AOP_SIZE(IC_LEFT(sic));
1762 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1764 if (strcmp(l,fReturn[offset]))
1765 emitcode("mov","%s,%s",
1770 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1776 emitcode("","%05d$:",(rlbl->key+100));
1779 /* if we need assign a result value */
1780 if ((IS_ITEMP(IC_RESULT(ic)) &&
1781 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1782 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
1783 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1786 aopOp(IC_RESULT(ic),ic,FALSE);
1789 assignResultValue(IC_RESULT(ic));
1791 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1794 /* adjust the stack for parameters if
1796 if (IC_LEFT(ic)->parmBytes) {
1798 if (IC_LEFT(ic)->parmBytes > 3) {
1799 emitcode("mov","a,%s",spname);
1800 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1801 emitcode("mov","%s,a",spname);
1803 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1804 emitcode("dec","%s",spname);
1808 /* if register bank was saved then unsave them */
1810 (SPEC_BANK(currFunc->etype) !=
1812 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1814 /* if we hade saved some registers then
1817 unsaveRegisters (ic);
1821 /*-----------------------------------------------------------------*/
1822 /* resultRemat - result is rematerializable */
1823 /*-----------------------------------------------------------------*/
1824 static int resultRemat (iCode *ic)
1826 if (SKIP_IC(ic) || ic->op == IFX)
1829 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1830 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1831 if (sym->remat && !POINTER_SET(ic))
1838 /*-----------------------------------------------------------------*/
1839 /* inExcludeList - return 1 if the string is in exclude Reg list */
1840 /*-----------------------------------------------------------------*/
1841 static bool inExcludeList(char *s)
1845 if (options.excludeRegs[i] &&
1846 strcasecmp(options.excludeRegs[i],"none") == 0)
1849 for ( i = 0 ; options.excludeRegs[i]; i++) {
1850 if (options.excludeRegs[i] &&
1851 strcasecmp(s,options.excludeRegs[i]) == 0)
1857 /*-----------------------------------------------------------------*/
1858 /* genFunction - generated code for function entry */
1859 /*-----------------------------------------------------------------*/
1860 static void genFunction (iCode *ic)
1866 /* create the function header */
1867 emitcode(";","-----------------------------------------");
1868 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1869 emitcode(";","-----------------------------------------");
1871 emitcode("","%s:",sym->rname);
1872 fetype = getSpec(operandType(IC_LEFT(ic)));
1874 /* if critical function then turn interrupts off */
1875 if (SPEC_CRTCL(fetype))
1876 emitcode("clr","ea");
1878 /* here we need to generate the equates for the
1879 register bank if required */
1880 if (SPEC_BANK(fetype) != rbank) {
1883 rbank = SPEC_BANK(fetype);
1884 for ( i = 0 ; i < mcs51_nRegs ; i++ ) {
1885 if (strcmp(regs8051[i].base,"0") == 0)
1886 emitcode("","%s = 0x%02x",
1888 8*rbank+regs8051[i].offset);
1890 emitcode ("","%s = %s + 0x%02x",
1893 8*rbank+regs8051[i].offset);
1897 /* if this is an interrupt service routine then
1898 save acc, b, dpl, dph */
1899 if (IS_ISR(sym->etype)) {
1901 if (!inExcludeList("acc"))
1902 emitcode ("push","acc");
1903 if (!inExcludeList("b"))
1904 emitcode ("push","b");
1905 if (!inExcludeList("dpl"))
1906 emitcode ("push","dpl");
1907 if (!inExcludeList("dph"))
1908 emitcode ("push","dph");
1909 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
1910 emitcode ("push", "dpx");
1911 /* if this isr has no bank i.e. is going to
1912 run with bank 0 , then we need to save more
1914 if (!SPEC_BANK(sym->etype)) {
1916 /* if this function does not call any other
1917 function then we can be economical and
1918 save only those registers that are used */
1919 if (! sym->hasFcall) {
1922 /* if any registers used */
1923 if (sym->regsUsed) {
1924 /* save the registers used */
1925 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
1926 if (bitVectBitValue(sym->regsUsed,i) ||
1927 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
1928 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
1933 /* this function has a function call cannot
1934 determines register usage so we will have the
1936 saverbank(0,ic,FALSE);
1940 /* if callee-save to be used for this function
1941 then save the registers being used in this function */
1942 if (sym->calleeSave) {
1945 /* if any registers used */
1946 if (sym->regsUsed) {
1947 /* save the registers used */
1948 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
1949 if (bitVectBitValue(sym->regsUsed,i) ||
1950 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
1951 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
1959 /* set the register bank to the desired value */
1960 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
1961 emitcode("push","psw");
1962 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
1965 if (IS_RENT(sym->etype) || options.stackAuto) {
1967 if (options.useXstack) {
1968 emitcode("mov","r0,%s",spname);
1969 emitcode("mov","a,_bp");
1970 emitcode("movx","@r0,a");
1971 emitcode("inc","%s",spname);
1974 /* set up the stack */
1975 emitcode ("push","_bp"); /* save the callers stack */
1976 emitcode ("mov","_bp,%s",spname);
1979 /* adjust the stack for the function */
1984 werror(W_STACK_OVERFLOW,sym->name);
1986 if (i > 3 && sym->recvSize < 4) {
1988 emitcode ("mov","a,sp");
1989 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
1990 emitcode ("mov","sp,a");
1995 emitcode("inc","sp");
2000 emitcode ("mov","a,_spx");
2001 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2002 emitcode ("mov","_spx,a");
2007 /*-----------------------------------------------------------------*/
2008 /* genEndFunction - generates epilogue for functions */
2009 /*-----------------------------------------------------------------*/
2010 static void genEndFunction (iCode *ic)
2012 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2014 if (IS_RENT(sym->etype) || options.stackAuto)
2015 emitcode ("mov","%s,_bp",spname);
2017 /* if use external stack but some variables were
2018 added to the local stack then decrement the
2020 if (options.useXstack && sym->stack) {
2021 emitcode("mov","a,sp");
2022 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2023 emitcode("mov","sp,a");
2027 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2028 if (options.useXstack) {
2029 emitcode("mov","r0,%s",spname);
2030 emitcode("movx","a,@r0");
2031 emitcode("mov","_bp,a");
2032 emitcode("dec","%s",spname);
2035 emitcode ("pop","_bp");
2038 /* restore the register bank */
2039 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2040 emitcode ("pop","psw");
2042 if (IS_ISR(sym->etype)) {
2044 /* now we need to restore the registers */
2045 /* if this isr has no bank i.e. is going to
2046 run with bank 0 , then we need to save more
2048 if (!SPEC_BANK(sym->etype)) {
2050 /* if this function does not call any other
2051 function then we can be economical and
2052 save only those registers that are used */
2053 if (! sym->hasFcall) {
2056 /* if any registers used */
2057 if (sym->regsUsed) {
2058 /* save the registers used */
2059 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2060 if (bitVectBitValue(sym->regsUsed,i) ||
2061 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2062 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
2067 /* this function has a function call cannot
2068 determines register usage so we will have the
2070 unsaverbank(0,ic,FALSE);
2074 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2075 emitcode ("pop", "dpx");
2076 if (!inExcludeList("dph"))
2077 emitcode ("pop","dph");
2078 if (!inExcludeList("dpl"))
2079 emitcode ("pop","dpl");
2080 if (!inExcludeList("b"))
2081 emitcode ("pop","b");
2082 if (!inExcludeList("acc"))
2083 emitcode ("pop","acc");
2085 if (SPEC_CRTCL(sym->etype))
2086 emitcode("setb","ea");
2088 /* if debug then send end of function */
2089 /* if (options.debug && currFunc) { */
2092 emitcode("","C$%s$%d$%d$%d ==.",
2093 ic->filename,currFunc->lastLine,
2094 ic->level,ic->block);
2095 if (IS_STATIC(currFunc->etype))
2096 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2098 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2102 emitcode ("reti","");
2105 if (SPEC_CRTCL(sym->etype))
2106 emitcode("setb","ea");
2108 if (sym->calleeSave) {
2111 /* if any registers used */
2112 if (sym->regsUsed) {
2113 /* save the registers used */
2114 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2115 if (bitVectBitValue(sym->regsUsed,i) ||
2116 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2117 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
2123 /* if debug then send end of function */
2124 /* if (options.debug && currFunc) { */
2127 emitcode("","C$%s$%d$%d$%d ==.",
2128 ic->filename,currFunc->lastLine,
2129 ic->level,ic->block);
2130 if (IS_STATIC(currFunc->etype))
2131 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2133 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2137 emitcode ("ret","");
2142 /*-----------------------------------------------------------------*/
2143 /* genRet - generate code for return statement */
2144 /*-----------------------------------------------------------------*/
2145 static void genRet (iCode *ic)
2147 int size,offset = 0 , pushed = 0;
2149 /* if we have no return value then
2150 just generate the "ret" */
2154 /* we have something to return then
2155 move the return value into place */
2156 aopOp(IC_LEFT(ic),ic,FALSE);
2157 size = AOP_SIZE(IC_LEFT(ic));
2161 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2162 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2164 emitcode("push","%s",l);
2167 l = aopGet(AOP(IC_LEFT(ic)),offset,
2169 if (strcmp(fReturn[offset],l))
2170 emitcode("mov","%s,%s",fReturn[offset++],l);
2177 if (strcmp(fReturn[pushed],"a"))
2178 emitcode("pop",fReturn[pushed]);
2180 emitcode("pop","acc");
2183 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2186 /* generate a jump to the return label
2187 if the next is not the return statement */
2188 if (!(ic->next && ic->next->op == LABEL &&
2189 IC_LABEL(ic->next) == returnLabel))
2191 emitcode("ljmp","%05d$",(returnLabel->key+100));
2195 /*-----------------------------------------------------------------*/
2196 /* genLabel - generates a label */
2197 /*-----------------------------------------------------------------*/
2198 static void genLabel (iCode *ic)
2200 /* special case never generate */
2201 if (IC_LABEL(ic) == entryLabel)
2204 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2207 /*-----------------------------------------------------------------*/
2208 /* genGoto - generates a ljmp */
2209 /*-----------------------------------------------------------------*/
2210 static void genGoto (iCode *ic)
2212 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2215 /*-----------------------------------------------------------------*/
2216 /* genPlusIncr :- does addition with increment if possible */
2217 /*-----------------------------------------------------------------*/
2218 static bool genPlusIncr (iCode *ic)
2220 unsigned int icount ;
2221 unsigned int size = getDataSize(IC_RESULT(ic));
2223 /* will try to generate an increment */
2224 /* if the right side is not a literal
2226 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2229 /* if the literal value of the right hand side
2230 is greater than 4 then it is not worth it */
2231 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2234 /* if increment 16 bits in register */
2235 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2238 symbol *tlbl = newiTempLabel(NULL);
2239 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2240 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2241 IS_AOP_PREG(IC_RESULT(ic)))
2242 emitcode("cjne","%s,#0x00,%05d$"
2243 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2246 emitcode("clr","a");
2247 emitcode("cjne","a,%s,%05d$"
2248 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2252 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2254 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2255 IS_AOP_PREG(IC_RESULT(ic)))
2256 emitcode("cjne","%s,#0x00,%05d$"
2257 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2260 emitcode("cjne","a,%s,%05d$"
2261 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2264 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2265 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2266 IS_AOP_PREG(IC_RESULT(ic)))
2267 emitcode("cjne","%s,#0x00,%05d$"
2268 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2271 emitcode("cjne","a,%s,%05d$"
2272 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2275 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2277 emitcode("","%05d$:",tlbl->key+100);
2281 /* if the sizes are greater than 1 then we cannot */
2282 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2283 AOP_SIZE(IC_LEFT(ic)) > 1 )
2286 /* we can if the aops of the left & result match or
2287 if they are in registers and the registers are the
2289 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2292 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2293 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2294 aopPut(AOP(IC_RESULT(ic)),"a",0);
2298 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2307 /*-----------------------------------------------------------------*/
2308 /* outBitAcc - output a bit in acc */
2309 /*-----------------------------------------------------------------*/
2310 static void outBitAcc(operand *result)
2312 symbol *tlbl = newiTempLabel(NULL);
2313 /* if the result is a bit */
2314 if (AOP_TYPE(result) == AOP_CRY){
2315 aopPut(AOP(result),"a",0);
2318 emitcode("jz","%05d$",tlbl->key+100);
2319 emitcode("mov","a,%s",one);
2320 emitcode("","%05d$:",tlbl->key+100);
2325 /*-----------------------------------------------------------------*/
2326 /* genPlusBits - generates code for addition of two bits */
2327 /*-----------------------------------------------------------------*/
2328 static void genPlusBits (iCode *ic)
2330 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2331 symbol *lbl = newiTempLabel(NULL);
2332 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2333 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2334 emitcode("cpl","c");
2335 emitcode("","%05d$:",(lbl->key+100));
2336 outBitC(IC_RESULT(ic));
2339 emitcode("clr","a");
2340 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2341 emitcode("rlc","a");
2342 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2343 emitcode("addc","a,#0x00");
2344 outAcc(IC_RESULT(ic));
2348 /*-----------------------------------------------------------------*/
2349 /* genPlus - generates code for addition */
2350 /*-----------------------------------------------------------------*/
2351 static void genPlus (iCode *ic)
2353 int size, offset = 0;
2355 /* special cases :- */
2357 aopOp (IC_LEFT(ic),ic,FALSE);
2358 aopOp (IC_RIGHT(ic),ic,FALSE);
2359 aopOp (IC_RESULT(ic),ic,TRUE);
2361 /* if literal, literal on the right or
2362 if left requires ACC or right is already
2364 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2365 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2366 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2367 operand *t = IC_RIGHT(ic);
2368 IC_RIGHT(ic) = IC_LEFT(ic);
2372 /* if both left & right are in bit
2374 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2375 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2380 /* if left in bit space & right literal */
2381 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2382 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2383 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2384 /* if result in bit space */
2385 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2386 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
2387 emitcode("cpl","c");
2388 outBitC(IC_RESULT(ic));
2390 size = getDataSize(IC_RESULT(ic));
2392 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2393 emitcode("addc","a,#00");
2394 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2400 /* if I can do an increment instead
2401 of add then GOOD for ME */
2402 if (genPlusIncr (ic) == TRUE)
2405 size = getDataSize(IC_RESULT(ic));
2408 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2409 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2411 emitcode("add","a,%s",
2412 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2414 emitcode("addc","a,%s",
2415 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2417 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2419 emitcode("add","a,%s",
2420 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2422 emitcode("addc","a,%s",
2423 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2425 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2428 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2429 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2430 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2431 aopPut(AOP(IC_RESULT(ic)),
2432 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2435 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2436 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
2437 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2438 aopPut(AOP(IC_RESULT(ic)),
2439 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2442 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2443 AOP_SIZE(IC_LEFT(ic)) < 3 &&
2444 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
2445 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2446 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2448 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2449 aopPut(AOP(IC_RESULT(ic)),buffer,2);
2452 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2453 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2454 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2457 /*-----------------------------------------------------------------*/
2458 /* genMinusDec :- does subtraction with deccrement if possible */
2459 /*-----------------------------------------------------------------*/
2460 static bool genMinusDec (iCode *ic)
2462 unsigned int icount ;
2463 unsigned int size = getDataSize(IC_RESULT(ic));
2465 /* will try to generate an increment */
2466 /* if the right side is not a literal
2468 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2471 /* if the literal value of the right hand side
2472 is greater than 4 then it is not worth it */
2473 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2476 size = getDataSize(IC_RESULT(ic));
2477 /* if decrement 16 bits in register */
2478 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2481 symbol *tlbl = newiTempLabel(NULL);
2482 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2483 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2484 IS_AOP_PREG(IC_RESULT(ic)))
2485 emitcode("cjne","%s,#0xff,%05d$"
2486 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2489 emitcode("mov","a,#0xff");
2490 emitcode("cjne","a,%s,%05d$"
2491 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2494 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2496 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2497 IS_AOP_PREG(IC_RESULT(ic)))
2498 emitcode("cjne","%s,#0xff,%05d$"
2499 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2502 emitcode("cjne","a,%s,%05d$"
2503 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2506 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2507 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2508 IS_AOP_PREG(IC_RESULT(ic)))
2509 emitcode("cjne","%s,#0xff,%05d$"
2510 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2513 emitcode("cjne","a,%s,%05d$"
2514 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2517 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2519 emitcode("","%05d$:",tlbl->key+100);
2523 /* if the sizes are greater than 1 then we cannot */
2524 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2525 AOP_SIZE(IC_LEFT(ic)) > 1 )
2528 /* we can if the aops of the left & result match or
2529 if they are in registers and the registers are the
2531 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2534 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2542 /*-----------------------------------------------------------------*/
2543 /* addSign - complete with sign */
2544 /*-----------------------------------------------------------------*/
2545 static void addSign(operand *result, int offset, int sign)
2547 int size = (getDataSize(result) - offset);
2550 emitcode("rlc","a");
2551 emitcode("subb","a,acc");
2553 aopPut(AOP(result),"a",offset++);
2556 aopPut(AOP(result),zero,offset++);
2560 /*-----------------------------------------------------------------*/
2561 /* genMinusBits - generates code for subtraction of two bits */
2562 /*-----------------------------------------------------------------*/
2563 static void genMinusBits (iCode *ic)
2565 symbol *lbl = newiTempLabel(NULL);
2566 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2567 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2568 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2569 emitcode("cpl","c");
2570 emitcode("","%05d$:",(lbl->key+100));
2571 outBitC(IC_RESULT(ic));
2574 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2575 emitcode("subb","a,acc");
2576 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
2577 emitcode("inc","a");
2578 emitcode("","%05d$:",(lbl->key+100));
2579 aopPut(AOP(IC_RESULT(ic)),"a",0);
2580 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
2584 /*-----------------------------------------------------------------*/
2585 /* genMinus - generates code for subtraction */
2586 /*-----------------------------------------------------------------*/
2587 static void genMinus (iCode *ic)
2589 int size, offset = 0;
2590 unsigned long lit = 0L;
2592 aopOp (IC_LEFT(ic),ic,FALSE);
2593 aopOp (IC_RIGHT(ic),ic,FALSE);
2594 aopOp (IC_RESULT(ic),ic,TRUE);
2596 /* special cases :- */
2597 /* if both left & right are in bit space */
2598 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2599 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2604 /* if I can do an decrement instead
2605 of subtract then GOOD for ME */
2606 if (genMinusDec (ic) == TRUE)
2609 size = getDataSize(IC_RESULT(ic));
2611 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
2615 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2619 /* if literal, add a,#-lit, else normal subb */
2621 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2622 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2623 emitcode("subb","a,%s",
2624 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2626 /* first add without previous c */
2628 emitcode("add","a,#0x%02x",
2629 (unsigned int)(lit & 0x0FFL));
2631 emitcode("addc","a,#0x%02x",
2632 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
2634 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2637 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2638 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2639 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2640 aopPut(AOP(IC_RESULT(ic)),
2641 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2644 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2645 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
2646 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2647 aopPut(AOP(IC_RESULT(ic)),
2648 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2651 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2652 AOP_SIZE(IC_LEFT(ic)) < 3 &&
2653 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
2654 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2655 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2657 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2658 aopPut(AOP(IC_RESULT(ic)),buffer,2);
2661 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2662 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2663 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2667 /*-----------------------------------------------------------------*/
2668 /* genMultbits :- multiplication of bits */
2669 /*-----------------------------------------------------------------*/
2670 static void genMultbits (operand *left,
2674 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2675 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
2680 /*-----------------------------------------------------------------*/
2681 /* genMultOneByte : 8 bit multiplication & division */
2682 /*-----------------------------------------------------------------*/
2683 static void genMultOneByte (operand *left,
2687 link *opetype = operandType(result);
2692 /* (if two literals, the value is computed before) */
2693 /* if one literal, literal on the right */
2694 if (AOP_TYPE(left) == AOP_LIT){
2700 size = AOP_SIZE(result);
2701 /* signed or unsigned */
2702 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2703 l = aopGet(AOP(left),0,FALSE,FALSE);
2705 emitcode("mul","ab");
2706 /* if result size = 1, mul signed = mul unsigned */
2707 aopPut(AOP(result),"a",0);
2709 if (SPEC_USIGN(opetype)){
2710 aopPut(AOP(result),"b",1);
2712 /* for filling the MSBs */
2713 emitcode("clr","a");
2716 emitcode("mov","a,b");
2718 /* adjust the MSB if left or right neg */
2720 /* if one literal */
2721 if (AOP_TYPE(right) == AOP_LIT){
2722 /* AND literal negative */
2723 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
2724 /* adjust MSB (c==0 after mul) */
2725 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2729 lbl = newiTempLabel(NULL);
2730 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2731 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
2732 emitcode("","%05d$:",(lbl->key+100));
2733 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2734 lbl = newiTempLabel(NULL);
2735 emitcode("jc","%05d$",(lbl->key+100));
2736 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2737 emitcode("","%05d$:",(lbl->key+100));
2740 lbl = newiTempLabel(NULL);
2741 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
2742 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
2743 emitcode("","%05d$:",(lbl->key+100));
2744 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
2745 lbl = newiTempLabel(NULL);
2746 emitcode("jc","%05d$",(lbl->key+100));
2747 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
2748 emitcode("","%05d$:",(lbl->key+100));
2750 aopPut(AOP(result),"a",1);
2753 emitcode("rlc","a");
2754 emitcode("subb","a,acc");
2761 aopPut(AOP(result),"a",offset++);
2765 /*-----------------------------------------------------------------*/
2766 /* genMult - generates code for multiplication */
2767 /*-----------------------------------------------------------------*/
2768 static void genMult (iCode *ic)
2770 operand *left = IC_LEFT(ic);
2771 operand *right = IC_RIGHT(ic);
2772 operand *result= IC_RESULT(ic);
2774 /* assign the amsops */
2775 aopOp (left,ic,FALSE);
2776 aopOp (right,ic,FALSE);
2777 aopOp (result,ic,TRUE);
2779 /* special cases first */
2781 if (AOP_TYPE(left) == AOP_CRY &&
2782 AOP_TYPE(right)== AOP_CRY) {
2783 genMultbits(left,right,result);
2787 /* if both are of size == 1 */
2788 if (AOP_SIZE(left) == 1 &&
2789 AOP_SIZE(right) == 1 ) {
2790 genMultOneByte(left,right,result);
2794 /* should have been converted to function call */
2798 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2799 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2800 freeAsmop(result,NULL,ic,TRUE);
2803 /*-----------------------------------------------------------------*/
2804 /* genDivbits :- division of bits */
2805 /*-----------------------------------------------------------------*/
2806 static void genDivbits (operand *left,
2813 /* the result must be bit */
2814 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
2815 l = aopGet(AOP(left),0,FALSE,FALSE);
2819 emitcode("div","ab");
2820 emitcode("rrc","a");
2821 aopPut(AOP(result),"c",0);
2824 /*-----------------------------------------------------------------*/
2825 /* genDivOneByte : 8 bit division */
2826 /*-----------------------------------------------------------------*/
2827 static void genDivOneByte (operand *left,
2831 link *opetype = operandType(result);
2836 size = AOP_SIZE(result) - 1;
2838 /* signed or unsigned */
2839 if (SPEC_USIGN(opetype)) {
2840 /* unsigned is easy */
2841 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2842 l = aopGet(AOP(left),0,FALSE,FALSE);
2844 emitcode("div","ab");
2845 aopPut(AOP(result),"a",0);
2847 aopPut(AOP(result),zero,offset++);
2851 /* signed is a little bit more difficult */
2853 /* save the signs of the operands */
2854 l = aopGet(AOP(left),0,FALSE,FALSE);
2856 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
2857 emitcode("push","acc"); /* save it on the stack */
2859 /* now sign adjust for both left & right */
2860 l = aopGet(AOP(right),0,FALSE,FALSE);
2862 lbl = newiTempLabel(NULL);
2863 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
2864 emitcode("cpl","a");
2865 emitcode("inc","a");
2866 emitcode("","%05d$:",(lbl->key+100));
2867 emitcode("mov","b,a");
2869 /* sign adjust left side */
2870 l = aopGet(AOP(left),0,FALSE,FALSE);
2873 lbl = newiTempLabel(NULL);
2874 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
2875 emitcode("cpl","a");
2876 emitcode("inc","a");
2877 emitcode("","%05d$:",(lbl->key+100));
2879 /* now the division */
2880 emitcode("div","ab");
2881 /* we are interested in the lower order
2883 emitcode("mov","b,a");
2884 lbl = newiTempLabel(NULL);
2885 emitcode("pop","acc");
2886 /* if there was an over flow we don't
2887 adjust the sign of the result */
2888 emitcode("jb","ov,%05d$",(lbl->key+100));
2889 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
2891 emitcode("clr","a");
2892 emitcode("subb","a,b");
2893 emitcode("mov","b,a");
2894 emitcode("","%05d$:",(lbl->key+100));
2896 /* now we are done */
2897 aopPut(AOP(result),"b",0);
2899 emitcode("mov","c,b.7");
2900 emitcode("subb","a,acc");
2903 aopPut(AOP(result),"a",offset++);
2907 /*-----------------------------------------------------------------*/
2908 /* genDiv - generates code for division */
2909 /*-----------------------------------------------------------------*/
2910 static void genDiv (iCode *ic)
2912 operand *left = IC_LEFT(ic);
2913 operand *right = IC_RIGHT(ic);
2914 operand *result= IC_RESULT(ic);
2916 /* assign the amsops */
2917 aopOp (left,ic,FALSE);
2918 aopOp (right,ic,FALSE);
2919 aopOp (result,ic,TRUE);
2921 /* special cases first */
2923 if (AOP_TYPE(left) == AOP_CRY &&
2924 AOP_TYPE(right)== AOP_CRY) {
2925 genDivbits(left,right,result);
2929 /* if both are of size == 1 */
2930 if (AOP_SIZE(left) == 1 &&
2931 AOP_SIZE(right) == 1 ) {
2932 genDivOneByte(left,right,result);
2936 /* should have been converted to function call */
2939 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2940 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2941 freeAsmop(result,NULL,ic,TRUE);
2944 /*-----------------------------------------------------------------*/
2945 /* genModbits :- modulus of bits */
2946 /*-----------------------------------------------------------------*/
2947 static void genModbits (operand *left,
2954 /* the result must be bit */
2955 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
2956 l = aopGet(AOP(left),0,FALSE,FALSE);
2960 emitcode("div","ab");
2961 emitcode("mov","a,b");
2962 emitcode("rrc","a");
2963 aopPut(AOP(result),"c",0);
2966 /*-----------------------------------------------------------------*/
2967 /* genModOneByte : 8 bit modulus */
2968 /*-----------------------------------------------------------------*/
2969 static void genModOneByte (operand *left,
2973 link *opetype = operandType(result);
2977 /* signed or unsigned */
2978 if (SPEC_USIGN(opetype)) {
2979 /* unsigned is easy */
2980 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2981 l = aopGet(AOP(left),0,FALSE,FALSE);
2983 emitcode("div","ab");
2984 aopPut(AOP(result),"b",0);
2988 /* signed is a little bit more difficult */
2990 /* save the signs of the operands */
2991 l = aopGet(AOP(left),0,FALSE,FALSE);
2994 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2995 emitcode("push","acc"); /* save it on the stack */
2997 /* now sign adjust for both left & right */
2998 l = aopGet(AOP(right),0,FALSE,FALSE);
3001 lbl = newiTempLabel(NULL);
3002 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3003 emitcode("cpl","a");
3004 emitcode("inc","a");
3005 emitcode("","%05d$:",(lbl->key+100));
3006 emitcode("mov","b,a");
3008 /* sign adjust left side */
3009 l = aopGet(AOP(left),0,FALSE,FALSE);
3012 lbl = newiTempLabel(NULL);
3013 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3014 emitcode("cpl","a");
3015 emitcode("inc","a");
3016 emitcode("","%05d$:",(lbl->key+100));
3018 /* now the multiplication */
3019 emitcode("div","ab");
3020 /* we are interested in the lower order
3022 lbl = newiTempLabel(NULL);
3023 emitcode("pop","acc");
3024 /* if there was an over flow we don't
3025 adjust the sign of the result */
3026 emitcode("jb","ov,%05d$",(lbl->key+100));
3027 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3029 emitcode("clr","a");
3030 emitcode("subb","a,b");
3031 emitcode("mov","b,a");
3032 emitcode("","%05d$:",(lbl->key+100));
3034 /* now we are done */
3035 aopPut(AOP(result),"b",0);
3039 /*-----------------------------------------------------------------*/
3040 /* genMod - generates code for division */
3041 /*-----------------------------------------------------------------*/
3042 static void genMod (iCode *ic)
3044 operand *left = IC_LEFT(ic);
3045 operand *right = IC_RIGHT(ic);
3046 operand *result= IC_RESULT(ic);
3048 /* assign the amsops */
3049 aopOp (left,ic,FALSE);
3050 aopOp (right,ic,FALSE);
3051 aopOp (result,ic,TRUE);
3053 /* special cases first */
3055 if (AOP_TYPE(left) == AOP_CRY &&
3056 AOP_TYPE(right)== AOP_CRY) {
3057 genModbits(left,right,result);
3061 /* if both are of size == 1 */
3062 if (AOP_SIZE(left) == 1 &&
3063 AOP_SIZE(right) == 1 ) {
3064 genModOneByte(left,right,result);
3068 /* should have been converted to function call */
3072 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3073 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3074 freeAsmop(result,NULL,ic,TRUE);
3077 /*-----------------------------------------------------------------*/
3078 /* genIfxJump :- will create a jump depending on the ifx */
3079 /*-----------------------------------------------------------------*/
3080 static void genIfxJump (iCode *ic, char *jval)
3083 symbol *tlbl = newiTempLabel(NULL);
3086 /* if true label then we jump if condition
3088 if ( IC_TRUE(ic) ) {
3090 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3091 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3094 /* false label is present */
3095 jlbl = IC_FALSE(ic) ;
3096 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3097 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3099 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3100 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3102 emitcode(inst,"%05d$",tlbl->key+100);
3103 emitcode("ljmp","%05d$",jlbl->key+100);
3104 emitcode("","%05d$:",tlbl->key+100);
3106 /* mark the icode as generated */
3110 /*-----------------------------------------------------------------*/
3111 /* genCmp :- greater or less than comparison */
3112 /*-----------------------------------------------------------------*/
3113 static void genCmp (operand *left,operand *right,
3114 operand *result, iCode *ifx, int sign)
3116 int size, offset = 0 ;
3117 unsigned long lit = 0L;
3119 /* if left & right are bit variables */
3120 if (AOP_TYPE(left) == AOP_CRY &&
3121 AOP_TYPE(right) == AOP_CRY ) {
3122 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3123 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3125 /* subtract right from left if at the
3126 end the carry flag is set then we know that
3127 left is greater than right */
3128 size = max(AOP_SIZE(left),AOP_SIZE(right));
3130 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3131 if((size == 1) && !sign &&
3132 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3133 symbol *lbl = newiTempLabel(NULL);
3134 emitcode("cjne","%s,%s,%05d$",
3135 aopGet(AOP(left),offset,FALSE,FALSE),
3136 aopGet(AOP(right),offset,FALSE,FALSE),
3138 emitcode("","%05d$:",lbl->key+100);
3140 if(AOP_TYPE(right) == AOP_LIT){
3141 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3142 /* optimize if(x < 0) or if(x >= 0) */
3148 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE));
3149 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3150 genIfxJump (ifx,"acc.7");
3154 emitcode("rlc","a");
3161 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3162 if (sign && size == 0) {
3163 emitcode("xrl","a,#0x80");
3164 if (AOP_TYPE(right) == AOP_LIT){
3165 unsigned long lit = (unsigned long)
3166 floatFromVal(AOP(right)->aopu.aop_lit);
3167 emitcode("subb","a,#0x%02x",
3168 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3170 emitcode("mov","b,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3171 emitcode("xrl","b,#0x80");
3172 emitcode("subb","a,b");
3175 emitcode("subb","a,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3181 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3184 /* if the result is used in the next
3185 ifx conditional branch then generate
3186 code a little differently */
3188 genIfxJump (ifx,"c");
3191 /* leave the result in acc */
3195 /*-----------------------------------------------------------------*/
3196 /* genCmpGt :- greater than comparison */
3197 /*-----------------------------------------------------------------*/
3198 static void genCmpGt (iCode *ic, iCode *ifx)
3200 operand *left, *right, *result;
3201 link *letype , *retype;
3205 right= IC_RIGHT(ic);
3206 result = IC_RESULT(ic);
3208 letype = getSpec(operandType(left));
3209 retype =getSpec(operandType(right));
3210 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3211 /* assign the amsops */
3212 aopOp (left,ic,FALSE);
3213 aopOp (right,ic,FALSE);
3214 aopOp (result,ic,TRUE);
3216 genCmp(right, left, result, ifx, sign);
3218 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3219 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3220 freeAsmop(result,NULL,ic,TRUE);
3223 /*-----------------------------------------------------------------*/
3224 /* genCmpLt - less than comparisons */
3225 /*-----------------------------------------------------------------*/
3226 static void genCmpLt (iCode *ic, iCode *ifx)
3228 operand *left, *right, *result;
3229 link *letype , *retype;
3233 right= IC_RIGHT(ic);
3234 result = IC_RESULT(ic);
3236 letype = getSpec(operandType(left));
3237 retype =getSpec(operandType(right));
3238 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3240 /* assign the amsops */
3241 aopOp (left,ic,FALSE);
3242 aopOp (right,ic,FALSE);
3243 aopOp (result,ic,TRUE);
3245 genCmp(left, right, result, ifx, sign);
3247 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3248 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3249 freeAsmop(result,NULL,ic,TRUE);
3252 /*-----------------------------------------------------------------*/
3253 /* gencjneshort - compare and jump if not equal */
3254 /*-----------------------------------------------------------------*/
3255 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3257 int size = max(AOP_SIZE(left),AOP_SIZE(right));
3259 unsigned long lit = 0L;
3261 /* if the left side is a literal or
3262 if the right is in a pointer register and left
3264 if ((AOP_TYPE(left) == AOP_LIT) ||
3265 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3270 if(AOP_TYPE(right) == AOP_LIT)
3271 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3273 /* if the right side is a literal then anything goes */
3274 if (AOP_TYPE(right) == AOP_LIT &&
3275 AOP_TYPE(left) != AOP_DIR ) {
3277 emitcode("cjne","%s,%s,%05d$",
3278 aopGet(AOP(left),offset,FALSE,FALSE),
3279 aopGet(AOP(right),offset,FALSE,FALSE),
3285 /* if the right side is in a register or in direct space or
3286 if the left is a pointer register & right is not */
3287 else if (AOP_TYPE(right) == AOP_REG ||
3288 AOP_TYPE(right) == AOP_DIR ||
3289 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3290 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3292 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3293 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3294 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
3295 emitcode("jnz","%05d$",lbl->key+100);
3297 emitcode("cjne","a,%s,%05d$",
3298 aopGet(AOP(right),offset,FALSE,TRUE),
3303 /* right is a pointer reg need both a & b */
3305 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
3307 emitcode("mov","b,%s",l);
3308 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3309 emitcode("cjne","a,b,%05d$",lbl->key+100);
3315 /*-----------------------------------------------------------------*/
3316 /* gencjne - compare and jump if not equal */
3317 /*-----------------------------------------------------------------*/
3318 static void gencjne(operand *left, operand *right, symbol *lbl)
3320 symbol *tlbl = newiTempLabel(NULL);
3322 gencjneshort(left, right, lbl);
3324 emitcode("mov","a,%s",one);
3325 emitcode("sjmp","%05d$",tlbl->key+100);
3326 emitcode("","%05d$:",lbl->key+100);
3327 emitcode("clr","a");
3328 emitcode("","%05d$:",tlbl->key+100);
3331 /*-----------------------------------------------------------------*/
3332 /* genCmpEq - generates code for equal to */
3333 /*-----------------------------------------------------------------*/
3334 static void genCmpEq (iCode *ic, iCode *ifx)
3336 operand *left, *right, *result;
3338 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3339 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3340 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3342 /* if literal, literal on the right or
3343 if the right is in a pointer register and left
3345 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
3346 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3347 operand *t = IC_RIGHT(ic);
3348 IC_RIGHT(ic) = IC_LEFT(ic);
3352 if(ifx && !AOP_SIZE(result)){
3354 /* if they are both bit variables */
3355 if (AOP_TYPE(left) == AOP_CRY &&
3356 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3357 if(AOP_TYPE(right) == AOP_LIT){
3358 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3360 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3361 emitcode("cpl","c");
3362 } else if(lit == 1L) {
3363 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3365 emitcode("clr","c");
3367 /* AOP_TYPE(right) == AOP_CRY */
3369 symbol *lbl = newiTempLabel(NULL);
3370 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3371 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3372 emitcode("cpl","c");
3373 emitcode("","%05d$:",(lbl->key+100));
3375 /* if true label then we jump if condition
3377 tlbl = newiTempLabel(NULL);
3378 if ( IC_TRUE(ifx) ) {
3379 emitcode("jnc","%05d$",tlbl->key+100);
3380 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3382 emitcode("jc","%05d$",tlbl->key+100);
3383 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3385 emitcode("","%05d$:",tlbl->key+100);
3387 tlbl = newiTempLabel(NULL);
3388 gencjneshort(left, right, tlbl);
3389 if ( IC_TRUE(ifx) ) {
3390 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3391 emitcode("","%05d$:",tlbl->key+100);
3393 symbol *lbl = newiTempLabel(NULL);
3394 emitcode("sjmp","%05d$",lbl->key+100);
3395 emitcode("","%05d$:",tlbl->key+100);
3396 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3397 emitcode("","%05d$:",lbl->key+100);
3400 /* mark the icode as generated */
3405 /* if they are both bit variables */
3406 if (AOP_TYPE(left) == AOP_CRY &&
3407 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3408 if(AOP_TYPE(right) == AOP_LIT){
3409 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3411 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3412 emitcode("cpl","c");
3413 } else if(lit == 1L) {
3414 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3416 emitcode("clr","c");
3418 /* AOP_TYPE(right) == AOP_CRY */
3420 symbol *lbl = newiTempLabel(NULL);
3421 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3422 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3423 emitcode("cpl","c");
3424 emitcode("","%05d$:",(lbl->key+100));
3427 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
3432 genIfxJump (ifx,"c");
3435 /* if the result is used in an arithmetic operation
3436 then put the result in place */
3439 gencjne(left,right,newiTempLabel(NULL));
3440 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3441 aopPut(AOP(result),"a",0);
3445 genIfxJump (ifx,"a");
3448 /* if the result is used in an arithmetic operation
3449 then put the result in place */
3450 if (AOP_TYPE(result) != AOP_CRY)
3452 /* leave the result in acc */
3456 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3457 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3458 freeAsmop(result,NULL,ic,TRUE);
3461 /*-----------------------------------------------------------------*/
3462 /* ifxForOp - returns the icode containing the ifx for operand */
3463 /*-----------------------------------------------------------------*/
3464 static iCode *ifxForOp ( operand *op, iCode *ic )
3466 /* if true symbol then needs to be assigned */
3467 if (IS_TRUE_SYMOP(op))
3470 /* if this has register type condition and
3471 the next instruction is ifx with the same operand
3472 and live to of the operand is upto the ifx only then */
3474 ic->next->op == IFX &&
3475 IC_COND(ic->next)->key == op->key &&
3476 OP_SYMBOL(op)->liveTo <= ic->next->seq )
3481 /*-----------------------------------------------------------------*/
3482 /* genAndOp - for && operation */
3483 /*-----------------------------------------------------------------*/
3484 static void genAndOp (iCode *ic)
3486 operand *left,*right, *result;
3489 /* note here that && operations that are in an
3490 if statement are taken away by backPatchLabels
3491 only those used in arthmetic operations remain */
3492 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3493 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3494 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3496 /* if both are bit variables */
3497 if (AOP_TYPE(left) == AOP_CRY &&
3498 AOP_TYPE(right) == AOP_CRY ) {
3499 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3500 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3503 tlbl = newiTempLabel(NULL);
3505 emitcode("jz","%05d$",tlbl->key+100);
3507 emitcode("","%05d$:",tlbl->key+100);
3511 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3512 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3513 freeAsmop(result,NULL,ic,TRUE);
3517 /*-----------------------------------------------------------------*/
3518 /* genOrOp - for || operation */
3519 /*-----------------------------------------------------------------*/
3520 static void genOrOp (iCode *ic)
3522 operand *left,*right, *result;
3525 /* note here that || operations that are in an
3526 if statement are taken away by backPatchLabels
3527 only those used in arthmetic operations remain */
3528 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3529 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3530 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3532 /* if both are bit variables */
3533 if (AOP_TYPE(left) == AOP_CRY &&
3534 AOP_TYPE(right) == AOP_CRY ) {
3535 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3536 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
3539 tlbl = newiTempLabel(NULL);
3541 emitcode("jnz","%05d$",tlbl->key+100);
3543 emitcode("","%05d$:",tlbl->key+100);
3547 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3548 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3549 freeAsmop(result,NULL,ic,TRUE);
3552 /*-----------------------------------------------------------------*/
3553 /* isLiteralBit - test if lit == 2^n */
3554 /*-----------------------------------------------------------------*/
3555 static int isLiteralBit(unsigned long lit)
3557 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
3558 0x100L,0x200L,0x400L,0x800L,
3559 0x1000L,0x2000L,0x4000L,0x8000L,
3560 0x10000L,0x20000L,0x40000L,0x80000L,
3561 0x100000L,0x200000L,0x400000L,0x800000L,
3562 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
3563 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
3566 for(idx = 0; idx < 32; idx++)
3572 /*-----------------------------------------------------------------*/
3573 /* continueIfTrue - */
3574 /*-----------------------------------------------------------------*/
3575 static void continueIfTrue (iCode *ic)
3578 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3582 /*-----------------------------------------------------------------*/
3584 /*-----------------------------------------------------------------*/
3585 static void jumpIfTrue (iCode *ic)
3588 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3592 /*-----------------------------------------------------------------*/
3593 /* jmpTrueOrFalse - */
3594 /*-----------------------------------------------------------------*/
3595 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
3597 // ugly but optimized by peephole
3599 symbol *nlbl = newiTempLabel(NULL);
3600 emitcode("sjmp","%05d$",nlbl->key+100);
3601 emitcode("","%05d$:",tlbl->key+100);
3602 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3603 emitcode("","%05d$:",nlbl->key+100);
3606 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3607 emitcode("","%05d$:",tlbl->key+100);
3612 /*-----------------------------------------------------------------*/
3613 /* genAnd - code for and */
3614 /*-----------------------------------------------------------------*/
3615 static void genAnd (iCode *ic, iCode *ifx)
3617 operand *left, *right, *result;
3619 unsigned long lit = 0L;
3623 aopOp((left = IC_LEFT(ic)),ic,FALSE);
3624 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3625 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3628 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3630 AOP_TYPE(left), AOP_TYPE(right));
3631 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3633 AOP_SIZE(left), AOP_SIZE(right));
3636 /* if left is a literal & right is not then exchange them */
3637 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3638 AOP_NEEDSACC(left)) {
3639 operand *tmp = right ;
3644 /* if result = right then exchange them */
3645 if(sameRegs(AOP(result),AOP(right))){
3646 operand *tmp = right ;
3651 /* if right is bit then exchange them */
3652 if (AOP_TYPE(right) == AOP_CRY &&
3653 AOP_TYPE(left) != AOP_CRY){
3654 operand *tmp = right ;
3658 if(AOP_TYPE(right) == AOP_LIT)
3659 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3661 size = AOP_SIZE(result);
3664 // result = bit & yy;
3665 if (AOP_TYPE(left) == AOP_CRY){
3666 // c = bit & literal;
3667 if(AOP_TYPE(right) == AOP_LIT){
3669 if(size && sameRegs(AOP(result),AOP(left)))
3672 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3675 if(size && (AOP_TYPE(result) == AOP_CRY)){
3676 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
3679 if((AOP_TYPE(result) == AOP_CRY) && ifx){
3683 emitcode("clr","c");
3686 if (AOP_TYPE(right) == AOP_CRY){
3688 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3689 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3692 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
3694 emitcode("rrc","a");
3695 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3703 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
3704 genIfxJump(ifx, "c");
3708 // if(val & 0xZZ) - size = 0, ifx != FALSE -
3709 // bit = val & 0xZZ - size = 1, ifx = FALSE -
3710 if((AOP_TYPE(right) == AOP_LIT) &&
3711 (AOP_TYPE(result) == AOP_CRY) &&
3712 (AOP_TYPE(left) != AOP_CRY)){
3713 int posbit = isLiteralBit(lit);
3717 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
3720 emitcode("mov","c,acc.%d",posbit&0x07);
3724 sprintf(buffer,"acc.%d",posbit&0x07);
3725 genIfxJump(ifx, buffer);
3730 symbol *tlbl = newiTempLabel(NULL);
3731 int sizel = AOP_SIZE(left);
3733 emitcode("setb","c");
3735 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
3736 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
3738 if((posbit = isLiteralBit(bytelit)) != 0)
3739 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
3741 if(bytelit != 0x0FFL)
3742 emitcode("anl","a,%s",
3743 aopGet(AOP(right),offset,FALSE,TRUE));
3744 emitcode("jnz","%05d$",tlbl->key+100);
3749 // bit = left & literal
3751 emitcode("clr","c");
3752 emitcode("","%05d$:",tlbl->key+100);
3754 // if(left & literal)
3757 jmpTrueOrFalse(ifx, tlbl);
3765 /* if left is same as result */
3766 if(sameRegs(AOP(result),AOP(left))){
3767 for(;size--; offset++) {
3768 if(AOP_TYPE(right) == AOP_LIT){
3769 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
3773 aopPut(AOP(result),zero,offset);
3775 if (IS_AOP_PREG(result)) {
3776 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3777 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
3778 aopPut(AOP(result),"a",offset);
3780 emitcode("anl","%s,%s",
3781 aopGet(AOP(left),offset,FALSE,TRUE),
3782 aopGet(AOP(right),offset,FALSE,FALSE));
3784 if (AOP_TYPE(left) == AOP_ACC)
3785 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
3787 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3788 if (IS_AOP_PREG(result)) {
3789 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
3790 aopPut(AOP(result),"a",offset);
3793 emitcode("anl","%s,a",
3794 aopGet(AOP(left),offset,FALSE,TRUE));
3799 // left & result in different registers
3800 if(AOP_TYPE(result) == AOP_CRY){
3802 // if(size), result in bit
3803 // if(!size && ifx), conditional oper: if(left & right)
3804 symbol *tlbl = newiTempLabel(NULL);
3805 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
3807 emitcode("setb","c");
3809 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3810 emitcode("anl","a,%s",
3811 aopGet(AOP(left),offset,FALSE,FALSE));
3812 emitcode("jnz","%05d$",tlbl->key+100);
3817 emitcode("","%05d$:",tlbl->key+100);
3820 jmpTrueOrFalse(ifx, tlbl);
3822 for(;(size--);offset++) {
3824 // result = left & right
3825 if(AOP_TYPE(right) == AOP_LIT){
3826 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
3828 aopGet(AOP(left),offset,FALSE,FALSE),
3831 } else if(bytelit == 0){
3832 aopPut(AOP(result),zero,offset);
3836 // faster than result <- left, anl result,right
3837 // and better if result is SFR
3838 if (AOP_TYPE(left) == AOP_ACC)
3839 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
3841 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3842 emitcode("anl","a,%s",
3843 aopGet(AOP(left),offset,FALSE,FALSE));
3845 aopPut(AOP(result),"a",offset);
3851 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3852 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3853 freeAsmop(result,NULL,ic,TRUE);
3856 /*-----------------------------------------------------------------*/
3857 /* genOr - code for or */
3858 /*-----------------------------------------------------------------*/
3859 static void genOr (iCode *ic, iCode *ifx)
3861 operand *left, *right, *result;
3863 unsigned long lit = 0L;
3865 aopOp((left = IC_LEFT(ic)),ic,FALSE);
3866 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3867 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3870 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3872 AOP_TYPE(left), AOP_TYPE(right));
3873 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3875 AOP_SIZE(left), AOP_SIZE(right));
3878 /* if left is a literal & right is not then exchange them */
3879 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3880 AOP_NEEDSACC(left)) {
3881 operand *tmp = right ;
3886 /* if result = right then exchange them */
3887 if(sameRegs(AOP(result),AOP(right))){
3888 operand *tmp = right ;
3893 /* if right is bit then exchange them */
3894 if (AOP_TYPE(right) == AOP_CRY &&
3895 AOP_TYPE(left) != AOP_CRY){
3896 operand *tmp = right ;
3900 if(AOP_TYPE(right) == AOP_LIT)
3901 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3903 size = AOP_SIZE(result);
3907 if (AOP_TYPE(left) == AOP_CRY){
3908 if(AOP_TYPE(right) == AOP_LIT){
3909 // c = bit & literal;
3911 // lit != 0 => result = 1
3912 if(AOP_TYPE(result) == AOP_CRY){
3914 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
3916 continueIfTrue(ifx);
3919 emitcode("setb","c");
3921 // lit == 0 => result = left
3922 if(size && sameRegs(AOP(result),AOP(left)))
3924 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3927 if (AOP_TYPE(right) == AOP_CRY){
3929 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3930 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
3934 symbol *tlbl = newiTempLabel(NULL);
3935 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
3936 emitcode("setb","c");
3937 emitcode("jb","%s,%05d$",
3938 AOP(left)->aopu.aop_dir,tlbl->key+100);
3940 emitcode("jnz","%05d$",tlbl->key+100);
3941 if((AOP_TYPE(result) == AOP_CRY) && ifx){
3942 jmpTrueOrFalse(ifx, tlbl);
3946 emitcode("","%05d$:",tlbl->key+100);
3955 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
3956 genIfxJump(ifx, "c");
3960 // if(val | 0xZZ) - size = 0, ifx != FALSE -
3961 // bit = val | 0xZZ - size = 1, ifx = FALSE -
3962 if((AOP_TYPE(right) == AOP_LIT) &&
3963 (AOP_TYPE(result) == AOP_CRY) &&
3964 (AOP_TYPE(left) != AOP_CRY)){
3968 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
3970 continueIfTrue(ifx);
3973 // lit = 0, result = boolean(left)
3975 emitcode("setb","c");
3978 symbol *tlbl = newiTempLabel(NULL);
3979 emitcode("jnz","%05d$",tlbl->key+100);
3981 emitcode("","%05d$:",tlbl->key+100);
3983 genIfxJump (ifx,"a");
3991 /* if left is same as result */
3992 if(sameRegs(AOP(result),AOP(left))){
3993 for(;size--; offset++) {
3994 if(AOP_TYPE(right) == AOP_LIT){
3995 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
3998 if (IS_AOP_PREG(left)) {
3999 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4000 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4001 aopPut(AOP(result),"a",offset);
4003 emitcode("orl","%s,%s",
4004 aopGet(AOP(left),offset,FALSE,TRUE),
4005 aopGet(AOP(right),offset,FALSE,FALSE));
4007 if (AOP_TYPE(left) == AOP_ACC)
4008 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4010 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4011 if (IS_AOP_PREG(left)) {
4012 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4013 aopPut(AOP(result),"a",offset);
4015 emitcode("orl","%s,a",
4016 aopGet(AOP(left),offset,FALSE,TRUE));
4021 // left & result in different registers
4022 if(AOP_TYPE(result) == AOP_CRY){
4024 // if(size), result in bit
4025 // if(!size && ifx), conditional oper: if(left | right)
4026 symbol *tlbl = newiTempLabel(NULL);
4027 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4029 emitcode("setb","c");
4031 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4032 emitcode("orl","a,%s",
4033 aopGet(AOP(left),offset,FALSE,FALSE));
4034 emitcode("jnz","%05d$",tlbl->key+100);
4039 emitcode("","%05d$:",tlbl->key+100);
4042 jmpTrueOrFalse(ifx, tlbl);
4043 } else for(;(size--);offset++){
4045 // result = left & right
4046 if(AOP_TYPE(right) == AOP_LIT){
4047 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4049 aopGet(AOP(left),offset,FALSE,FALSE),
4054 // faster than result <- left, anl result,right
4055 // and better if result is SFR
4056 if (AOP_TYPE(left) == AOP_ACC)
4057 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4059 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4060 emitcode("orl","a,%s",
4061 aopGet(AOP(left),offset,FALSE,FALSE));
4063 aopPut(AOP(result),"a",offset);
4068 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4069 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4070 freeAsmop(result,NULL,ic,TRUE);
4073 /*-----------------------------------------------------------------*/
4074 /* genXor - code for xclusive or */
4075 /*-----------------------------------------------------------------*/
4076 static void genXor (iCode *ic, iCode *ifx)
4078 operand *left, *right, *result;
4080 unsigned long lit = 0L;
4082 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4083 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4084 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4087 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4089 AOP_TYPE(left), AOP_TYPE(right));
4090 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4092 AOP_SIZE(left), AOP_SIZE(right));
4095 /* if left is a literal & right is not ||
4096 if left needs acc & right does not */
4097 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4098 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4099 operand *tmp = right ;
4104 /* if result = right then exchange them */
4105 if(sameRegs(AOP(result),AOP(right))){
4106 operand *tmp = right ;
4111 /* if right is bit then exchange them */
4112 if (AOP_TYPE(right) == AOP_CRY &&
4113 AOP_TYPE(left) != AOP_CRY){
4114 operand *tmp = right ;
4118 if(AOP_TYPE(right) == AOP_LIT)
4119 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4121 size = AOP_SIZE(result);
4125 if (AOP_TYPE(left) == AOP_CRY){
4126 if(AOP_TYPE(right) == AOP_LIT){
4127 // c = bit & literal;
4129 // lit>>1 != 0 => result = 1
4130 if(AOP_TYPE(result) == AOP_CRY){
4132 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4134 continueIfTrue(ifx);
4137 emitcode("setb","c");
4141 // lit == 0, result = left
4142 if(size && sameRegs(AOP(result),AOP(left)))
4144 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4146 // lit == 1, result = not(left)
4147 if(size && sameRegs(AOP(result),AOP(left))){
4148 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4151 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4152 emitcode("cpl","c");
4159 symbol *tlbl = newiTempLabel(NULL);
4160 if (AOP_TYPE(right) == AOP_CRY){
4162 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4165 int sizer = AOP_SIZE(right);
4167 // if val>>1 != 0, result = 1
4168 emitcode("setb","c");
4170 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
4172 // test the msb of the lsb
4173 emitcode("anl","a,#0xfe");
4174 emitcode("jnz","%05d$",tlbl->key+100);
4178 emitcode("rrc","a");
4180 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4181 emitcode("cpl","c");
4182 emitcode("","%05d$:",(tlbl->key+100));
4189 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4190 genIfxJump(ifx, "c");
4194 if(sameRegs(AOP(result),AOP(left))){
4195 /* if left is same as result */
4196 for(;size--; offset++) {
4197 if(AOP_TYPE(right) == AOP_LIT){
4198 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4201 if (IS_AOP_PREG(left)) {
4202 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4203 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4204 aopPut(AOP(result),"a",offset);
4206 emitcode("xrl","%s,%s",
4207 aopGet(AOP(left),offset,FALSE,TRUE),
4208 aopGet(AOP(right),offset,FALSE,FALSE));
4210 if (AOP_TYPE(left) == AOP_ACC)
4211 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4213 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4214 if (IS_AOP_PREG(left)) {
4215 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4216 aopPut(AOP(result),"a",offset);
4218 emitcode("xrl","%s,a",
4219 aopGet(AOP(left),offset,FALSE,TRUE));
4224 // left & result in different registers
4225 if(AOP_TYPE(result) == AOP_CRY){
4227 // if(size), result in bit
4228 // if(!size && ifx), conditional oper: if(left ^ right)
4229 symbol *tlbl = newiTempLabel(NULL);
4230 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4232 emitcode("setb","c");
4234 if((AOP_TYPE(right) == AOP_LIT) &&
4235 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4236 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4238 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4239 emitcode("xrl","a,%s",
4240 aopGet(AOP(left),offset,FALSE,FALSE));
4242 emitcode("jnz","%05d$",tlbl->key+100);
4247 emitcode("","%05d$:",tlbl->key+100);
4250 jmpTrueOrFalse(ifx, tlbl);
4251 } else for(;(size--);offset++){
4253 // result = left & right
4254 if(AOP_TYPE(right) == AOP_LIT){
4255 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4257 aopGet(AOP(left),offset,FALSE,FALSE),
4262 // faster than result <- left, anl result,right
4263 // and better if result is SFR
4264 if (AOP_TYPE(left) == AOP_ACC)
4265 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4267 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4268 emitcode("xrl","a,%s",
4269 aopGet(AOP(left),offset,FALSE,TRUE));
4271 aopPut(AOP(result),"a",offset);
4276 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4277 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4278 freeAsmop(result,NULL,ic,TRUE);
4281 /*-----------------------------------------------------------------*/
4282 /* genInline - write the inline code out */
4283 /*-----------------------------------------------------------------*/
4284 static void genInline (iCode *ic)
4286 char buffer[MAX_INLINEASM];
4290 _G.inLine += (!options.asmpeep);
4291 strcpy(buffer,IC_INLINE(ic));
4293 /* emit each line as a code */
4312 /* emitcode("",buffer); */
4313 _G.inLine -= (!options.asmpeep);
4316 /*-----------------------------------------------------------------*/
4317 /* genRRC - rotate right with carry */
4318 /*-----------------------------------------------------------------*/
4319 static void genRRC (iCode *ic)
4321 operand *left , *result ;
4322 int size, offset = 0;
4325 /* rotate right with carry */
4327 result=IC_RESULT(ic);
4328 aopOp (left,ic,FALSE);
4329 aopOp (result,ic,FALSE);
4331 /* move it to the result */
4332 size = AOP_SIZE(result);
4336 l = aopGet(AOP(left),offset,FALSE,FALSE);
4338 emitcode("rrc","a");
4339 if (AOP_SIZE(result) > 1)
4340 aopPut(AOP(result),"a",offset--);
4342 /* now we need to put the carry into the
4343 highest order byte of the result */
4344 if (AOP_SIZE(result) > 1) {
4345 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
4348 emitcode("mov","acc.7,c");
4349 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
4350 freeAsmop(left,NULL,ic,TRUE);
4351 freeAsmop(result,NULL,ic,TRUE);
4354 /*-----------------------------------------------------------------*/
4355 /* genRLC - generate code for rotate left with carry */
4356 /*-----------------------------------------------------------------*/
4357 static void genRLC (iCode *ic)
4359 operand *left , *result ;
4360 int size, offset = 0;
4363 /* rotate right with carry */
4365 result=IC_RESULT(ic);
4366 aopOp (left,ic,FALSE);
4367 aopOp (result,ic,FALSE);
4369 /* move it to the result */
4370 size = AOP_SIZE(result);
4373 l = aopGet(AOP(left),offset,FALSE,FALSE);
4375 emitcode("add","a,acc");
4376 if (AOP_SIZE(result) > 1)
4377 aopPut(AOP(result),"a",offset++);
4379 l = aopGet(AOP(left),offset,FALSE,FALSE);
4381 emitcode("rlc","a");
4382 if (AOP_SIZE(result) > 1)
4383 aopPut(AOP(result),"a",offset++);
4386 /* now we need to put the carry into the
4387 highest order byte of the result */
4388 if (AOP_SIZE(result) > 1) {
4389 l = aopGet(AOP(result),0,FALSE,FALSE);
4392 emitcode("mov","acc.0,c");
4393 aopPut(AOP(result),"a",0);
4394 freeAsmop(left,NULL,ic,TRUE);
4395 freeAsmop(result,NULL,ic,TRUE);
4398 /*-----------------------------------------------------------------*/
4399 /* genGetHbit - generates code get highest order bit */
4400 /*-----------------------------------------------------------------*/
4401 static void genGetHbit (iCode *ic)
4403 operand *left, *result;
4405 result=IC_RESULT(ic);
4406 aopOp (left,ic,FALSE);
4407 aopOp (result,ic,FALSE);
4409 /* get the highest order byte into a */
4410 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
4411 if(AOP_TYPE(result) == AOP_CRY){
4412 emitcode("rlc","a");
4417 emitcode("anl","a,#0x01");
4422 freeAsmop(left,NULL,ic,TRUE);
4423 freeAsmop(result,NULL,ic,TRUE);
4426 /*-----------------------------------------------------------------*/
4427 /* AccRol - rotate left accumulator by known count */
4428 /*-----------------------------------------------------------------*/
4429 static void AccRol (int shCount)
4431 shCount &= 0x0007; // shCount : 0..7
4443 emitcode("swap","a");
4447 emitcode("swap","a");
4450 emitcode("swap","a");
4463 /*-----------------------------------------------------------------*/
4464 /* AccLsh - left shift accumulator by known count */
4465 /*-----------------------------------------------------------------*/
4466 static void AccLsh (int shCount)
4470 emitcode("add","a,acc");
4473 emitcode("add","a,acc");
4474 emitcode("add","a,acc");
4476 /* rotate left accumulator */
4478 /* and kill the lower order bits */
4479 emitcode("anl","a,#0x%02x", SLMask[shCount]);
4484 /*-----------------------------------------------------------------*/
4485 /* AccRsh - right shift accumulator by known count */
4486 /*-----------------------------------------------------------------*/
4487 static void AccRsh (int shCount)
4492 emitcode("rrc","a");
4494 /* rotate right accumulator */
4495 AccRol(8 - shCount);
4496 /* and kill the higher order bits */
4497 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4502 /*-----------------------------------------------------------------*/
4503 /* AccSRsh - signed right shift accumulator by known count */
4504 /*-----------------------------------------------------------------*/
4505 static void AccSRsh (int shCount)
4510 emitcode("mov","c,acc.7");
4511 emitcode("rrc","a");
4512 } else if(shCount == 2){
4513 emitcode("mov","c,acc.7");
4514 emitcode("rrc","a");
4515 emitcode("mov","c,acc.7");
4516 emitcode("rrc","a");
4518 tlbl = newiTempLabel(NULL);
4519 /* rotate right accumulator */
4520 AccRol(8 - shCount);
4521 /* and kill the higher order bits */
4522 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4523 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4524 emitcode("orl","a,#0x%02x",
4525 (unsigned char)~SRMask[shCount]);
4526 emitcode("","%05d$:",tlbl->key+100);
4531 /*-----------------------------------------------------------------*/
4532 /* shiftR1Left2Result - shift right one byte from left to result */
4533 /*-----------------------------------------------------------------*/
4534 static void shiftR1Left2Result (operand *left, int offl,
4535 operand *result, int offr,
4536 int shCount, int sign)
4538 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4539 /* shift right accumulator */
4544 aopPut(AOP(result),"a",offr);
4547 /*-----------------------------------------------------------------*/
4548 /* shiftL1Left2Result - shift left one byte from left to result */
4549 /*-----------------------------------------------------------------*/
4550 static void shiftL1Left2Result (operand *left, int offl,
4551 operand *result, int offr, int shCount)
4554 l = aopGet(AOP(left),offl,FALSE,FALSE);
4556 /* shift left accumulator */
4558 aopPut(AOP(result),"a",offr);
4561 /*-----------------------------------------------------------------*/
4562 /* movLeft2Result - move byte from left to result */
4563 /*-----------------------------------------------------------------*/
4564 static void movLeft2Result (operand *left, int offl,
4565 operand *result, int offr, int sign)
4568 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
4569 l = aopGet(AOP(left),offl,FALSE,FALSE);
4571 if (*l == '@' && (IS_AOP_PREG(result))) {
4572 emitcode("mov","a,%s",l);
4573 aopPut(AOP(result),"a",offr);
4576 aopPut(AOP(result),l,offr);
4578 /* MSB sign in acc.7 ! */
4579 if(getDataSize(left) == offl+1){
4580 emitcode("mov","a,%s",l);
4581 aopPut(AOP(result),"a",offr);
4588 /*-----------------------------------------------------------------*/
4589 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
4590 /*-----------------------------------------------------------------*/
4591 static void AccAXRrl1 (char *x)
4593 emitcode("rrc","a");
4594 emitcode("xch","a,%s", x);
4595 emitcode("rrc","a");
4596 emitcode("xch","a,%s", x);
4599 /*-----------------------------------------------------------------*/
4600 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
4601 /*-----------------------------------------------------------------*/
4602 static void AccAXLrl1 (char *x)
4604 emitcode("xch","a,%s",x);
4605 emitcode("rlc","a");
4606 emitcode("xch","a,%s",x);
4607 emitcode("rlc","a");
4610 /*-----------------------------------------------------------------*/
4611 /* AccAXLsh1 - left shift a:x<-0 by 1 */
4612 /*-----------------------------------------------------------------*/
4613 static void AccAXLsh1 (char *x)
4615 emitcode("xch","a,%s",x);
4616 emitcode("add","a,acc");
4617 emitcode("xch","a,%s",x);
4618 emitcode("rlc","a");
4621 /*-----------------------------------------------------------------*/
4622 /* AccAXLsh - left shift a:x by known count (0..7) */
4623 /*-----------------------------------------------------------------*/
4624 static void AccAXLsh (char *x, int shCount)
4638 case 5 : // AAAAABBB:CCCCCDDD
4639 AccRol(shCount); // BBBAAAAA:CCCCCDDD
4640 emitcode("anl","a,#0x%02x",
4641 SLMask[shCount]); // BBB00000:CCCCCDDD
4642 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
4643 AccRol(shCount); // DDDCCCCC:BBB00000
4644 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
4645 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
4646 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
4647 emitcode("anl","a,#0x%02x",
4648 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
4649 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
4650 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
4652 case 6 : // AAAAAABB:CCCCCCDD
4653 emitcode("anl","a,#0x%02x",
4654 SRMask[shCount]); // 000000BB:CCCCCCDD
4655 emitcode("mov","c,acc.0"); // c = B
4656 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
4657 AccAXRrl1(x); // BCCCCCCD:D000000B
4658 AccAXRrl1(x); // BBCCCCCC:DD000000
4660 case 7 : // a:x <<= 7
4661 emitcode("anl","a,#0x%02x",
4662 SRMask[shCount]); // 0000000B:CCCCCCCD
4663 emitcode("mov","c,acc.0"); // c = B
4664 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
4665 AccAXRrl1(x); // BCCCCCCC:D0000000
4672 /*-----------------------------------------------------------------*/
4673 /* AccAXRsh - right shift a:x known count (0..7) */
4674 /*-----------------------------------------------------------------*/
4675 static void AccAXRsh (char *x, int shCount)
4682 AccAXRrl1(x); // 0->a:x
4686 AccAXRrl1(x); // 0->a:x
4688 AccAXRrl1(x); // 0->a:x
4692 case 5 : // AAAAABBB:CCCCCDDD = a:x
4693 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
4694 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
4695 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
4696 emitcode("anl","a,#0x%02x",
4697 SRMask[shCount]); // 000CCCCC:BBBAAAAA
4698 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
4699 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
4700 emitcode("anl","a,#0x%02x",
4701 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
4702 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
4703 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
4704 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
4706 case 6 : // AABBBBBB:CCDDDDDD
4707 emitcode("mov","c,acc.7");
4708 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
4709 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
4710 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
4711 emitcode("anl","a,#0x%02x",
4712 SRMask[shCount]); // 000000AA:BBBBBBCC
4714 case 7 : // ABBBBBBB:CDDDDDDD
4715 emitcode("mov","c,acc.7"); // c = A
4716 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
4717 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
4718 emitcode("anl","a,#0x%02x",
4719 SRMask[shCount]); // 0000000A:BBBBBBBC
4726 /*-----------------------------------------------------------------*/
4727 /* AccAXRshS - right shift signed a:x known count (0..7) */
4728 /*-----------------------------------------------------------------*/
4729 static void AccAXRshS (char *x, int shCount)
4736 emitcode("mov","c,acc.7");
4737 AccAXRrl1(x); // s->a:x
4740 emitcode("mov","c,acc.7");
4741 AccAXRrl1(x); // s->a:x
4742 emitcode("mov","c,acc.7");
4743 AccAXRrl1(x); // s->a:x
4747 case 5 : // AAAAABBB:CCCCCDDD = a:x
4748 tlbl = newiTempLabel(NULL);
4749 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
4750 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
4751 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
4752 emitcode("anl","a,#0x%02x",
4753 SRMask[shCount]); // 000CCCCC:BBBAAAAA
4754 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
4755 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
4756 emitcode("anl","a,#0x%02x",
4757 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
4758 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
4759 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
4760 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
4761 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4762 emitcode("orl","a,#0x%02x",
4763 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
4764 emitcode("","%05d$:",tlbl->key+100);
4765 break; // SSSSAAAA:BBBCCCCC
4766 case 6 : // AABBBBBB:CCDDDDDD
4767 tlbl = newiTempLabel(NULL);
4768 emitcode("mov","c,acc.7");
4769 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
4770 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
4771 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
4772 emitcode("anl","a,#0x%02x",
4773 SRMask[shCount]); // 000000AA:BBBBBBCC
4774 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4775 emitcode("orl","a,#0x%02x",
4776 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
4777 emitcode("","%05d$:",tlbl->key+100);
4779 case 7 : // ABBBBBBB:CDDDDDDD
4780 tlbl = newiTempLabel(NULL);
4781 emitcode("mov","c,acc.7"); // c = A
4782 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
4783 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
4784 emitcode("anl","a,#0x%02x",
4785 SRMask[shCount]); // 0000000A:BBBBBBBC
4786 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4787 emitcode("orl","a,#0x%02x",
4788 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
4789 emitcode("","%05d$:",tlbl->key+100);
4796 /*-----------------------------------------------------------------*/
4797 /* shiftL2Left2Result - shift left two bytes from left to result */
4798 /*-----------------------------------------------------------------*/
4799 static void shiftL2Left2Result (operand *left, int offl,
4800 operand *result, int offr, int shCount)
4802 if(sameRegs(AOP(result), AOP(left)) &&
4803 ((offl + MSB16) == offr)){
4804 /* don't crash result[offr] */
4805 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4806 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4808 movLeft2Result(left,offl, result, offr, 0);
4809 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4811 /* ax << shCount (x = lsb(result))*/
4812 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
4813 aopPut(AOP(result),"a",offr+MSB16);
4817 /*-----------------------------------------------------------------*/
4818 /* shiftR2Left2Result - shift right two bytes from left to result */
4819 /*-----------------------------------------------------------------*/
4820 static void shiftR2Left2Result (operand *left, int offl,
4821 operand *result, int offr,
4822 int shCount, int sign)
4824 if(sameRegs(AOP(result), AOP(left)) &&
4825 ((offl + MSB16) == offr)){
4826 /* don't crash result[offr] */
4827 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4828 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4830 movLeft2Result(left,offl, result, offr, 0);
4831 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4833 /* a:x >> shCount (x = lsb(result))*/
4835 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
4837 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
4838 if(getDataSize(result) > 1)
4839 aopPut(AOP(result),"a",offr+MSB16);
4842 /*-----------------------------------------------------------------*/
4843 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
4844 /*-----------------------------------------------------------------*/
4845 static void shiftLLeftOrResult (operand *left, int offl,
4846 operand *result, int offr, int shCount)
4848 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4849 /* shift left accumulator */
4851 /* or with result */
4852 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
4853 /* back to result */
4854 aopPut(AOP(result),"a",offr);
4857 /*-----------------------------------------------------------------*/
4858 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
4859 /*-----------------------------------------------------------------*/
4860 static void shiftRLeftOrResult (operand *left, int offl,
4861 operand *result, int offr, int shCount)
4863 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4864 /* shift right accumulator */
4866 /* or with result */
4867 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
4868 /* back to result */
4869 aopPut(AOP(result),"a",offr);
4872 /*-----------------------------------------------------------------*/
4873 /* genlshOne - left shift a one byte quantity by known count */
4874 /*-----------------------------------------------------------------*/
4875 static void genlshOne (operand *result, operand *left, int shCount)
4877 shiftL1Left2Result(left, LSB, result, LSB, shCount);
4880 /*-----------------------------------------------------------------*/
4881 /* genlshTwo - left shift two bytes by known amount != 0 */
4882 /*-----------------------------------------------------------------*/
4883 static void genlshTwo (operand *result,operand *left, int shCount)
4885 int size = AOP_SIZE(result);
4890 /* if shCount >= 8 */
4896 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
4898 movLeft2Result(left, LSB, result, MSB16, 0);
4900 aopPut(AOP(result),zero,LSB);
4903 /* 1 <= shCount <= 7 */
4906 shiftL1Left2Result(left, LSB, result, LSB, shCount);
4908 shiftL2Left2Result(left, LSB, result, LSB, shCount);
4912 /*-----------------------------------------------------------------*/
4913 /* shiftLLong - shift left one long from left to result */
4914 /* offl = LSB or MSB16 */
4915 /*-----------------------------------------------------------------*/
4916 static void shiftLLong (operand *left, operand *result, int offr )
4919 int size = AOP_SIZE(result);
4921 if(size >= LSB+offr){
4922 l = aopGet(AOP(left),LSB,FALSE,FALSE);
4924 emitcode("add","a,acc");
4925 if (sameRegs(AOP(left),AOP(result)) &&
4926 size >= MSB16+offr && offr != LSB )
4927 emitcode("xch","a,%s",
4928 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
4930 aopPut(AOP(result),"a",LSB+offr);
4933 if(size >= MSB16+offr){
4934 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
4935 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
4938 emitcode("rlc","a");
4939 if (sameRegs(AOP(left),AOP(result)) &&
4940 size >= MSB24+offr && offr != LSB)
4941 emitcode("xch","a,%s",
4942 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
4944 aopPut(AOP(result),"a",MSB16+offr);
4947 if(size >= MSB24+offr){
4948 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
4949 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
4952 emitcode("rlc","a");
4953 if (sameRegs(AOP(left),AOP(result)) &&
4954 size >= MSB32+offr && offr != LSB )
4955 emitcode("xch","a,%s",
4956 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
4958 aopPut(AOP(result),"a",MSB24+offr);
4961 if(size > MSB32+offr){
4962 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
4963 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
4966 emitcode("rlc","a");
4967 aopPut(AOP(result),"a",MSB32+offr);
4970 aopPut(AOP(result),zero,LSB);
4973 /*-----------------------------------------------------------------*/
4974 /* genlshFour - shift four byte by a known amount != 0 */
4975 /*-----------------------------------------------------------------*/
4976 static void genlshFour (operand *result, operand *left, int shCount)
4980 size = AOP_SIZE(result);
4982 /* if shifting more that 3 bytes */
4983 if (shCount >= 24 ) {
4986 /* lowest order of left goes to the highest
4987 order of the destination */
4988 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
4990 movLeft2Result(left, LSB, result, MSB32, 0);
4991 aopPut(AOP(result),zero,LSB);
4992 aopPut(AOP(result),zero,MSB16);
4993 aopPut(AOP(result),zero,MSB32);
4997 /* more than two bytes */
4998 else if ( shCount >= 16 ) {
4999 /* lower order two bytes goes to higher order two bytes */
5001 /* if some more remaining */
5003 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5005 movLeft2Result(left, MSB16, result, MSB32, 0);
5006 movLeft2Result(left, LSB, result, MSB24, 0);
5008 aopPut(AOP(result),zero,MSB16);
5009 aopPut(AOP(result),zero,LSB);
5013 /* if more than 1 byte */
5014 else if ( shCount >= 8 ) {
5015 /* lower order three bytes goes to higher order three bytes */
5019 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5021 movLeft2Result(left, LSB, result, MSB16, 0);
5023 else{ /* size = 4 */
5025 movLeft2Result(left, MSB24, result, MSB32, 0);
5026 movLeft2Result(left, MSB16, result, MSB24, 0);
5027 movLeft2Result(left, LSB, result, MSB16, 0);
5028 aopPut(AOP(result),zero,LSB);
5030 else if(shCount == 1)
5031 shiftLLong(left, result, MSB16);
5033 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5034 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5035 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5036 aopPut(AOP(result),zero,LSB);
5041 /* 1 <= shCount <= 7 */
5042 else if(shCount <= 2){
5043 shiftLLong(left, result, LSB);
5045 shiftLLong(result, result, LSB);
5047 /* 3 <= shCount <= 7, optimize */
5049 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5050 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5051 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5055 /*-----------------------------------------------------------------*/
5056 /* genLeftShiftLiteral - left shifting by known count */
5057 /*-----------------------------------------------------------------*/
5058 static void genLeftShiftLiteral (operand *left,
5063 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5066 freeAsmop(right,NULL,ic,TRUE);
5068 aopOp(left,ic,FALSE);
5069 aopOp(result,ic,FALSE);
5071 size = getSize(operandType(result));
5074 emitcode("; shift left ","result %d, left %d",size,
5078 /* I suppose that the left size >= result size */
5081 movLeft2Result(left, size, result, size, 0);
5085 else if(shCount >= (size * 8))
5087 aopPut(AOP(result),zero,size);
5091 genlshOne (result,left,shCount);
5096 genlshTwo (result,left,shCount);
5100 genlshFour (result,left,shCount);
5104 freeAsmop(left,NULL,ic,TRUE);
5105 freeAsmop(result,NULL,ic,TRUE);
5108 /*-----------------------------------------------------------------*/
5109 /* genLeftShift - generates code for left shifting */
5110 /*-----------------------------------------------------------------*/
5111 static void genLeftShift (iCode *ic)
5113 operand *left,*right, *result;
5116 symbol *tlbl , *tlbl1;
5118 right = IC_RIGHT(ic);
5120 result = IC_RESULT(ic);
5122 aopOp(right,ic,FALSE);
5124 /* if the shift count is known then do it
5125 as efficiently as possible */
5126 if (AOP_TYPE(right) == AOP_LIT) {
5127 genLeftShiftLiteral (left,right,result,ic);
5131 /* shift count is unknown then we have to form
5132 a loop get the loop count in B : Note: we take
5133 only the lower order byte since shifting
5134 more that 32 bits make no sense anyway, ( the
5135 largest size of an object can be only 32 bits ) */
5137 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5138 emitcode("inc","b");
5139 freeAsmop (right,NULL,ic,TRUE);
5140 aopOp(left,ic,FALSE);
5141 aopOp(result,ic,FALSE);
5143 /* now move the left to the result if they are not the
5145 if (!sameRegs(AOP(left),AOP(result)) &&
5146 AOP_SIZE(result) > 1) {
5148 size = AOP_SIZE(result);
5151 l = aopGet(AOP(left),offset,FALSE,TRUE);
5152 if (*l == '@' && (IS_AOP_PREG(result))) {
5154 emitcode("mov","a,%s",l);
5155 aopPut(AOP(result),"a",offset);
5157 aopPut(AOP(result),l,offset);
5162 tlbl = newiTempLabel(NULL);
5163 size = AOP_SIZE(result);
5165 tlbl1 = newiTempLabel(NULL);
5167 /* if it is only one byte then */
5169 symbol *tlbl1 = newiTempLabel(NULL);
5171 l = aopGet(AOP(left),0,FALSE,FALSE);
5173 emitcode("sjmp","%05d$",tlbl1->key+100);
5174 emitcode("","%05d$:",tlbl->key+100);
5175 emitcode("add","a,acc");
5176 emitcode("","%05d$:",tlbl1->key+100);
5177 emitcode("djnz","b,%05d$",tlbl->key+100);
5178 aopPut(AOP(result),"a",0);
5182 reAdjustPreg(AOP(result));
5184 emitcode("sjmp","%05d$",tlbl1->key+100);
5185 emitcode("","%05d$:",tlbl->key+100);
5186 l = aopGet(AOP(result),offset,FALSE,FALSE);
5188 emitcode("add","a,acc");
5189 aopPut(AOP(result),"a",offset++);
5191 l = aopGet(AOP(result),offset,FALSE,FALSE);
5193 emitcode("rlc","a");
5194 aopPut(AOP(result),"a",offset++);
5196 reAdjustPreg(AOP(result));
5198 emitcode("","%05d$:",tlbl1->key+100);
5199 emitcode("djnz","b,%05d$",tlbl->key+100);
5201 freeAsmop(left,NULL,ic,TRUE);
5202 freeAsmop(result,NULL,ic,TRUE);
5205 /*-----------------------------------------------------------------*/
5206 /* genrshOne - right shift a one byte quantity by known count */
5207 /*-----------------------------------------------------------------*/
5208 static void genrshOne (operand *result, operand *left,
5209 int shCount, int sign)
5211 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
5214 /*-----------------------------------------------------------------*/
5215 /* genrshTwo - right shift two bytes by known amount != 0 */
5216 /*-----------------------------------------------------------------*/
5217 static void genrshTwo (operand *result,operand *left,
5218 int shCount, int sign)
5220 /* if shCount >= 8 */
5224 shiftR1Left2Result(left, MSB16, result, LSB,
5227 movLeft2Result(left, MSB16, result, LSB, sign);
5228 addSign(result, MSB16, sign);
5231 /* 1 <= shCount <= 7 */
5233 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
5236 /*-----------------------------------------------------------------*/
5237 /* shiftRLong - shift right one long from left to result */
5238 /* offl = LSB or MSB16 */
5239 /*-----------------------------------------------------------------*/
5240 static void shiftRLong (operand *left, int offl,
5241 operand *result, int sign)
5244 emitcode("clr","c");
5245 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
5247 emitcode("mov","c,acc.7");
5248 emitcode("rrc","a");
5249 aopPut(AOP(result),"a",MSB32-offl);
5251 /* add sign of "a" */
5252 addSign(result, MSB32, sign);
5254 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
5255 emitcode("rrc","a");
5256 aopPut(AOP(result),"a",MSB24-offl);
5258 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
5259 emitcode("rrc","a");
5260 aopPut(AOP(result),"a",MSB16-offl);
5263 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
5264 emitcode("rrc","a");
5265 aopPut(AOP(result),"a",LSB);
5269 /*-----------------------------------------------------------------*/
5270 /* genrshFour - shift four byte by a known amount != 0 */
5271 /*-----------------------------------------------------------------*/
5272 static void genrshFour (operand *result, operand *left,
5273 int shCount, int sign)
5275 /* if shifting more that 3 bytes */
5276 if(shCount >= 24 ) {
5279 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
5281 movLeft2Result(left, MSB32, result, LSB, sign);
5282 addSign(result, MSB16, sign);
5284 else if(shCount >= 16){
5287 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
5289 movLeft2Result(left, MSB24, result, LSB, 0);
5290 movLeft2Result(left, MSB32, result, MSB16, sign);
5292 addSign(result, MSB24, sign);
5294 else if(shCount >= 8){
5297 shiftRLong(left, MSB16, result, sign);
5298 else if(shCount == 0){
5299 movLeft2Result(left, MSB16, result, LSB, 0);
5300 movLeft2Result(left, MSB24, result, MSB16, 0);
5301 movLeft2Result(left, MSB32, result, MSB24, sign);
5302 addSign(result, MSB32, sign);
5305 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
5306 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
5307 /* the last shift is signed */
5308 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
5309 addSign(result, MSB32, sign);
5312 else{ /* 1 <= shCount <= 7 */
5314 shiftRLong(left, LSB, result, sign);
5316 shiftRLong(result, LSB, result, sign);
5319 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
5320 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
5321 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
5326 /*-----------------------------------------------------------------*/
5327 /* genRightShiftLiteral - right shifting by known count */
5328 /*-----------------------------------------------------------------*/
5329 static void genRightShiftLiteral (operand *left,
5335 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5338 freeAsmop(right,NULL,ic,TRUE);
5340 aopOp(left,ic,FALSE);
5341 aopOp(result,ic,FALSE);
5344 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
5348 size = getDataSize(left);
5349 /* test the LEFT size !!! */
5351 /* I suppose that the left size >= result size */
5353 size = getDataSize(result);
5355 movLeft2Result(left, size, result, size, 0);
5358 else if(shCount >= (size * 8)){
5360 /* get sign in acc.7 */
5361 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
5362 addSign(result, LSB, sign);
5366 genrshOne (result,left,shCount,sign);
5370 genrshTwo (result,left,shCount,sign);
5374 genrshFour (result,left,shCount,sign);
5380 freeAsmop(left,NULL,ic,TRUE);
5381 freeAsmop(result,NULL,ic,TRUE);
5385 /*-----------------------------------------------------------------*/
5386 /* genSignedRightShift - right shift of signed number */
5387 /*-----------------------------------------------------------------*/
5388 static void genSignedRightShift (iCode *ic)
5390 operand *right, *left, *result;
5393 symbol *tlbl, *tlbl1 ;
5395 /* we do it the hard way put the shift count in b
5396 and loop thru preserving the sign */
5398 right = IC_RIGHT(ic);
5400 result = IC_RESULT(ic);
5402 aopOp(right,ic,FALSE);
5405 if ( AOP_TYPE(right) == AOP_LIT) {
5406 genRightShiftLiteral (left,right,result,ic,1);
5409 /* shift count is unknown then we have to form
5410 a loop get the loop count in B : Note: we take
5411 only the lower order byte since shifting
5412 more that 32 bits make no sense anyway, ( the
5413 largest size of an object can be only 32 bits ) */
5415 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5416 emitcode("inc","b");
5417 freeAsmop (right,NULL,ic,TRUE);
5418 aopOp(left,ic,FALSE);
5419 aopOp(result,ic,FALSE);
5421 /* now move the left to the result if they are not the
5423 if (!sameRegs(AOP(left),AOP(result)) &&
5424 AOP_SIZE(result) > 1) {
5426 size = AOP_SIZE(result);
5429 l = aopGet(AOP(left),offset,FALSE,TRUE);
5430 if (*l == '@' && IS_AOP_PREG(result)) {
5432 emitcode("mov","a,%s",l);
5433 aopPut(AOP(result),"a",offset);
5435 aopPut(AOP(result),l,offset);
5440 /* mov the highest order bit to OVR */
5441 tlbl = newiTempLabel(NULL);
5442 tlbl1= newiTempLabel(NULL);
5444 size = AOP_SIZE(result);
5446 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
5447 emitcode("rlc","a");
5448 emitcode("mov","ov,c");
5449 /* if it is only one byte then */
5451 l = aopGet(AOP(left),0,FALSE,FALSE);
5453 emitcode("sjmp","%05d$",tlbl1->key+100);
5454 emitcode("","%05d$:",tlbl->key+100);
5455 emitcode("mov","c,ov");
5456 emitcode("rrc","a");
5457 emitcode("","%05d$:",tlbl1->key+100);
5458 emitcode("djnz","b,%05d$",tlbl->key+100);
5459 aopPut(AOP(result),"a",0);
5463 reAdjustPreg(AOP(result));
5464 emitcode("sjmp","%05d$",tlbl1->key+100);
5465 emitcode("","%05d$:",tlbl->key+100);
5466 emitcode("mov","c,ov");
5468 l = aopGet(AOP(result),offset,FALSE,FALSE);
5470 emitcode("rrc","a");
5471 aopPut(AOP(result),"a",offset--);
5473 reAdjustPreg(AOP(result));
5474 emitcode("","%05d$:",tlbl1->key+100);
5475 emitcode("djnz","b,%05d$",tlbl->key+100);
5478 freeAsmop(left,NULL,ic,TRUE);
5479 freeAsmop(result,NULL,ic,TRUE);
5482 /*-----------------------------------------------------------------*/
5483 /* genRightShift - generate code for right shifting */
5484 /*-----------------------------------------------------------------*/
5485 static void genRightShift (iCode *ic)
5487 operand *right, *left, *result;
5491 symbol *tlbl, *tlbl1 ;
5493 /* if signed then we do it the hard way preserve the
5494 sign bit moving it inwards */
5495 retype = getSpec(operandType(IC_RESULT(ic)));
5497 if (!SPEC_USIGN(retype)) {
5498 genSignedRightShift (ic);
5502 /* signed & unsigned types are treated the same : i.e. the
5503 signed is NOT propagated inwards : quoting from the
5504 ANSI - standard : "for E1 >> E2, is equivalent to division
5505 by 2**E2 if unsigned or if it has a non-negative value,
5506 otherwise the result is implementation defined ", MY definition
5507 is that the sign does not get propagated */
5509 right = IC_RIGHT(ic);
5511 result = IC_RESULT(ic);
5513 aopOp(right,ic,FALSE);
5515 /* if the shift count is known then do it
5516 as efficiently as possible */
5517 if (AOP_TYPE(right) == AOP_LIT) {
5518 genRightShiftLiteral (left,right,result,ic, 0);
5522 /* shift count is unknown then we have to form
5523 a loop get the loop count in B : Note: we take
5524 only the lower order byte since shifting
5525 more that 32 bits make no sense anyway, ( the
5526 largest size of an object can be only 32 bits ) */
5528 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5529 emitcode("inc","b");
5530 freeAsmop (right,NULL,ic,TRUE);
5531 aopOp(left,ic,FALSE);
5532 aopOp(result,ic,FALSE);
5534 /* now move the left to the result if they are not the
5536 if (!sameRegs(AOP(left),AOP(result)) &&
5537 AOP_SIZE(result) > 1) {
5539 size = AOP_SIZE(result);
5542 l = aopGet(AOP(left),offset,FALSE,TRUE);
5543 if (*l == '@' && IS_AOP_PREG(result)) {
5545 emitcode("mov","a,%s",l);
5546 aopPut(AOP(result),"a",offset);
5548 aopPut(AOP(result),l,offset);
5553 tlbl = newiTempLabel(NULL);
5554 tlbl1= newiTempLabel(NULL);
5555 size = AOP_SIZE(result);
5558 /* if it is only one byte then */
5560 l = aopGet(AOP(left),0,FALSE,FALSE);
5562 emitcode("sjmp","%05d$",tlbl1->key+100);
5563 emitcode("","%05d$:",tlbl->key+100);
5565 emitcode("rrc","a");
5566 emitcode("","%05d$:",tlbl1->key+100);
5567 emitcode("djnz","b,%05d$",tlbl->key+100);
5568 aopPut(AOP(result),"a",0);
5572 reAdjustPreg(AOP(result));
5573 emitcode("sjmp","%05d$",tlbl1->key+100);
5574 emitcode("","%05d$:",tlbl->key+100);
5577 l = aopGet(AOP(result),offset,FALSE,FALSE);
5579 emitcode("rrc","a");
5580 aopPut(AOP(result),"a",offset--);
5582 reAdjustPreg(AOP(result));
5584 emitcode("","%05d$:",tlbl1->key+100);
5585 emitcode("djnz","b,%05d$",tlbl->key+100);
5588 freeAsmop(left,NULL,ic,TRUE);
5589 freeAsmop(result,NULL,ic,TRUE);
5592 /*-----------------------------------------------------------------*/
5593 /* genUnpackBits - generates code for unpacking bits */
5594 /*-----------------------------------------------------------------*/
5595 static void genUnpackBits (operand *result, char *rname, int ptype)
5602 etype = getSpec(operandType(result));
5604 /* read the first byte */
5609 emitcode("mov","a,@%s",rname);
5613 emitcode("movx","a,@%s",rname);
5617 emitcode("movx","a,@dptr");
5621 emitcode("clr","a");
5622 emitcode("movc","a","@a+dptr");
5626 emitcode("lcall","__gptrget");
5630 /* if we have bitdisplacement then it fits */
5631 /* into this byte completely or if length is */
5632 /* less than a byte */
5633 if ((shCnt = SPEC_BSTR(etype)) ||
5634 (SPEC_BLEN(etype) <= 8)) {
5636 /* shift right acc */
5639 emitcode("anl","a,#0x%02x",
5640 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
5641 aopPut(AOP(result),"a",offset);
5645 /* bit field did not fit in a byte */
5646 rlen = SPEC_BLEN(etype) - 8;
5647 aopPut(AOP(result),"a",offset++);
5654 emitcode("inc","%s",rname);
5655 emitcode("mov","a,@%s",rname);
5659 emitcode("inc","%s",rname);
5660 emitcode("movx","a,@%s",rname);
5664 emitcode("inc","dptr");
5665 emitcode("movx","a,@dptr");
5669 emitcode("clr","a");
5670 emitcode("inc","dptr");
5671 emitcode("movc","a","@a+dptr");
5675 emitcode("inc","dptr");
5676 emitcode("lcall","__gptrget");
5681 /* if we are done */
5685 aopPut(AOP(result),"a",offset++);
5690 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
5691 aopPut(AOP(result),"a",offset);
5698 /*-----------------------------------------------------------------*/
5699 /* genDataPointerGet - generates code when ptr offset is known */
5700 /*-----------------------------------------------------------------*/
5701 static void genDataPointerGet (operand *left,
5707 int size , offset = 0;
5708 aopOp(result,ic,TRUE);
5710 /* get the string representation of the name */
5711 l = aopGet(AOP(left),0,FALSE,TRUE);
5712 size = AOP_SIZE(result);
5715 sprintf(buffer,"(%s + %d)",l+1,offset);
5717 sprintf(buffer,"%s",l+1);
5718 aopPut(AOP(result),buffer,offset++);
5721 freeAsmop(left,NULL,ic,TRUE);
5722 freeAsmop(result,NULL,ic,TRUE);
5725 /*-----------------------------------------------------------------*/
5726 /* genNearPointerGet - emitcode for near pointer fetch */
5727 /*-----------------------------------------------------------------*/
5728 static void genNearPointerGet (operand *left,
5735 link *rtype, *retype;
5736 link *ltype = operandType(left);
5739 rtype = operandType(result);
5740 retype= getSpec(rtype);
5742 aopOp(left,ic,FALSE);
5744 /* if left is rematerialisable and
5745 result is not bit variable type and
5746 the left is pointer to data space i.e
5747 lower 128 bytes of space */
5748 if (AOP_TYPE(left) == AOP_IMMD &&
5749 !IS_BITVAR(retype) &&
5750 DCL_TYPE(ltype) == POINTER) {
5751 genDataPointerGet (left,result,ic);
5755 /* if the value is already in a pointer register
5756 then don't need anything more */
5757 if (!AOP_INPREG(AOP(left))) {
5758 /* otherwise get a free pointer register */
5760 preg = getFreePtr(ic,&aop,FALSE);
5761 emitcode("mov","%s,%s",
5763 aopGet(AOP(left),0,FALSE,TRUE));
5764 rname = preg->name ;
5766 rname = aopGet(AOP(left),0,FALSE,FALSE);
5768 freeAsmop(left,NULL,ic,TRUE);
5769 aopOp (result,ic,FALSE);
5771 /* if bitfield then unpack the bits */
5772 if (IS_BITVAR(retype))
5773 genUnpackBits (result,rname,POINTER);
5775 /* we have can just get the values */
5776 int size = AOP_SIZE(result);
5780 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
5782 emitcode("mov","a,@%s",rname);
5783 aopPut(AOP(result),"a",offset);
5785 sprintf(buffer,"@%s",rname);
5786 aopPut(AOP(result),buffer,offset);
5790 emitcode("inc","%s",rname);
5794 /* now some housekeeping stuff */
5796 /* we had to allocate for this iCode */
5797 freeAsmop(NULL,aop,ic,TRUE);
5799 /* we did not allocate which means left
5800 already in a pointer register, then
5801 if size > 0 && this could be used again
5802 we have to point it back to where it
5804 if (AOP_SIZE(result) > 1 &&
5805 !OP_SYMBOL(left)->remat &&
5806 ( OP_SYMBOL(left)->liveTo > ic->seq ||
5808 int size = AOP_SIZE(result) - 1;
5810 emitcode("dec","%s",rname);
5815 freeAsmop(result,NULL,ic,TRUE);
5819 /*-----------------------------------------------------------------*/
5820 /* genPagedPointerGet - emitcode for paged pointer fetch */
5821 /*-----------------------------------------------------------------*/
5822 static void genPagedPointerGet (operand *left,
5829 link *rtype, *retype;
5831 rtype = operandType(result);
5832 retype= getSpec(rtype);
5834 aopOp(left,ic,FALSE);
5836 /* if the value is already in a pointer register
5837 then don't need anything more */
5838 if (!AOP_INPREG(AOP(left))) {
5839 /* otherwise get a free pointer register */
5841 preg = getFreePtr(ic,&aop,FALSE);
5842 emitcode("mov","%s,%s",
5844 aopGet(AOP(left),0,FALSE,TRUE));
5845 rname = preg->name ;
5847 rname = aopGet(AOP(left),0,FALSE,FALSE);
5849 freeAsmop(left,NULL,ic,TRUE);
5850 aopOp (result,ic,FALSE);
5852 /* if bitfield then unpack the bits */
5853 if (IS_BITVAR(retype))
5854 genUnpackBits (result,rname,PPOINTER);
5856 /* we have can just get the values */
5857 int size = AOP_SIZE(result);
5862 emitcode("movx","a,@%s",rname);
5863 aopPut(AOP(result),"a",offset);
5868 emitcode("inc","%s",rname);
5872 /* now some housekeeping stuff */
5874 /* we had to allocate for this iCode */
5875 freeAsmop(NULL,aop,ic,TRUE);
5877 /* we did not allocate which means left
5878 already in a pointer register, then
5879 if size > 0 && this could be used again
5880 we have to point it back to where it
5882 if (AOP_SIZE(result) > 1 &&
5883 !OP_SYMBOL(left)->remat &&
5884 ( OP_SYMBOL(left)->liveTo > ic->seq ||
5886 int size = AOP_SIZE(result) - 1;
5888 emitcode("dec","%s",rname);
5893 freeAsmop(result,NULL,ic,TRUE);
5898 /*-----------------------------------------------------------------*/
5899 /* genFarPointerGet - gget value from far space */
5900 /*-----------------------------------------------------------------*/
5901 static void genFarPointerGet (operand *left,
5902 operand *result, iCode *ic)
5905 link *retype = getSpec(operandType(result));
5907 aopOp(left,ic,FALSE);
5909 /* if the operand is already in dptr
5910 then we do nothing else we move the value to dptr */
5911 if (AOP_TYPE(left) != AOP_STR) {
5912 /* if this is remateriazable */
5913 if (AOP_TYPE(left) == AOP_IMMD)
5914 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
5915 else { /* we need to get it byte by byte */
5916 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
5917 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
5918 if (options.model == MODEL_FLAT24)
5920 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
5924 /* so dptr know contains the address */
5925 freeAsmop(left,NULL,ic,TRUE);
5926 aopOp(result,ic,FALSE);
5928 /* if bit then unpack */
5929 if (IS_BITVAR(retype))
5930 genUnpackBits(result,"dptr",FPOINTER);
5932 size = AOP_SIZE(result);
5936 emitcode("movx","a,@dptr");
5937 aopPut(AOP(result),"a",offset++);
5939 emitcode("inc","dptr");
5943 freeAsmop(result,NULL,ic,TRUE);
5946 /*-----------------------------------------------------------------*/
5947 /* emitcodePointerGet - gget value from code space */
5948 /*-----------------------------------------------------------------*/
5949 static void emitcodePointerGet (operand *left,
5950 operand *result, iCode *ic)
5953 link *retype = getSpec(operandType(result));
5955 aopOp(left,ic,FALSE);
5957 /* if the operand is already in dptr
5958 then we do nothing else we move the value to dptr */
5959 if (AOP_TYPE(left) != AOP_STR) {
5960 /* if this is remateriazable */
5961 if (AOP_TYPE(left) == AOP_IMMD)
5962 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
5963 else { /* we need to get it byte by byte */
5964 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
5965 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
5966 if (options.model == MODEL_FLAT24)
5968 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
5972 /* so dptr know contains the address */
5973 freeAsmop(left,NULL,ic,TRUE);
5974 aopOp(result,ic,FALSE);
5976 /* if bit then unpack */
5977 if (IS_BITVAR(retype))
5978 genUnpackBits(result,"dptr",CPOINTER);
5980 size = AOP_SIZE(result);
5984 emitcode("clr","a");
5985 emitcode("movc","a,@a+dptr");
5986 aopPut(AOP(result),"a",offset++);
5988 emitcode("inc","dptr");
5992 freeAsmop(result,NULL,ic,TRUE);
5995 /*-----------------------------------------------------------------*/
5996 /* genGenPointerGet - gget value from generic pointer space */
5997 /*-----------------------------------------------------------------*/
5998 static void genGenPointerGet (operand *left,
5999 operand *result, iCode *ic)
6002 link *retype = getSpec(operandType(result));
6004 aopOp(left,ic,FALSE);
6006 /* if the operand is already in dptr
6007 then we do nothing else we move the value to dptr */
6008 if (AOP_TYPE(left) != AOP_STR) {
6009 /* if this is remateriazable */
6010 if (AOP_TYPE(left) == AOP_IMMD) {
6011 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6012 emitcode("mov","b,#%d",pointerCode(retype));
6014 else { /* we need to get it byte by byte */
6015 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6016 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6017 if (options.model == MODEL_FLAT24)
6019 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6020 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
6024 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
6028 /* so dptr know contains the address */
6029 freeAsmop(left,NULL,ic,TRUE);
6030 aopOp(result,ic,FALSE);
6032 /* if bit then unpack */
6033 if (IS_BITVAR(retype))
6034 genUnpackBits(result,"dptr",GPOINTER);
6036 size = AOP_SIZE(result);
6040 emitcode("lcall","__gptrget");
6041 aopPut(AOP(result),"a",offset++);
6043 emitcode("inc","dptr");
6047 freeAsmop(result,NULL,ic,TRUE);
6050 /*-----------------------------------------------------------------*/
6051 /* genPointerGet - generate code for pointer get */
6052 /*-----------------------------------------------------------------*/
6053 static void genPointerGet (iCode *ic)
6055 operand *left, *result ;
6060 result = IC_RESULT(ic) ;
6062 /* depending on the type of pointer we need to
6063 move it to the correct pointer register */
6064 type = operandType(left);
6065 etype = getSpec(type);
6066 /* if left is of type of pointer then it is simple */
6067 if (IS_PTR(type) && !IS_FUNC(type->next))
6068 p_type = DCL_TYPE(type);
6071 /* we have to go by the storage class */
6072 if (SPEC_OCLS(etype)->codesp ) {
6076 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
6079 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
6082 if (SPEC_OCLS(etype) == idata )
6088 /* now that we have the pointer type we assign
6089 the pointer values */
6094 genNearPointerGet (left,result,ic);
6098 genPagedPointerGet(left,result,ic);
6102 genFarPointerGet (left,result,ic);
6106 emitcodePointerGet (left,result,ic);
6110 genGenPointerGet (left,result,ic);
6116 /*-----------------------------------------------------------------*/
6117 /* genPackBits - generates code for packed bit storage */
6118 /*-----------------------------------------------------------------*/
6119 static void genPackBits (link *etype ,
6121 char *rname, int p_type)
6129 blen = SPEC_BLEN(etype);
6130 bstr = SPEC_BSTR(etype);
6132 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6135 /* if the bit lenth is less than or */
6136 /* it exactly fits a byte then */
6137 if (SPEC_BLEN(etype) <= 8 ) {
6138 shCount = SPEC_BSTR(etype) ;
6140 /* shift left acc */
6143 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6148 emitcode ("mov","b,a");
6149 emitcode("mov","a,@%s",rname);
6153 emitcode ("mov","b,a");
6154 emitcode("movx","a,@dptr");
6158 emitcode ("push","b");
6159 emitcode ("push","acc");
6160 emitcode ("lcall","__gptrget");
6161 emitcode ("pop","b");
6165 emitcode ("anl","a,#0x%02x",(unsigned char)
6166 ((unsigned char)(0xFF << (blen+bstr)) |
6167 (unsigned char)(0xFF >> (8-bstr)) ) );
6168 emitcode ("orl","a,b");
6169 if (p_type == GPOINTER)
6170 emitcode("pop","b");
6176 emitcode("mov","@%s,a",rname);
6180 emitcode("movx","@dptr,a");
6184 emitcode("lcall","__gptrput");
6189 if ( SPEC_BLEN(etype) <= 8 )
6192 emitcode("inc","%s",rname);
6193 rLen = SPEC_BLEN(etype) ;
6195 /* now generate for lengths greater than one byte */
6198 l = aopGet(AOP(right),offset++,FALSE,TRUE);
6208 emitcode("mov","@%s,a",rname);
6210 emitcode("mov","@%s,%s",rname,l);
6215 emitcode("movx","@dptr,a");
6220 emitcode("lcall","__gptrput");
6223 emitcode ("inc","%s",rname);
6228 /* last last was not complete */
6230 /* save the byte & read byte */
6233 emitcode ("mov","b,a");
6234 emitcode("mov","a,@%s",rname);
6238 emitcode ("mov","b,a");
6239 emitcode("movx","a,@dptr");
6243 emitcode ("push","b");
6244 emitcode ("push","acc");
6245 emitcode ("lcall","__gptrget");
6246 emitcode ("pop","b");
6250 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
6251 emitcode ("orl","a,b");
6254 if (p_type == GPOINTER)
6255 emitcode("pop","b");
6260 emitcode("mov","@%s,a",rname);
6264 emitcode("movx","@dptr,a");
6268 emitcode("lcall","__gptrput");
6272 /*-----------------------------------------------------------------*/
6273 /* genDataPointerSet - remat pointer to data space */
6274 /*-----------------------------------------------------------------*/
6275 static void genDataPointerSet(operand *right,
6279 int size, offset = 0 ;
6280 char *l, buffer[256];
6282 aopOp(right,ic,FALSE);
6284 l = aopGet(AOP(result),0,FALSE,TRUE);
6285 size = AOP_SIZE(right);
6288 sprintf(buffer,"(%s + %d)",l+1,offset);
6290 sprintf(buffer,"%s",l+1);
6291 emitcode("mov","%s,%s",buffer,
6292 aopGet(AOP(right),offset++,FALSE,FALSE));
6295 freeAsmop(right,NULL,ic,TRUE);
6296 freeAsmop(result,NULL,ic,TRUE);
6299 /*-----------------------------------------------------------------*/
6300 /* genNearPointerSet - emitcode for near pointer put */
6301 /*-----------------------------------------------------------------*/
6302 static void genNearPointerSet (operand *right,
6310 link *ptype = operandType(result);
6312 retype= getSpec(operandType(right));
6314 aopOp(result,ic,FALSE);
6316 /* if the result is rematerializable &
6317 in data space & not a bit variable */
6318 if (AOP_TYPE(result) == AOP_IMMD &&
6319 DCL_TYPE(ptype) == POINTER &&
6320 !IS_BITVAR(retype)) {
6321 genDataPointerSet (right,result,ic);
6325 /* if the value is already in a pointer register
6326 then don't need anything more */
6327 if (!AOP_INPREG(AOP(result))) {
6328 /* otherwise get a free pointer register */
6330 preg = getFreePtr(ic,&aop,FALSE);
6331 emitcode("mov","%s,%s",
6333 aopGet(AOP(result),0,FALSE,TRUE));
6334 rname = preg->name ;
6336 rname = aopGet(AOP(result),0,FALSE,FALSE);
6338 freeAsmop(result,NULL,ic,TRUE);
6339 aopOp (right,ic,FALSE);
6341 /* if bitfield then unpack the bits */
6342 if (IS_BITVAR(retype))
6343 genPackBits (retype,right,rname,POINTER);
6345 /* we have can just get the values */
6346 int size = AOP_SIZE(right);
6350 l = aopGet(AOP(right),offset,FALSE,TRUE);
6353 emitcode("mov","@%s,a",rname);
6355 emitcode("mov","@%s,%s",rname,l);
6357 emitcode("inc","%s",rname);
6362 /* now some housekeeping stuff */
6364 /* we had to allocate for this iCode */
6365 freeAsmop(NULL,aop,ic,TRUE);
6367 /* we did not allocate which means left
6368 already in a pointer register, then
6369 if size > 0 && this could be used again
6370 we have to point it back to where it
6372 if (AOP_SIZE(right) > 1 &&
6373 !OP_SYMBOL(result)->remat &&
6374 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6376 int size = AOP_SIZE(right) - 1;
6378 emitcode("dec","%s",rname);
6383 freeAsmop(right,NULL,ic,TRUE);
6388 /*-----------------------------------------------------------------*/
6389 /* genPagedPointerSet - emitcode for Paged pointer put */
6390 /*-----------------------------------------------------------------*/
6391 static void genPagedPointerSet (operand *right,
6400 retype= getSpec(operandType(right));
6402 aopOp(result,ic,FALSE);
6404 /* if the value is already in a pointer register
6405 then don't need anything more */
6406 if (!AOP_INPREG(AOP(result))) {
6407 /* otherwise get a free pointer register */
6409 preg = getFreePtr(ic,&aop,FALSE);
6410 emitcode("mov","%s,%s",
6412 aopGet(AOP(result),0,FALSE,TRUE));
6413 rname = preg->name ;
6415 rname = aopGet(AOP(result),0,FALSE,FALSE);
6417 freeAsmop(result,NULL,ic,TRUE);
6418 aopOp (right,ic,FALSE);
6420 /* if bitfield then unpack the bits */
6421 if (IS_BITVAR(retype))
6422 genPackBits (retype,right,rname,PPOINTER);
6424 /* we have can just get the values */
6425 int size = AOP_SIZE(right);
6429 l = aopGet(AOP(right),offset,FALSE,TRUE);
6432 emitcode("movx","@%s,a",rname);
6435 emitcode("inc","%s",rname);
6441 /* now some housekeeping stuff */
6443 /* we had to allocate for this iCode */
6444 freeAsmop(NULL,aop,ic,TRUE);
6446 /* we did not allocate which means left
6447 already in a pointer register, then
6448 if size > 0 && this could be used again
6449 we have to point it back to where it
6451 if (AOP_SIZE(right) > 1 &&
6452 !OP_SYMBOL(result)->remat &&
6453 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6455 int size = AOP_SIZE(right) - 1;
6457 emitcode("dec","%s",rname);
6462 freeAsmop(right,NULL,ic,TRUE);
6467 /*-----------------------------------------------------------------*/
6468 /* genFarPointerSet - set value from far space */
6469 /*-----------------------------------------------------------------*/
6470 static void genFarPointerSet (operand *right,
6471 operand *result, iCode *ic)
6474 link *retype = getSpec(operandType(right));
6476 aopOp(result,ic,FALSE);
6478 /* if the operand is already in dptr
6479 then we do nothing else we move the value to dptr */
6480 if (AOP_TYPE(result) != AOP_STR) {
6481 /* if this is remateriazable */
6482 if (AOP_TYPE(result) == AOP_IMMD)
6483 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6484 else { /* we need to get it byte by byte */
6485 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6486 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6487 if (options.model == MODEL_FLAT24)
6489 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6493 /* so dptr know contains the address */
6494 freeAsmop(result,NULL,ic,TRUE);
6495 aopOp(right,ic,FALSE);
6497 /* if bit then unpack */
6498 if (IS_BITVAR(retype))
6499 genPackBits(retype,right,"dptr",FPOINTER);
6501 size = AOP_SIZE(right);
6505 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6507 emitcode("movx","@dptr,a");
6509 emitcode("inc","dptr");
6513 freeAsmop(right,NULL,ic,TRUE);
6516 /*-----------------------------------------------------------------*/
6517 /* genGenPointerSet - set value from generic pointer space */
6518 /*-----------------------------------------------------------------*/
6519 static void genGenPointerSet (operand *right,
6520 operand *result, iCode *ic)
6523 link *retype = getSpec(operandType(right));
6525 aopOp(result,ic,FALSE);
6527 /* if the operand is already in dptr
6528 then we do nothing else we move the value to dptr */
6529 if (AOP_TYPE(result) != AOP_STR) {
6530 /* if this is remateriazable */
6531 if (AOP_TYPE(result) == AOP_IMMD) {
6532 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6533 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
6535 else { /* we need to get it byte by byte */
6536 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6537 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6538 if (options.model == MODEL_FLAT24)
6540 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6541 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
6545 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
6549 /* so dptr know contains the address */
6550 freeAsmop(result,NULL,ic,TRUE);
6551 aopOp(right,ic,FALSE);
6553 /* if bit then unpack */
6554 if (IS_BITVAR(retype))
6555 genPackBits(retype,right,"dptr",GPOINTER);
6557 size = AOP_SIZE(right);
6561 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6563 emitcode("lcall","__gptrput");
6565 emitcode("inc","dptr");
6569 freeAsmop(right,NULL,ic,TRUE);
6572 /*-----------------------------------------------------------------*/
6573 /* genPointerSet - stores the value into a pointer location */
6574 /*-----------------------------------------------------------------*/
6575 static void genPointerSet (iCode *ic)
6577 operand *right, *result ;
6581 right = IC_RIGHT(ic);
6582 result = IC_RESULT(ic) ;
6584 /* depending on the type of pointer we need to
6585 move it to the correct pointer register */
6586 type = operandType(result);
6587 etype = getSpec(type);
6588 /* if left is of type of pointer then it is simple */
6589 if (IS_PTR(type) && !IS_FUNC(type->next)) {
6590 p_type = DCL_TYPE(type);
6594 /* we have to go by the storage class */
6595 if (SPEC_OCLS(etype)->codesp ) {
6599 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
6602 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
6605 if (SPEC_OCLS(etype) == idata )
6611 /* now that we have the pointer type we assign
6612 the pointer values */
6617 genNearPointerSet (right,result,ic);
6621 genPagedPointerSet (right,result,ic);
6625 genFarPointerSet (right,result,ic);
6629 genGenPointerSet (right,result,ic);
6635 /*-----------------------------------------------------------------*/
6636 /* genIfx - generate code for Ifx statement */
6637 /*-----------------------------------------------------------------*/
6638 static void genIfx (iCode *ic, iCode *popIc)
6640 operand *cond = IC_COND(ic);
6643 aopOp(cond,ic,FALSE);
6645 /* get the value into acc */
6646 if (AOP_TYPE(cond) != AOP_CRY)
6650 /* the result is now in the accumulator */
6651 freeAsmop(cond,NULL,ic,TRUE);
6653 /* if there was something to be popped then do it */
6657 /* if the condition is a bit variable */
6658 if (isbit && IS_ITEMP(cond) &&
6660 genIfxJump(ic,SPIL_LOC(cond)->rname);
6662 if (isbit && !IS_ITEMP(cond))
6663 genIfxJump(ic,OP_SYMBOL(cond)->rname);
6670 /*-----------------------------------------------------------------*/
6671 /* genAddrOf - generates code for address of */
6672 /*-----------------------------------------------------------------*/
6673 static void genAddrOf (iCode *ic)
6675 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
6678 aopOp(IC_RESULT(ic),ic,FALSE);
6680 /* if the operand is on the stack then we
6681 need to get the stack offset of this
6684 /* if it has an offset then we need to compute
6687 emitcode("mov","a,_bp");
6688 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
6689 aopPut(AOP(IC_RESULT(ic)),"a",0);
6691 /* we can just move _bp */
6692 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
6693 /* fill the result with zero */
6694 size = AOP_SIZE(IC_RESULT(ic)) - 1;
6697 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
6702 /* object not on stack then we need the name */
6703 size = AOP_SIZE(IC_RESULT(ic));
6707 char s[SDCC_NAME_MAX];
6709 sprintf(s,"#(%s >> %d)",
6713 sprintf(s,"#%s",sym->rname);
6714 aopPut(AOP(IC_RESULT(ic)),s,offset++);
6718 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
6722 /*-----------------------------------------------------------------*/
6723 /* genFarFarAssign - assignment when both are in far space */
6724 /*-----------------------------------------------------------------*/
6725 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
6727 int size = AOP_SIZE(right);
6730 /* first push the right side on to the stack */
6732 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6734 emitcode ("push","acc");
6737 freeAsmop(right,NULL,ic,FALSE);
6738 /* now assign DPTR to result */
6739 aopOp(result,ic,FALSE);
6740 size = AOP_SIZE(result);
6742 emitcode ("pop","acc");
6743 aopPut(AOP(result),"a",--offset);
6745 freeAsmop(result,NULL,ic,FALSE);
6749 /*-----------------------------------------------------------------*/
6750 /* genAssign - generate code for assignment */
6751 /*-----------------------------------------------------------------*/
6752 static void genAssign (iCode *ic)
6754 operand *result, *right;
6756 unsigned long lit = 0L;
6758 result = IC_RESULT(ic);
6759 right = IC_RIGHT(ic) ;
6761 /* if they are the same */
6762 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
6765 aopOp(right,ic,FALSE);
6767 /* special case both in far space */
6768 if (AOP_TYPE(right) == AOP_DPTR &&
6769 IS_TRUE_SYMOP(result) &&
6770 isOperandInFarSpace(result)) {
6772 genFarFarAssign (result,right,ic);
6776 aopOp(result,ic,TRUE);
6778 /* if they are the same registers */
6779 if (sameRegs(AOP(right),AOP(result)))
6782 /* if the result is a bit */
6783 if (AOP_TYPE(result) == AOP_CRY) {
6785 /* if the right size is a literal then
6786 we know what the value is */
6787 if (AOP_TYPE(right) == AOP_LIT) {
6788 if (((int) operandLitValue(right)))
6789 aopPut(AOP(result),one,0);
6791 aopPut(AOP(result),zero,0);
6795 /* the right is also a bit variable */
6796 if (AOP_TYPE(right) == AOP_CRY) {
6797 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6798 aopPut(AOP(result),"c",0);
6804 aopPut(AOP(result),"a",0);
6808 /* bit variables done */
6810 size = AOP_SIZE(result);
6812 if(AOP_TYPE(right) == AOP_LIT)
6813 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6815 (AOP_TYPE(result) != AOP_REG) &&
6816 (AOP_TYPE(right) == AOP_LIT) &&
6817 !IS_FLOAT(operandType(right)) &&
6819 emitcode("clr","a");
6821 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
6822 aopPut(AOP(result),"a",size);
6825 aopGet(AOP(right),size,FALSE,FALSE),
6831 aopGet(AOP(right),offset,FALSE,FALSE),
6838 freeAsmop (right,NULL,ic,FALSE);
6839 freeAsmop (result,NULL,ic,TRUE);
6842 /*-----------------------------------------------------------------*/
6843 /* genJumpTab - genrates code for jump table */
6844 /*-----------------------------------------------------------------*/
6845 static void genJumpTab (iCode *ic)
6850 aopOp(IC_JTCOND(ic),ic,FALSE);
6851 /* get the condition into accumulator */
6852 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
6854 /* multiply by three */
6855 emitcode("add","a,acc");
6856 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
6857 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
6859 jtab = newiTempLabel(NULL);
6860 emitcode("mov","dptr,#%05d$",jtab->key+100);
6861 emitcode("jmp","@a+dptr");
6862 emitcode("","%05d$:",jtab->key+100);
6863 /* now generate the jump labels */
6864 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
6865 jtab = setNextItem(IC_JTLABELS(ic)))
6866 emitcode("ljmp","%05d$",jtab->key+100);
6870 /*-----------------------------------------------------------------*/
6871 /* genCast - gen code for casting */
6872 /*-----------------------------------------------------------------*/
6873 static void genCast (iCode *ic)
6875 operand *result = IC_RESULT(ic);
6876 link *ctype = operandType(IC_LEFT(ic));
6877 operand *right = IC_RIGHT(ic);
6880 /* if they are equivalent then do nothing */
6881 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
6884 aopOp(right,ic,FALSE) ;
6885 aopOp(result,ic,FALSE);
6887 /* if the result is a bit */
6888 if (AOP_TYPE(result) == AOP_CRY) {
6889 /* if the right size is a literal then
6890 we know what the value is */
6891 if (AOP_TYPE(right) == AOP_LIT) {
6892 if (((int) operandLitValue(right)))
6893 aopPut(AOP(result),one,0);
6895 aopPut(AOP(result),zero,0);
6900 /* the right is also a bit variable */
6901 if (AOP_TYPE(right) == AOP_CRY) {
6902 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6903 aopPut(AOP(result),"c",0);
6909 aopPut(AOP(result),"a",0);
6913 /* if they are the same size : or less */
6914 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
6916 /* if they are in the same place */
6917 if (sameRegs(AOP(right),AOP(result)))
6920 /* if they in different places then copy */
6921 size = AOP_SIZE(result);
6925 aopGet(AOP(right),offset,FALSE,FALSE),
6933 /* if the result is of type pointer */
6934 if (IS_PTR(ctype)) {
6937 link *type = operandType(right);
6938 link *etype = getSpec(type);
6940 /* pointer to generic pointer */
6941 if (IS_GENPTR(ctype)) {
6945 p_type = DCL_TYPE(type);
6947 /* we have to go by the storage class */
6948 if (SPEC_OCLS(etype)->codesp )
6951 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
6954 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
6957 if (SPEC_OCLS(etype) == idata )
6963 /* the first two bytes are known */
6964 size = GPTRSIZE - 1;
6968 aopGet(AOP(right),offset,FALSE,FALSE),
6972 /* the last byte depending on type */
6989 /* this should never happen */
6990 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
6991 "got unknown pointer type");
6994 aopPut(AOP(result),l, GPTRSIZE - 1);
6998 /* just copy the pointers */
6999 size = AOP_SIZE(result);
7003 aopGet(AOP(right),offset,FALSE,FALSE),
7010 /* so we now know that the size of destination is greater
7011 than the size of the source */
7012 /* we move to result for the size of source */
7013 size = AOP_SIZE(right);
7017 aopGet(AOP(right),offset,FALSE,FALSE),
7022 /* now depending on the sign of the destination */
7023 size = AOP_SIZE(result) - AOP_SIZE(right);
7024 /* if unsigned or not an integral type */
7025 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
7027 aopPut(AOP(result),zero,offset++);
7029 /* we need to extend the sign :{ */
7030 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
7033 emitcode("rlc","a");
7034 emitcode("subb","a,acc");
7036 aopPut(AOP(result),"a",offset++);
7039 /* we are done hurray !!!! */
7042 freeAsmop(right,NULL,ic,TRUE);
7043 freeAsmop(result,NULL,ic,TRUE);
7047 /*-----------------------------------------------------------------*/
7048 /* genDjnz - generate decrement & jump if not zero instrucion */
7049 /*-----------------------------------------------------------------*/
7050 static int genDjnz (iCode *ic, iCode *ifx)
7056 /* if the if condition has a false label
7057 then we cannot save */
7061 /* if the minus is not of the form
7063 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
7064 !IS_OP_LITERAL(IC_RIGHT(ic)))
7067 if (operandLitValue(IC_RIGHT(ic)) != 1)
7070 /* if the size of this greater than one then no
7072 if (getSize(operandType(IC_RESULT(ic))) > 1)
7075 /* otherwise we can save BIG */
7076 lbl = newiTempLabel(NULL);
7077 lbl1= newiTempLabel(NULL);
7079 aopOp(IC_RESULT(ic),ic,FALSE);
7081 if (IS_AOP_PREG(IC_RESULT(ic))) {
7082 emitcode("dec","%s",
7083 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7084 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7085 emitcode("jnz","%05d$",lbl->key+100);
7087 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
7090 emitcode ("sjmp","%05d$",lbl1->key+100);
7091 emitcode ("","%05d$:",lbl->key+100);
7092 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
7093 emitcode ("","%05d$:",lbl1->key+100);
7095 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7100 /*-----------------------------------------------------------------*/
7101 /* genReceive - generate code for a receive iCode */
7102 /*-----------------------------------------------------------------*/
7103 static void genReceive (iCode *ic)
7105 if (isOperandInFarSpace(IC_RESULT(ic)) &&
7106 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
7107 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
7109 int size = getSize(operandType(IC_RESULT(ic)));
7110 int offset = 4 - size;
7112 emitcode ("push","%s", (strcmp(fReturn[3 - offset],"a") ?
7113 fReturn[3 - offset] : "acc"));
7116 aopOp(IC_RESULT(ic),ic,FALSE);
7117 size = AOP_SIZE(IC_RESULT(ic));
7120 emitcode ("pop","acc");
7121 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
7126 aopOp(IC_RESULT(ic),ic,FALSE);
7128 assignResultValue(IC_RESULT(ic));
7131 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7134 /*-----------------------------------------------------------------*/
7135 /* gen51Code - generate code for 8051 based controllers */
7136 /*-----------------------------------------------------------------*/
7137 void gen51Code (iCode *lic)
7142 lineHead = lineCurr = NULL;
7144 /* if debug information required */
7145 /* if (options.debug && currFunc) { */
7147 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
7149 if (IS_STATIC(currFunc->etype))
7150 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
7152 emitcode("","G$%s$0$0 ==.",currFunc->name);
7155 /* stack pointer name */
7156 if (options.useXstack)
7162 for (ic = lic ; ic ; ic = ic->next ) {
7164 if ( cln != ic->lineno ) {
7165 if ( options.debug ) {
7167 emitcode("","C$%s$%d$%d$%d ==.",
7168 ic->filename,ic->lineno,
7169 ic->level,ic->block);
7172 emitcode(";","%s %d",ic->filename,ic->lineno);
7175 /* if the result is marked as
7176 spilt and rematerializable or code for
7177 this has already been generated then
7179 if (resultRemat(ic) || ic->generated )
7182 /* depending on the operation */
7201 /* IPOP happens only when trying to restore a
7202 spilt live range, if there is an ifx statement
7203 following this pop then the if statement might
7204 be using some of the registers being popped which
7205 would destory the contents of the register so
7206 we need to check for this condition and handle it */
7208 ic->next->op == IFX &&
7209 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
7210 genIfx (ic->next,ic);
7228 genEndFunction (ic);
7248 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
7265 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
7269 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
7276 /* note these two are xlated by algebraic equivalence
7277 during parsing SDCC.y */
7278 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7279 "got '>=' or '<=' shouldn't have come here");
7283 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
7295 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
7299 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
7303 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
7330 case GET_VALUE_AT_ADDRESS:
7335 if (POINTER_SET(ic))
7362 addSet(&_G.sendSet,ic);
7367 /* piCode(ic,stdout); */
7373 /* now we are ready to call the
7374 peep hole optimizer */
7375 if (!options.nopeep)
7376 peepHole (&lineHead);
7378 /* now do the actual printing */
7379 printLine (lineHead,codeOutFile);