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";
64 char *fReturn8051[] = {"dpl","dph","b","a" };
65 char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
66 unsigned fReturnSize = 4; /* shared with ralloc.c */
67 char **fReturn = fReturn8051;
68 static char *accUse[] = {"a","b"};
70 static short rbank = -1;
82 extern int mcs51_ptrRegReq ;
83 extern int mcs51_nRegs;
84 extern FILE *codeOutFile;
85 static void saverbank (int, iCode *,bool);
86 #define RESULTONSTACK(x) \
87 (IC_RESULT(x) && IC_RESULT(x)->aop && \
88 IC_RESULT(x)->aop->type == AOP_STK )
90 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x);
91 #define CLRC emitcode("clr","c");
93 static lineNode *lineHead = NULL;
94 static lineNode *lineCurr = NULL;
96 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
97 0xE0, 0xC0, 0x80, 0x00};
98 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
99 0x07, 0x03, 0x01, 0x00};
106 /*-----------------------------------------------------------------*/
107 /* emitcode - writes the code into a file : for now it is simple */
108 /*-----------------------------------------------------------------*/
109 static void emitcode (char *inst,char *fmt, ...)
112 char lb[MAX_INLINEASM];
119 sprintf(lb,"%s\t",inst);
121 sprintf(lb,"%s",inst);
122 vsprintf(lb+(strlen(lb)),fmt,ap);
126 while (isspace(*lbp)) lbp++;
129 lineCurr = (lineCurr ?
130 connectLine(lineCurr,newLineNode(lb)) :
131 (lineHead = newLineNode(lb)));
132 lineCurr->isInline = _G.inLine;
133 lineCurr->isDebug = _G.debugLine;
137 /*-----------------------------------------------------------------*/
138 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
139 /*-----------------------------------------------------------------*/
140 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
142 bool r0iu = FALSE , r1iu = FALSE;
143 bool r0ou = FALSE , r1ou = FALSE;
145 /* the logic: if r0 & r1 used in the instruction
146 then we are in trouble otherwise */
148 /* first check if r0 & r1 are used by this
149 instruction, in which case we are in trouble */
150 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
151 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
156 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
157 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
159 /* if no usage of r0 then return it */
160 if (!r0iu && !r0ou) {
161 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
162 (*aopp)->type = AOP_R0;
164 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R0_IDX);
167 /* if no usage of r1 then return it */
168 if (!r1iu && !r1ou) {
169 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
170 (*aopp)->type = AOP_R1;
172 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R1_IDX);
175 /* now we know they both have usage */
176 /* if r0 not used in this instruction */
178 /* push it if not already pushed */
180 emitcode ("push","%s",
181 mcs51_regWithIdx(R0_IDX)->dname);
185 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
186 (*aopp)->type = AOP_R0;
188 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R0_IDX);
191 /* if r1 not used then */
194 /* push it if not already pushed */
196 emitcode ("push","%s",
197 mcs51_regWithIdx(R1_IDX)->dname);
201 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
202 (*aopp)->type = AOP_R1;
203 return mcs51_regWithIdx(R1_IDX);
207 /* I said end of world but not quite end of world yet */
208 /* if this is a result then we can push it on the stack*/
210 (*aopp)->type = AOP_STK;
215 /* other wise this is true end of the world */
216 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
217 "getFreePtr should never reach here");
221 /*-----------------------------------------------------------------*/
222 /* newAsmop - creates a new asmOp */
223 /*-----------------------------------------------------------------*/
224 static asmop *newAsmop (short type)
228 ALLOC(aop,sizeof(asmop));
233 /*-----------------------------------------------------------------*/
234 /* pointerCode - returns the code for a pointer type */
235 /*-----------------------------------------------------------------*/
236 static int pointerCode (link *etype)
240 return PTR_TYPE(SPEC_OCLS(etype));
242 /* if (SPEC_OCLS(etype)->codesp ) { */
243 /* p_type = CPOINTER ; */
246 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
247 /* p_type = FPOINTER ; */
249 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
250 /* p_type = PPOINTER; */
252 /* if (SPEC_OCLS(etype) == idata ) */
253 /* p_type = IPOINTER; */
255 /* p_type = POINTER ; */
259 /*-----------------------------------------------------------------*/
260 /* aopForSym - for a true symbol */
261 /*-----------------------------------------------------------------*/
262 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
265 memmap *space= SPEC_OCLS(sym->etype);
267 /* if already has one */
271 /* assign depending on the storage class */
272 /* if it is on the stack or indirectly addressable */
273 /* space we need to assign either r0 or r1 to it */
274 if (sym->onStack || sym->iaccess) {
275 sym->aop = aop = newAsmop(0);
276 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
277 aop->size = getSize(sym->type);
279 /* now assign the address of the variable to
280 the pointer register */
281 if (aop->type != AOP_STK) {
286 emitcode("push","acc");
288 emitcode("mov","a,_bp");
289 emitcode("add","a,#0x%02x",
291 ((char)(sym->stack - _G.nRegsSaved )) :
292 ((char)sym->stack)) & 0xff);
293 emitcode("mov","%s,a",
294 aop->aopu.aop_ptr->name);
297 emitcode("pop","acc");
300 emitcode("mov","%s,#%s",
301 aop->aopu.aop_ptr->name,
303 aop->paged = space->paged;
305 aop->aopu.aop_stk = sym->stack;
309 /* if in bit space */
310 if (IN_BITSPACE(space)) {
311 sym->aop = aop = newAsmop (AOP_CRY);
312 aop->aopu.aop_dir = sym->rname ;
313 aop->size = getSize(sym->type);
316 /* if it is in direct space */
317 if (IN_DIRSPACE(space)) {
318 sym->aop = aop = newAsmop (AOP_DIR);
319 aop->aopu.aop_dir = sym->rname ;
320 aop->size = getSize(sym->type);
324 /* special case for a function */
325 if (IS_FUNC(sym->type)) {
326 sym->aop = aop = newAsmop(AOP_IMMD);
327 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
328 strcpy(aop->aopu.aop_immd,sym->rname);
329 aop->size = FPTRSIZE;
333 /* only remaining is far space */
334 /* in which case DPTR gets the address */
335 sym->aop = aop = newAsmop(AOP_DPTR);
336 emitcode ("mov","dptr,#%s", sym->rname);
337 aop->size = getSize(sym->type);
339 /* if it is in code space */
340 if (IN_CODESPACE(space))
346 /*-----------------------------------------------------------------*/
347 /* aopForRemat - rematerialzes an object */
348 /*-----------------------------------------------------------------*/
349 static asmop *aopForRemat (symbol *sym)
352 iCode *ic = sym->rematiCode;
353 asmop *aop = newAsmop(AOP_IMMD);
357 /* if plus or minus print the right hand side */
358 if (ic->op == '+' || ic->op == '-') {
359 sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
362 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
366 /* we reached the end */
367 sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
371 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
372 strcpy(aop->aopu.aop_immd,buffer);
376 /*-----------------------------------------------------------------*/
377 /* regsInCommon - two operands have some registers in common */
378 /*-----------------------------------------------------------------*/
379 static bool regsInCommon (operand *op1, operand *op2)
384 /* if they have registers in common */
385 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
388 sym1 = OP_SYMBOL(op1);
389 sym2 = OP_SYMBOL(op2);
391 if (sym1->nRegs == 0 || sym2->nRegs == 0)
394 for (i = 0 ; i < sym1->nRegs ; i++) {
399 for (j = 0 ; j < sym2->nRegs ;j++ ) {
403 if (sym2->regs[j] == sym1->regs[i])
411 /*-----------------------------------------------------------------*/
412 /* operandsEqu - equivalent */
413 /*-----------------------------------------------------------------*/
414 static bool operandsEqu ( operand *op1, operand *op2)
418 /* if they not symbols */
419 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
422 sym1 = OP_SYMBOL(op1);
423 sym2 = OP_SYMBOL(op2);
425 /* if both are itemps & one is spilt
426 and the other is not then false */
427 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
428 sym1->isspilt != sym2->isspilt )
431 /* if they are the same */
435 if (strcmp(sym1->rname,sym2->rname) == 0)
439 /* if left is a tmp & right is not */
443 (sym1->usl.spillLoc == sym2))
450 (sym2->usl.spillLoc == sym1))
456 /*-----------------------------------------------------------------*/
457 /* sameRegs - two asmops have the same registers */
458 /*-----------------------------------------------------------------*/
459 static bool sameRegs (asmop *aop1, asmop *aop2 )
466 if (aop1->type != AOP_REG ||
467 aop2->type != AOP_REG )
470 if (aop1->size != aop2->size )
473 for (i = 0 ; i < aop1->size ; i++ )
474 if (aop1->aopu.aop_reg[i] !=
475 aop2->aopu.aop_reg[i] )
481 /*-----------------------------------------------------------------*/
482 /* aopOp - allocates an asmop for an operand : */
483 /*-----------------------------------------------------------------*/
484 static void aopOp (operand *op, iCode *ic, bool result)
493 /* if this a literal */
494 if (IS_OP_LITERAL(op)) {
495 op->aop = aop = newAsmop(AOP_LIT);
496 aop->aopu.aop_lit = op->operand.valOperand;
497 aop->size = getSize(operandType(op));
501 /* if already has a asmop then continue */
505 /* if the underlying symbol has a aop */
506 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
507 op->aop = OP_SYMBOL(op)->aop;
511 /* if this is a true symbol */
512 if (IS_TRUE_SYMOP(op)) {
513 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
517 /* this is a temporary : this has
523 e) can be a return use only */
528 /* if the type is a conditional */
529 if (sym->regType == REG_CND) {
530 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
535 /* if it is spilt then two situations
537 b) has a spill location */
538 if (sym->isspilt || sym->nRegs == 0) {
540 /* rematerialize it NOW */
542 sym->aop = op->aop = aop =
544 aop->size = getSize(sym->type);
550 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
551 aop->size = getSize(sym->type);
552 for ( i = 0 ; i < 2 ; i++ )
553 aop->aopu.aop_str[i] = accUse[i];
559 aop = op->aop = sym->aop = newAsmop(AOP_STR);
560 aop->size = getSize(sym->type);
561 for ( i = 0 ; i < fReturnSize ; i++ )
562 aop->aopu.aop_str[i] = fReturn[i];
566 /* else spill location */
567 sym->aop = op->aop = aop =
568 aopForSym(ic,sym->usl.spillLoc,result);
569 aop->size = getSize(sym->type);
573 /* must be in a register */
574 sym->aop = op->aop = aop = newAsmop(AOP_REG);
575 aop->size = sym->nRegs;
576 for ( i = 0 ; i < sym->nRegs ;i++)
577 aop->aopu.aop_reg[i] = sym->regs[i];
580 /*-----------------------------------------------------------------*/
581 /* freeAsmop - free up the asmop given to an operand */
582 /*----------------------------------------------------------------*/
583 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
600 /* depending on the asmop type only three cases need work AOP_RO
601 , AOP_R1 && AOP_STK */
606 emitcode ("pop","ar0");
610 bitVectUnSetBit(ic->rUsed,R0_IDX);
616 emitcode ("pop","ar1");
620 bitVectUnSetBit(ic->rUsed,R1_IDX);
626 int stk = aop->aopu.aop_stk + aop->size;
627 bitVectUnSetBit(ic->rUsed,R0_IDX);
628 bitVectUnSetBit(ic->rUsed,R1_IDX);
630 getFreePtr(ic,&aop,FALSE);
632 emitcode ("mov","a,_bp");
633 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
634 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
636 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
639 emitcode("pop","acc");
640 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
642 emitcode("dec","%s",aop->aopu.aop_ptr->name);
645 freeAsmop(op,NULL,ic,TRUE);
647 emitcode("pop","ar0");
652 emitcode("pop","ar1");
659 /* all other cases just dealloc */
663 OP_SYMBOL(op)->aop = NULL;
664 /* if the symbol has a spill */
666 SPIL_LOC(op)->aop = NULL;
671 /*-----------------------------------------------------------------*/
672 /* aopGet - for fetching value of the aop */
673 /*-----------------------------------------------------------------*/
674 static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
679 /* offset is greater than
681 if (offset > (aop->size - 1) &&
682 aop->type != AOP_LIT)
685 /* depending on type */
690 /* if we need to increment it */
691 while (offset > aop->coff) {
692 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
696 while (offset < aop->coff) {
697 emitcode("dec","%s",aop->aopu.aop_ptr->name);
703 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
704 return (dname ? "acc" : "a");
706 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
707 ALLOC_ATOMIC(rs,strlen(s)+1);
712 while (offset > aop->coff) {
713 emitcode ("inc","dptr");
717 while (offset < aop->coff) {
718 emitcode("lcall","__decdptr");
725 emitcode("movc","a,@a+dptr");
728 emitcode("movx","a,@dptr");
729 return (dname ? "acc" : "a");
734 sprintf (s,"#(%s)",aop->aopu.aop_immd);
737 sprintf(s,"#(%s >> %d)",
743 ALLOC_ATOMIC(rs,strlen(s)+1);
749 sprintf(s,"(%s + %d)",
753 sprintf(s,"%s",aop->aopu.aop_dir);
754 ALLOC_ATOMIC(rs,strlen(s)+1);
760 return aop->aopu.aop_reg[offset]->dname;
762 return aop->aopu.aop_reg[offset]->name;
766 emitcode("mov","c,%s",aop->aopu.aop_dir);
767 emitcode("rlc","a") ;
768 return (dname ? "acc" : "a");
771 if (!offset && dname)
773 return aop->aopu.aop_str[offset];
776 return aopLiteral (aop->aopu.aop_lit,offset);
780 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
784 return aop->aopu.aop_str[offset];
788 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
789 "aopget got unsupported aop->type");
792 /*-----------------------------------------------------------------*/
793 /* aopPut - puts a string for a aop */
794 /*-----------------------------------------------------------------*/
795 static void aopPut (asmop *aop, char *s, int offset)
800 if (aop->size && offset > ( aop->size - 1)) {
801 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
802 "aopPut got offset > aop->size");
806 /* will assign value to value */
807 /* depending on where it is ofcourse */
811 sprintf(d,"(%s + %d)",
812 aop->aopu.aop_dir,offset);
814 sprintf(d,"%s",aop->aopu.aop_dir);
817 emitcode("mov","%s,%s",d,s);
822 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
823 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
825 strcmp(s,"r0") == 0 ||
826 strcmp(s,"r1") == 0 ||
827 strcmp(s,"r2") == 0 ||
828 strcmp(s,"r3") == 0 ||
829 strcmp(s,"r4") == 0 ||
830 strcmp(s,"r5") == 0 ||
831 strcmp(s,"r6") == 0 ||
832 strcmp(s,"r7") == 0 )
833 emitcode("mov","%s,%s",
834 aop->aopu.aop_reg[offset]->dname,s);
836 emitcode("mov","%s,%s",
837 aop->aopu.aop_reg[offset]->name,s);
843 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
844 "aopPut writting to code space");
848 while (offset > aop->coff) {
850 emitcode ("inc","dptr");
853 while (offset < aop->coff) {
855 emitcode("lcall","__decdptr");
860 /* if not in accumulater */
863 emitcode ("movx","@dptr,a");
868 while (offset > aop->coff) {
870 emitcode("inc","%s",aop->aopu.aop_ptr->name);
872 while (offset < aop->coff) {
874 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
880 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
885 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
887 if (strcmp(s,"r0") == 0 ||
888 strcmp(s,"r1") == 0 ||
889 strcmp(s,"r2") == 0 ||
890 strcmp(s,"r3") == 0 ||
891 strcmp(s,"r4") == 0 ||
892 strcmp(s,"r5") == 0 ||
893 strcmp(s,"r6") == 0 ||
894 strcmp(s,"r7") == 0 ) {
896 sprintf(buffer,"a%s",s);
897 emitcode("mov","@%s,%s",
898 aop->aopu.aop_ptr->name,buffer);
900 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
905 if (strcmp(s,"a") == 0)
906 emitcode("push","acc");
908 emitcode("push","%s",s);
913 /* if bit variable */
914 if (!aop->aopu.aop_dir) {
919 emitcode("clr","%s",aop->aopu.aop_dir);
922 emitcode("setb","%s",aop->aopu.aop_dir);
925 emitcode("mov","%s,c",aop->aopu.aop_dir);
927 lbl = newiTempLabel(NULL);
933 emitcode("jz","%05d$",lbl->key+100);
935 emitcode("","%05d$:",lbl->key+100);
936 emitcode("mov","%s,c",aop->aopu.aop_dir);
943 if (strcmp(aop->aopu.aop_str[offset],s))
944 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
949 if (!offset && (strcmp(s,"acc") == 0))
952 if (strcmp(aop->aopu.aop_str[offset],s))
953 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
957 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
958 "aopPut got unsupported aop->type");
966 /*-----------------------------------------------------------------*/
967 /* pointToEnd :- points to the last byte of the operand */
968 /*-----------------------------------------------------------------*/
969 static void pointToEnd (asmop *aop)
975 aop->coff = count = (aop->size - 1);
980 emitcode("inc","%s",aop->aopu.aop_ptr->name);
984 emitcode("inc","dptr");
991 /*-----------------------------------------------------------------*/
992 /* reAdjustPreg - points a register back to where it should */
993 /*-----------------------------------------------------------------*/
994 static void reAdjustPreg (asmop *aop)
999 if ((size = aop->size) <= 1)
1002 switch (aop->type) {
1006 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1010 emitcode("lcall","__decdptr");
1017 #define AOP(op) op->aop
1018 #define AOP_TYPE(op) AOP(op)->type
1019 #define AOP_SIZE(op) AOP(op)->size
1020 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1021 AOP_TYPE(x) == AOP_R0))
1023 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1024 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1026 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1027 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1028 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1030 /*-----------------------------------------------------------------*/
1031 /* genNotFloat - generates not for float operations */
1032 /*-----------------------------------------------------------------*/
1033 static void genNotFloat (operand *op, operand *res)
1039 /* we will put 127 in the first byte of
1041 aopPut(AOP(res),"#127",0);
1042 size = AOP_SIZE(op) - 1;
1045 l = aopGet(op->aop,offset++,FALSE,FALSE);
1049 emitcode("orl","a,%s",
1051 offset++,FALSE,FALSE));
1053 tlbl = newiTempLabel(NULL);
1055 tlbl = newiTempLabel(NULL);
1056 aopPut(res->aop,one,1);
1057 emitcode("jz","%05d$",(tlbl->key+100));
1058 aopPut(res->aop,zero,1);
1059 emitcode("","%05d$:",(tlbl->key+100));
1061 size = res->aop->size - 2;
1063 /* put zeros in the rest */
1065 aopPut(res->aop,zero,offset++);
1068 /*-----------------------------------------------------------------*/
1069 /* opIsGptr: returns non-zero if the passed operand is */
1070 /* a generic pointer type. */
1071 /*-----------------------------------------------------------------*/
1072 static int opIsGptr(operand *op)
1074 link *type = operandType(op);
1076 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1083 /*-----------------------------------------------------------------*/
1084 /* getDataSize - get the operand data size */
1085 /*-----------------------------------------------------------------*/
1086 static int getDataSize(operand *op)
1089 size = AOP_SIZE(op);
1090 if (size == GPTRSIZE)
1092 link *type = operandType(op);
1093 if (IS_GENPTR(type))
1095 /* generic pointer; arithmetic operations
1096 * should ignore the high byte (pointer type).
1104 /*-----------------------------------------------------------------*/
1105 /* outAcc - output Acc */
1106 /*-----------------------------------------------------------------*/
1107 static void outAcc(operand *result)
1110 size = getDataSize(result);
1112 aopPut(AOP(result),"a",0);
1115 /* unsigned or positive */
1117 aopPut(AOP(result),zero,offset++);
1122 /*-----------------------------------------------------------------*/
1123 /* outBitC - output a bit C */
1124 /*-----------------------------------------------------------------*/
1125 static void outBitC(operand *result)
1127 /* if the result is bit */
1128 if (AOP_TYPE(result) == AOP_CRY)
1129 aopPut(AOP(result),"c",0);
1131 emitcode("clr","a");
1132 emitcode("rlc","a");
1137 /*-----------------------------------------------------------------*/
1138 /* toBoolean - emit code for orl a,operator(sizeop) */
1139 /*-----------------------------------------------------------------*/
1140 static void toBoolean(operand *oper)
1142 int size = AOP_SIZE(oper) - 1;
1144 MOVA(aopGet(AOP(oper),0,FALSE,FALSE));
1146 emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE));
1150 /*-----------------------------------------------------------------*/
1151 /* genNot - generate code for ! operation */
1152 /*-----------------------------------------------------------------*/
1153 static void genNot (iCode *ic)
1156 link *optype = operandType(IC_LEFT(ic));
1158 /* assign asmOps to operand & result */
1159 aopOp (IC_LEFT(ic),ic,FALSE);
1160 aopOp (IC_RESULT(ic),ic,TRUE);
1162 /* if in bit space then a special case */
1163 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1164 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1165 emitcode("cpl","c");
1166 outBitC(IC_RESULT(ic));
1170 /* if type float then do float */
1171 if (IS_FLOAT(optype)) {
1172 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1176 toBoolean(IC_LEFT(ic));
1178 tlbl = newiTempLabel(NULL);
1179 emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1180 emitcode("","%05d$:",tlbl->key+100);
1181 outBitC(IC_RESULT(ic));
1184 /* release the aops */
1185 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1186 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1190 /*-----------------------------------------------------------------*/
1191 /* genCpl - generate code for complement */
1192 /*-----------------------------------------------------------------*/
1193 static void genCpl (iCode *ic)
1199 /* assign asmOps to operand & result */
1200 aopOp (IC_LEFT(ic),ic,FALSE);
1201 aopOp (IC_RESULT(ic),ic,TRUE);
1203 /* if both are in bit space then
1205 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1206 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1208 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1209 emitcode("cpl","c");
1210 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1214 size = AOP_SIZE(IC_RESULT(ic));
1216 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1218 emitcode("cpl","a");
1219 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1224 /* release the aops */
1225 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1226 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1229 /*-----------------------------------------------------------------*/
1230 /* genUminusFloat - unary minus for floating points */
1231 /*-----------------------------------------------------------------*/
1232 static void genUminusFloat(operand *op,operand *result)
1234 int size ,offset =0 ;
1236 /* for this we just need to flip the
1237 first it then copy the rest in place */
1238 size = AOP_SIZE(op) - 1;
1239 l = aopGet(AOP(op),3,FALSE,FALSE);
1243 emitcode("cpl","acc.7");
1244 aopPut(AOP(result),"a",3);
1248 aopGet(AOP(op),offset,FALSE,FALSE),
1254 /*-----------------------------------------------------------------*/
1255 /* genUminus - unary minus code generation */
1256 /*-----------------------------------------------------------------*/
1257 static void genUminus (iCode *ic)
1260 link *optype, *rtype;
1264 aopOp(IC_LEFT(ic),ic,FALSE);
1265 aopOp(IC_RESULT(ic),ic,TRUE);
1267 /* if both in bit space then special
1269 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1270 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1272 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1273 emitcode("cpl","c");
1274 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1278 optype = operandType(IC_LEFT(ic));
1279 rtype = operandType(IC_RESULT(ic));
1281 /* if float then do float stuff */
1282 if (IS_FLOAT(optype)) {
1283 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1287 /* otherwise subtract from zero */
1288 size = AOP_SIZE(IC_LEFT(ic));
1292 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1293 if (!strcmp(l,"a")) {
1294 emitcode("cpl","a");
1295 emitcode("inc","a");
1297 emitcode("clr","a");
1298 emitcode("subb","a,%s",l);
1300 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1303 /* if any remaining bytes in the result */
1304 /* we just need to propagate the sign */
1305 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1306 emitcode("rlc","a");
1307 emitcode("subb","a,acc");
1309 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1313 /* release the aops */
1314 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1315 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1318 /*-----------------------------------------------------------------*/
1319 /* saveRegisters - will look for a call and save the registers */
1320 /*-----------------------------------------------------------------*/
1321 static void saveRegisters(iCode *lic)
1329 for (ic = lic ; ic ; ic = ic->next)
1330 if (ic->op == CALL || ic->op == PCALL)
1334 fprintf(stderr,"found parameter push with no function call\n");
1338 /* if the registers have been saved already then
1340 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1343 /* find the registers in use at this time
1344 and push them away to safety */
1345 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1349 if (options.useXstack) {
1350 if (bitVectBitValue(rsave,R0_IDX))
1351 emitcode("mov","b,r0");
1352 emitcode("mov","r0,%s",spname);
1353 for (i = 0 ; i < mcs51_nRegs ; i++) {
1354 if (bitVectBitValue(rsave,i)) {
1356 emitcode("mov","a,b");
1358 emitcode("mov","a,%s",mcs51_regWithIdx(i)->name);
1359 emitcode("movx","@r0,a");
1360 emitcode("inc","r0");
1363 emitcode("mov","%s,r0",spname);
1364 if (bitVectBitValue(rsave,R0_IDX))
1365 emitcode("mov","r0,b");
1367 for (i = 0 ; i < mcs51_nRegs ; i++) {
1368 if (bitVectBitValue(rsave,i))
1369 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
1372 detype = getSpec(operandType(IC_LEFT(ic)));
1374 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1375 IS_ISR(currFunc->etype) &&
1378 saverbank(SPEC_BANK(detype),ic,TRUE);
1381 /*-----------------------------------------------------------------*/
1382 /* unsaveRegisters - pop the pushed registers */
1383 /*-----------------------------------------------------------------*/
1384 static void unsaveRegisters (iCode *ic)
1388 /* find the registers in use at this time
1389 and push them away to safety */
1390 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1393 if (options.useXstack) {
1394 emitcode("mov","r0,%s",spname);
1395 for (i = mcs51_nRegs ; i >= 0 ; i--) {
1396 if (bitVectBitValue(rsave,i)) {
1397 emitcode("dec","r0");
1398 emitcode("movx","a,@r0");
1400 emitcode("mov","b,a");
1402 emitcode("mov","%s,a",mcs51_regWithIdx(i)->name);
1406 emitcode("mov","%s,r0",spname);
1407 if (bitVectBitValue(rsave,R0_IDX))
1408 emitcode("mov","r0,b");
1410 for (i = mcs51_nRegs ; i >= 0 ; i--) {
1411 if (bitVectBitValue(rsave,i))
1412 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
1418 /*-----------------------------------------------------------------*/
1420 /*-----------------------------------------------------------------*/
1421 static void pushSide(operand * oper, int size)
1425 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1426 if (AOP_TYPE(oper) != AOP_REG &&
1427 AOP_TYPE(oper) != AOP_DIR &&
1429 emitcode("mov","a,%s",l);
1430 emitcode("push","acc");
1432 emitcode("push","%s",l);
1436 /*-----------------------------------------------------------------*/
1437 /* assignResultValue - */
1438 /*-----------------------------------------------------------------*/
1439 static void assignResultValue(operand * oper)
1442 int size = AOP_SIZE(oper);
1444 aopPut(AOP(oper),fReturn[offset],offset);
1450 /*-----------------------------------------------------------------*/
1451 /* genXpush - pushes onto the external stack */
1452 /*-----------------------------------------------------------------*/
1453 static void genXpush (iCode *ic)
1455 asmop *aop = newAsmop(0);
1457 int size,offset = 0;
1459 aopOp(IC_LEFT(ic),ic,FALSE);
1460 r = getFreePtr(ic,&aop,FALSE);
1463 emitcode("mov","%s,_spx",r->name);
1465 size = AOP_SIZE(IC_LEFT(ic));
1468 char *l = aopGet(AOP(IC_LEFT(ic)),
1469 offset++,FALSE,FALSE);
1471 emitcode("movx","@%s,a",r->name);
1472 emitcode("inc","%s",r->name);
1477 emitcode("mov","_spx,%s",r->name);
1479 freeAsmop(NULL,aop,ic,TRUE);
1480 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1483 /*-----------------------------------------------------------------*/
1484 /* genIpush - genrate code for pushing this gets a little complex */
1485 /*-----------------------------------------------------------------*/
1486 static void genIpush (iCode *ic)
1488 int size, offset = 0 ;
1492 /* if this is not a parm push : ie. it is spill push
1493 and spill push is always done on the local stack */
1494 if (!ic->parmPush) {
1496 /* and the item is spilt then do nothing */
1497 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1500 aopOp(IC_LEFT(ic),ic,FALSE);
1501 size = AOP_SIZE(IC_LEFT(ic));
1502 /* push it on the stack */
1504 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1509 emitcode("push","%s",l);
1514 /* this is a paramter push: in this case we call
1515 the routine to find the call and save those
1516 registers that need to be saved */
1519 /* if use external stack then call the external
1520 stack pushing routine */
1521 if (options.useXstack) {
1526 /* then do the push */
1527 aopOp(IC_LEFT(ic),ic,FALSE);
1530 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1531 size = AOP_SIZE(IC_LEFT(ic));
1534 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1535 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1536 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1538 emitcode("mov","a,%s",l);
1539 emitcode("push","acc");
1541 emitcode("push","%s",l);
1544 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1547 /*-----------------------------------------------------------------*/
1548 /* genIpop - recover the registers: can happen only for spilling */
1549 /*-----------------------------------------------------------------*/
1550 static void genIpop (iCode *ic)
1555 /* if the temp was not pushed then */
1556 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1559 aopOp(IC_LEFT(ic),ic,FALSE);
1560 size = AOP_SIZE(IC_LEFT(ic));
1563 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1566 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1569 /*-----------------------------------------------------------------*/
1570 /* unsaverbank - restores the resgister bank from stack */
1571 /*-----------------------------------------------------------------*/
1572 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1579 if (options.useXstack) {
1581 r = getFreePtr(ic,&aop,FALSE);
1584 emitcode("mov","%s,_spx",r->name);
1585 emitcode("movx","a,@%s",r->name);
1586 emitcode("mov","psw,a");
1587 emitcode("dec","%s",r->name);
1590 emitcode ("pop","psw");
1593 for (i = (mcs51_nRegs - 1) ; i >= 0 ;i--) {
1594 if (options.useXstack) {
1595 emitcode("movx","a,@%s",r->name);
1596 emitcode("mov","(%s+%d),a",
1597 regs8051[i].base,8*bank+regs8051[i].offset);
1598 emitcode("dec","%s",r->name);
1601 emitcode("pop","(%s+%d)",
1602 regs8051[i].base,8*bank+regs8051[i].offset);
1605 if (options.useXstack) {
1607 emitcode("mov","_spx,%s",r->name);
1608 freeAsmop(NULL,aop,ic,TRUE);
1613 /*-----------------------------------------------------------------*/
1614 /* saverbank - saves an entire register bank on the stack */
1615 /*-----------------------------------------------------------------*/
1616 static void saverbank (int bank, iCode *ic, bool pushPsw)
1622 if (options.useXstack) {
1625 r = getFreePtr(ic,&aop,FALSE);
1626 emitcode("mov","%s,_spx",r->name);
1630 for (i = 0 ; i < mcs51_nRegs ;i++) {
1631 if (options.useXstack) {
1632 emitcode("inc","%s",r->name);
1633 emitcode("mov","a,(%s+%d)",
1634 regs8051[i].base,8*bank+regs8051[i].offset);
1635 emitcode("movx","@%s,a",r->name);
1637 emitcode("push","(%s+%d)",
1638 regs8051[i].base,8*bank+regs8051[i].offset);
1642 if (options.useXstack) {
1643 emitcode("mov","a,psw");
1644 emitcode("movx","@%s,a",r->name);
1645 emitcode("inc","%s",r->name);
1646 emitcode("mov","_spx,%s",r->name);
1647 freeAsmop (NULL,aop,ic,TRUE);
1650 emitcode("push","psw");
1652 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1658 /*-----------------------------------------------------------------*/
1659 /* genCall - generates a call statement */
1660 /*-----------------------------------------------------------------*/
1661 static void genCall (iCode *ic)
1665 /* if caller saves & we have not saved then */
1669 /* if we are calling a function that is not using
1670 the same register bank then we need to save the
1671 destination registers on the stack */
1672 detype = getSpec(operandType(IC_LEFT(ic)));
1674 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1675 IS_ISR(currFunc->etype) &&
1678 saverbank(SPEC_BANK(detype),ic,TRUE);
1680 /* if send set is not empty the assign */
1684 for (sic = setFirstItem(_G.sendSet) ; sic ;
1685 sic = setNextItem(_G.sendSet)) {
1686 int size, offset = 0;
1687 aopOp(IC_LEFT(sic),sic,FALSE);
1688 size = AOP_SIZE(IC_LEFT(sic));
1690 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1692 if (strcmp(l,fReturn[offset]))
1693 emitcode("mov","%s,%s",
1698 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1703 emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1704 OP_SYMBOL(IC_LEFT(ic))->rname :
1705 OP_SYMBOL(IC_LEFT(ic))->name));
1707 /* if we need assign a result value */
1708 if ((IS_ITEMP(IC_RESULT(ic)) &&
1709 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1710 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1711 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1714 aopOp(IC_RESULT(ic),ic,FALSE);
1717 assignResultValue(IC_RESULT(ic));
1719 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1722 /* adjust the stack for parameters if
1724 if (IC_LEFT(ic)->parmBytes) {
1726 if (IC_LEFT(ic)->parmBytes > 3) {
1727 emitcode("mov","a,%s",spname);
1728 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1729 emitcode("mov","%s,a",spname);
1731 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1732 emitcode("dec","%s",spname);
1736 /* if register bank was saved then pop them */
1738 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1740 /* if we hade saved some registers then unsave them */
1741 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1742 unsaveRegisters (ic);
1747 /*-----------------------------------------------------------------*/
1748 /* genPcall - generates a call by pointer statement */
1749 /*-----------------------------------------------------------------*/
1750 static void genPcall (iCode *ic)
1753 symbol *rlbl = newiTempLabel(NULL);
1756 /* if caller saves & we have not saved then */
1760 /* if we are calling a function that is not using
1761 the same register bank then we need to save the
1762 destination registers on the stack */
1763 detype = getSpec(operandType(IC_LEFT(ic)));
1765 IS_ISR(currFunc->etype) &&
1766 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
1767 saverbank(SPEC_BANK(detype),ic,TRUE);
1770 /* push the return address on to the stack */
1771 emitcode("mov","a,#%05d$",(rlbl->key+100));
1772 emitcode("push","acc");
1773 emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
1774 emitcode("push","acc");
1776 if (options.model == MODEL_FLAT24)
1778 emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
1779 emitcode("push","acc");
1782 /* now push the calling address */
1783 aopOp(IC_LEFT(ic),ic,FALSE);
1785 pushSide(IC_LEFT(ic), FPTRSIZE);
1787 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1789 /* if send set is not empty the assign */
1793 for (sic = setFirstItem(_G.sendSet) ; sic ;
1794 sic = setNextItem(_G.sendSet)) {
1795 int size, offset = 0;
1796 aopOp(IC_LEFT(sic),sic,FALSE);
1797 size = AOP_SIZE(IC_LEFT(sic));
1799 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1801 if (strcmp(l,fReturn[offset]))
1802 emitcode("mov","%s,%s",
1807 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1813 emitcode("","%05d$:",(rlbl->key+100));
1816 /* if we need assign a result value */
1817 if ((IS_ITEMP(IC_RESULT(ic)) &&
1818 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1819 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
1820 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1823 aopOp(IC_RESULT(ic),ic,FALSE);
1826 assignResultValue(IC_RESULT(ic));
1828 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1831 /* adjust the stack for parameters if
1833 if (IC_LEFT(ic)->parmBytes) {
1835 if (IC_LEFT(ic)->parmBytes > 3) {
1836 emitcode("mov","a,%s",spname);
1837 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1838 emitcode("mov","%s,a",spname);
1840 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1841 emitcode("dec","%s",spname);
1845 /* if register bank was saved then unsave them */
1847 (SPEC_BANK(currFunc->etype) !=
1849 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1851 /* if we hade saved some registers then
1854 unsaveRegisters (ic);
1858 /*-----------------------------------------------------------------*/
1859 /* resultRemat - result is rematerializable */
1860 /*-----------------------------------------------------------------*/
1861 static int resultRemat (iCode *ic)
1863 if (SKIP_IC(ic) || ic->op == IFX)
1866 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1867 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1868 if (sym->remat && !POINTER_SET(ic))
1875 /*-----------------------------------------------------------------*/
1876 /* inExcludeList - return 1 if the string is in exclude Reg list */
1877 /*-----------------------------------------------------------------*/
1878 static bool inExcludeList(char *s)
1882 if (options.excludeRegs[i] &&
1883 strcasecmp(options.excludeRegs[i],"none") == 0)
1886 for ( i = 0 ; options.excludeRegs[i]; i++) {
1887 if (options.excludeRegs[i] &&
1888 strcasecmp(s,options.excludeRegs[i]) == 0)
1894 /*-----------------------------------------------------------------*/
1895 /* genFunction - generated code for function entry */
1896 /*-----------------------------------------------------------------*/
1897 static void genFunction (iCode *ic)
1903 /* create the function header */
1904 emitcode(";","-----------------------------------------");
1905 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1906 emitcode(";","-----------------------------------------");
1908 emitcode("","%s:",sym->rname);
1909 fetype = getSpec(operandType(IC_LEFT(ic)));
1911 /* if critical function then turn interrupts off */
1912 if (SPEC_CRTCL(fetype))
1913 emitcode("clr","ea");
1915 /* here we need to generate the equates for the
1916 register bank if required */
1917 if (SPEC_BANK(fetype) != rbank) {
1920 rbank = SPEC_BANK(fetype);
1921 for ( i = 0 ; i < mcs51_nRegs ; i++ ) {
1922 if (strcmp(regs8051[i].base,"0") == 0)
1923 emitcode("","%s = 0x%02x",
1925 8*rbank+regs8051[i].offset);
1927 emitcode ("","%s = %s + 0x%02x",
1930 8*rbank+regs8051[i].offset);
1934 /* if this is an interrupt service routine then
1935 save acc, b, dpl, dph */
1936 if (IS_ISR(sym->etype)) {
1938 if (!inExcludeList("acc"))
1939 emitcode ("push","acc");
1940 if (!inExcludeList("b"))
1941 emitcode ("push","b");
1942 if (!inExcludeList("dpl"))
1943 emitcode ("push","dpl");
1944 if (!inExcludeList("dph"))
1945 emitcode ("push","dph");
1946 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
1947 emitcode ("push", "dpx");
1948 /* if this isr has no bank i.e. is going to
1949 run with bank 0 , then we need to save more
1951 if (!SPEC_BANK(sym->etype)) {
1953 /* if this function does not call any other
1954 function then we can be economical and
1955 save only those registers that are used */
1956 if (! sym->hasFcall) {
1959 /* if any registers used */
1960 if (sym->regsUsed) {
1961 /* save the registers used */
1962 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
1963 if (bitVectBitValue(sym->regsUsed,i) ||
1964 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
1965 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
1970 /* this function has a function call cannot
1971 determines register usage so we will have the
1973 saverbank(0,ic,FALSE);
1977 /* if callee-save to be used for this function
1978 then save the registers being used in this function */
1979 if (sym->calleeSave) {
1982 /* if any registers used */
1983 if (sym->regsUsed) {
1984 /* save the registers used */
1985 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
1986 if (bitVectBitValue(sym->regsUsed,i) ||
1987 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
1988 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
1996 /* set the register bank to the desired value */
1997 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
1998 emitcode("push","psw");
1999 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2002 if (IS_RENT(sym->etype) || options.stackAuto) {
2004 if (options.useXstack) {
2005 emitcode("mov","r0,%s",spname);
2006 emitcode("mov","a,_bp");
2007 emitcode("movx","@r0,a");
2008 emitcode("inc","%s",spname);
2011 /* set up the stack */
2012 emitcode ("push","_bp"); /* save the callers stack */
2013 emitcode ("mov","_bp,%s",spname);
2016 /* adjust the stack for the function */
2021 werror(W_STACK_OVERFLOW,sym->name);
2023 if (i > 3 && sym->recvSize < 4) {
2025 emitcode ("mov","a,sp");
2026 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2027 emitcode ("mov","sp,a");
2032 emitcode("inc","sp");
2037 emitcode ("mov","a,_spx");
2038 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2039 emitcode ("mov","_spx,a");
2044 /*-----------------------------------------------------------------*/
2045 /* genEndFunction - generates epilogue for functions */
2046 /*-----------------------------------------------------------------*/
2047 static void genEndFunction (iCode *ic)
2049 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2051 if (IS_RENT(sym->etype) || options.stackAuto)
2052 emitcode ("mov","%s,_bp",spname);
2054 /* if use external stack but some variables were
2055 added to the local stack then decrement the
2057 if (options.useXstack && sym->stack) {
2058 emitcode("mov","a,sp");
2059 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2060 emitcode("mov","sp,a");
2064 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2065 if (options.useXstack) {
2066 emitcode("mov","r0,%s",spname);
2067 emitcode("movx","a,@r0");
2068 emitcode("mov","_bp,a");
2069 emitcode("dec","%s",spname);
2072 emitcode ("pop","_bp");
2075 /* restore the register bank */
2076 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2077 emitcode ("pop","psw");
2079 if (IS_ISR(sym->etype)) {
2081 /* now we need to restore the registers */
2082 /* if this isr has no bank i.e. is going to
2083 run with bank 0 , then we need to save more
2085 if (!SPEC_BANK(sym->etype)) {
2087 /* if this function does not call any other
2088 function then we can be economical and
2089 save only those registers that are used */
2090 if (! sym->hasFcall) {
2093 /* if any registers used */
2094 if (sym->regsUsed) {
2095 /* save the registers used */
2096 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2097 if (bitVectBitValue(sym->regsUsed,i) ||
2098 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2099 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
2104 /* this function has a function call cannot
2105 determines register usage so we will have the
2107 unsaverbank(0,ic,FALSE);
2111 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2112 emitcode ("pop", "dpx");
2113 if (!inExcludeList("dph"))
2114 emitcode ("pop","dph");
2115 if (!inExcludeList("dpl"))
2116 emitcode ("pop","dpl");
2117 if (!inExcludeList("b"))
2118 emitcode ("pop","b");
2119 if (!inExcludeList("acc"))
2120 emitcode ("pop","acc");
2122 if (SPEC_CRTCL(sym->etype))
2123 emitcode("setb","ea");
2125 /* if debug then send end of function */
2126 /* if (options.debug && currFunc) { */
2129 emitcode("","C$%s$%d$%d$%d ==.",
2130 ic->filename,currFunc->lastLine,
2131 ic->level,ic->block);
2132 if (IS_STATIC(currFunc->etype))
2133 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2135 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2139 emitcode ("reti","");
2142 if (SPEC_CRTCL(sym->etype))
2143 emitcode("setb","ea");
2145 if (sym->calleeSave) {
2148 /* if any registers used */
2149 if (sym->regsUsed) {
2150 /* save the registers used */
2151 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2152 if (bitVectBitValue(sym->regsUsed,i) ||
2153 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2154 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
2160 /* if debug then send end of function */
2161 /* if (options.debug && currFunc) { */
2164 emitcode("","C$%s$%d$%d$%d ==.",
2165 ic->filename,currFunc->lastLine,
2166 ic->level,ic->block);
2167 if (IS_STATIC(currFunc->etype))
2168 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2170 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2174 emitcode ("ret","");
2179 /*-----------------------------------------------------------------*/
2180 /* genRet - generate code for return statement */
2181 /*-----------------------------------------------------------------*/
2182 static void genRet (iCode *ic)
2184 int size,offset = 0 , pushed = 0;
2186 /* if we have no return value then
2187 just generate the "ret" */
2191 /* we have something to return then
2192 move the return value into place */
2193 aopOp(IC_LEFT(ic),ic,FALSE);
2194 size = AOP_SIZE(IC_LEFT(ic));
2198 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2199 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2201 emitcode("push","%s",l);
2204 l = aopGet(AOP(IC_LEFT(ic)),offset,
2206 if (strcmp(fReturn[offset],l))
2207 emitcode("mov","%s,%s",fReturn[offset++],l);
2214 if (strcmp(fReturn[pushed],"a"))
2215 emitcode("pop",fReturn[pushed]);
2217 emitcode("pop","acc");
2220 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2223 /* generate a jump to the return label
2224 if the next is not the return statement */
2225 if (!(ic->next && ic->next->op == LABEL &&
2226 IC_LABEL(ic->next) == returnLabel))
2228 emitcode("ljmp","%05d$",(returnLabel->key+100));
2232 /*-----------------------------------------------------------------*/
2233 /* genLabel - generates a label */
2234 /*-----------------------------------------------------------------*/
2235 static void genLabel (iCode *ic)
2237 /* special case never generate */
2238 if (IC_LABEL(ic) == entryLabel)
2241 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2244 /*-----------------------------------------------------------------*/
2245 /* genGoto - generates a ljmp */
2246 /*-----------------------------------------------------------------*/
2247 static void genGoto (iCode *ic)
2249 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2252 /*-----------------------------------------------------------------*/
2253 /* findLabelBackwards: walks back through the iCode chain looking */
2254 /* for the given label. Returns number of iCode instructions */
2255 /* between that label and given ic. */
2256 /* Returns zero if label not found. */
2257 /*-----------------------------------------------------------------*/
2258 static int findLabelBackwards(iCode *ic, int key)
2267 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2269 /* printf("findLabelBackwards = %d\n", count); */
2274 /* printf("findLabelBackwards: not found.\n"); */
2279 /*-----------------------------------------------------------------*/
2280 /* genPlusIncr :- does addition with increment if possible */
2281 /*-----------------------------------------------------------------*/
2282 static bool genPlusIncr (iCode *ic)
2284 unsigned int icount ;
2285 unsigned int size = getDataSize(IC_RESULT(ic));
2287 /* will try to generate an increment */
2288 /* if the right side is not a literal
2290 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2293 /* if the literal value of the right hand side
2294 is greater than 4 then it is not worth it */
2295 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2298 /* if increment 16 bits in register */
2299 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2306 /* If the next instruction is a goto and the goto target
2307 * is < 10 instructions previous to this, we can generate
2308 * jumps straight to that target.
2310 if (ic->next && ic->next->op == GOTO
2311 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2312 && labelRange <= 10 )
2314 emitcode(";", "tail increment optimized");
2315 tlbl = IC_LABEL(ic->next);
2320 tlbl = newiTempLabel(NULL);
2323 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2324 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2325 IS_AOP_PREG(IC_RESULT(ic)))
2326 emitcode("cjne","%s,#0x00,%05d$"
2327 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2330 emitcode("clr","a");
2331 emitcode("cjne","a,%s,%05d$"
2332 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2336 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2339 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2340 IS_AOP_PREG(IC_RESULT(ic)))
2341 emitcode("cjne","%s,#0x00,%05d$"
2342 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2345 emitcode("cjne","a,%s,%05d$"
2346 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2349 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2353 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2354 IS_AOP_PREG(IC_RESULT(ic)))
2355 emitcode("cjne","%s,#0x00,%05d$"
2356 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2359 emitcode("cjne","a,%s,%05d$"
2360 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2363 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2368 emitcode("","%05d$:",tlbl->key+100);
2373 /* if the sizes are greater than 1 then we cannot */
2374 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2375 AOP_SIZE(IC_LEFT(ic)) > 1 )
2378 /* we can if the aops of the left & result match or
2379 if they are in registers and the registers are the
2381 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2384 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2385 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2386 aopPut(AOP(IC_RESULT(ic)),"a",0);
2390 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2399 /*-----------------------------------------------------------------*/
2400 /* outBitAcc - output a bit in acc */
2401 /*-----------------------------------------------------------------*/
2402 static void outBitAcc(operand *result)
2404 symbol *tlbl = newiTempLabel(NULL);
2405 /* if the result is a bit */
2406 if (AOP_TYPE(result) == AOP_CRY){
2407 aopPut(AOP(result),"a",0);
2410 emitcode("jz","%05d$",tlbl->key+100);
2411 emitcode("mov","a,%s",one);
2412 emitcode("","%05d$:",tlbl->key+100);
2417 /*-----------------------------------------------------------------*/
2418 /* genPlusBits - generates code for addition of two bits */
2419 /*-----------------------------------------------------------------*/
2420 static void genPlusBits (iCode *ic)
2422 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2423 symbol *lbl = newiTempLabel(NULL);
2424 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2425 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2426 emitcode("cpl","c");
2427 emitcode("","%05d$:",(lbl->key+100));
2428 outBitC(IC_RESULT(ic));
2431 emitcode("clr","a");
2432 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2433 emitcode("rlc","a");
2434 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2435 emitcode("addc","a,#0x00");
2436 outAcc(IC_RESULT(ic));
2441 /* This is the original version of this code.
2443 * This is being kept around for reference,
2444 * because I am not entirely sure I got it right...
2446 static void adjustArithmeticResult(iCode *ic)
2448 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2449 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2450 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2451 aopPut(AOP(IC_RESULT(ic)),
2452 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2455 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2456 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
2457 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2458 aopPut(AOP(IC_RESULT(ic)),
2459 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2462 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2463 AOP_SIZE(IC_LEFT(ic)) < 3 &&
2464 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
2465 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2466 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2468 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2469 aopPut(AOP(IC_RESULT(ic)),buffer,2);
2473 /* This is the pure and virtuous version of this code.
2474 * I'm pretty certain it's right, but not enough to toss the old
2477 static void adjustArithmeticResult(iCode *ic)
2479 if (opIsGptr(IC_RESULT(ic)) &&
2480 opIsGptr(IC_LEFT(ic)) &&
2481 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2483 aopPut(AOP(IC_RESULT(ic)),
2484 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
2488 if (opIsGptr(IC_RESULT(ic)) &&
2489 opIsGptr(IC_RIGHT(ic)) &&
2490 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2492 aopPut(AOP(IC_RESULT(ic)),
2493 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
2497 if (opIsGptr(IC_RESULT(ic)) &&
2498 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2499 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2500 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2501 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2503 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2504 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2509 /*-----------------------------------------------------------------*/
2510 /* genPlus - generates code for addition */
2511 /*-----------------------------------------------------------------*/
2512 static void genPlus (iCode *ic)
2514 int size, offset = 0;
2516 /* special cases :- */
2518 aopOp (IC_LEFT(ic),ic,FALSE);
2519 aopOp (IC_RIGHT(ic),ic,FALSE);
2520 aopOp (IC_RESULT(ic),ic,TRUE);
2522 /* if literal, literal on the right or
2523 if left requires ACC or right is already
2525 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2526 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2527 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2528 operand *t = IC_RIGHT(ic);
2529 IC_RIGHT(ic) = IC_LEFT(ic);
2533 /* if both left & right are in bit
2535 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2536 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2541 /* if left in bit space & right literal */
2542 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2543 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2544 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2545 /* if result in bit space */
2546 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2547 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
2548 emitcode("cpl","c");
2549 outBitC(IC_RESULT(ic));
2551 size = getDataSize(IC_RESULT(ic));
2553 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2554 emitcode("addc","a,#00");
2555 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2561 /* if I can do an increment instead
2562 of add then GOOD for ME */
2563 if (genPlusIncr (ic) == TRUE)
2566 size = getDataSize(IC_RESULT(ic));
2569 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2570 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2572 emitcode("add","a,%s",
2573 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2575 emitcode("addc","a,%s",
2576 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2578 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2580 emitcode("add","a,%s",
2581 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2583 emitcode("addc","a,%s",
2584 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2586 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2589 adjustArithmeticResult(ic);
2592 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2593 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2594 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2597 /*-----------------------------------------------------------------*/
2598 /* genMinusDec :- does subtraction with deccrement if possible */
2599 /*-----------------------------------------------------------------*/
2600 static bool genMinusDec (iCode *ic)
2602 unsigned int icount ;
2603 unsigned int size = getDataSize(IC_RESULT(ic));
2605 /* will try to generate an increment */
2606 /* if the right side is not a literal
2608 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2611 /* if the literal value of the right hand side
2612 is greater than 4 then it is not worth it */
2613 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2616 /* if decrement 16 bits in register */
2617 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2624 /* If the next instruction is a goto and the goto target
2625 * is <= 10 instructions previous to this, we can generate
2626 * jumps straight to that target.
2628 if (ic->next && ic->next->op == GOTO
2629 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2630 && labelRange <= 10 )
2632 emitcode(";", "tail decrement optimized");
2633 tlbl = IC_LABEL(ic->next);
2638 tlbl = newiTempLabel(NULL);
2642 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2643 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2644 IS_AOP_PREG(IC_RESULT(ic)))
2645 emitcode("cjne","%s,#0xff,%05d$"
2646 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2649 emitcode("mov","a,#0xff");
2650 emitcode("cjne","a,%s,%05d$"
2651 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2654 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2657 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2658 IS_AOP_PREG(IC_RESULT(ic)))
2659 emitcode("cjne","%s,#0xff,%05d$"
2660 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2663 emitcode("cjne","a,%s,%05d$"
2664 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2667 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2671 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2672 IS_AOP_PREG(IC_RESULT(ic)))
2673 emitcode("cjne","%s,#0xff,%05d$"
2674 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2677 emitcode("cjne","a,%s,%05d$"
2678 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2681 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2685 emitcode("","%05d$:",tlbl->key+100);
2690 /* if the sizes are greater than 1 then we cannot */
2691 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2692 AOP_SIZE(IC_LEFT(ic)) > 1 )
2695 /* we can if the aops of the left & result match or
2696 if they are in registers and the registers are the
2698 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2701 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2709 /*-----------------------------------------------------------------*/
2710 /* addSign - complete with sign */
2711 /*-----------------------------------------------------------------*/
2712 static void addSign(operand *result, int offset, int sign)
2714 int size = (getDataSize(result) - offset);
2717 emitcode("rlc","a");
2718 emitcode("subb","a,acc");
2720 aopPut(AOP(result),"a",offset++);
2723 aopPut(AOP(result),zero,offset++);
2727 /*-----------------------------------------------------------------*/
2728 /* genMinusBits - generates code for subtraction of two bits */
2729 /*-----------------------------------------------------------------*/
2730 static void genMinusBits (iCode *ic)
2732 symbol *lbl = newiTempLabel(NULL);
2733 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2734 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2735 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2736 emitcode("cpl","c");
2737 emitcode("","%05d$:",(lbl->key+100));
2738 outBitC(IC_RESULT(ic));
2741 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2742 emitcode("subb","a,acc");
2743 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
2744 emitcode("inc","a");
2745 emitcode("","%05d$:",(lbl->key+100));
2746 aopPut(AOP(IC_RESULT(ic)),"a",0);
2747 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
2751 /*-----------------------------------------------------------------*/
2752 /* genMinus - generates code for subtraction */
2753 /*-----------------------------------------------------------------*/
2754 static void genMinus (iCode *ic)
2756 int size, offset = 0;
2757 unsigned long lit = 0L;
2759 aopOp (IC_LEFT(ic),ic,FALSE);
2760 aopOp (IC_RIGHT(ic),ic,FALSE);
2761 aopOp (IC_RESULT(ic),ic,TRUE);
2763 /* special cases :- */
2764 /* if both left & right are in bit space */
2765 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2766 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2771 /* if I can do an decrement instead
2772 of subtract then GOOD for ME */
2773 if (genMinusDec (ic) == TRUE)
2776 size = getDataSize(IC_RESULT(ic));
2778 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
2782 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2786 /* if literal, add a,#-lit, else normal subb */
2788 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2789 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2790 emitcode("subb","a,%s",
2791 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2793 /* first add without previous c */
2795 emitcode("add","a,#0x%02x",
2796 (unsigned int)(lit & 0x0FFL));
2798 emitcode("addc","a,#0x%02x",
2799 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
2801 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2804 adjustArithmeticResult(ic);
2807 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2808 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2809 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2813 /*-----------------------------------------------------------------*/
2814 /* genMultbits :- multiplication of bits */
2815 /*-----------------------------------------------------------------*/
2816 static void genMultbits (operand *left,
2820 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2821 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
2826 /*-----------------------------------------------------------------*/
2827 /* genMultOneByte : 8 bit multiplication & division */
2828 /*-----------------------------------------------------------------*/
2829 static void genMultOneByte (operand *left,
2833 link *opetype = operandType(result);
2838 /* (if two literals, the value is computed before) */
2839 /* if one literal, literal on the right */
2840 if (AOP_TYPE(left) == AOP_LIT){
2846 size = AOP_SIZE(result);
2847 /* signed or unsigned */
2848 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2849 l = aopGet(AOP(left),0,FALSE,FALSE);
2851 emitcode("mul","ab");
2852 /* if result size = 1, mul signed = mul unsigned */
2853 aopPut(AOP(result),"a",0);
2855 if (SPEC_USIGN(opetype)){
2856 aopPut(AOP(result),"b",1);
2858 /* for filling the MSBs */
2859 emitcode("clr","a");
2862 emitcode("mov","a,b");
2864 /* adjust the MSB if left or right neg */
2866 /* if one literal */
2867 if (AOP_TYPE(right) == AOP_LIT){
2868 /* AND literal negative */
2869 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
2870 /* adjust MSB (c==0 after mul) */
2871 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2875 lbl = newiTempLabel(NULL);
2876 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2877 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
2878 emitcode("","%05d$:",(lbl->key+100));
2879 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2880 lbl = newiTempLabel(NULL);
2881 emitcode("jc","%05d$",(lbl->key+100));
2882 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2883 emitcode("","%05d$:",(lbl->key+100));
2886 lbl = newiTempLabel(NULL);
2887 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
2888 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
2889 emitcode("","%05d$:",(lbl->key+100));
2890 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
2891 lbl = newiTempLabel(NULL);
2892 emitcode("jc","%05d$",(lbl->key+100));
2893 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
2894 emitcode("","%05d$:",(lbl->key+100));
2896 aopPut(AOP(result),"a",1);
2899 emitcode("rlc","a");
2900 emitcode("subb","a,acc");
2907 aopPut(AOP(result),"a",offset++);
2911 /*-----------------------------------------------------------------*/
2912 /* genMult - generates code for multiplication */
2913 /*-----------------------------------------------------------------*/
2914 static void genMult (iCode *ic)
2916 operand *left = IC_LEFT(ic);
2917 operand *right = IC_RIGHT(ic);
2918 operand *result= IC_RESULT(ic);
2920 /* assign the amsops */
2921 aopOp (left,ic,FALSE);
2922 aopOp (right,ic,FALSE);
2923 aopOp (result,ic,TRUE);
2925 /* special cases first */
2927 if (AOP_TYPE(left) == AOP_CRY &&
2928 AOP_TYPE(right)== AOP_CRY) {
2929 genMultbits(left,right,result);
2933 /* if both are of size == 1 */
2934 if (AOP_SIZE(left) == 1 &&
2935 AOP_SIZE(right) == 1 ) {
2936 genMultOneByte(left,right,result);
2940 /* should have been converted to function call */
2944 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2945 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2946 freeAsmop(result,NULL,ic,TRUE);
2949 /*-----------------------------------------------------------------*/
2950 /* genDivbits :- division of bits */
2951 /*-----------------------------------------------------------------*/
2952 static void genDivbits (operand *left,
2959 /* the result must be bit */
2960 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
2961 l = aopGet(AOP(left),0,FALSE,FALSE);
2965 emitcode("div","ab");
2966 emitcode("rrc","a");
2967 aopPut(AOP(result),"c",0);
2970 /*-----------------------------------------------------------------*/
2971 /* genDivOneByte : 8 bit division */
2972 /*-----------------------------------------------------------------*/
2973 static void genDivOneByte (operand *left,
2977 link *opetype = operandType(result);
2982 size = AOP_SIZE(result) - 1;
2984 /* signed or unsigned */
2985 if (SPEC_USIGN(opetype)) {
2986 /* unsigned is easy */
2987 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2988 l = aopGet(AOP(left),0,FALSE,FALSE);
2990 emitcode("div","ab");
2991 aopPut(AOP(result),"a",0);
2993 aopPut(AOP(result),zero,offset++);
2997 /* signed is a little bit more difficult */
2999 /* save the signs of the operands */
3000 l = aopGet(AOP(left),0,FALSE,FALSE);
3002 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3003 emitcode("push","acc"); /* save it on the stack */
3005 /* now sign adjust for both left & right */
3006 l = aopGet(AOP(right),0,FALSE,FALSE);
3008 lbl = newiTempLabel(NULL);
3009 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3010 emitcode("cpl","a");
3011 emitcode("inc","a");
3012 emitcode("","%05d$:",(lbl->key+100));
3013 emitcode("mov","b,a");
3015 /* sign adjust left side */
3016 l = aopGet(AOP(left),0,FALSE,FALSE);
3019 lbl = newiTempLabel(NULL);
3020 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3021 emitcode("cpl","a");
3022 emitcode("inc","a");
3023 emitcode("","%05d$:",(lbl->key+100));
3025 /* now the division */
3026 emitcode("div","ab");
3027 /* we are interested in the lower order
3029 emitcode("mov","b,a");
3030 lbl = newiTempLabel(NULL);
3031 emitcode("pop","acc");
3032 /* if there was an over flow we don't
3033 adjust the sign of the result */
3034 emitcode("jb","ov,%05d$",(lbl->key+100));
3035 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3037 emitcode("clr","a");
3038 emitcode("subb","a,b");
3039 emitcode("mov","b,a");
3040 emitcode("","%05d$:",(lbl->key+100));
3042 /* now we are done */
3043 aopPut(AOP(result),"b",0);
3045 emitcode("mov","c,b.7");
3046 emitcode("subb","a,acc");
3049 aopPut(AOP(result),"a",offset++);
3053 /*-----------------------------------------------------------------*/
3054 /* genDiv - generates code for division */
3055 /*-----------------------------------------------------------------*/
3056 static void genDiv (iCode *ic)
3058 operand *left = IC_LEFT(ic);
3059 operand *right = IC_RIGHT(ic);
3060 operand *result= IC_RESULT(ic);
3062 /* assign the amsops */
3063 aopOp (left,ic,FALSE);
3064 aopOp (right,ic,FALSE);
3065 aopOp (result,ic,TRUE);
3067 /* special cases first */
3069 if (AOP_TYPE(left) == AOP_CRY &&
3070 AOP_TYPE(right)== AOP_CRY) {
3071 genDivbits(left,right,result);
3075 /* if both are of size == 1 */
3076 if (AOP_SIZE(left) == 1 &&
3077 AOP_SIZE(right) == 1 ) {
3078 genDivOneByte(left,right,result);
3082 /* should have been converted to function call */
3085 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3086 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3087 freeAsmop(result,NULL,ic,TRUE);
3090 /*-----------------------------------------------------------------*/
3091 /* genModbits :- modulus of bits */
3092 /*-----------------------------------------------------------------*/
3093 static void genModbits (operand *left,
3100 /* the result must be bit */
3101 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3102 l = aopGet(AOP(left),0,FALSE,FALSE);
3106 emitcode("div","ab");
3107 emitcode("mov","a,b");
3108 emitcode("rrc","a");
3109 aopPut(AOP(result),"c",0);
3112 /*-----------------------------------------------------------------*/
3113 /* genModOneByte : 8 bit modulus */
3114 /*-----------------------------------------------------------------*/
3115 static void genModOneByte (operand *left,
3119 link *opetype = operandType(result);
3123 /* signed or unsigned */
3124 if (SPEC_USIGN(opetype)) {
3125 /* unsigned is easy */
3126 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3127 l = aopGet(AOP(left),0,FALSE,FALSE);
3129 emitcode("div","ab");
3130 aopPut(AOP(result),"b",0);
3134 /* signed is a little bit more difficult */
3136 /* save the signs of the operands */
3137 l = aopGet(AOP(left),0,FALSE,FALSE);
3140 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3141 emitcode("push","acc"); /* save it on the stack */
3143 /* now sign adjust for both left & right */
3144 l = aopGet(AOP(right),0,FALSE,FALSE);
3147 lbl = newiTempLabel(NULL);
3148 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3149 emitcode("cpl","a");
3150 emitcode("inc","a");
3151 emitcode("","%05d$:",(lbl->key+100));
3152 emitcode("mov","b,a");
3154 /* sign adjust left side */
3155 l = aopGet(AOP(left),0,FALSE,FALSE);
3158 lbl = newiTempLabel(NULL);
3159 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3160 emitcode("cpl","a");
3161 emitcode("inc","a");
3162 emitcode("","%05d$:",(lbl->key+100));
3164 /* now the multiplication */
3165 emitcode("div","ab");
3166 /* we are interested in the lower order
3168 lbl = newiTempLabel(NULL);
3169 emitcode("pop","acc");
3170 /* if there was an over flow we don't
3171 adjust the sign of the result */
3172 emitcode("jb","ov,%05d$",(lbl->key+100));
3173 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3175 emitcode("clr","a");
3176 emitcode("subb","a,b");
3177 emitcode("mov","b,a");
3178 emitcode("","%05d$:",(lbl->key+100));
3180 /* now we are done */
3181 aopPut(AOP(result),"b",0);
3185 /*-----------------------------------------------------------------*/
3186 /* genMod - generates code for division */
3187 /*-----------------------------------------------------------------*/
3188 static void genMod (iCode *ic)
3190 operand *left = IC_LEFT(ic);
3191 operand *right = IC_RIGHT(ic);
3192 operand *result= IC_RESULT(ic);
3194 /* assign the amsops */
3195 aopOp (left,ic,FALSE);
3196 aopOp (right,ic,FALSE);
3197 aopOp (result,ic,TRUE);
3199 /* special cases first */
3201 if (AOP_TYPE(left) == AOP_CRY &&
3202 AOP_TYPE(right)== AOP_CRY) {
3203 genModbits(left,right,result);
3207 /* if both are of size == 1 */
3208 if (AOP_SIZE(left) == 1 &&
3209 AOP_SIZE(right) == 1 ) {
3210 genModOneByte(left,right,result);
3214 /* should have been converted to function call */
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 /* genIfxJump :- will create a jump depending on the ifx */
3225 /*-----------------------------------------------------------------*/
3226 static void genIfxJump (iCode *ic, char *jval)
3229 symbol *tlbl = newiTempLabel(NULL);
3232 /* if true label then we jump if condition
3234 if ( IC_TRUE(ic) ) {
3236 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3237 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3240 /* false label is present */
3241 jlbl = IC_FALSE(ic) ;
3242 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3243 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3245 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3246 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3248 emitcode(inst,"%05d$",tlbl->key+100);
3249 emitcode("ljmp","%05d$",jlbl->key+100);
3250 emitcode("","%05d$:",tlbl->key+100);
3252 /* mark the icode as generated */
3256 /*-----------------------------------------------------------------*/
3257 /* genCmp :- greater or less than comparison */
3258 /*-----------------------------------------------------------------*/
3259 static void genCmp (operand *left,operand *right,
3260 operand *result, iCode *ifx, int sign)
3262 int size, offset = 0 ;
3263 unsigned long lit = 0L;
3265 /* if left & right are bit variables */
3266 if (AOP_TYPE(left) == AOP_CRY &&
3267 AOP_TYPE(right) == AOP_CRY ) {
3268 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3269 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3271 /* subtract right from left if at the
3272 end the carry flag is set then we know that
3273 left is greater than right */
3274 size = max(AOP_SIZE(left),AOP_SIZE(right));
3276 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3277 if((size == 1) && !sign &&
3278 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3279 symbol *lbl = newiTempLabel(NULL);
3280 emitcode("cjne","%s,%s,%05d$",
3281 aopGet(AOP(left),offset,FALSE,FALSE),
3282 aopGet(AOP(right),offset,FALSE,FALSE),
3284 emitcode("","%05d$:",lbl->key+100);
3286 if(AOP_TYPE(right) == AOP_LIT){
3287 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3288 /* optimize if(x < 0) or if(x >= 0) */
3294 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE));
3295 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3296 genIfxJump (ifx,"acc.7");
3300 emitcode("rlc","a");
3307 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3308 if (sign && size == 0) {
3309 emitcode("xrl","a,#0x80");
3310 if (AOP_TYPE(right) == AOP_LIT){
3311 unsigned long lit = (unsigned long)
3312 floatFromVal(AOP(right)->aopu.aop_lit);
3313 emitcode("subb","a,#0x%02x",
3314 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3316 emitcode("mov","b,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3317 emitcode("xrl","b,#0x80");
3318 emitcode("subb","a,b");
3321 emitcode("subb","a,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3327 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3330 /* if the result is used in the next
3331 ifx conditional branch then generate
3332 code a little differently */
3334 genIfxJump (ifx,"c");
3337 /* leave the result in acc */
3341 /*-----------------------------------------------------------------*/
3342 /* genCmpGt :- greater than comparison */
3343 /*-----------------------------------------------------------------*/
3344 static void genCmpGt (iCode *ic, iCode *ifx)
3346 operand *left, *right, *result;
3347 link *letype , *retype;
3351 right= IC_RIGHT(ic);
3352 result = IC_RESULT(ic);
3354 letype = getSpec(operandType(left));
3355 retype =getSpec(operandType(right));
3356 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3357 /* assign the amsops */
3358 aopOp (left,ic,FALSE);
3359 aopOp (right,ic,FALSE);
3360 aopOp (result,ic,TRUE);
3362 genCmp(right, left, result, ifx, sign);
3364 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3365 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3366 freeAsmop(result,NULL,ic,TRUE);
3369 /*-----------------------------------------------------------------*/
3370 /* genCmpLt - less than comparisons */
3371 /*-----------------------------------------------------------------*/
3372 static void genCmpLt (iCode *ic, iCode *ifx)
3374 operand *left, *right, *result;
3375 link *letype , *retype;
3379 right= IC_RIGHT(ic);
3380 result = IC_RESULT(ic);
3382 letype = getSpec(operandType(left));
3383 retype =getSpec(operandType(right));
3384 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3386 /* assign the amsops */
3387 aopOp (left,ic,FALSE);
3388 aopOp (right,ic,FALSE);
3389 aopOp (result,ic,TRUE);
3391 genCmp(left, right, result, ifx, sign);
3393 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3394 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3395 freeAsmop(result,NULL,ic,TRUE);
3398 /*-----------------------------------------------------------------*/
3399 /* gencjneshort - compare and jump if not equal */
3400 /*-----------------------------------------------------------------*/
3401 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3403 int size = max(AOP_SIZE(left),AOP_SIZE(right));
3405 unsigned long lit = 0L;
3407 /* if the left side is a literal or
3408 if the right is in a pointer register and left
3410 if ((AOP_TYPE(left) == AOP_LIT) ||
3411 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3416 if(AOP_TYPE(right) == AOP_LIT)
3417 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3419 /* if the right side is a literal then anything goes */
3420 if (AOP_TYPE(right) == AOP_LIT &&
3421 AOP_TYPE(left) != AOP_DIR ) {
3423 emitcode("cjne","%s,%s,%05d$",
3424 aopGet(AOP(left),offset,FALSE,FALSE),
3425 aopGet(AOP(right),offset,FALSE,FALSE),
3431 /* if the right side is in a register or in direct space or
3432 if the left is a pointer register & right is not */
3433 else if (AOP_TYPE(right) == AOP_REG ||
3434 AOP_TYPE(right) == AOP_DIR ||
3435 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3436 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3438 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3439 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3440 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
3441 emitcode("jnz","%05d$",lbl->key+100);
3443 emitcode("cjne","a,%s,%05d$",
3444 aopGet(AOP(right),offset,FALSE,TRUE),
3449 /* right is a pointer reg need both a & b */
3451 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
3453 emitcode("mov","b,%s",l);
3454 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3455 emitcode("cjne","a,b,%05d$",lbl->key+100);
3461 /*-----------------------------------------------------------------*/
3462 /* gencjne - compare and jump if not equal */
3463 /*-----------------------------------------------------------------*/
3464 static void gencjne(operand *left, operand *right, symbol *lbl)
3466 symbol *tlbl = newiTempLabel(NULL);
3468 gencjneshort(left, right, lbl);
3470 emitcode("mov","a,%s",one);
3471 emitcode("sjmp","%05d$",tlbl->key+100);
3472 emitcode("","%05d$:",lbl->key+100);
3473 emitcode("clr","a");
3474 emitcode("","%05d$:",tlbl->key+100);
3477 /*-----------------------------------------------------------------*/
3478 /* genCmpEq - generates code for equal to */
3479 /*-----------------------------------------------------------------*/
3480 static void genCmpEq (iCode *ic, iCode *ifx)
3482 operand *left, *right, *result;
3484 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3485 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3486 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3488 /* if literal, literal on the right or
3489 if the right is in a pointer register and left
3491 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
3492 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3493 operand *t = IC_RIGHT(ic);
3494 IC_RIGHT(ic) = IC_LEFT(ic);
3498 if(ifx && !AOP_SIZE(result)){
3500 /* if they are both bit variables */
3501 if (AOP_TYPE(left) == AOP_CRY &&
3502 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3503 if(AOP_TYPE(right) == AOP_LIT){
3504 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3506 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3507 emitcode("cpl","c");
3508 } else if(lit == 1L) {
3509 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3511 emitcode("clr","c");
3513 /* AOP_TYPE(right) == AOP_CRY */
3515 symbol *lbl = newiTempLabel(NULL);
3516 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3517 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3518 emitcode("cpl","c");
3519 emitcode("","%05d$:",(lbl->key+100));
3521 /* if true label then we jump if condition
3523 tlbl = newiTempLabel(NULL);
3524 if ( IC_TRUE(ifx) ) {
3525 emitcode("jnc","%05d$",tlbl->key+100);
3526 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3528 emitcode("jc","%05d$",tlbl->key+100);
3529 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3531 emitcode("","%05d$:",tlbl->key+100);
3533 tlbl = newiTempLabel(NULL);
3534 gencjneshort(left, right, tlbl);
3535 if ( IC_TRUE(ifx) ) {
3536 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3537 emitcode("","%05d$:",tlbl->key+100);
3539 symbol *lbl = newiTempLabel(NULL);
3540 emitcode("sjmp","%05d$",lbl->key+100);
3541 emitcode("","%05d$:",tlbl->key+100);
3542 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3543 emitcode("","%05d$:",lbl->key+100);
3546 /* mark the icode as generated */
3551 /* if they are both bit variables */
3552 if (AOP_TYPE(left) == AOP_CRY &&
3553 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3554 if(AOP_TYPE(right) == AOP_LIT){
3555 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3557 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3558 emitcode("cpl","c");
3559 } else if(lit == 1L) {
3560 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3562 emitcode("clr","c");
3564 /* AOP_TYPE(right) == AOP_CRY */
3566 symbol *lbl = newiTempLabel(NULL);
3567 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3568 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3569 emitcode("cpl","c");
3570 emitcode("","%05d$:",(lbl->key+100));
3573 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
3578 genIfxJump (ifx,"c");
3581 /* if the result is used in an arithmetic operation
3582 then put the result in place */
3585 gencjne(left,right,newiTempLabel(NULL));
3586 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3587 aopPut(AOP(result),"a",0);
3591 genIfxJump (ifx,"a");
3594 /* if the result is used in an arithmetic operation
3595 then put the result in place */
3596 if (AOP_TYPE(result) != AOP_CRY)
3598 /* leave the result in acc */
3602 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3603 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3604 freeAsmop(result,NULL,ic,TRUE);
3607 /*-----------------------------------------------------------------*/
3608 /* ifxForOp - returns the icode containing the ifx for operand */
3609 /*-----------------------------------------------------------------*/
3610 static iCode *ifxForOp ( operand *op, iCode *ic )
3612 /* if true symbol then needs to be assigned */
3613 if (IS_TRUE_SYMOP(op))
3616 /* if this has register type condition and
3617 the next instruction is ifx with the same operand
3618 and live to of the operand is upto the ifx only then */
3620 ic->next->op == IFX &&
3621 IC_COND(ic->next)->key == op->key &&
3622 OP_SYMBOL(op)->liveTo <= ic->next->seq )
3627 /*-----------------------------------------------------------------*/
3628 /* genAndOp - for && operation */
3629 /*-----------------------------------------------------------------*/
3630 static void genAndOp (iCode *ic)
3632 operand *left,*right, *result;
3635 /* note here that && operations that are in an
3636 if statement are taken away by backPatchLabels
3637 only those used in arthmetic operations remain */
3638 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3639 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3640 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3642 /* if both are bit variables */
3643 if (AOP_TYPE(left) == AOP_CRY &&
3644 AOP_TYPE(right) == AOP_CRY ) {
3645 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3646 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3649 tlbl = newiTempLabel(NULL);
3651 emitcode("jz","%05d$",tlbl->key+100);
3653 emitcode("","%05d$:",tlbl->key+100);
3657 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3658 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3659 freeAsmop(result,NULL,ic,TRUE);
3663 /*-----------------------------------------------------------------*/
3664 /* genOrOp - for || operation */
3665 /*-----------------------------------------------------------------*/
3666 static void genOrOp (iCode *ic)
3668 operand *left,*right, *result;
3671 /* note here that || operations that are in an
3672 if statement are taken away by backPatchLabels
3673 only those used in arthmetic operations remain */
3674 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3675 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3676 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3678 /* if both are bit variables */
3679 if (AOP_TYPE(left) == AOP_CRY &&
3680 AOP_TYPE(right) == AOP_CRY ) {
3681 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3682 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
3685 tlbl = newiTempLabel(NULL);
3687 emitcode("jnz","%05d$",tlbl->key+100);
3689 emitcode("","%05d$:",tlbl->key+100);
3693 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3694 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3695 freeAsmop(result,NULL,ic,TRUE);
3698 /*-----------------------------------------------------------------*/
3699 /* isLiteralBit - test if lit == 2^n */
3700 /*-----------------------------------------------------------------*/
3701 static int isLiteralBit(unsigned long lit)
3703 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
3704 0x100L,0x200L,0x400L,0x800L,
3705 0x1000L,0x2000L,0x4000L,0x8000L,
3706 0x10000L,0x20000L,0x40000L,0x80000L,
3707 0x100000L,0x200000L,0x400000L,0x800000L,
3708 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
3709 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
3712 for(idx = 0; idx < 32; idx++)
3718 /*-----------------------------------------------------------------*/
3719 /* continueIfTrue - */
3720 /*-----------------------------------------------------------------*/
3721 static void continueIfTrue (iCode *ic)
3724 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3728 /*-----------------------------------------------------------------*/
3730 /*-----------------------------------------------------------------*/
3731 static void jumpIfTrue (iCode *ic)
3734 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3738 /*-----------------------------------------------------------------*/
3739 /* jmpTrueOrFalse - */
3740 /*-----------------------------------------------------------------*/
3741 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
3743 // ugly but optimized by peephole
3745 symbol *nlbl = newiTempLabel(NULL);
3746 emitcode("sjmp","%05d$",nlbl->key+100);
3747 emitcode("","%05d$:",tlbl->key+100);
3748 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3749 emitcode("","%05d$:",nlbl->key+100);
3752 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3753 emitcode("","%05d$:",tlbl->key+100);
3758 /*-----------------------------------------------------------------*/
3759 /* genAnd - code for and */
3760 /*-----------------------------------------------------------------*/
3761 static void genAnd (iCode *ic, iCode *ifx)
3763 operand *left, *right, *result;
3765 unsigned long lit = 0L;
3769 aopOp((left = IC_LEFT(ic)),ic,FALSE);
3770 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3771 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3774 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3776 AOP_TYPE(left), AOP_TYPE(right));
3777 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3779 AOP_SIZE(left), AOP_SIZE(right));
3782 /* if left is a literal & right is not then exchange them */
3783 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3784 AOP_NEEDSACC(left)) {
3785 operand *tmp = right ;
3790 /* if result = right then exchange them */
3791 if(sameRegs(AOP(result),AOP(right))){
3792 operand *tmp = right ;
3797 /* if right is bit then exchange them */
3798 if (AOP_TYPE(right) == AOP_CRY &&
3799 AOP_TYPE(left) != AOP_CRY){
3800 operand *tmp = right ;
3804 if(AOP_TYPE(right) == AOP_LIT)
3805 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3807 size = AOP_SIZE(result);
3810 // result = bit & yy;
3811 if (AOP_TYPE(left) == AOP_CRY){
3812 // c = bit & literal;
3813 if(AOP_TYPE(right) == AOP_LIT){
3815 if(size && sameRegs(AOP(result),AOP(left)))
3818 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3821 if(size && (AOP_TYPE(result) == AOP_CRY)){
3822 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
3825 if((AOP_TYPE(result) == AOP_CRY) && ifx){
3829 emitcode("clr","c");
3832 if (AOP_TYPE(right) == AOP_CRY){
3834 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3835 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3838 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
3840 emitcode("rrc","a");
3841 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3849 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
3850 genIfxJump(ifx, "c");
3854 // if(val & 0xZZ) - size = 0, ifx != FALSE -
3855 // bit = val & 0xZZ - size = 1, ifx = FALSE -
3856 if((AOP_TYPE(right) == AOP_LIT) &&
3857 (AOP_TYPE(result) == AOP_CRY) &&
3858 (AOP_TYPE(left) != AOP_CRY)){
3859 int posbit = isLiteralBit(lit);
3863 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
3866 emitcode("mov","c,acc.%d",posbit&0x07);
3870 sprintf(buffer,"acc.%d",posbit&0x07);
3871 genIfxJump(ifx, buffer);
3876 symbol *tlbl = newiTempLabel(NULL);
3877 int sizel = AOP_SIZE(left);
3879 emitcode("setb","c");
3881 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
3882 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
3884 if((posbit = isLiteralBit(bytelit)) != 0)
3885 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
3887 if(bytelit != 0x0FFL)
3888 emitcode("anl","a,%s",
3889 aopGet(AOP(right),offset,FALSE,TRUE));
3890 emitcode("jnz","%05d$",tlbl->key+100);
3895 // bit = left & literal
3897 emitcode("clr","c");
3898 emitcode("","%05d$:",tlbl->key+100);
3900 // if(left & literal)
3903 jmpTrueOrFalse(ifx, tlbl);
3911 /* if left is same as result */
3912 if(sameRegs(AOP(result),AOP(left))){
3913 for(;size--; offset++) {
3914 if(AOP_TYPE(right) == AOP_LIT){
3915 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
3919 aopPut(AOP(result),zero,offset);
3921 if (IS_AOP_PREG(result)) {
3922 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3923 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
3924 aopPut(AOP(result),"a",offset);
3926 emitcode("anl","%s,%s",
3927 aopGet(AOP(left),offset,FALSE,TRUE),
3928 aopGet(AOP(right),offset,FALSE,FALSE));
3930 if (AOP_TYPE(left) == AOP_ACC)
3931 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
3933 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3934 if (IS_AOP_PREG(result)) {
3935 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
3936 aopPut(AOP(result),"a",offset);
3939 emitcode("anl","%s,a",
3940 aopGet(AOP(left),offset,FALSE,TRUE));
3945 // left & result in different registers
3946 if(AOP_TYPE(result) == AOP_CRY){
3948 // if(size), result in bit
3949 // if(!size && ifx), conditional oper: if(left & right)
3950 symbol *tlbl = newiTempLabel(NULL);
3951 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
3953 emitcode("setb","c");
3955 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3956 emitcode("anl","a,%s",
3957 aopGet(AOP(left),offset,FALSE,FALSE));
3958 emitcode("jnz","%05d$",tlbl->key+100);
3963 emitcode("","%05d$:",tlbl->key+100);
3966 jmpTrueOrFalse(ifx, tlbl);
3968 for(;(size--);offset++) {
3970 // result = left & right
3971 if(AOP_TYPE(right) == AOP_LIT){
3972 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
3974 aopGet(AOP(left),offset,FALSE,FALSE),
3977 } else if(bytelit == 0){
3978 aopPut(AOP(result),zero,offset);
3982 // faster than result <- left, anl result,right
3983 // and better if result is SFR
3984 if (AOP_TYPE(left) == AOP_ACC)
3985 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
3987 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3988 emitcode("anl","a,%s",
3989 aopGet(AOP(left),offset,FALSE,FALSE));
3991 aopPut(AOP(result),"a",offset);
3997 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3998 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3999 freeAsmop(result,NULL,ic,TRUE);
4002 /*-----------------------------------------------------------------*/
4003 /* genOr - code for or */
4004 /*-----------------------------------------------------------------*/
4005 static void genOr (iCode *ic, iCode *ifx)
4007 operand *left, *right, *result;
4009 unsigned long lit = 0L;
4011 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4012 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4013 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4016 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4018 AOP_TYPE(left), AOP_TYPE(right));
4019 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4021 AOP_SIZE(left), AOP_SIZE(right));
4024 /* if left is a literal & right is not then exchange them */
4025 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4026 AOP_NEEDSACC(left)) {
4027 operand *tmp = right ;
4032 /* if result = right then exchange them */
4033 if(sameRegs(AOP(result),AOP(right))){
4034 operand *tmp = right ;
4039 /* if right is bit then exchange them */
4040 if (AOP_TYPE(right) == AOP_CRY &&
4041 AOP_TYPE(left) != AOP_CRY){
4042 operand *tmp = right ;
4046 if(AOP_TYPE(right) == AOP_LIT)
4047 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4049 size = AOP_SIZE(result);
4053 if (AOP_TYPE(left) == AOP_CRY){
4054 if(AOP_TYPE(right) == AOP_LIT){
4055 // c = bit & literal;
4057 // lit != 0 => result = 1
4058 if(AOP_TYPE(result) == AOP_CRY){
4060 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4062 continueIfTrue(ifx);
4065 emitcode("setb","c");
4067 // lit == 0 => result = left
4068 if(size && sameRegs(AOP(result),AOP(left)))
4070 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4073 if (AOP_TYPE(right) == AOP_CRY){
4075 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4076 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4080 symbol *tlbl = newiTempLabel(NULL);
4081 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4082 emitcode("setb","c");
4083 emitcode("jb","%s,%05d$",
4084 AOP(left)->aopu.aop_dir,tlbl->key+100);
4086 emitcode("jnz","%05d$",tlbl->key+100);
4087 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4088 jmpTrueOrFalse(ifx, tlbl);
4092 emitcode("","%05d$:",tlbl->key+100);
4101 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4102 genIfxJump(ifx, "c");
4106 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4107 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4108 if((AOP_TYPE(right) == AOP_LIT) &&
4109 (AOP_TYPE(result) == AOP_CRY) &&
4110 (AOP_TYPE(left) != AOP_CRY)){
4114 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4116 continueIfTrue(ifx);
4119 // lit = 0, result = boolean(left)
4121 emitcode("setb","c");
4124 symbol *tlbl = newiTempLabel(NULL);
4125 emitcode("jnz","%05d$",tlbl->key+100);
4127 emitcode("","%05d$:",tlbl->key+100);
4129 genIfxJump (ifx,"a");
4137 /* if left is same as result */
4138 if(sameRegs(AOP(result),AOP(left))){
4139 for(;size--; offset++) {
4140 if(AOP_TYPE(right) == AOP_LIT){
4141 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4144 if (IS_AOP_PREG(left)) {
4145 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4146 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4147 aopPut(AOP(result),"a",offset);
4149 emitcode("orl","%s,%s",
4150 aopGet(AOP(left),offset,FALSE,TRUE),
4151 aopGet(AOP(right),offset,FALSE,FALSE));
4153 if (AOP_TYPE(left) == AOP_ACC)
4154 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4156 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4157 if (IS_AOP_PREG(left)) {
4158 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4159 aopPut(AOP(result),"a",offset);
4161 emitcode("orl","%s,a",
4162 aopGet(AOP(left),offset,FALSE,TRUE));
4167 // left & result in different registers
4168 if(AOP_TYPE(result) == AOP_CRY){
4170 // if(size), result in bit
4171 // if(!size && ifx), conditional oper: if(left | right)
4172 symbol *tlbl = newiTempLabel(NULL);
4173 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4175 emitcode("setb","c");
4177 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4178 emitcode("orl","a,%s",
4179 aopGet(AOP(left),offset,FALSE,FALSE));
4180 emitcode("jnz","%05d$",tlbl->key+100);
4185 emitcode("","%05d$:",tlbl->key+100);
4188 jmpTrueOrFalse(ifx, tlbl);
4189 } else for(;(size--);offset++){
4191 // result = left & right
4192 if(AOP_TYPE(right) == AOP_LIT){
4193 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4195 aopGet(AOP(left),offset,FALSE,FALSE),
4200 // faster than result <- left, anl result,right
4201 // and better if result is SFR
4202 if (AOP_TYPE(left) == AOP_ACC)
4203 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4205 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4206 emitcode("orl","a,%s",
4207 aopGet(AOP(left),offset,FALSE,FALSE));
4209 aopPut(AOP(result),"a",offset);
4214 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4215 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4216 freeAsmop(result,NULL,ic,TRUE);
4219 /*-----------------------------------------------------------------*/
4220 /* genXor - code for xclusive or */
4221 /*-----------------------------------------------------------------*/
4222 static void genXor (iCode *ic, iCode *ifx)
4224 operand *left, *right, *result;
4226 unsigned long lit = 0L;
4228 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4229 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4230 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4233 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4235 AOP_TYPE(left), AOP_TYPE(right));
4236 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4238 AOP_SIZE(left), AOP_SIZE(right));
4241 /* if left is a literal & right is not ||
4242 if left needs acc & right does not */
4243 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4244 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4245 operand *tmp = right ;
4250 /* if result = right then exchange them */
4251 if(sameRegs(AOP(result),AOP(right))){
4252 operand *tmp = right ;
4257 /* if right is bit then exchange them */
4258 if (AOP_TYPE(right) == AOP_CRY &&
4259 AOP_TYPE(left) != AOP_CRY){
4260 operand *tmp = right ;
4264 if(AOP_TYPE(right) == AOP_LIT)
4265 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4267 size = AOP_SIZE(result);
4271 if (AOP_TYPE(left) == AOP_CRY){
4272 if(AOP_TYPE(right) == AOP_LIT){
4273 // c = bit & literal;
4275 // lit>>1 != 0 => result = 1
4276 if(AOP_TYPE(result) == AOP_CRY){
4278 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4280 continueIfTrue(ifx);
4283 emitcode("setb","c");
4287 // lit == 0, result = left
4288 if(size && sameRegs(AOP(result),AOP(left)))
4290 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4292 // lit == 1, result = not(left)
4293 if(size && sameRegs(AOP(result),AOP(left))){
4294 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4297 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4298 emitcode("cpl","c");
4305 symbol *tlbl = newiTempLabel(NULL);
4306 if (AOP_TYPE(right) == AOP_CRY){
4308 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4311 int sizer = AOP_SIZE(right);
4313 // if val>>1 != 0, result = 1
4314 emitcode("setb","c");
4316 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
4318 // test the msb of the lsb
4319 emitcode("anl","a,#0xfe");
4320 emitcode("jnz","%05d$",tlbl->key+100);
4324 emitcode("rrc","a");
4326 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4327 emitcode("cpl","c");
4328 emitcode("","%05d$:",(tlbl->key+100));
4335 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4336 genIfxJump(ifx, "c");
4340 if(sameRegs(AOP(result),AOP(left))){
4341 /* if left is same as result */
4342 for(;size--; offset++) {
4343 if(AOP_TYPE(right) == AOP_LIT){
4344 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4347 if (IS_AOP_PREG(left)) {
4348 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4349 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4350 aopPut(AOP(result),"a",offset);
4352 emitcode("xrl","%s,%s",
4353 aopGet(AOP(left),offset,FALSE,TRUE),
4354 aopGet(AOP(right),offset,FALSE,FALSE));
4356 if (AOP_TYPE(left) == AOP_ACC)
4357 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4359 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4360 if (IS_AOP_PREG(left)) {
4361 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4362 aopPut(AOP(result),"a",offset);
4364 emitcode("xrl","%s,a",
4365 aopGet(AOP(left),offset,FALSE,TRUE));
4370 // left & result in different registers
4371 if(AOP_TYPE(result) == AOP_CRY){
4373 // if(size), result in bit
4374 // if(!size && ifx), conditional oper: if(left ^ right)
4375 symbol *tlbl = newiTempLabel(NULL);
4376 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4378 emitcode("setb","c");
4380 if((AOP_TYPE(right) == AOP_LIT) &&
4381 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4382 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4384 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4385 emitcode("xrl","a,%s",
4386 aopGet(AOP(left),offset,FALSE,FALSE));
4388 emitcode("jnz","%05d$",tlbl->key+100);
4393 emitcode("","%05d$:",tlbl->key+100);
4396 jmpTrueOrFalse(ifx, tlbl);
4397 } else for(;(size--);offset++){
4399 // result = left & right
4400 if(AOP_TYPE(right) == AOP_LIT){
4401 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4403 aopGet(AOP(left),offset,FALSE,FALSE),
4408 // faster than result <- left, anl result,right
4409 // and better if result is SFR
4410 if (AOP_TYPE(left) == AOP_ACC)
4411 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4413 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4414 emitcode("xrl","a,%s",
4415 aopGet(AOP(left),offset,FALSE,TRUE));
4417 aopPut(AOP(result),"a",offset);
4422 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4423 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4424 freeAsmop(result,NULL,ic,TRUE);
4427 /*-----------------------------------------------------------------*/
4428 /* genInline - write the inline code out */
4429 /*-----------------------------------------------------------------*/
4430 static void genInline (iCode *ic)
4432 char buffer[MAX_INLINEASM];
4436 _G.inLine += (!options.asmpeep);
4437 strcpy(buffer,IC_INLINE(ic));
4439 /* emit each line as a code */
4458 /* emitcode("",buffer); */
4459 _G.inLine -= (!options.asmpeep);
4462 /*-----------------------------------------------------------------*/
4463 /* genRRC - rotate right with carry */
4464 /*-----------------------------------------------------------------*/
4465 static void genRRC (iCode *ic)
4467 operand *left , *result ;
4468 int size, offset = 0;
4471 /* rotate right with carry */
4473 result=IC_RESULT(ic);
4474 aopOp (left,ic,FALSE);
4475 aopOp (result,ic,FALSE);
4477 /* move it to the result */
4478 size = AOP_SIZE(result);
4482 l = aopGet(AOP(left),offset,FALSE,FALSE);
4484 emitcode("rrc","a");
4485 if (AOP_SIZE(result) > 1)
4486 aopPut(AOP(result),"a",offset--);
4488 /* now we need to put the carry into the
4489 highest order byte of the result */
4490 if (AOP_SIZE(result) > 1) {
4491 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
4494 emitcode("mov","acc.7,c");
4495 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
4496 freeAsmop(left,NULL,ic,TRUE);
4497 freeAsmop(result,NULL,ic,TRUE);
4500 /*-----------------------------------------------------------------*/
4501 /* genRLC - generate code for rotate left with carry */
4502 /*-----------------------------------------------------------------*/
4503 static void genRLC (iCode *ic)
4505 operand *left , *result ;
4506 int size, offset = 0;
4509 /* rotate right with carry */
4511 result=IC_RESULT(ic);
4512 aopOp (left,ic,FALSE);
4513 aopOp (result,ic,FALSE);
4515 /* move it to the result */
4516 size = AOP_SIZE(result);
4519 l = aopGet(AOP(left),offset,FALSE,FALSE);
4521 emitcode("add","a,acc");
4522 if (AOP_SIZE(result) > 1)
4523 aopPut(AOP(result),"a",offset++);
4525 l = aopGet(AOP(left),offset,FALSE,FALSE);
4527 emitcode("rlc","a");
4528 if (AOP_SIZE(result) > 1)
4529 aopPut(AOP(result),"a",offset++);
4532 /* now we need to put the carry into the
4533 highest order byte of the result */
4534 if (AOP_SIZE(result) > 1) {
4535 l = aopGet(AOP(result),0,FALSE,FALSE);
4538 emitcode("mov","acc.0,c");
4539 aopPut(AOP(result),"a",0);
4540 freeAsmop(left,NULL,ic,TRUE);
4541 freeAsmop(result,NULL,ic,TRUE);
4544 /*-----------------------------------------------------------------*/
4545 /* genGetHbit - generates code get highest order bit */
4546 /*-----------------------------------------------------------------*/
4547 static void genGetHbit (iCode *ic)
4549 operand *left, *result;
4551 result=IC_RESULT(ic);
4552 aopOp (left,ic,FALSE);
4553 aopOp (result,ic,FALSE);
4555 /* get the highest order byte into a */
4556 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
4557 if(AOP_TYPE(result) == AOP_CRY){
4558 emitcode("rlc","a");
4563 emitcode("anl","a,#0x01");
4568 freeAsmop(left,NULL,ic,TRUE);
4569 freeAsmop(result,NULL,ic,TRUE);
4572 /*-----------------------------------------------------------------*/
4573 /* AccRol - rotate left accumulator by known count */
4574 /*-----------------------------------------------------------------*/
4575 static void AccRol (int shCount)
4577 shCount &= 0x0007; // shCount : 0..7
4589 emitcode("swap","a");
4593 emitcode("swap","a");
4596 emitcode("swap","a");
4609 /*-----------------------------------------------------------------*/
4610 /* AccLsh - left shift accumulator by known count */
4611 /*-----------------------------------------------------------------*/
4612 static void AccLsh (int shCount)
4616 emitcode("add","a,acc");
4619 emitcode("add","a,acc");
4620 emitcode("add","a,acc");
4622 /* rotate left accumulator */
4624 /* and kill the lower order bits */
4625 emitcode("anl","a,#0x%02x", SLMask[shCount]);
4630 /*-----------------------------------------------------------------*/
4631 /* AccRsh - right shift accumulator by known count */
4632 /*-----------------------------------------------------------------*/
4633 static void AccRsh (int shCount)
4638 emitcode("rrc","a");
4640 /* rotate right accumulator */
4641 AccRol(8 - shCount);
4642 /* and kill the higher order bits */
4643 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4648 /*-----------------------------------------------------------------*/
4649 /* AccSRsh - signed right shift accumulator by known count */
4650 /*-----------------------------------------------------------------*/
4651 static void AccSRsh (int shCount)
4656 emitcode("mov","c,acc.7");
4657 emitcode("rrc","a");
4658 } else if(shCount == 2){
4659 emitcode("mov","c,acc.7");
4660 emitcode("rrc","a");
4661 emitcode("mov","c,acc.7");
4662 emitcode("rrc","a");
4664 tlbl = newiTempLabel(NULL);
4665 /* rotate right accumulator */
4666 AccRol(8 - shCount);
4667 /* and kill the higher order bits */
4668 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4669 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4670 emitcode("orl","a,#0x%02x",
4671 (unsigned char)~SRMask[shCount]);
4672 emitcode("","%05d$:",tlbl->key+100);
4677 /*-----------------------------------------------------------------*/
4678 /* shiftR1Left2Result - shift right one byte from left to result */
4679 /*-----------------------------------------------------------------*/
4680 static void shiftR1Left2Result (operand *left, int offl,
4681 operand *result, int offr,
4682 int shCount, int sign)
4684 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4685 /* shift right accumulator */
4690 aopPut(AOP(result),"a",offr);
4693 /*-----------------------------------------------------------------*/
4694 /* shiftL1Left2Result - shift left one byte from left to result */
4695 /*-----------------------------------------------------------------*/
4696 static void shiftL1Left2Result (operand *left, int offl,
4697 operand *result, int offr, int shCount)
4700 l = aopGet(AOP(left),offl,FALSE,FALSE);
4702 /* shift left accumulator */
4704 aopPut(AOP(result),"a",offr);
4707 /*-----------------------------------------------------------------*/
4708 /* movLeft2Result - move byte from left to result */
4709 /*-----------------------------------------------------------------*/
4710 static void movLeft2Result (operand *left, int offl,
4711 operand *result, int offr, int sign)
4714 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
4715 l = aopGet(AOP(left),offl,FALSE,FALSE);
4717 if (*l == '@' && (IS_AOP_PREG(result))) {
4718 emitcode("mov","a,%s",l);
4719 aopPut(AOP(result),"a",offr);
4722 aopPut(AOP(result),l,offr);
4724 /* MSB sign in acc.7 ! */
4725 if(getDataSize(left) == offl+1){
4726 emitcode("mov","a,%s",l);
4727 aopPut(AOP(result),"a",offr);
4734 /*-----------------------------------------------------------------*/
4735 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
4736 /*-----------------------------------------------------------------*/
4737 static void AccAXRrl1 (char *x)
4739 emitcode("rrc","a");
4740 emitcode("xch","a,%s", x);
4741 emitcode("rrc","a");
4742 emitcode("xch","a,%s", x);
4745 /*-----------------------------------------------------------------*/
4746 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
4747 /*-----------------------------------------------------------------*/
4748 static void AccAXLrl1 (char *x)
4750 emitcode("xch","a,%s",x);
4751 emitcode("rlc","a");
4752 emitcode("xch","a,%s",x);
4753 emitcode("rlc","a");
4756 /*-----------------------------------------------------------------*/
4757 /* AccAXLsh1 - left shift a:x<-0 by 1 */
4758 /*-----------------------------------------------------------------*/
4759 static void AccAXLsh1 (char *x)
4761 emitcode("xch","a,%s",x);
4762 emitcode("add","a,acc");
4763 emitcode("xch","a,%s",x);
4764 emitcode("rlc","a");
4767 /*-----------------------------------------------------------------*/
4768 /* AccAXLsh - left shift a:x by known count (0..7) */
4769 /*-----------------------------------------------------------------*/
4770 static void AccAXLsh (char *x, int shCount)
4784 case 5 : // AAAAABBB:CCCCCDDD
4785 AccRol(shCount); // BBBAAAAA:CCCCCDDD
4786 emitcode("anl","a,#0x%02x",
4787 SLMask[shCount]); // BBB00000:CCCCCDDD
4788 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
4789 AccRol(shCount); // DDDCCCCC:BBB00000
4790 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
4791 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
4792 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
4793 emitcode("anl","a,#0x%02x",
4794 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
4795 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
4796 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
4798 case 6 : // AAAAAABB:CCCCCCDD
4799 emitcode("anl","a,#0x%02x",
4800 SRMask[shCount]); // 000000BB:CCCCCCDD
4801 emitcode("mov","c,acc.0"); // c = B
4802 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
4803 AccAXRrl1(x); // BCCCCCCD:D000000B
4804 AccAXRrl1(x); // BBCCCCCC:DD000000
4806 case 7 : // a:x <<= 7
4807 emitcode("anl","a,#0x%02x",
4808 SRMask[shCount]); // 0000000B:CCCCCCCD
4809 emitcode("mov","c,acc.0"); // c = B
4810 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
4811 AccAXRrl1(x); // BCCCCCCC:D0000000
4818 /*-----------------------------------------------------------------*/
4819 /* AccAXRsh - right shift a:x known count (0..7) */
4820 /*-----------------------------------------------------------------*/
4821 static void AccAXRsh (char *x, int shCount)
4828 AccAXRrl1(x); // 0->a:x
4832 AccAXRrl1(x); // 0->a:x
4834 AccAXRrl1(x); // 0->a:x
4838 case 5 : // AAAAABBB:CCCCCDDD = a:x
4839 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
4840 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
4841 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
4842 emitcode("anl","a,#0x%02x",
4843 SRMask[shCount]); // 000CCCCC:BBBAAAAA
4844 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
4845 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
4846 emitcode("anl","a,#0x%02x",
4847 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
4848 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
4849 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
4850 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
4852 case 6 : // AABBBBBB:CCDDDDDD
4853 emitcode("mov","c,acc.7");
4854 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
4855 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
4856 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
4857 emitcode("anl","a,#0x%02x",
4858 SRMask[shCount]); // 000000AA:BBBBBBCC
4860 case 7 : // ABBBBBBB:CDDDDDDD
4861 emitcode("mov","c,acc.7"); // c = A
4862 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
4863 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
4864 emitcode("anl","a,#0x%02x",
4865 SRMask[shCount]); // 0000000A:BBBBBBBC
4872 /*-----------------------------------------------------------------*/
4873 /* AccAXRshS - right shift signed a:x known count (0..7) */
4874 /*-----------------------------------------------------------------*/
4875 static void AccAXRshS (char *x, int shCount)
4882 emitcode("mov","c,acc.7");
4883 AccAXRrl1(x); // s->a:x
4886 emitcode("mov","c,acc.7");
4887 AccAXRrl1(x); // s->a:x
4888 emitcode("mov","c,acc.7");
4889 AccAXRrl1(x); // s->a:x
4893 case 5 : // AAAAABBB:CCCCCDDD = a:x
4894 tlbl = newiTempLabel(NULL);
4895 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
4896 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
4897 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
4898 emitcode("anl","a,#0x%02x",
4899 SRMask[shCount]); // 000CCCCC:BBBAAAAA
4900 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
4901 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
4902 emitcode("anl","a,#0x%02x",
4903 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
4904 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
4905 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
4906 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
4907 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4908 emitcode("orl","a,#0x%02x",
4909 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
4910 emitcode("","%05d$:",tlbl->key+100);
4911 break; // SSSSAAAA:BBBCCCCC
4912 case 6 : // AABBBBBB:CCDDDDDD
4913 tlbl = newiTempLabel(NULL);
4914 emitcode("mov","c,acc.7");
4915 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
4916 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
4917 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
4918 emitcode("anl","a,#0x%02x",
4919 SRMask[shCount]); // 000000AA:BBBBBBCC
4920 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4921 emitcode("orl","a,#0x%02x",
4922 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
4923 emitcode("","%05d$:",tlbl->key+100);
4925 case 7 : // ABBBBBBB:CDDDDDDD
4926 tlbl = newiTempLabel(NULL);
4927 emitcode("mov","c,acc.7"); // c = A
4928 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
4929 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
4930 emitcode("anl","a,#0x%02x",
4931 SRMask[shCount]); // 0000000A:BBBBBBBC
4932 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4933 emitcode("orl","a,#0x%02x",
4934 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
4935 emitcode("","%05d$:",tlbl->key+100);
4942 /*-----------------------------------------------------------------*/
4943 /* shiftL2Left2Result - shift left two bytes from left to result */
4944 /*-----------------------------------------------------------------*/
4945 static void shiftL2Left2Result (operand *left, int offl,
4946 operand *result, int offr, int shCount)
4948 if(sameRegs(AOP(result), AOP(left)) &&
4949 ((offl + MSB16) == offr)){
4950 /* don't crash result[offr] */
4951 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4952 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4954 movLeft2Result(left,offl, result, offr, 0);
4955 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4957 /* ax << shCount (x = lsb(result))*/
4958 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
4959 aopPut(AOP(result),"a",offr+MSB16);
4963 /*-----------------------------------------------------------------*/
4964 /* shiftR2Left2Result - shift right two bytes from left to result */
4965 /*-----------------------------------------------------------------*/
4966 static void shiftR2Left2Result (operand *left, int offl,
4967 operand *result, int offr,
4968 int shCount, int sign)
4970 if(sameRegs(AOP(result), AOP(left)) &&
4971 ((offl + MSB16) == offr)){
4972 /* don't crash result[offr] */
4973 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4974 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4976 movLeft2Result(left,offl, result, offr, 0);
4977 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4979 /* a:x >> shCount (x = lsb(result))*/
4981 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
4983 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
4984 if(getDataSize(result) > 1)
4985 aopPut(AOP(result),"a",offr+MSB16);
4988 /*-----------------------------------------------------------------*/
4989 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
4990 /*-----------------------------------------------------------------*/
4991 static void shiftLLeftOrResult (operand *left, int offl,
4992 operand *result, int offr, int shCount)
4994 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4995 /* shift left accumulator */
4997 /* or with result */
4998 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
4999 /* back to result */
5000 aopPut(AOP(result),"a",offr);
5003 /*-----------------------------------------------------------------*/
5004 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5005 /*-----------------------------------------------------------------*/
5006 static void shiftRLeftOrResult (operand *left, int offl,
5007 operand *result, int offr, int shCount)
5009 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5010 /* shift right accumulator */
5012 /* or with result */
5013 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5014 /* back to result */
5015 aopPut(AOP(result),"a",offr);
5018 /*-----------------------------------------------------------------*/
5019 /* genlshOne - left shift a one byte quantity by known count */
5020 /*-----------------------------------------------------------------*/
5021 static void genlshOne (operand *result, operand *left, int shCount)
5023 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5026 /*-----------------------------------------------------------------*/
5027 /* genlshTwo - left shift two bytes by known amount != 0 */
5028 /*-----------------------------------------------------------------*/
5029 static void genlshTwo (operand *result,operand *left, int shCount)
5033 size = getDataSize(result);
5035 /* if shCount >= 8 */
5041 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5043 movLeft2Result(left, LSB, result, MSB16, 0);
5045 aopPut(AOP(result),zero,LSB);
5048 /* 1 <= shCount <= 7 */
5051 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5053 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5057 /*-----------------------------------------------------------------*/
5058 /* shiftLLong - shift left one long from left to result */
5059 /* offl = LSB or MSB16 */
5060 /*-----------------------------------------------------------------*/
5061 static void shiftLLong (operand *left, operand *result, int offr )
5064 int size = AOP_SIZE(result);
5066 if(size >= LSB+offr){
5067 l = aopGet(AOP(left),LSB,FALSE,FALSE);
5069 emitcode("add","a,acc");
5070 if (sameRegs(AOP(left),AOP(result)) &&
5071 size >= MSB16+offr && offr != LSB )
5072 emitcode("xch","a,%s",
5073 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
5075 aopPut(AOP(result),"a",LSB+offr);
5078 if(size >= MSB16+offr){
5079 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5080 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
5083 emitcode("rlc","a");
5084 if (sameRegs(AOP(left),AOP(result)) &&
5085 size >= MSB24+offr && offr != LSB)
5086 emitcode("xch","a,%s",
5087 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
5089 aopPut(AOP(result),"a",MSB16+offr);
5092 if(size >= MSB24+offr){
5093 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5094 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
5097 emitcode("rlc","a");
5098 if (sameRegs(AOP(left),AOP(result)) &&
5099 size >= MSB32+offr && offr != LSB )
5100 emitcode("xch","a,%s",
5101 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
5103 aopPut(AOP(result),"a",MSB24+offr);
5106 if(size > MSB32+offr){
5107 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5108 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
5111 emitcode("rlc","a");
5112 aopPut(AOP(result),"a",MSB32+offr);
5115 aopPut(AOP(result),zero,LSB);
5118 /*-----------------------------------------------------------------*/
5119 /* genlshFour - shift four byte by a known amount != 0 */
5120 /*-----------------------------------------------------------------*/
5121 static void genlshFour (operand *result, operand *left, int shCount)
5125 size = AOP_SIZE(result);
5127 /* if shifting more that 3 bytes */
5128 if (shCount >= 24 ) {
5131 /* lowest order of left goes to the highest
5132 order of the destination */
5133 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5135 movLeft2Result(left, LSB, result, MSB32, 0);
5136 aopPut(AOP(result),zero,LSB);
5137 aopPut(AOP(result),zero,MSB16);
5138 aopPut(AOP(result),zero,MSB32);
5142 /* more than two bytes */
5143 else if ( shCount >= 16 ) {
5144 /* lower order two bytes goes to higher order two bytes */
5146 /* if some more remaining */
5148 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5150 movLeft2Result(left, MSB16, result, MSB32, 0);
5151 movLeft2Result(left, LSB, result, MSB24, 0);
5153 aopPut(AOP(result),zero,MSB16);
5154 aopPut(AOP(result),zero,LSB);
5158 /* if more than 1 byte */
5159 else if ( shCount >= 8 ) {
5160 /* lower order three bytes goes to higher order three bytes */
5164 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5166 movLeft2Result(left, LSB, result, MSB16, 0);
5168 else{ /* size = 4 */
5170 movLeft2Result(left, MSB24, result, MSB32, 0);
5171 movLeft2Result(left, MSB16, result, MSB24, 0);
5172 movLeft2Result(left, LSB, result, MSB16, 0);
5173 aopPut(AOP(result),zero,LSB);
5175 else if(shCount == 1)
5176 shiftLLong(left, result, MSB16);
5178 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5179 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5180 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5181 aopPut(AOP(result),zero,LSB);
5186 /* 1 <= shCount <= 7 */
5187 else if(shCount <= 2){
5188 shiftLLong(left, result, LSB);
5190 shiftLLong(result, result, LSB);
5192 /* 3 <= shCount <= 7, optimize */
5194 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5195 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5196 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5200 /*-----------------------------------------------------------------*/
5201 /* genLeftShiftLiteral - left shifting by known count */
5202 /*-----------------------------------------------------------------*/
5203 static void genLeftShiftLiteral (operand *left,
5208 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5211 freeAsmop(right,NULL,ic,TRUE);
5213 aopOp(left,ic,FALSE);
5214 aopOp(result,ic,FALSE);
5216 size = getSize(operandType(result));
5219 emitcode("; shift left ","result %d, left %d",size,
5223 /* I suppose that the left size >= result size */
5226 movLeft2Result(left, size, result, size, 0);
5230 else if(shCount >= (size * 8))
5232 aopPut(AOP(result),zero,size);
5236 genlshOne (result,left,shCount);
5241 genlshTwo (result,left,shCount);
5245 genlshFour (result,left,shCount);
5249 freeAsmop(left,NULL,ic,TRUE);
5250 freeAsmop(result,NULL,ic,TRUE);
5253 /*-----------------------------------------------------------------*/
5254 /* genLeftShift - generates code for left shifting */
5255 /*-----------------------------------------------------------------*/
5256 static void genLeftShift (iCode *ic)
5258 operand *left,*right, *result;
5261 symbol *tlbl , *tlbl1;
5263 right = IC_RIGHT(ic);
5265 result = IC_RESULT(ic);
5267 aopOp(right,ic,FALSE);
5269 /* if the shift count is known then do it
5270 as efficiently as possible */
5271 if (AOP_TYPE(right) == AOP_LIT) {
5272 genLeftShiftLiteral (left,right,result,ic);
5276 /* shift count is unknown then we have to form
5277 a loop get the loop count in B : Note: we take
5278 only the lower order byte since shifting
5279 more that 32 bits make no sense anyway, ( the
5280 largest size of an object can be only 32 bits ) */
5282 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5283 emitcode("inc","b");
5284 freeAsmop (right,NULL,ic,TRUE);
5285 aopOp(left,ic,FALSE);
5286 aopOp(result,ic,FALSE);
5288 /* now move the left to the result if they are not the
5290 if (!sameRegs(AOP(left),AOP(result)) &&
5291 AOP_SIZE(result) > 1) {
5293 size = AOP_SIZE(result);
5296 l = aopGet(AOP(left),offset,FALSE,TRUE);
5297 if (*l == '@' && (IS_AOP_PREG(result))) {
5299 emitcode("mov","a,%s",l);
5300 aopPut(AOP(result),"a",offset);
5302 aopPut(AOP(result),l,offset);
5307 tlbl = newiTempLabel(NULL);
5308 size = AOP_SIZE(result);
5310 tlbl1 = newiTempLabel(NULL);
5312 /* if it is only one byte then */
5314 symbol *tlbl1 = newiTempLabel(NULL);
5316 l = aopGet(AOP(left),0,FALSE,FALSE);
5318 emitcode("sjmp","%05d$",tlbl1->key+100);
5319 emitcode("","%05d$:",tlbl->key+100);
5320 emitcode("add","a,acc");
5321 emitcode("","%05d$:",tlbl1->key+100);
5322 emitcode("djnz","b,%05d$",tlbl->key+100);
5323 aopPut(AOP(result),"a",0);
5327 reAdjustPreg(AOP(result));
5329 emitcode("sjmp","%05d$",tlbl1->key+100);
5330 emitcode("","%05d$:",tlbl->key+100);
5331 l = aopGet(AOP(result),offset,FALSE,FALSE);
5333 emitcode("add","a,acc");
5334 aopPut(AOP(result),"a",offset++);
5336 l = aopGet(AOP(result),offset,FALSE,FALSE);
5338 emitcode("rlc","a");
5339 aopPut(AOP(result),"a",offset++);
5341 reAdjustPreg(AOP(result));
5343 emitcode("","%05d$:",tlbl1->key+100);
5344 emitcode("djnz","b,%05d$",tlbl->key+100);
5346 freeAsmop(left,NULL,ic,TRUE);
5347 freeAsmop(result,NULL,ic,TRUE);
5350 /*-----------------------------------------------------------------*/
5351 /* genrshOne - right shift a one byte quantity by known count */
5352 /*-----------------------------------------------------------------*/
5353 static void genrshOne (operand *result, operand *left,
5354 int shCount, int sign)
5356 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
5359 /*-----------------------------------------------------------------*/
5360 /* genrshTwo - right shift two bytes by known amount != 0 */
5361 /*-----------------------------------------------------------------*/
5362 static void genrshTwo (operand *result,operand *left,
5363 int shCount, int sign)
5365 /* if shCount >= 8 */
5369 shiftR1Left2Result(left, MSB16, result, LSB,
5372 movLeft2Result(left, MSB16, result, LSB, sign);
5373 addSign(result, MSB16, sign);
5376 /* 1 <= shCount <= 7 */
5378 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
5381 /*-----------------------------------------------------------------*/
5382 /* shiftRLong - shift right one long from left to result */
5383 /* offl = LSB or MSB16 */
5384 /*-----------------------------------------------------------------*/
5385 static void shiftRLong (operand *left, int offl,
5386 operand *result, int sign)
5389 emitcode("clr","c");
5390 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
5392 emitcode("mov","c,acc.7");
5393 emitcode("rrc","a");
5394 aopPut(AOP(result),"a",MSB32-offl);
5396 /* add sign of "a" */
5397 addSign(result, MSB32, sign);
5399 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
5400 emitcode("rrc","a");
5401 aopPut(AOP(result),"a",MSB24-offl);
5403 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
5404 emitcode("rrc","a");
5405 aopPut(AOP(result),"a",MSB16-offl);
5408 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
5409 emitcode("rrc","a");
5410 aopPut(AOP(result),"a",LSB);
5414 /*-----------------------------------------------------------------*/
5415 /* genrshFour - shift four byte by a known amount != 0 */
5416 /*-----------------------------------------------------------------*/
5417 static void genrshFour (operand *result, operand *left,
5418 int shCount, int sign)
5420 /* if shifting more that 3 bytes */
5421 if(shCount >= 24 ) {
5424 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
5426 movLeft2Result(left, MSB32, result, LSB, sign);
5427 addSign(result, MSB16, sign);
5429 else if(shCount >= 16){
5432 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
5434 movLeft2Result(left, MSB24, result, LSB, 0);
5435 movLeft2Result(left, MSB32, result, MSB16, sign);
5437 addSign(result, MSB24, sign);
5439 else if(shCount >= 8){
5442 shiftRLong(left, MSB16, result, sign);
5443 else if(shCount == 0){
5444 movLeft2Result(left, MSB16, result, LSB, 0);
5445 movLeft2Result(left, MSB24, result, MSB16, 0);
5446 movLeft2Result(left, MSB32, result, MSB24, sign);
5447 addSign(result, MSB32, sign);
5450 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
5451 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
5452 /* the last shift is signed */
5453 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
5454 addSign(result, MSB32, sign);
5457 else{ /* 1 <= shCount <= 7 */
5459 shiftRLong(left, LSB, result, sign);
5461 shiftRLong(result, LSB, result, sign);
5464 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
5465 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
5466 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
5471 /*-----------------------------------------------------------------*/
5472 /* genRightShiftLiteral - right shifting by known count */
5473 /*-----------------------------------------------------------------*/
5474 static void genRightShiftLiteral (operand *left,
5480 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5483 freeAsmop(right,NULL,ic,TRUE);
5485 aopOp(left,ic,FALSE);
5486 aopOp(result,ic,FALSE);
5489 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
5493 size = getDataSize(left);
5494 /* test the LEFT size !!! */
5496 /* I suppose that the left size >= result size */
5498 size = getDataSize(result);
5500 movLeft2Result(left, size, result, size, 0);
5503 else if(shCount >= (size * 8)){
5505 /* get sign in acc.7 */
5506 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
5507 addSign(result, LSB, sign);
5511 genrshOne (result,left,shCount,sign);
5515 genrshTwo (result,left,shCount,sign);
5519 genrshFour (result,left,shCount,sign);
5525 freeAsmop(left,NULL,ic,TRUE);
5526 freeAsmop(result,NULL,ic,TRUE);
5530 /*-----------------------------------------------------------------*/
5531 /* genSignedRightShift - right shift of signed number */
5532 /*-----------------------------------------------------------------*/
5533 static void genSignedRightShift (iCode *ic)
5535 operand *right, *left, *result;
5538 symbol *tlbl, *tlbl1 ;
5540 /* we do it the hard way put the shift count in b
5541 and loop thru preserving the sign */
5543 right = IC_RIGHT(ic);
5545 result = IC_RESULT(ic);
5547 aopOp(right,ic,FALSE);
5550 if ( AOP_TYPE(right) == AOP_LIT) {
5551 genRightShiftLiteral (left,right,result,ic,1);
5554 /* shift count is unknown then we have to form
5555 a loop get the loop count in B : Note: we take
5556 only the lower order byte since shifting
5557 more that 32 bits make no sense anyway, ( the
5558 largest size of an object can be only 32 bits ) */
5560 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5561 emitcode("inc","b");
5562 freeAsmop (right,NULL,ic,TRUE);
5563 aopOp(left,ic,FALSE);
5564 aopOp(result,ic,FALSE);
5566 /* now move the left to the result if they are not the
5568 if (!sameRegs(AOP(left),AOP(result)) &&
5569 AOP_SIZE(result) > 1) {
5571 size = AOP_SIZE(result);
5574 l = aopGet(AOP(left),offset,FALSE,TRUE);
5575 if (*l == '@' && IS_AOP_PREG(result)) {
5577 emitcode("mov","a,%s",l);
5578 aopPut(AOP(result),"a",offset);
5580 aopPut(AOP(result),l,offset);
5585 /* mov the highest order bit to OVR */
5586 tlbl = newiTempLabel(NULL);
5587 tlbl1= newiTempLabel(NULL);
5589 size = AOP_SIZE(result);
5591 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
5592 emitcode("rlc","a");
5593 emitcode("mov","ov,c");
5594 /* if it is only one byte then */
5596 l = aopGet(AOP(left),0,FALSE,FALSE);
5598 emitcode("sjmp","%05d$",tlbl1->key+100);
5599 emitcode("","%05d$:",tlbl->key+100);
5600 emitcode("mov","c,ov");
5601 emitcode("rrc","a");
5602 emitcode("","%05d$:",tlbl1->key+100);
5603 emitcode("djnz","b,%05d$",tlbl->key+100);
5604 aopPut(AOP(result),"a",0);
5608 reAdjustPreg(AOP(result));
5609 emitcode("sjmp","%05d$",tlbl1->key+100);
5610 emitcode("","%05d$:",tlbl->key+100);
5611 emitcode("mov","c,ov");
5613 l = aopGet(AOP(result),offset,FALSE,FALSE);
5615 emitcode("rrc","a");
5616 aopPut(AOP(result),"a",offset--);
5618 reAdjustPreg(AOP(result));
5619 emitcode("","%05d$:",tlbl1->key+100);
5620 emitcode("djnz","b,%05d$",tlbl->key+100);
5623 freeAsmop(left,NULL,ic,TRUE);
5624 freeAsmop(result,NULL,ic,TRUE);
5627 /*-----------------------------------------------------------------*/
5628 /* genRightShift - generate code for right shifting */
5629 /*-----------------------------------------------------------------*/
5630 static void genRightShift (iCode *ic)
5632 operand *right, *left, *result;
5636 symbol *tlbl, *tlbl1 ;
5638 /* if signed then we do it the hard way preserve the
5639 sign bit moving it inwards */
5640 retype = getSpec(operandType(IC_RESULT(ic)));
5642 if (!SPEC_USIGN(retype)) {
5643 genSignedRightShift (ic);
5647 /* signed & unsigned types are treated the same : i.e. the
5648 signed is NOT propagated inwards : quoting from the
5649 ANSI - standard : "for E1 >> E2, is equivalent to division
5650 by 2**E2 if unsigned or if it has a non-negative value,
5651 otherwise the result is implementation defined ", MY definition
5652 is that the sign does not get propagated */
5654 right = IC_RIGHT(ic);
5656 result = IC_RESULT(ic);
5658 aopOp(right,ic,FALSE);
5660 /* if the shift count is known then do it
5661 as efficiently as possible */
5662 if (AOP_TYPE(right) == AOP_LIT) {
5663 genRightShiftLiteral (left,right,result,ic, 0);
5667 /* shift count is unknown then we have to form
5668 a loop get the loop count in B : Note: we take
5669 only the lower order byte since shifting
5670 more that 32 bits make no sense anyway, ( the
5671 largest size of an object can be only 32 bits ) */
5673 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5674 emitcode("inc","b");
5675 freeAsmop (right,NULL,ic,TRUE);
5676 aopOp(left,ic,FALSE);
5677 aopOp(result,ic,FALSE);
5679 /* now move the left to the result if they are not the
5681 if (!sameRegs(AOP(left),AOP(result)) &&
5682 AOP_SIZE(result) > 1) {
5684 size = AOP_SIZE(result);
5687 l = aopGet(AOP(left),offset,FALSE,TRUE);
5688 if (*l == '@' && IS_AOP_PREG(result)) {
5690 emitcode("mov","a,%s",l);
5691 aopPut(AOP(result),"a",offset);
5693 aopPut(AOP(result),l,offset);
5698 tlbl = newiTempLabel(NULL);
5699 tlbl1= newiTempLabel(NULL);
5700 size = AOP_SIZE(result);
5703 /* if it is only one byte then */
5705 l = aopGet(AOP(left),0,FALSE,FALSE);
5707 emitcode("sjmp","%05d$",tlbl1->key+100);
5708 emitcode("","%05d$:",tlbl->key+100);
5710 emitcode("rrc","a");
5711 emitcode("","%05d$:",tlbl1->key+100);
5712 emitcode("djnz","b,%05d$",tlbl->key+100);
5713 aopPut(AOP(result),"a",0);
5717 reAdjustPreg(AOP(result));
5718 emitcode("sjmp","%05d$",tlbl1->key+100);
5719 emitcode("","%05d$:",tlbl->key+100);
5722 l = aopGet(AOP(result),offset,FALSE,FALSE);
5724 emitcode("rrc","a");
5725 aopPut(AOP(result),"a",offset--);
5727 reAdjustPreg(AOP(result));
5729 emitcode("","%05d$:",tlbl1->key+100);
5730 emitcode("djnz","b,%05d$",tlbl->key+100);
5733 freeAsmop(left,NULL,ic,TRUE);
5734 freeAsmop(result,NULL,ic,TRUE);
5737 /*-----------------------------------------------------------------*/
5738 /* genUnpackBits - generates code for unpacking bits */
5739 /*-----------------------------------------------------------------*/
5740 static void genUnpackBits (operand *result, char *rname, int ptype)
5747 etype = getSpec(operandType(result));
5749 /* read the first byte */
5754 emitcode("mov","a,@%s",rname);
5758 emitcode("movx","a,@%s",rname);
5762 emitcode("movx","a,@dptr");
5766 emitcode("clr","a");
5767 emitcode("movc","a","@a+dptr");
5771 emitcode("lcall","__gptrget");
5775 /* if we have bitdisplacement then it fits */
5776 /* into this byte completely or if length is */
5777 /* less than a byte */
5778 if ((shCnt = SPEC_BSTR(etype)) ||
5779 (SPEC_BLEN(etype) <= 8)) {
5781 /* shift right acc */
5784 emitcode("anl","a,#0x%02x",
5785 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
5786 aopPut(AOP(result),"a",offset);
5790 /* bit field did not fit in a byte */
5791 rlen = SPEC_BLEN(etype) - 8;
5792 aopPut(AOP(result),"a",offset++);
5799 emitcode("inc","%s",rname);
5800 emitcode("mov","a,@%s",rname);
5804 emitcode("inc","%s",rname);
5805 emitcode("movx","a,@%s",rname);
5809 emitcode("inc","dptr");
5810 emitcode("movx","a,@dptr");
5814 emitcode("clr","a");
5815 emitcode("inc","dptr");
5816 emitcode("movc","a","@a+dptr");
5820 emitcode("inc","dptr");
5821 emitcode("lcall","__gptrget");
5826 /* if we are done */
5830 aopPut(AOP(result),"a",offset++);
5835 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
5836 aopPut(AOP(result),"a",offset);
5843 /*-----------------------------------------------------------------*/
5844 /* genDataPointerGet - generates code when ptr offset is known */
5845 /*-----------------------------------------------------------------*/
5846 static void genDataPointerGet (operand *left,
5852 int size , offset = 0;
5853 aopOp(result,ic,TRUE);
5855 /* get the string representation of the name */
5856 l = aopGet(AOP(left),0,FALSE,TRUE);
5857 size = AOP_SIZE(result);
5860 sprintf(buffer,"(%s + %d)",l+1,offset);
5862 sprintf(buffer,"%s",l+1);
5863 aopPut(AOP(result),buffer,offset++);
5866 freeAsmop(left,NULL,ic,TRUE);
5867 freeAsmop(result,NULL,ic,TRUE);
5870 /*-----------------------------------------------------------------*/
5871 /* genNearPointerGet - emitcode for near pointer fetch */
5872 /*-----------------------------------------------------------------*/
5873 static void genNearPointerGet (operand *left,
5880 link *rtype, *retype;
5881 link *ltype = operandType(left);
5884 rtype = operandType(result);
5885 retype= getSpec(rtype);
5887 aopOp(left,ic,FALSE);
5889 /* if left is rematerialisable and
5890 result is not bit variable type and
5891 the left is pointer to data space i.e
5892 lower 128 bytes of space */
5893 if (AOP_TYPE(left) == AOP_IMMD &&
5894 !IS_BITVAR(retype) &&
5895 DCL_TYPE(ltype) == POINTER) {
5896 genDataPointerGet (left,result,ic);
5900 /* if the value is already in a pointer register
5901 then don't need anything more */
5902 if (!AOP_INPREG(AOP(left))) {
5903 /* otherwise get a free pointer register */
5905 preg = getFreePtr(ic,&aop,FALSE);
5906 emitcode("mov","%s,%s",
5908 aopGet(AOP(left),0,FALSE,TRUE));
5909 rname = preg->name ;
5911 rname = aopGet(AOP(left),0,FALSE,FALSE);
5913 freeAsmop(left,NULL,ic,TRUE);
5914 aopOp (result,ic,FALSE);
5916 /* if bitfield then unpack the bits */
5917 if (IS_BITVAR(retype))
5918 genUnpackBits (result,rname,POINTER);
5920 /* we have can just get the values */
5921 int size = AOP_SIZE(result);
5925 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
5927 emitcode("mov","a,@%s",rname);
5928 aopPut(AOP(result),"a",offset);
5930 sprintf(buffer,"@%s",rname);
5931 aopPut(AOP(result),buffer,offset);
5935 emitcode("inc","%s",rname);
5939 /* now some housekeeping stuff */
5941 /* we had to allocate for this iCode */
5942 freeAsmop(NULL,aop,ic,TRUE);
5944 /* we did not allocate which means left
5945 already in a pointer register, then
5946 if size > 0 && this could be used again
5947 we have to point it back to where it
5949 if (AOP_SIZE(result) > 1 &&
5950 !OP_SYMBOL(left)->remat &&
5951 ( OP_SYMBOL(left)->liveTo > ic->seq ||
5953 int size = AOP_SIZE(result) - 1;
5955 emitcode("dec","%s",rname);
5960 freeAsmop(result,NULL,ic,TRUE);
5964 /*-----------------------------------------------------------------*/
5965 /* genPagedPointerGet - emitcode for paged pointer fetch */
5966 /*-----------------------------------------------------------------*/
5967 static void genPagedPointerGet (operand *left,
5974 link *rtype, *retype;
5976 rtype = operandType(result);
5977 retype= getSpec(rtype);
5979 aopOp(left,ic,FALSE);
5981 /* if the value is already in a pointer register
5982 then don't need anything more */
5983 if (!AOP_INPREG(AOP(left))) {
5984 /* otherwise get a free pointer register */
5986 preg = getFreePtr(ic,&aop,FALSE);
5987 emitcode("mov","%s,%s",
5989 aopGet(AOP(left),0,FALSE,TRUE));
5990 rname = preg->name ;
5992 rname = aopGet(AOP(left),0,FALSE,FALSE);
5994 freeAsmop(left,NULL,ic,TRUE);
5995 aopOp (result,ic,FALSE);
5997 /* if bitfield then unpack the bits */
5998 if (IS_BITVAR(retype))
5999 genUnpackBits (result,rname,PPOINTER);
6001 /* we have can just get the values */
6002 int size = AOP_SIZE(result);
6007 emitcode("movx","a,@%s",rname);
6008 aopPut(AOP(result),"a",offset);
6013 emitcode("inc","%s",rname);
6017 /* now some housekeeping stuff */
6019 /* we had to allocate for this iCode */
6020 freeAsmop(NULL,aop,ic,TRUE);
6022 /* we did not allocate which means left
6023 already in a pointer register, then
6024 if size > 0 && this could be used again
6025 we have to point it back to where it
6027 if (AOP_SIZE(result) > 1 &&
6028 !OP_SYMBOL(left)->remat &&
6029 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6031 int size = AOP_SIZE(result) - 1;
6033 emitcode("dec","%s",rname);
6038 freeAsmop(result,NULL,ic,TRUE);
6043 /*-----------------------------------------------------------------*/
6044 /* genFarPointerGet - gget value from far space */
6045 /*-----------------------------------------------------------------*/
6046 static void genFarPointerGet (operand *left,
6047 operand *result, iCode *ic)
6050 link *retype = getSpec(operandType(result));
6052 aopOp(left,ic,FALSE);
6054 /* if the operand is already in dptr
6055 then we do nothing else we move the value to dptr */
6056 if (AOP_TYPE(left) != AOP_STR) {
6057 /* if this is remateriazable */
6058 if (AOP_TYPE(left) == AOP_IMMD)
6059 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6060 else { /* we need to get it byte by byte */
6061 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6062 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6063 if (options.model == MODEL_FLAT24)
6065 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6069 /* so dptr know contains the address */
6070 freeAsmop(left,NULL,ic,TRUE);
6071 aopOp(result,ic,FALSE);
6073 /* if bit then unpack */
6074 if (IS_BITVAR(retype))
6075 genUnpackBits(result,"dptr",FPOINTER);
6077 size = AOP_SIZE(result);
6081 emitcode("movx","a,@dptr");
6082 aopPut(AOP(result),"a",offset++);
6084 emitcode("inc","dptr");
6088 freeAsmop(result,NULL,ic,TRUE);
6091 /*-----------------------------------------------------------------*/
6092 /* emitcodePointerGet - gget value from code space */
6093 /*-----------------------------------------------------------------*/
6094 static void emitcodePointerGet (operand *left,
6095 operand *result, iCode *ic)
6098 link *retype = getSpec(operandType(result));
6100 aopOp(left,ic,FALSE);
6102 /* if the operand is already in dptr
6103 then we do nothing else we move the value to dptr */
6104 if (AOP_TYPE(left) != AOP_STR) {
6105 /* if this is remateriazable */
6106 if (AOP_TYPE(left) == AOP_IMMD)
6107 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6108 else { /* we need to get it byte by byte */
6109 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6110 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6111 if (options.model == MODEL_FLAT24)
6113 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6117 /* so dptr know contains the address */
6118 freeAsmop(left,NULL,ic,TRUE);
6119 aopOp(result,ic,FALSE);
6121 /* if bit then unpack */
6122 if (IS_BITVAR(retype))
6123 genUnpackBits(result,"dptr",CPOINTER);
6125 size = AOP_SIZE(result);
6129 emitcode("clr","a");
6130 emitcode("movc","a,@a+dptr");
6131 aopPut(AOP(result),"a",offset++);
6133 emitcode("inc","dptr");
6137 freeAsmop(result,NULL,ic,TRUE);
6140 /*-----------------------------------------------------------------*/
6141 /* genGenPointerGet - gget value from generic pointer space */
6142 /*-----------------------------------------------------------------*/
6143 static void genGenPointerGet (operand *left,
6144 operand *result, iCode *ic)
6147 link *retype = getSpec(operandType(result));
6149 aopOp(left,ic,FALSE);
6151 /* if the operand is already in dptr
6152 then we do nothing else we move the value to dptr */
6153 if (AOP_TYPE(left) != AOP_STR) {
6154 /* if this is remateriazable */
6155 if (AOP_TYPE(left) == AOP_IMMD) {
6156 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6157 emitcode("mov","b,#%d",pointerCode(retype));
6159 else { /* we need to get it byte by byte */
6160 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6161 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6162 if (options.model == MODEL_FLAT24)
6164 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6165 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
6169 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
6173 /* so dptr know contains the address */
6174 freeAsmop(left,NULL,ic,TRUE);
6175 aopOp(result,ic,FALSE);
6177 /* if bit then unpack */
6178 if (IS_BITVAR(retype))
6179 genUnpackBits(result,"dptr",GPOINTER);
6181 size = AOP_SIZE(result);
6185 emitcode("lcall","__gptrget");
6186 aopPut(AOP(result),"a",offset++);
6188 emitcode("inc","dptr");
6192 freeAsmop(result,NULL,ic,TRUE);
6195 /*-----------------------------------------------------------------*/
6196 /* genPointerGet - generate code for pointer get */
6197 /*-----------------------------------------------------------------*/
6198 static void genPointerGet (iCode *ic)
6200 operand *left, *result ;
6205 result = IC_RESULT(ic) ;
6207 /* depending on the type of pointer we need to
6208 move it to the correct pointer register */
6209 type = operandType(left);
6210 etype = getSpec(type);
6211 /* if left is of type of pointer then it is simple */
6212 if (IS_PTR(type) && !IS_FUNC(type->next))
6213 p_type = DCL_TYPE(type);
6215 /* we have to go by the storage class */
6216 p_type = PTR_TYPE(SPEC_OCLS(etype));
6218 /* if (SPEC_OCLS(etype)->codesp ) { */
6219 /* p_type = CPOINTER ; */
6222 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6223 /* p_type = FPOINTER ; */
6225 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6226 /* p_type = PPOINTER; */
6228 /* if (SPEC_OCLS(etype) == idata ) */
6229 /* p_type = IPOINTER; */
6231 /* p_type = POINTER ; */
6234 /* now that we have the pointer type we assign
6235 the pointer values */
6240 genNearPointerGet (left,result,ic);
6244 genPagedPointerGet(left,result,ic);
6248 genFarPointerGet (left,result,ic);
6252 emitcodePointerGet (left,result,ic);
6256 genGenPointerGet (left,result,ic);
6262 /*-----------------------------------------------------------------*/
6263 /* genPackBits - generates code for packed bit storage */
6264 /*-----------------------------------------------------------------*/
6265 static void genPackBits (link *etype ,
6267 char *rname, int p_type)
6275 blen = SPEC_BLEN(etype);
6276 bstr = SPEC_BSTR(etype);
6278 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6281 /* if the bit lenth is less than or */
6282 /* it exactly fits a byte then */
6283 if (SPEC_BLEN(etype) <= 8 ) {
6284 shCount = SPEC_BSTR(etype) ;
6286 /* shift left acc */
6289 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6294 emitcode ("mov","b,a");
6295 emitcode("mov","a,@%s",rname);
6299 emitcode ("mov","b,a");
6300 emitcode("movx","a,@dptr");
6304 emitcode ("push","b");
6305 emitcode ("push","acc");
6306 emitcode ("lcall","__gptrget");
6307 emitcode ("pop","b");
6311 emitcode ("anl","a,#0x%02x",(unsigned char)
6312 ((unsigned char)(0xFF << (blen+bstr)) |
6313 (unsigned char)(0xFF >> (8-bstr)) ) );
6314 emitcode ("orl","a,b");
6315 if (p_type == GPOINTER)
6316 emitcode("pop","b");
6322 emitcode("mov","@%s,a",rname);
6326 emitcode("movx","@dptr,a");
6330 emitcode("lcall","__gptrput");
6335 if ( SPEC_BLEN(etype) <= 8 )
6338 emitcode("inc","%s",rname);
6339 rLen = SPEC_BLEN(etype) ;
6341 /* now generate for lengths greater than one byte */
6344 l = aopGet(AOP(right),offset++,FALSE,TRUE);
6354 emitcode("mov","@%s,a",rname);
6356 emitcode("mov","@%s,%s",rname,l);
6361 emitcode("movx","@dptr,a");
6366 emitcode("lcall","__gptrput");
6369 emitcode ("inc","%s",rname);
6374 /* last last was not complete */
6376 /* save the byte & read byte */
6379 emitcode ("mov","b,a");
6380 emitcode("mov","a,@%s",rname);
6384 emitcode ("mov","b,a");
6385 emitcode("movx","a,@dptr");
6389 emitcode ("push","b");
6390 emitcode ("push","acc");
6391 emitcode ("lcall","__gptrget");
6392 emitcode ("pop","b");
6396 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
6397 emitcode ("orl","a,b");
6400 if (p_type == GPOINTER)
6401 emitcode("pop","b");
6406 emitcode("mov","@%s,a",rname);
6410 emitcode("movx","@dptr,a");
6414 emitcode("lcall","__gptrput");
6418 /*-----------------------------------------------------------------*/
6419 /* genDataPointerSet - remat pointer to data space */
6420 /*-----------------------------------------------------------------*/
6421 static void genDataPointerSet(operand *right,
6425 int size, offset = 0 ;
6426 char *l, buffer[256];
6428 aopOp(right,ic,FALSE);
6430 l = aopGet(AOP(result),0,FALSE,TRUE);
6431 size = AOP_SIZE(right);
6434 sprintf(buffer,"(%s + %d)",l+1,offset);
6436 sprintf(buffer,"%s",l+1);
6437 emitcode("mov","%s,%s",buffer,
6438 aopGet(AOP(right),offset++,FALSE,FALSE));
6441 freeAsmop(right,NULL,ic,TRUE);
6442 freeAsmop(result,NULL,ic,TRUE);
6445 /*-----------------------------------------------------------------*/
6446 /* genNearPointerSet - emitcode for near pointer put */
6447 /*-----------------------------------------------------------------*/
6448 static void genNearPointerSet (operand *right,
6456 link *ptype = operandType(result);
6458 retype= getSpec(operandType(right));
6460 aopOp(result,ic,FALSE);
6462 /* if the result is rematerializable &
6463 in data space & not a bit variable */
6464 if (AOP_TYPE(result) == AOP_IMMD &&
6465 DCL_TYPE(ptype) == POINTER &&
6466 !IS_BITVAR(retype)) {
6467 genDataPointerSet (right,result,ic);
6471 /* if the value is already in a pointer register
6472 then don't need anything more */
6473 if (!AOP_INPREG(AOP(result))) {
6474 /* otherwise get a free pointer register */
6476 preg = getFreePtr(ic,&aop,FALSE);
6477 emitcode("mov","%s,%s",
6479 aopGet(AOP(result),0,FALSE,TRUE));
6480 rname = preg->name ;
6482 rname = aopGet(AOP(result),0,FALSE,FALSE);
6484 freeAsmop(result,NULL,ic,TRUE);
6485 aopOp (right,ic,FALSE);
6487 /* if bitfield then unpack the bits */
6488 if (IS_BITVAR(retype))
6489 genPackBits (retype,right,rname,POINTER);
6491 /* we have can just get the values */
6492 int size = AOP_SIZE(right);
6496 l = aopGet(AOP(right),offset,FALSE,TRUE);
6499 emitcode("mov","@%s,a",rname);
6501 emitcode("mov","@%s,%s",rname,l);
6503 emitcode("inc","%s",rname);
6508 /* now some housekeeping stuff */
6510 /* we had to allocate for this iCode */
6511 freeAsmop(NULL,aop,ic,TRUE);
6513 /* we did not allocate which means left
6514 already in a pointer register, then
6515 if size > 0 && this could be used again
6516 we have to point it back to where it
6518 if (AOP_SIZE(right) > 1 &&
6519 !OP_SYMBOL(result)->remat &&
6520 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6522 int size = AOP_SIZE(right) - 1;
6524 emitcode("dec","%s",rname);
6529 freeAsmop(right,NULL,ic,TRUE);
6534 /*-----------------------------------------------------------------*/
6535 /* genPagedPointerSet - emitcode for Paged pointer put */
6536 /*-----------------------------------------------------------------*/
6537 static void genPagedPointerSet (operand *right,
6546 retype= getSpec(operandType(right));
6548 aopOp(result,ic,FALSE);
6550 /* if the value is already in a pointer register
6551 then don't need anything more */
6552 if (!AOP_INPREG(AOP(result))) {
6553 /* otherwise get a free pointer register */
6555 preg = getFreePtr(ic,&aop,FALSE);
6556 emitcode("mov","%s,%s",
6558 aopGet(AOP(result),0,FALSE,TRUE));
6559 rname = preg->name ;
6561 rname = aopGet(AOP(result),0,FALSE,FALSE);
6563 freeAsmop(result,NULL,ic,TRUE);
6564 aopOp (right,ic,FALSE);
6566 /* if bitfield then unpack the bits */
6567 if (IS_BITVAR(retype))
6568 genPackBits (retype,right,rname,PPOINTER);
6570 /* we have can just get the values */
6571 int size = AOP_SIZE(right);
6575 l = aopGet(AOP(right),offset,FALSE,TRUE);
6578 emitcode("movx","@%s,a",rname);
6581 emitcode("inc","%s",rname);
6587 /* now some housekeeping stuff */
6589 /* we had to allocate for this iCode */
6590 freeAsmop(NULL,aop,ic,TRUE);
6592 /* we did not allocate which means left
6593 already in a pointer register, then
6594 if size > 0 && this could be used again
6595 we have to point it back to where it
6597 if (AOP_SIZE(right) > 1 &&
6598 !OP_SYMBOL(result)->remat &&
6599 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6601 int size = AOP_SIZE(right) - 1;
6603 emitcode("dec","%s",rname);
6608 freeAsmop(right,NULL,ic,TRUE);
6613 /*-----------------------------------------------------------------*/
6614 /* genFarPointerSet - set value from far space */
6615 /*-----------------------------------------------------------------*/
6616 static void genFarPointerSet (operand *right,
6617 operand *result, iCode *ic)
6620 link *retype = getSpec(operandType(right));
6622 aopOp(result,ic,FALSE);
6624 /* if the operand is already in dptr
6625 then we do nothing else we move the value to dptr */
6626 if (AOP_TYPE(result) != AOP_STR) {
6627 /* if this is remateriazable */
6628 if (AOP_TYPE(result) == AOP_IMMD)
6629 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6630 else { /* we need to get it byte by byte */
6631 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6632 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6633 if (options.model == MODEL_FLAT24)
6635 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6639 /* so dptr know contains the address */
6640 freeAsmop(result,NULL,ic,TRUE);
6641 aopOp(right,ic,FALSE);
6643 /* if bit then unpack */
6644 if (IS_BITVAR(retype))
6645 genPackBits(retype,right,"dptr",FPOINTER);
6647 size = AOP_SIZE(right);
6651 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6653 emitcode("movx","@dptr,a");
6655 emitcode("inc","dptr");
6659 freeAsmop(right,NULL,ic,TRUE);
6662 /*-----------------------------------------------------------------*/
6663 /* genGenPointerSet - set value from generic pointer space */
6664 /*-----------------------------------------------------------------*/
6665 static void genGenPointerSet (operand *right,
6666 operand *result, iCode *ic)
6669 link *retype = getSpec(operandType(right));
6671 aopOp(result,ic,FALSE);
6673 /* if the operand is already in dptr
6674 then we do nothing else we move the value to dptr */
6675 if (AOP_TYPE(result) != AOP_STR) {
6676 /* if this is remateriazable */
6677 if (AOP_TYPE(result) == AOP_IMMD) {
6678 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6679 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
6681 else { /* we need to get it byte by byte */
6682 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6683 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6684 if (options.model == MODEL_FLAT24)
6686 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6687 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
6691 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
6695 /* so dptr know contains the address */
6696 freeAsmop(result,NULL,ic,TRUE);
6697 aopOp(right,ic,FALSE);
6699 /* if bit then unpack */
6700 if (IS_BITVAR(retype))
6701 genPackBits(retype,right,"dptr",GPOINTER);
6703 size = AOP_SIZE(right);
6707 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6709 emitcode("lcall","__gptrput");
6711 emitcode("inc","dptr");
6715 freeAsmop(right,NULL,ic,TRUE);
6718 /*-----------------------------------------------------------------*/
6719 /* genPointerSet - stores the value into a pointer location */
6720 /*-----------------------------------------------------------------*/
6721 static void genPointerSet (iCode *ic)
6723 operand *right, *result ;
6727 right = IC_RIGHT(ic);
6728 result = IC_RESULT(ic) ;
6730 /* depending on the type of pointer we need to
6731 move it to the correct pointer register */
6732 type = operandType(result);
6733 etype = getSpec(type);
6734 /* if left is of type of pointer then it is simple */
6735 if (IS_PTR(type) && !IS_FUNC(type->next)) {
6736 p_type = DCL_TYPE(type);
6739 /* we have to go by the storage class */
6740 p_type = PTR_TYPE(SPEC_OCLS(etype));
6742 /* if (SPEC_OCLS(etype)->codesp ) { */
6743 /* p_type = CPOINTER ; */
6746 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6747 /* p_type = FPOINTER ; */
6749 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6750 /* p_type = PPOINTER ; */
6752 /* if (SPEC_OCLS(etype) == idata ) */
6753 /* p_type = IPOINTER ; */
6755 /* p_type = POINTER ; */
6758 /* now that we have the pointer type we assign
6759 the pointer values */
6764 genNearPointerSet (right,result,ic);
6768 genPagedPointerSet (right,result,ic);
6772 genFarPointerSet (right,result,ic);
6776 genGenPointerSet (right,result,ic);
6782 /*-----------------------------------------------------------------*/
6783 /* genIfx - generate code for Ifx statement */
6784 /*-----------------------------------------------------------------*/
6785 static void genIfx (iCode *ic, iCode *popIc)
6787 operand *cond = IC_COND(ic);
6790 aopOp(cond,ic,FALSE);
6792 /* get the value into acc */
6793 if (AOP_TYPE(cond) != AOP_CRY)
6797 /* the result is now in the accumulator */
6798 freeAsmop(cond,NULL,ic,TRUE);
6800 /* if there was something to be popped then do it */
6804 /* if the condition is a bit variable */
6805 if (isbit && IS_ITEMP(cond) &&
6807 genIfxJump(ic,SPIL_LOC(cond)->rname);
6809 if (isbit && !IS_ITEMP(cond))
6810 genIfxJump(ic,OP_SYMBOL(cond)->rname);
6817 /*-----------------------------------------------------------------*/
6818 /* genAddrOf - generates code for address of */
6819 /*-----------------------------------------------------------------*/
6820 static void genAddrOf (iCode *ic)
6822 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
6825 aopOp(IC_RESULT(ic),ic,FALSE);
6827 /* if the operand is on the stack then we
6828 need to get the stack offset of this
6831 /* if it has an offset then we need to compute
6834 emitcode("mov","a,_bp");
6835 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
6836 aopPut(AOP(IC_RESULT(ic)),"a",0);
6838 /* we can just move _bp */
6839 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
6840 /* fill the result with zero */
6841 size = AOP_SIZE(IC_RESULT(ic)) - 1;
6844 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
6849 /* object not on stack then we need the name */
6850 size = AOP_SIZE(IC_RESULT(ic));
6854 char s[SDCC_NAME_MAX];
6856 sprintf(s,"#(%s >> %d)",
6860 sprintf(s,"#%s",sym->rname);
6861 aopPut(AOP(IC_RESULT(ic)),s,offset++);
6865 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
6869 /*-----------------------------------------------------------------*/
6870 /* genFarFarAssign - assignment when both are in far space */
6871 /*-----------------------------------------------------------------*/
6872 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
6874 int size = AOP_SIZE(right);
6877 /* first push the right side on to the stack */
6879 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6881 emitcode ("push","acc");
6884 freeAsmop(right,NULL,ic,FALSE);
6885 /* now assign DPTR to result */
6886 aopOp(result,ic,FALSE);
6887 size = AOP_SIZE(result);
6889 emitcode ("pop","acc");
6890 aopPut(AOP(result),"a",--offset);
6892 freeAsmop(result,NULL,ic,FALSE);
6896 /*-----------------------------------------------------------------*/
6897 /* genAssign - generate code for assignment */
6898 /*-----------------------------------------------------------------*/
6899 static void genAssign (iCode *ic)
6901 operand *result, *right;
6903 unsigned long lit = 0L;
6905 result = IC_RESULT(ic);
6906 right = IC_RIGHT(ic) ;
6908 /* if they are the same */
6909 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
6912 aopOp(right,ic,FALSE);
6914 /* special case both in far space */
6915 if (AOP_TYPE(right) == AOP_DPTR &&
6916 IS_TRUE_SYMOP(result) &&
6917 isOperandInFarSpace(result)) {
6919 genFarFarAssign (result,right,ic);
6923 aopOp(result,ic,TRUE);
6925 /* if they are the same registers */
6926 if (sameRegs(AOP(right),AOP(result)))
6929 /* if the result is a bit */
6930 if (AOP_TYPE(result) == AOP_CRY) {
6932 /* if the right size is a literal then
6933 we know what the value is */
6934 if (AOP_TYPE(right) == AOP_LIT) {
6935 if (((int) operandLitValue(right)))
6936 aopPut(AOP(result),one,0);
6938 aopPut(AOP(result),zero,0);
6942 /* the right is also a bit variable */
6943 if (AOP_TYPE(right) == AOP_CRY) {
6944 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6945 aopPut(AOP(result),"c",0);
6951 aopPut(AOP(result),"a",0);
6955 /* bit variables done */
6957 size = AOP_SIZE(result);
6959 if(AOP_TYPE(right) == AOP_LIT)
6960 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6962 (AOP_TYPE(result) != AOP_REG) &&
6963 (AOP_TYPE(right) == AOP_LIT) &&
6964 !IS_FLOAT(operandType(right)) &&
6966 emitcode("clr","a");
6968 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
6969 aopPut(AOP(result),"a",size);
6972 aopGet(AOP(right),size,FALSE,FALSE),
6978 aopGet(AOP(right),offset,FALSE,FALSE),
6985 freeAsmop (right,NULL,ic,FALSE);
6986 freeAsmop (result,NULL,ic,TRUE);
6989 /*-----------------------------------------------------------------*/
6990 /* genJumpTab - genrates code for jump table */
6991 /*-----------------------------------------------------------------*/
6992 static void genJumpTab (iCode *ic)
6997 aopOp(IC_JTCOND(ic),ic,FALSE);
6998 /* get the condition into accumulator */
6999 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
7001 /* multiply by three */
7002 emitcode("add","a,acc");
7003 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
7004 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7006 jtab = newiTempLabel(NULL);
7007 emitcode("mov","dptr,#%05d$",jtab->key+100);
7008 emitcode("jmp","@a+dptr");
7009 emitcode("","%05d$:",jtab->key+100);
7010 /* now generate the jump labels */
7011 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
7012 jtab = setNextItem(IC_JTLABELS(ic)))
7013 emitcode("ljmp","%05d$",jtab->key+100);
7017 /*-----------------------------------------------------------------*/
7018 /* genCast - gen code for casting */
7019 /*-----------------------------------------------------------------*/
7020 static void genCast (iCode *ic)
7022 operand *result = IC_RESULT(ic);
7023 link *ctype = operandType(IC_LEFT(ic));
7024 operand *right = IC_RIGHT(ic);
7027 /* if they are equivalent then do nothing */
7028 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
7031 aopOp(right,ic,FALSE) ;
7032 aopOp(result,ic,FALSE);
7034 /* if the result is a bit */
7035 if (AOP_TYPE(result) == AOP_CRY) {
7036 /* if the right size is a literal then
7037 we know what the value is */
7038 if (AOP_TYPE(right) == AOP_LIT) {
7039 if (((int) operandLitValue(right)))
7040 aopPut(AOP(result),one,0);
7042 aopPut(AOP(result),zero,0);
7047 /* the right is also a bit variable */
7048 if (AOP_TYPE(right) == AOP_CRY) {
7049 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7050 aopPut(AOP(result),"c",0);
7056 aopPut(AOP(result),"a",0);
7060 /* if they are the same size : or less */
7061 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
7063 /* if they are in the same place */
7064 if (sameRegs(AOP(right),AOP(result)))
7067 /* if they in different places then copy */
7068 size = AOP_SIZE(result);
7072 aopGet(AOP(right),offset,FALSE,FALSE),
7080 /* if the result is of type pointer */
7081 if (IS_PTR(ctype)) {
7084 link *type = operandType(right);
7085 link *etype = getSpec(type);
7087 /* pointer to generic pointer */
7088 if (IS_GENPTR(ctype)) {
7092 p_type = DCL_TYPE(type);
7094 /* we have to go by the storage class */
7095 p_type = PTR_TYPE(SPEC_OCLS(etype));
7097 /* if (SPEC_OCLS(etype)->codesp ) */
7098 /* p_type = CPOINTER ; */
7100 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7101 /* p_type = FPOINTER ; */
7103 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7104 /* p_type = PPOINTER; */
7106 /* if (SPEC_OCLS(etype) == idata ) */
7107 /* p_type = IPOINTER ; */
7109 /* p_type = POINTER ; */
7112 /* the first two bytes are known */
7113 size = GPTRSIZE - 1;
7117 aopGet(AOP(right),offset,FALSE,FALSE),
7121 /* the last byte depending on type */
7138 /* this should never happen */
7139 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7140 "got unknown pointer type");
7143 aopPut(AOP(result),l, GPTRSIZE - 1);
7147 /* just copy the pointers */
7148 size = AOP_SIZE(result);
7152 aopGet(AOP(right),offset,FALSE,FALSE),
7159 /* so we now know that the size of destination is greater
7160 than the size of the source */
7161 /* we move to result for the size of source */
7162 size = AOP_SIZE(right);
7166 aopGet(AOP(right),offset,FALSE,FALSE),
7171 /* now depending on the sign of the destination */
7172 size = AOP_SIZE(result) - AOP_SIZE(right);
7173 /* if unsigned or not an integral type */
7174 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
7176 aopPut(AOP(result),zero,offset++);
7178 /* we need to extend the sign :{ */
7179 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
7182 emitcode("rlc","a");
7183 emitcode("subb","a,acc");
7185 aopPut(AOP(result),"a",offset++);
7188 /* we are done hurray !!!! */
7191 freeAsmop(right,NULL,ic,TRUE);
7192 freeAsmop(result,NULL,ic,TRUE);
7196 /*-----------------------------------------------------------------*/
7197 /* genDjnz - generate decrement & jump if not zero instrucion */
7198 /*-----------------------------------------------------------------*/
7199 static int genDjnz (iCode *ic, iCode *ifx)
7205 /* if the if condition has a false label
7206 then we cannot save */
7210 /* if the minus is not of the form
7212 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
7213 !IS_OP_LITERAL(IC_RIGHT(ic)))
7216 if (operandLitValue(IC_RIGHT(ic)) != 1)
7219 /* if the size of this greater than one then no
7221 if (getSize(operandType(IC_RESULT(ic))) > 1)
7224 /* otherwise we can save BIG */
7225 lbl = newiTempLabel(NULL);
7226 lbl1= newiTempLabel(NULL);
7228 aopOp(IC_RESULT(ic),ic,FALSE);
7230 if (IS_AOP_PREG(IC_RESULT(ic))) {
7231 emitcode("dec","%s",
7232 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7233 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7234 emitcode("jnz","%05d$",lbl->key+100);
7236 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
7239 emitcode ("sjmp","%05d$",lbl1->key+100);
7240 emitcode ("","%05d$:",lbl->key+100);
7241 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
7242 emitcode ("","%05d$:",lbl1->key+100);
7244 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7249 /*-----------------------------------------------------------------*/
7250 /* genReceive - generate code for a receive iCode */
7251 /*-----------------------------------------------------------------*/
7252 static void genReceive (iCode *ic)
7254 if (isOperandInFarSpace(IC_RESULT(ic)) &&
7255 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
7256 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
7258 int size = getSize(operandType(IC_RESULT(ic)));
7259 int offset = fReturnSize - size;
7261 emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
7262 fReturn[fReturnSize - offset - 1] : "acc"));
7265 aopOp(IC_RESULT(ic),ic,FALSE);
7266 size = AOP_SIZE(IC_RESULT(ic));
7269 emitcode ("pop","acc");
7270 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
7275 aopOp(IC_RESULT(ic),ic,FALSE);
7277 assignResultValue(IC_RESULT(ic));
7280 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7283 /*-----------------------------------------------------------------*/
7284 /* gen51Code - generate code for 8051 based controllers */
7285 /*-----------------------------------------------------------------*/
7286 void gen51Code (iCode *lic)
7291 lineHead = lineCurr = NULL;
7293 /* if debug information required */
7294 /* if (options.debug && currFunc) { */
7296 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
7298 if (IS_STATIC(currFunc->etype))
7299 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
7301 emitcode("","G$%s$0$0 ==.",currFunc->name);
7304 /* stack pointer name */
7305 if (options.useXstack)
7311 for (ic = lic ; ic ; ic = ic->next ) {
7313 if ( cln != ic->lineno ) {
7314 if ( options.debug ) {
7316 emitcode("","C$%s$%d$%d$%d ==.",
7317 ic->filename,ic->lineno,
7318 ic->level,ic->block);
7321 emitcode(";","%s %d",ic->filename,ic->lineno);
7324 /* if the result is marked as
7325 spilt and rematerializable or code for
7326 this has already been generated then
7328 if (resultRemat(ic) || ic->generated )
7331 /* depending on the operation */
7350 /* IPOP happens only when trying to restore a
7351 spilt live range, if there is an ifx statement
7352 following this pop then the if statement might
7353 be using some of the registers being popped which
7354 would destory the contents of the register so
7355 we need to check for this condition and handle it */
7357 ic->next->op == IFX &&
7358 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
7359 genIfx (ic->next,ic);
7377 genEndFunction (ic);
7397 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
7414 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
7418 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
7425 /* note these two are xlated by algebraic equivalence
7426 during parsing SDCC.y */
7427 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7428 "got '>=' or '<=' shouldn't have come here");
7432 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
7444 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
7448 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
7452 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
7479 case GET_VALUE_AT_ADDRESS:
7484 if (POINTER_SET(ic))
7511 addSet(&_G.sendSet,ic);
7516 /* piCode(ic,stdout); */
7522 /* now we are ready to call the
7523 peep hole optimizer */
7524 if (!options.nopeep)
7525 peepHole (&lineHead);
7527 /* now do the actual printing */
7528 printLine (lineHead,codeOutFile);