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 static char *fReturn8051[] = {"dpl","dph","b","a" };
65 static char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
66 unsigned fReturnSize = 4; /* shared with ralloc.c */
67 static 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);
932 emitcode("cjne","a,#0x01,%05d$",lbl->key+100);
933 emitcode("","%05d$:",lbl->key+100);
935 emitcode("mov","%s,c",aop->aopu.aop_dir);
942 if (strcmp(aop->aopu.aop_str[offset],s))
943 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
948 if (!offset && (strcmp(s,"acc") == 0))
951 if (strcmp(aop->aopu.aop_str[offset],s))
952 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
956 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
957 "aopPut got unsupported aop->type");
965 /*-----------------------------------------------------------------*/
966 /* pointToEnd :- points to the last byte of the operand */
967 /*-----------------------------------------------------------------*/
968 static void pointToEnd (asmop *aop)
974 aop->coff = count = (aop->size - 1);
979 emitcode("inc","%s",aop->aopu.aop_ptr->name);
983 emitcode("inc","dptr");
990 /*-----------------------------------------------------------------*/
991 /* reAdjustPreg - points a register back to where it should */
992 /*-----------------------------------------------------------------*/
993 static void reAdjustPreg (asmop *aop)
998 if ((size = aop->size) <= 1)
1001 switch (aop->type) {
1005 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1009 emitcode("lcall","__decdptr");
1016 #define AOP(op) op->aop
1017 #define AOP_TYPE(op) AOP(op)->type
1018 #define AOP_SIZE(op) AOP(op)->size
1019 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1020 AOP_TYPE(x) == AOP_R0))
1022 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1023 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1025 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1026 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1027 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1029 /*-----------------------------------------------------------------*/
1030 /* genNotFloat - generates not for float operations */
1031 /*-----------------------------------------------------------------*/
1032 static void genNotFloat (operand *op, operand *res)
1038 /* we will put 127 in the first byte of
1040 aopPut(AOP(res),"#127",0);
1041 size = AOP_SIZE(op) - 1;
1044 l = aopGet(op->aop,offset++,FALSE,FALSE);
1048 emitcode("orl","a,%s",
1050 offset++,FALSE,FALSE));
1052 tlbl = newiTempLabel(NULL);
1054 tlbl = newiTempLabel(NULL);
1055 aopPut(res->aop,one,1);
1056 emitcode("jz","%05d$",(tlbl->key+100));
1057 aopPut(res->aop,zero,1);
1058 emitcode("","%05d$:",(tlbl->key+100));
1060 size = res->aop->size - 2;
1062 /* put zeros in the rest */
1064 aopPut(res->aop,zero,offset++);
1067 /*-----------------------------------------------------------------*/
1068 /* opIsGptr: returns non-zero if the passed operand is */
1069 /* a generic pointer type. */
1070 /*-----------------------------------------------------------------*/
1071 static int opIsGptr(operand *op)
1073 link *type = operandType(op);
1075 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1082 /*-----------------------------------------------------------------*/
1083 /* getDataSize - get the operand data size */
1084 /*-----------------------------------------------------------------*/
1085 static int getDataSize(operand *op)
1088 size = AOP_SIZE(op);
1089 if (size == GPTRSIZE)
1091 link *type = operandType(op);
1092 if (IS_GENPTR(type))
1094 /* generic pointer; arithmetic operations
1095 * should ignore the high byte (pointer type).
1103 /*-----------------------------------------------------------------*/
1104 /* outAcc - output Acc */
1105 /*-----------------------------------------------------------------*/
1106 static void outAcc(operand *result)
1109 size = getDataSize(result);
1111 aopPut(AOP(result),"a",0);
1114 /* unsigned or positive */
1116 aopPut(AOP(result),zero,offset++);
1121 /*-----------------------------------------------------------------*/
1122 /* outBitC - output a bit C */
1123 /*-----------------------------------------------------------------*/
1124 static void outBitC(operand *result)
1126 /* if the result is bit */
1127 if (AOP_TYPE(result) == AOP_CRY)
1128 aopPut(AOP(result),"c",0);
1130 emitcode("clr","a");
1131 emitcode("rlc","a");
1136 /*-----------------------------------------------------------------*/
1137 /* toBoolean - emit code for orl a,operator(sizeop) */
1138 /*-----------------------------------------------------------------*/
1139 static void toBoolean(operand *oper)
1141 int size = AOP_SIZE(oper) - 1;
1143 MOVA(aopGet(AOP(oper),0,FALSE,FALSE));
1145 emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE));
1149 /*-----------------------------------------------------------------*/
1150 /* genNot - generate code for ! operation */
1151 /*-----------------------------------------------------------------*/
1152 static void genNot (iCode *ic)
1155 link *optype = operandType(IC_LEFT(ic));
1157 /* assign asmOps to operand & result */
1158 aopOp (IC_LEFT(ic),ic,FALSE);
1159 aopOp (IC_RESULT(ic),ic,TRUE);
1161 /* if in bit space then a special case */
1162 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1163 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1164 emitcode("cpl","c");
1165 outBitC(IC_RESULT(ic));
1169 /* if type float then do float */
1170 if (IS_FLOAT(optype)) {
1171 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1175 toBoolean(IC_LEFT(ic));
1177 tlbl = newiTempLabel(NULL);
1178 emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1179 emitcode("","%05d$:",tlbl->key+100);
1180 outBitC(IC_RESULT(ic));
1183 /* release the aops */
1184 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1185 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1189 /*-----------------------------------------------------------------*/
1190 /* genCpl - generate code for complement */
1191 /*-----------------------------------------------------------------*/
1192 static void genCpl (iCode *ic)
1198 /* assign asmOps to operand & result */
1199 aopOp (IC_LEFT(ic),ic,FALSE);
1200 aopOp (IC_RESULT(ic),ic,TRUE);
1202 /* if both are in bit space then
1204 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1205 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1207 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1208 emitcode("cpl","c");
1209 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1213 size = AOP_SIZE(IC_RESULT(ic));
1215 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1217 emitcode("cpl","a");
1218 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1223 /* release the aops */
1224 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1225 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1228 /*-----------------------------------------------------------------*/
1229 /* genUminusFloat - unary minus for floating points */
1230 /*-----------------------------------------------------------------*/
1231 static void genUminusFloat(operand *op,operand *result)
1233 int size ,offset =0 ;
1235 /* for this we just need to flip the
1236 first it then copy the rest in place */
1237 size = AOP_SIZE(op) - 1;
1238 l = aopGet(AOP(op),3,FALSE,FALSE);
1242 emitcode("cpl","acc.7");
1243 aopPut(AOP(result),"a",3);
1247 aopGet(AOP(op),offset,FALSE,FALSE),
1253 /*-----------------------------------------------------------------*/
1254 /* genUminus - unary minus code generation */
1255 /*-----------------------------------------------------------------*/
1256 static void genUminus (iCode *ic)
1259 link *optype, *rtype;
1263 aopOp(IC_LEFT(ic),ic,FALSE);
1264 aopOp(IC_RESULT(ic),ic,TRUE);
1266 /* if both in bit space then special
1268 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1269 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1271 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1272 emitcode("cpl","c");
1273 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1277 optype = operandType(IC_LEFT(ic));
1278 rtype = operandType(IC_RESULT(ic));
1280 /* if float then do float stuff */
1281 if (IS_FLOAT(optype)) {
1282 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1286 /* otherwise subtract from zero */
1287 size = AOP_SIZE(IC_LEFT(ic));
1291 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1292 if (!strcmp(l,"a")) {
1293 emitcode("cpl","a");
1294 emitcode("inc","a");
1296 emitcode("clr","a");
1297 emitcode("subb","a,%s",l);
1299 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1302 /* if any remaining bytes in the result */
1303 /* we just need to propagate the sign */
1304 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1305 emitcode("rlc","a");
1306 emitcode("subb","a,acc");
1308 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1312 /* release the aops */
1313 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1314 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1317 /*-----------------------------------------------------------------*/
1318 /* saveRegisters - will look for a call and save the registers */
1319 /*-----------------------------------------------------------------*/
1320 static void saveRegisters(iCode *lic)
1328 for (ic = lic ; ic ; ic = ic->next)
1329 if (ic->op == CALL || ic->op == PCALL)
1333 fprintf(stderr,"found parameter push with no function call\n");
1337 /* if the registers have been saved already then
1339 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1342 /* find the registers in use at this time
1343 and push them away to safety */
1344 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1348 if (options.useXstack) {
1349 if (bitVectBitValue(rsave,R0_IDX))
1350 emitcode("mov","b,r0");
1351 emitcode("mov","r0,%s",spname);
1352 for (i = 0 ; i < mcs51_nRegs ; i++) {
1353 if (bitVectBitValue(rsave,i)) {
1355 emitcode("mov","a,b");
1357 emitcode("mov","a,%s",mcs51_regWithIdx(i)->name);
1358 emitcode("movx","@r0,a");
1359 emitcode("inc","r0");
1362 emitcode("mov","%s,r0",spname);
1363 if (bitVectBitValue(rsave,R0_IDX))
1364 emitcode("mov","r0,b");
1366 for (i = 0 ; i < mcs51_nRegs ; i++) {
1367 if (bitVectBitValue(rsave,i))
1368 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
1371 detype = getSpec(operandType(IC_LEFT(ic)));
1373 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1374 IS_ISR(currFunc->etype) &&
1377 saverbank(SPEC_BANK(detype),ic,TRUE);
1380 /*-----------------------------------------------------------------*/
1381 /* unsaveRegisters - pop the pushed registers */
1382 /*-----------------------------------------------------------------*/
1383 static void unsaveRegisters (iCode *ic)
1387 /* find the registers in use at this time
1388 and push them away to safety */
1389 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1392 if (options.useXstack) {
1393 emitcode("mov","r0,%s",spname);
1394 for (i = mcs51_nRegs ; i >= 0 ; i--) {
1395 if (bitVectBitValue(rsave,i)) {
1396 emitcode("dec","r0");
1397 emitcode("movx","a,@r0");
1399 emitcode("mov","b,a");
1401 emitcode("mov","%s,a",mcs51_regWithIdx(i)->name);
1405 emitcode("mov","%s,r0",spname);
1406 if (bitVectBitValue(rsave,R0_IDX))
1407 emitcode("mov","r0,b");
1409 for (i = mcs51_nRegs ; i >= 0 ; i--) {
1410 if (bitVectBitValue(rsave,i))
1411 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
1417 /*-----------------------------------------------------------------*/
1419 /*-----------------------------------------------------------------*/
1420 static void pushSide(operand * oper, int size)
1424 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1425 if (AOP_TYPE(oper) != AOP_REG &&
1426 AOP_TYPE(oper) != AOP_DIR &&
1428 emitcode("mov","a,%s",l);
1429 emitcode("push","acc");
1431 emitcode("push","%s",l);
1435 /*-----------------------------------------------------------------*/
1436 /* assignResultValue - */
1437 /*-----------------------------------------------------------------*/
1438 static void assignResultValue(operand * oper)
1441 int size = AOP_SIZE(oper);
1443 aopPut(AOP(oper),fReturn[offset],offset);
1449 /*-----------------------------------------------------------------*/
1450 /* genXpush - pushes onto the external stack */
1451 /*-----------------------------------------------------------------*/
1452 static void genXpush (iCode *ic)
1454 asmop *aop = newAsmop(0);
1456 int size,offset = 0;
1458 aopOp(IC_LEFT(ic),ic,FALSE);
1459 r = getFreePtr(ic,&aop,FALSE);
1462 emitcode("mov","%s,_spx",r->name);
1464 size = AOP_SIZE(IC_LEFT(ic));
1467 char *l = aopGet(AOP(IC_LEFT(ic)),
1468 offset++,FALSE,FALSE);
1470 emitcode("movx","@%s,a",r->name);
1471 emitcode("inc","%s",r->name);
1476 emitcode("mov","_spx,%s",r->name);
1478 freeAsmop(NULL,aop,ic,TRUE);
1479 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1482 /*-----------------------------------------------------------------*/
1483 /* genIpush - genrate code for pushing this gets a little complex */
1484 /*-----------------------------------------------------------------*/
1485 static void genIpush (iCode *ic)
1487 int size, offset = 0 ;
1491 /* if this is not a parm push : ie. it is spill push
1492 and spill push is always done on the local stack */
1493 if (!ic->parmPush) {
1495 /* and the item is spilt then do nothing */
1496 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1499 aopOp(IC_LEFT(ic),ic,FALSE);
1500 size = AOP_SIZE(IC_LEFT(ic));
1501 /* push it on the stack */
1503 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1508 emitcode("push","%s",l);
1513 /* this is a paramter push: in this case we call
1514 the routine to find the call and save those
1515 registers that need to be saved */
1518 /* if use external stack then call the external
1519 stack pushing routine */
1520 if (options.useXstack) {
1525 /* then do the push */
1526 aopOp(IC_LEFT(ic),ic,FALSE);
1529 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1530 size = AOP_SIZE(IC_LEFT(ic));
1533 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1534 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1535 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1537 emitcode("mov","a,%s",l);
1538 emitcode("push","acc");
1540 emitcode("push","%s",l);
1543 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1546 /*-----------------------------------------------------------------*/
1547 /* genIpop - recover the registers: can happen only for spilling */
1548 /*-----------------------------------------------------------------*/
1549 static void genIpop (iCode *ic)
1554 /* if the temp was not pushed then */
1555 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1558 aopOp(IC_LEFT(ic),ic,FALSE);
1559 size = AOP_SIZE(IC_LEFT(ic));
1562 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1565 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1568 /*-----------------------------------------------------------------*/
1569 /* unsaverbank - restores the resgister bank from stack */
1570 /*-----------------------------------------------------------------*/
1571 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1578 if (options.useXstack) {
1580 r = getFreePtr(ic,&aop,FALSE);
1583 emitcode("mov","%s,_spx",r->name);
1584 emitcode("movx","a,@%s",r->name);
1585 emitcode("mov","psw,a");
1586 emitcode("dec","%s",r->name);
1589 emitcode ("pop","psw");
1592 for (i = (mcs51_nRegs - 1) ; i >= 0 ;i--) {
1593 if (options.useXstack) {
1594 emitcode("movx","a,@%s",r->name);
1595 emitcode("mov","(%s+%d),a",
1596 regs8051[i].base,8*bank+regs8051[i].offset);
1597 emitcode("dec","%s",r->name);
1600 emitcode("pop","(%s+%d)",
1601 regs8051[i].base,8*bank+regs8051[i].offset);
1604 if (options.useXstack) {
1606 emitcode("mov","_spx,%s",r->name);
1607 freeAsmop(NULL,aop,ic,TRUE);
1612 /*-----------------------------------------------------------------*/
1613 /* saverbank - saves an entire register bank on the stack */
1614 /*-----------------------------------------------------------------*/
1615 static void saverbank (int bank, iCode *ic, bool pushPsw)
1621 if (options.useXstack) {
1624 r = getFreePtr(ic,&aop,FALSE);
1625 emitcode("mov","%s,_spx",r->name);
1629 for (i = 0 ; i < mcs51_nRegs ;i++) {
1630 if (options.useXstack) {
1631 emitcode("inc","%s",r->name);
1632 emitcode("mov","a,(%s+%d)",
1633 regs8051[i].base,8*bank+regs8051[i].offset);
1634 emitcode("movx","@%s,a",r->name);
1636 emitcode("push","(%s+%d)",
1637 regs8051[i].base,8*bank+regs8051[i].offset);
1641 if (options.useXstack) {
1642 emitcode("mov","a,psw");
1643 emitcode("movx","@%s,a",r->name);
1644 emitcode("inc","%s",r->name);
1645 emitcode("mov","_spx,%s",r->name);
1646 freeAsmop (NULL,aop,ic,TRUE);
1649 emitcode("push","psw");
1651 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1657 /*-----------------------------------------------------------------*/
1658 /* genCall - generates a call statement */
1659 /*-----------------------------------------------------------------*/
1660 static void genCall (iCode *ic)
1664 /* if caller saves & we have not saved then */
1668 /* if we are calling a function that is not using
1669 the same register bank then we need to save the
1670 destination registers on the stack */
1671 detype = getSpec(operandType(IC_LEFT(ic)));
1673 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1674 IS_ISR(currFunc->etype) &&
1677 saverbank(SPEC_BANK(detype),ic,TRUE);
1679 /* if send set is not empty the assign */
1683 for (sic = setFirstItem(_G.sendSet) ; sic ;
1684 sic = setNextItem(_G.sendSet)) {
1685 int size, offset = 0;
1686 aopOp(IC_LEFT(sic),sic,FALSE);
1687 size = AOP_SIZE(IC_LEFT(sic));
1689 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1691 if (strcmp(l,fReturn[offset]))
1692 emitcode("mov","%s,%s",
1697 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1702 emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1703 OP_SYMBOL(IC_LEFT(ic))->rname :
1704 OP_SYMBOL(IC_LEFT(ic))->name));
1706 /* if we need assign a result value */
1707 if ((IS_ITEMP(IC_RESULT(ic)) &&
1708 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1709 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1710 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1713 aopOp(IC_RESULT(ic),ic,FALSE);
1716 assignResultValue(IC_RESULT(ic));
1718 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1721 /* adjust the stack for parameters if
1723 if (IC_LEFT(ic)->parmBytes) {
1725 if (IC_LEFT(ic)->parmBytes > 3) {
1726 emitcode("mov","a,%s",spname);
1727 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1728 emitcode("mov","%s,a",spname);
1730 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1731 emitcode("dec","%s",spname);
1735 /* if register bank was saved then pop them */
1737 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1739 /* if we hade saved some registers then unsave them */
1740 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1741 unsaveRegisters (ic);
1746 /*-----------------------------------------------------------------*/
1747 /* genPcall - generates a call by pointer statement */
1748 /*-----------------------------------------------------------------*/
1749 static void genPcall (iCode *ic)
1752 symbol *rlbl = newiTempLabel(NULL);
1755 /* if caller saves & we have not saved then */
1759 /* if we are calling a function that is not using
1760 the same register bank then we need to save the
1761 destination registers on the stack */
1762 detype = getSpec(operandType(IC_LEFT(ic)));
1764 IS_ISR(currFunc->etype) &&
1765 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
1766 saverbank(SPEC_BANK(detype),ic,TRUE);
1769 /* push the return address on to the stack */
1770 emitcode("mov","a,#%05d$",(rlbl->key+100));
1771 emitcode("push","acc");
1772 emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
1773 emitcode("push","acc");
1775 if (options.model == MODEL_FLAT24)
1777 emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
1778 emitcode("push","acc");
1781 /* now push the calling address */
1782 aopOp(IC_LEFT(ic),ic,FALSE);
1784 pushSide(IC_LEFT(ic), FPTRSIZE);
1786 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1788 /* if send set is not empty the assign */
1792 for (sic = setFirstItem(_G.sendSet) ; sic ;
1793 sic = setNextItem(_G.sendSet)) {
1794 int size, offset = 0;
1795 aopOp(IC_LEFT(sic),sic,FALSE);
1796 size = AOP_SIZE(IC_LEFT(sic));
1798 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1800 if (strcmp(l,fReturn[offset]))
1801 emitcode("mov","%s,%s",
1806 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1812 emitcode("","%05d$:",(rlbl->key+100));
1815 /* if we need assign a result value */
1816 if ((IS_ITEMP(IC_RESULT(ic)) &&
1817 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1818 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
1819 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1822 aopOp(IC_RESULT(ic),ic,FALSE);
1825 assignResultValue(IC_RESULT(ic));
1827 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1830 /* adjust the stack for parameters if
1832 if (IC_LEFT(ic)->parmBytes) {
1834 if (IC_LEFT(ic)->parmBytes > 3) {
1835 emitcode("mov","a,%s",spname);
1836 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1837 emitcode("mov","%s,a",spname);
1839 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1840 emitcode("dec","%s",spname);
1844 /* if register bank was saved then unsave them */
1846 (SPEC_BANK(currFunc->etype) !=
1848 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1850 /* if we hade saved some registers then
1853 unsaveRegisters (ic);
1857 /*-----------------------------------------------------------------*/
1858 /* resultRemat - result is rematerializable */
1859 /*-----------------------------------------------------------------*/
1860 static int resultRemat (iCode *ic)
1862 if (SKIP_IC(ic) || ic->op == IFX)
1865 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1866 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1867 if (sym->remat && !POINTER_SET(ic))
1874 /*-----------------------------------------------------------------*/
1875 /* inExcludeList - return 1 if the string is in exclude Reg list */
1876 /*-----------------------------------------------------------------*/
1877 static bool inExcludeList(char *s)
1881 if (options.excludeRegs[i] &&
1882 strcasecmp(options.excludeRegs[i],"none") == 0)
1885 for ( i = 0 ; options.excludeRegs[i]; i++) {
1886 if (options.excludeRegs[i] &&
1887 strcasecmp(s,options.excludeRegs[i]) == 0)
1893 /*-----------------------------------------------------------------*/
1894 /* genFunction - generated code for function entry */
1895 /*-----------------------------------------------------------------*/
1896 static void genFunction (iCode *ic)
1902 /* create the function header */
1903 emitcode(";","-----------------------------------------");
1904 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1905 emitcode(";","-----------------------------------------");
1907 emitcode("","%s:",sym->rname);
1908 fetype = getSpec(operandType(IC_LEFT(ic)));
1910 /* if critical function then turn interrupts off */
1911 if (SPEC_CRTCL(fetype))
1912 emitcode("clr","ea");
1914 /* here we need to generate the equates for the
1915 register bank if required */
1916 if (SPEC_BANK(fetype) != rbank) {
1919 rbank = SPEC_BANK(fetype);
1920 for ( i = 0 ; i < mcs51_nRegs ; i++ ) {
1921 if (strcmp(regs8051[i].base,"0") == 0)
1922 emitcode("","%s = 0x%02x",
1924 8*rbank+regs8051[i].offset);
1926 emitcode ("","%s = %s + 0x%02x",
1929 8*rbank+regs8051[i].offset);
1933 /* if this is an interrupt service routine then
1934 save acc, b, dpl, dph */
1935 if (IS_ISR(sym->etype)) {
1937 if (!inExcludeList("acc"))
1938 emitcode ("push","acc");
1939 if (!inExcludeList("b"))
1940 emitcode ("push","b");
1941 if (!inExcludeList("dpl"))
1942 emitcode ("push","dpl");
1943 if (!inExcludeList("dph"))
1944 emitcode ("push","dph");
1945 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
1946 emitcode ("push", "dpx");
1947 /* if this isr has no bank i.e. is going to
1948 run with bank 0 , then we need to save more
1950 if (!SPEC_BANK(sym->etype)) {
1952 /* if this function does not call any other
1953 function then we can be economical and
1954 save only those registers that are used */
1955 if (! sym->hasFcall) {
1958 /* if any registers used */
1959 if (sym->regsUsed) {
1960 /* save the registers used */
1961 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
1962 if (bitVectBitValue(sym->regsUsed,i) ||
1963 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
1964 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
1969 /* this function has a function call cannot
1970 determines register usage so we will have the
1972 saverbank(0,ic,FALSE);
1976 /* if callee-save to be used for this function
1977 then save the registers being used in this function */
1978 if (sym->calleeSave) {
1981 /* if any registers used */
1982 if (sym->regsUsed) {
1983 /* save the registers used */
1984 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
1985 if (bitVectBitValue(sym->regsUsed,i) ||
1986 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
1987 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
1995 /* set the register bank to the desired value */
1996 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
1997 emitcode("push","psw");
1998 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2001 if (IS_RENT(sym->etype) || options.stackAuto) {
2003 if (options.useXstack) {
2004 emitcode("mov","r0,%s",spname);
2005 emitcode("mov","a,_bp");
2006 emitcode("movx","@r0,a");
2007 emitcode("inc","%s",spname);
2010 /* set up the stack */
2011 emitcode ("push","_bp"); /* save the callers stack */
2012 emitcode ("mov","_bp,%s",spname);
2015 /* adjust the stack for the function */
2020 werror(W_STACK_OVERFLOW,sym->name);
2022 if (i > 3 && sym->recvSize < 4) {
2024 emitcode ("mov","a,sp");
2025 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2026 emitcode ("mov","sp,a");
2031 emitcode("inc","sp");
2036 emitcode ("mov","a,_spx");
2037 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2038 emitcode ("mov","_spx,a");
2043 /*-----------------------------------------------------------------*/
2044 /* genEndFunction - generates epilogue for functions */
2045 /*-----------------------------------------------------------------*/
2046 static void genEndFunction (iCode *ic)
2048 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2050 if (IS_RENT(sym->etype) || options.stackAuto)
2051 emitcode ("mov","%s,_bp",spname);
2053 /* if use external stack but some variables were
2054 added to the local stack then decrement the
2056 if (options.useXstack && sym->stack) {
2057 emitcode("mov","a,sp");
2058 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2059 emitcode("mov","sp,a");
2063 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2064 if (options.useXstack) {
2065 emitcode("mov","r0,%s",spname);
2066 emitcode("movx","a,@r0");
2067 emitcode("mov","_bp,a");
2068 emitcode("dec","%s",spname);
2071 emitcode ("pop","_bp");
2074 /* restore the register bank */
2075 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2076 emitcode ("pop","psw");
2078 if (IS_ISR(sym->etype)) {
2080 /* now we need to restore the registers */
2081 /* if this isr has no bank i.e. is going to
2082 run with bank 0 , then we need to save more
2084 if (!SPEC_BANK(sym->etype)) {
2086 /* if this function does not call any other
2087 function then we can be economical and
2088 save only those registers that are used */
2089 if (! sym->hasFcall) {
2092 /* if any registers used */
2093 if (sym->regsUsed) {
2094 /* save the registers used */
2095 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2096 if (bitVectBitValue(sym->regsUsed,i) ||
2097 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2098 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
2103 /* this function has a function call cannot
2104 determines register usage so we will have the
2106 unsaverbank(0,ic,FALSE);
2110 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2111 emitcode ("pop", "dpx");
2112 if (!inExcludeList("dph"))
2113 emitcode ("pop","dph");
2114 if (!inExcludeList("dpl"))
2115 emitcode ("pop","dpl");
2116 if (!inExcludeList("b"))
2117 emitcode ("pop","b");
2118 if (!inExcludeList("acc"))
2119 emitcode ("pop","acc");
2121 if (SPEC_CRTCL(sym->etype))
2122 emitcode("setb","ea");
2124 /* if debug then send end of function */
2125 /* if (options.debug && currFunc) { */
2128 emitcode("","C$%s$%d$%d$%d ==.",
2129 ic->filename,currFunc->lastLine,
2130 ic->level,ic->block);
2131 if (IS_STATIC(currFunc->etype))
2132 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2134 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2138 emitcode ("reti","");
2141 if (SPEC_CRTCL(sym->etype))
2142 emitcode("setb","ea");
2144 if (sym->calleeSave) {
2147 /* if any registers used */
2148 if (sym->regsUsed) {
2149 /* save the registers used */
2150 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2151 if (bitVectBitValue(sym->regsUsed,i) ||
2152 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2153 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
2159 /* if debug then send end of function */
2160 /* if (options.debug && currFunc) { */
2163 emitcode("","C$%s$%d$%d$%d ==.",
2164 ic->filename,currFunc->lastLine,
2165 ic->level,ic->block);
2166 if (IS_STATIC(currFunc->etype))
2167 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2169 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2173 emitcode ("ret","");
2178 /*-----------------------------------------------------------------*/
2179 /* genRet - generate code for return statement */
2180 /*-----------------------------------------------------------------*/
2181 static void genRet (iCode *ic)
2183 int size,offset = 0 , pushed = 0;
2185 /* if we have no return value then
2186 just generate the "ret" */
2190 /* we have something to return then
2191 move the return value into place */
2192 aopOp(IC_LEFT(ic),ic,FALSE);
2193 size = AOP_SIZE(IC_LEFT(ic));
2197 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2198 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2200 emitcode("push","%s",l);
2203 l = aopGet(AOP(IC_LEFT(ic)),offset,
2205 if (strcmp(fReturn[offset],l))
2206 emitcode("mov","%s,%s",fReturn[offset++],l);
2213 if (strcmp(fReturn[pushed],"a"))
2214 emitcode("pop",fReturn[pushed]);
2216 emitcode("pop","acc");
2219 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2222 /* generate a jump to the return label
2223 if the next is not the return statement */
2224 if (!(ic->next && ic->next->op == LABEL &&
2225 IC_LABEL(ic->next) == returnLabel))
2227 emitcode("ljmp","%05d$",(returnLabel->key+100));
2231 /*-----------------------------------------------------------------*/
2232 /* genLabel - generates a label */
2233 /*-----------------------------------------------------------------*/
2234 static void genLabel (iCode *ic)
2236 /* special case never generate */
2237 if (IC_LABEL(ic) == entryLabel)
2240 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2243 /*-----------------------------------------------------------------*/
2244 /* genGoto - generates a ljmp */
2245 /*-----------------------------------------------------------------*/
2246 static void genGoto (iCode *ic)
2248 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2251 /*-----------------------------------------------------------------*/
2252 /* findLabelBackwards: walks back through the iCode chain looking */
2253 /* for the given label. Returns number of iCode instructions */
2254 /* between that label and given ic. */
2255 /* Returns zero if label not found. */
2256 /*-----------------------------------------------------------------*/
2257 static int findLabelBackwards(iCode *ic, int key)
2266 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2268 printf("findLabelBackwards = %d\n", count);
2273 printf("findLabelBackwards: not found.\n");
2278 /*-----------------------------------------------------------------*/
2279 /* genPlusIncr :- does addition with increment if possible */
2280 /*-----------------------------------------------------------------*/
2281 static bool genPlusIncr (iCode *ic)
2283 unsigned int icount ;
2284 unsigned int size = getDataSize(IC_RESULT(ic));
2286 /* will try to generate an increment */
2287 /* if the right side is not a literal
2289 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2292 /* if the literal value of the right hand side
2293 is greater than 4 then it is not worth it */
2294 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2297 /* if increment 16 bits in register */
2298 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2305 /* If the next instruction is a goto and the goto target
2306 * is < 10 instructions previous to this, we can generate
2307 * jumps straight to that target.
2309 if (ic->next && ic->next->op == GOTO
2310 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2311 && labelRange <= 10 )
2313 emitcode(";", "tail increment optimized");
2314 tlbl = IC_LABEL(ic->next);
2319 tlbl = newiTempLabel(NULL);
2322 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2323 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2324 IS_AOP_PREG(IC_RESULT(ic)))
2325 emitcode("cjne","%s,#0x00,%05d$"
2326 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2329 emitcode("clr","a");
2330 emitcode("cjne","a,%s,%05d$"
2331 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2335 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2338 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2339 IS_AOP_PREG(IC_RESULT(ic)))
2340 emitcode("cjne","%s,#0x00,%05d$"
2341 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2344 emitcode("cjne","a,%s,%05d$"
2345 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2348 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2352 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2353 IS_AOP_PREG(IC_RESULT(ic)))
2354 emitcode("cjne","%s,#0x00,%05d$"
2355 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2358 emitcode("cjne","a,%s,%05d$"
2359 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2362 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2367 emitcode("","%05d$:",tlbl->key+100);
2372 /* if the sizes are greater than 1 then we cannot */
2373 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2374 AOP_SIZE(IC_LEFT(ic)) > 1 )
2377 /* we can if the aops of the left & result match or
2378 if they are in registers and the registers are the
2380 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2383 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2384 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2385 aopPut(AOP(IC_RESULT(ic)),"a",0);
2389 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2398 /*-----------------------------------------------------------------*/
2399 /* outBitAcc - output a bit in acc */
2400 /*-----------------------------------------------------------------*/
2401 static void outBitAcc(operand *result)
2403 symbol *tlbl = newiTempLabel(NULL);
2404 /* if the result is a bit */
2405 if (AOP_TYPE(result) == AOP_CRY){
2406 aopPut(AOP(result),"a",0);
2409 emitcode("jz","%05d$",tlbl->key+100);
2410 emitcode("mov","a,%s",one);
2411 emitcode("","%05d$:",tlbl->key+100);
2416 /*-----------------------------------------------------------------*/
2417 /* genPlusBits - generates code for addition of two bits */
2418 /*-----------------------------------------------------------------*/
2419 static void genPlusBits (iCode *ic)
2421 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2422 symbol *lbl = newiTempLabel(NULL);
2423 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2424 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2425 emitcode("cpl","c");
2426 emitcode("","%05d$:",(lbl->key+100));
2427 outBitC(IC_RESULT(ic));
2430 emitcode("clr","a");
2431 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2432 emitcode("rlc","a");
2433 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2434 emitcode("addc","a,#0x00");
2435 outAcc(IC_RESULT(ic));
2440 /* This is the original version of this code.
2442 * This is being kept around for reference,
2443 * because I am not entirely sure I got it right...
2445 static void adjustArithmeticResult(iCode *ic)
2447 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2448 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2449 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2450 aopPut(AOP(IC_RESULT(ic)),
2451 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2454 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2455 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
2456 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2457 aopPut(AOP(IC_RESULT(ic)),
2458 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2461 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2462 AOP_SIZE(IC_LEFT(ic)) < 3 &&
2463 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
2464 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2465 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2467 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2468 aopPut(AOP(IC_RESULT(ic)),buffer,2);
2472 /* This is the pure and virtuous version of this code.
2473 * I'm pretty certain it's right, but not enough to toss the old
2476 static void adjustArithmeticResult(iCode *ic)
2478 if (opIsGptr(IC_RESULT(ic)) &&
2479 opIsGptr(IC_LEFT(ic)) &&
2480 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2482 aopPut(AOP(IC_RESULT(ic)),
2483 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
2487 if (opIsGptr(IC_RESULT(ic)) &&
2488 opIsGptr(IC_RIGHT(ic)) &&
2489 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2491 aopPut(AOP(IC_RESULT(ic)),
2492 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
2496 if (opIsGptr(IC_RESULT(ic)) &&
2497 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2498 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2499 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2500 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2502 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2503 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2508 /*-----------------------------------------------------------------*/
2509 /* genPlus - generates code for addition */
2510 /*-----------------------------------------------------------------*/
2511 static void genPlus (iCode *ic)
2513 int size, offset = 0;
2515 /* special cases :- */
2517 aopOp (IC_LEFT(ic),ic,FALSE);
2518 aopOp (IC_RIGHT(ic),ic,FALSE);
2519 aopOp (IC_RESULT(ic),ic,TRUE);
2521 /* if literal, literal on the right or
2522 if left requires ACC or right is already
2524 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2525 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2526 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2527 operand *t = IC_RIGHT(ic);
2528 IC_RIGHT(ic) = IC_LEFT(ic);
2532 /* if both left & right are in bit
2534 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2535 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2540 /* if left in bit space & right literal */
2541 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2542 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2543 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2544 /* if result in bit space */
2545 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2546 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
2547 emitcode("cpl","c");
2548 outBitC(IC_RESULT(ic));
2550 size = getDataSize(IC_RESULT(ic));
2552 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2553 emitcode("addc","a,#00");
2554 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2560 /* if I can do an increment instead
2561 of add then GOOD for ME */
2562 if (genPlusIncr (ic) == TRUE)
2565 size = getDataSize(IC_RESULT(ic));
2568 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2569 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2571 emitcode("add","a,%s",
2572 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2574 emitcode("addc","a,%s",
2575 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2577 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2579 emitcode("add","a,%s",
2580 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2582 emitcode("addc","a,%s",
2583 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2585 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2588 adjustArithmeticResult(ic);
2591 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2592 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2593 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2596 /*-----------------------------------------------------------------*/
2597 /* genMinusDec :- does subtraction with deccrement if possible */
2598 /*-----------------------------------------------------------------*/
2599 static bool genMinusDec (iCode *ic)
2601 unsigned int icount ;
2602 unsigned int size = getDataSize(IC_RESULT(ic));
2604 /* will try to generate an increment */
2605 /* if the right side is not a literal
2607 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2610 /* if the literal value of the right hand side
2611 is greater than 4 then it is not worth it */
2612 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2615 /* if decrement 16 bits in register */
2616 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2623 /* If the next instruction is a goto and the goto target
2624 * is <= 10 instructions previous to this, we can generate
2625 * jumps straight to that target.
2627 if (ic->next && ic->next->op == GOTO
2628 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2629 && labelRange <= 10 )
2631 emitcode(";", "tail decrement optimized");
2632 tlbl = IC_LABEL(ic->next);
2637 tlbl = newiTempLabel(NULL);
2641 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2642 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2643 IS_AOP_PREG(IC_RESULT(ic)))
2644 emitcode("cjne","%s,#0xff,%05d$"
2645 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2648 emitcode("mov","a,#0xff");
2649 emitcode("cjne","a,%s,%05d$"
2650 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2653 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2656 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2657 IS_AOP_PREG(IC_RESULT(ic)))
2658 emitcode("cjne","%s,#0xff,%05d$"
2659 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2662 emitcode("cjne","a,%s,%05d$"
2663 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2666 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2670 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2671 IS_AOP_PREG(IC_RESULT(ic)))
2672 emitcode("cjne","%s,#0xff,%05d$"
2673 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2676 emitcode("cjne","a,%s,%05d$"
2677 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2680 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2684 emitcode("","%05d$:",tlbl->key+100);
2689 /* if the sizes are greater than 1 then we cannot */
2690 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2691 AOP_SIZE(IC_LEFT(ic)) > 1 )
2694 /* we can if the aops of the left & result match or
2695 if they are in registers and the registers are the
2697 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2700 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2708 /*-----------------------------------------------------------------*/
2709 /* addSign - complete with sign */
2710 /*-----------------------------------------------------------------*/
2711 static void addSign(operand *result, int offset, int sign)
2713 int size = (getDataSize(result) - offset);
2716 emitcode("rlc","a");
2717 emitcode("subb","a,acc");
2719 aopPut(AOP(result),"a",offset++);
2722 aopPut(AOP(result),zero,offset++);
2726 /*-----------------------------------------------------------------*/
2727 /* genMinusBits - generates code for subtraction of two bits */
2728 /*-----------------------------------------------------------------*/
2729 static void genMinusBits (iCode *ic)
2731 symbol *lbl = newiTempLabel(NULL);
2732 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2733 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2734 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2735 emitcode("cpl","c");
2736 emitcode("","%05d$:",(lbl->key+100));
2737 outBitC(IC_RESULT(ic));
2740 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2741 emitcode("subb","a,acc");
2742 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
2743 emitcode("inc","a");
2744 emitcode("","%05d$:",(lbl->key+100));
2745 aopPut(AOP(IC_RESULT(ic)),"a",0);
2746 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
2750 /*-----------------------------------------------------------------*/
2751 /* genMinus - generates code for subtraction */
2752 /*-----------------------------------------------------------------*/
2753 static void genMinus (iCode *ic)
2755 int size, offset = 0;
2756 unsigned long lit = 0L;
2758 aopOp (IC_LEFT(ic),ic,FALSE);
2759 aopOp (IC_RIGHT(ic),ic,FALSE);
2760 aopOp (IC_RESULT(ic),ic,TRUE);
2762 /* special cases :- */
2763 /* if both left & right are in bit space */
2764 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2765 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2770 /* if I can do an decrement instead
2771 of subtract then GOOD for ME */
2772 if (genMinusDec (ic) == TRUE)
2775 size = getDataSize(IC_RESULT(ic));
2777 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
2781 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2785 /* if literal, add a,#-lit, else normal subb */
2787 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2788 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2789 emitcode("subb","a,%s",
2790 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2792 /* first add without previous c */
2794 emitcode("add","a,#0x%02x",
2795 (unsigned int)(lit & 0x0FFL));
2797 emitcode("addc","a,#0x%02x",
2798 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
2800 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2803 adjustArithmeticResult(ic);
2806 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2807 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2808 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2812 /*-----------------------------------------------------------------*/
2813 /* genMultbits :- multiplication of bits */
2814 /*-----------------------------------------------------------------*/
2815 static void genMultbits (operand *left,
2819 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2820 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
2825 /*-----------------------------------------------------------------*/
2826 /* genMultOneByte : 8 bit multiplication & division */
2827 /*-----------------------------------------------------------------*/
2828 static void genMultOneByte (operand *left,
2832 link *opetype = operandType(result);
2837 /* (if two literals, the value is computed before) */
2838 /* if one literal, literal on the right */
2839 if (AOP_TYPE(left) == AOP_LIT){
2845 size = AOP_SIZE(result);
2846 /* signed or unsigned */
2847 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2848 l = aopGet(AOP(left),0,FALSE,FALSE);
2850 emitcode("mul","ab");
2851 /* if result size = 1, mul signed = mul unsigned */
2852 aopPut(AOP(result),"a",0);
2854 if (SPEC_USIGN(opetype)){
2855 aopPut(AOP(result),"b",1);
2857 /* for filling the MSBs */
2858 emitcode("clr","a");
2861 emitcode("mov","a,b");
2863 /* adjust the MSB if left or right neg */
2865 /* if one literal */
2866 if (AOP_TYPE(right) == AOP_LIT){
2867 /* AND literal negative */
2868 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
2869 /* adjust MSB (c==0 after mul) */
2870 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2874 lbl = newiTempLabel(NULL);
2875 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2876 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
2877 emitcode("","%05d$:",(lbl->key+100));
2878 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2879 lbl = newiTempLabel(NULL);
2880 emitcode("jc","%05d$",(lbl->key+100));
2881 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2882 emitcode("","%05d$:",(lbl->key+100));
2885 lbl = newiTempLabel(NULL);
2886 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
2887 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
2888 emitcode("","%05d$:",(lbl->key+100));
2889 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
2890 lbl = newiTempLabel(NULL);
2891 emitcode("jc","%05d$",(lbl->key+100));
2892 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
2893 emitcode("","%05d$:",(lbl->key+100));
2895 aopPut(AOP(result),"a",1);
2898 emitcode("rlc","a");
2899 emitcode("subb","a,acc");
2906 aopPut(AOP(result),"a",offset++);
2910 /*-----------------------------------------------------------------*/
2911 /* genMult - generates code for multiplication */
2912 /*-----------------------------------------------------------------*/
2913 static void genMult (iCode *ic)
2915 operand *left = IC_LEFT(ic);
2916 operand *right = IC_RIGHT(ic);
2917 operand *result= IC_RESULT(ic);
2919 /* assign the amsops */
2920 aopOp (left,ic,FALSE);
2921 aopOp (right,ic,FALSE);
2922 aopOp (result,ic,TRUE);
2924 /* special cases first */
2926 if (AOP_TYPE(left) == AOP_CRY &&
2927 AOP_TYPE(right)== AOP_CRY) {
2928 genMultbits(left,right,result);
2932 /* if both are of size == 1 */
2933 if (AOP_SIZE(left) == 1 &&
2934 AOP_SIZE(right) == 1 ) {
2935 genMultOneByte(left,right,result);
2939 /* should have been converted to function call */
2943 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2944 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2945 freeAsmop(result,NULL,ic,TRUE);
2948 /*-----------------------------------------------------------------*/
2949 /* genDivbits :- division of bits */
2950 /*-----------------------------------------------------------------*/
2951 static void genDivbits (operand *left,
2958 /* the result must be bit */
2959 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
2960 l = aopGet(AOP(left),0,FALSE,FALSE);
2964 emitcode("div","ab");
2965 emitcode("rrc","a");
2966 aopPut(AOP(result),"c",0);
2969 /*-----------------------------------------------------------------*/
2970 /* genDivOneByte : 8 bit division */
2971 /*-----------------------------------------------------------------*/
2972 static void genDivOneByte (operand *left,
2976 link *opetype = operandType(result);
2981 size = AOP_SIZE(result) - 1;
2983 /* signed or unsigned */
2984 if (SPEC_USIGN(opetype)) {
2985 /* unsigned is easy */
2986 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2987 l = aopGet(AOP(left),0,FALSE,FALSE);
2989 emitcode("div","ab");
2990 aopPut(AOP(result),"a",0);
2992 aopPut(AOP(result),zero,offset++);
2996 /* signed is a little bit more difficult */
2998 /* save the signs of the operands */
2999 l = aopGet(AOP(left),0,FALSE,FALSE);
3001 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3002 emitcode("push","acc"); /* save it on the stack */
3004 /* now sign adjust for both left & right */
3005 l = aopGet(AOP(right),0,FALSE,FALSE);
3007 lbl = newiTempLabel(NULL);
3008 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3009 emitcode("cpl","a");
3010 emitcode("inc","a");
3011 emitcode("","%05d$:",(lbl->key+100));
3012 emitcode("mov","b,a");
3014 /* sign adjust left side */
3015 l = aopGet(AOP(left),0,FALSE,FALSE);
3018 lbl = newiTempLabel(NULL);
3019 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3020 emitcode("cpl","a");
3021 emitcode("inc","a");
3022 emitcode("","%05d$:",(lbl->key+100));
3024 /* now the division */
3025 emitcode("div","ab");
3026 /* we are interested in the lower order
3028 emitcode("mov","b,a");
3029 lbl = newiTempLabel(NULL);
3030 emitcode("pop","acc");
3031 /* if there was an over flow we don't
3032 adjust the sign of the result */
3033 emitcode("jb","ov,%05d$",(lbl->key+100));
3034 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3036 emitcode("clr","a");
3037 emitcode("subb","a,b");
3038 emitcode("mov","b,a");
3039 emitcode("","%05d$:",(lbl->key+100));
3041 /* now we are done */
3042 aopPut(AOP(result),"b",0);
3044 emitcode("mov","c,b.7");
3045 emitcode("subb","a,acc");
3048 aopPut(AOP(result),"a",offset++);
3052 /*-----------------------------------------------------------------*/
3053 /* genDiv - generates code for division */
3054 /*-----------------------------------------------------------------*/
3055 static void genDiv (iCode *ic)
3057 operand *left = IC_LEFT(ic);
3058 operand *right = IC_RIGHT(ic);
3059 operand *result= IC_RESULT(ic);
3061 /* assign the amsops */
3062 aopOp (left,ic,FALSE);
3063 aopOp (right,ic,FALSE);
3064 aopOp (result,ic,TRUE);
3066 /* special cases first */
3068 if (AOP_TYPE(left) == AOP_CRY &&
3069 AOP_TYPE(right)== AOP_CRY) {
3070 genDivbits(left,right,result);
3074 /* if both are of size == 1 */
3075 if (AOP_SIZE(left) == 1 &&
3076 AOP_SIZE(right) == 1 ) {
3077 genDivOneByte(left,right,result);
3081 /* should have been converted to function call */
3084 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3085 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3086 freeAsmop(result,NULL,ic,TRUE);
3089 /*-----------------------------------------------------------------*/
3090 /* genModbits :- modulus of bits */
3091 /*-----------------------------------------------------------------*/
3092 static void genModbits (operand *left,
3099 /* the result must be bit */
3100 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3101 l = aopGet(AOP(left),0,FALSE,FALSE);
3105 emitcode("div","ab");
3106 emitcode("mov","a,b");
3107 emitcode("rrc","a");
3108 aopPut(AOP(result),"c",0);
3111 /*-----------------------------------------------------------------*/
3112 /* genModOneByte : 8 bit modulus */
3113 /*-----------------------------------------------------------------*/
3114 static void genModOneByte (operand *left,
3118 link *opetype = operandType(result);
3122 /* signed or unsigned */
3123 if (SPEC_USIGN(opetype)) {
3124 /* unsigned is easy */
3125 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3126 l = aopGet(AOP(left),0,FALSE,FALSE);
3128 emitcode("div","ab");
3129 aopPut(AOP(result),"b",0);
3133 /* signed is a little bit more difficult */
3135 /* save the signs of the operands */
3136 l = aopGet(AOP(left),0,FALSE,FALSE);
3139 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3140 emitcode("push","acc"); /* save it on the stack */
3142 /* now sign adjust for both left & right */
3143 l = aopGet(AOP(right),0,FALSE,FALSE);
3146 lbl = newiTempLabel(NULL);
3147 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3148 emitcode("cpl","a");
3149 emitcode("inc","a");
3150 emitcode("","%05d$:",(lbl->key+100));
3151 emitcode("mov","b,a");
3153 /* sign adjust left side */
3154 l = aopGet(AOP(left),0,FALSE,FALSE);
3157 lbl = newiTempLabel(NULL);
3158 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3159 emitcode("cpl","a");
3160 emitcode("inc","a");
3161 emitcode("","%05d$:",(lbl->key+100));
3163 /* now the multiplication */
3164 emitcode("div","ab");
3165 /* we are interested in the lower order
3167 lbl = newiTempLabel(NULL);
3168 emitcode("pop","acc");
3169 /* if there was an over flow we don't
3170 adjust the sign of the result */
3171 emitcode("jb","ov,%05d$",(lbl->key+100));
3172 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3174 emitcode("clr","a");
3175 emitcode("subb","a,b");
3176 emitcode("mov","b,a");
3177 emitcode("","%05d$:",(lbl->key+100));
3179 /* now we are done */
3180 aopPut(AOP(result),"b",0);
3184 /*-----------------------------------------------------------------*/
3185 /* genMod - generates code for division */
3186 /*-----------------------------------------------------------------*/
3187 static void genMod (iCode *ic)
3189 operand *left = IC_LEFT(ic);
3190 operand *right = IC_RIGHT(ic);
3191 operand *result= IC_RESULT(ic);
3193 /* assign the amsops */
3194 aopOp (left,ic,FALSE);
3195 aopOp (right,ic,FALSE);
3196 aopOp (result,ic,TRUE);
3198 /* special cases first */
3200 if (AOP_TYPE(left) == AOP_CRY &&
3201 AOP_TYPE(right)== AOP_CRY) {
3202 genModbits(left,right,result);
3206 /* if both are of size == 1 */
3207 if (AOP_SIZE(left) == 1 &&
3208 AOP_SIZE(right) == 1 ) {
3209 genModOneByte(left,right,result);
3213 /* should have been converted to function call */
3217 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3218 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3219 freeAsmop(result,NULL,ic,TRUE);
3222 /*-----------------------------------------------------------------*/
3223 /* genIfxJump :- will create a jump depending on the ifx */
3224 /*-----------------------------------------------------------------*/
3225 static void genIfxJump (iCode *ic, char *jval)
3228 symbol *tlbl = newiTempLabel(NULL);
3231 /* if true label then we jump if condition
3233 if ( IC_TRUE(ic) ) {
3235 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3236 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3239 /* false label is present */
3240 jlbl = IC_FALSE(ic) ;
3241 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3242 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3244 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3245 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3247 emitcode(inst,"%05d$",tlbl->key+100);
3248 emitcode("ljmp","%05d$",jlbl->key+100);
3249 emitcode("","%05d$:",tlbl->key+100);
3251 /* mark the icode as generated */
3255 /*-----------------------------------------------------------------*/
3256 /* genCmp :- greater or less than comparison */
3257 /*-----------------------------------------------------------------*/
3258 static void genCmp (operand *left,operand *right,
3259 operand *result, iCode *ifx, int sign)
3261 int size, offset = 0 ;
3262 unsigned long lit = 0L;
3264 /* if left & right are bit variables */
3265 if (AOP_TYPE(left) == AOP_CRY &&
3266 AOP_TYPE(right) == AOP_CRY ) {
3267 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3268 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3270 /* subtract right from left if at the
3271 end the carry flag is set then we know that
3272 left is greater than right */
3273 size = max(AOP_SIZE(left),AOP_SIZE(right));
3275 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3276 if((size == 1) && !sign &&
3277 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3278 symbol *lbl = newiTempLabel(NULL);
3279 emitcode("cjne","%s,%s,%05d$",
3280 aopGet(AOP(left),offset,FALSE,FALSE),
3281 aopGet(AOP(right),offset,FALSE,FALSE),
3283 emitcode("","%05d$:",lbl->key+100);
3285 if(AOP_TYPE(right) == AOP_LIT){
3286 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3287 /* optimize if(x < 0) or if(x >= 0) */
3293 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE));
3294 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3295 genIfxJump (ifx,"acc.7");
3299 emitcode("rlc","a");
3306 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3307 if (sign && size == 0) {
3308 emitcode("xrl","a,#0x80");
3309 if (AOP_TYPE(right) == AOP_LIT){
3310 unsigned long lit = (unsigned long)
3311 floatFromVal(AOP(right)->aopu.aop_lit);
3312 emitcode("subb","a,#0x%02x",
3313 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3315 emitcode("mov","b,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3316 emitcode("xrl","b,#0x80");
3317 emitcode("subb","a,b");
3320 emitcode("subb","a,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3326 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3329 /* if the result is used in the next
3330 ifx conditional branch then generate
3331 code a little differently */
3333 genIfxJump (ifx,"c");
3336 /* leave the result in acc */
3340 /*-----------------------------------------------------------------*/
3341 /* genCmpGt :- greater than comparison */
3342 /*-----------------------------------------------------------------*/
3343 static void genCmpGt (iCode *ic, iCode *ifx)
3345 operand *left, *right, *result;
3346 link *letype , *retype;
3350 right= IC_RIGHT(ic);
3351 result = IC_RESULT(ic);
3353 letype = getSpec(operandType(left));
3354 retype =getSpec(operandType(right));
3355 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3356 /* assign the amsops */
3357 aopOp (left,ic,FALSE);
3358 aopOp (right,ic,FALSE);
3359 aopOp (result,ic,TRUE);
3361 genCmp(right, left, result, ifx, sign);
3363 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3364 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3365 freeAsmop(result,NULL,ic,TRUE);
3368 /*-----------------------------------------------------------------*/
3369 /* genCmpLt - less than comparisons */
3370 /*-----------------------------------------------------------------*/
3371 static void genCmpLt (iCode *ic, iCode *ifx)
3373 operand *left, *right, *result;
3374 link *letype , *retype;
3378 right= IC_RIGHT(ic);
3379 result = IC_RESULT(ic);
3381 letype = getSpec(operandType(left));
3382 retype =getSpec(operandType(right));
3383 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3385 /* assign the amsops */
3386 aopOp (left,ic,FALSE);
3387 aopOp (right,ic,FALSE);
3388 aopOp (result,ic,TRUE);
3390 genCmp(left, right, result, ifx, sign);
3392 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3393 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3394 freeAsmop(result,NULL,ic,TRUE);
3397 /*-----------------------------------------------------------------*/
3398 /* gencjneshort - compare and jump if not equal */
3399 /*-----------------------------------------------------------------*/
3400 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3402 int size = max(AOP_SIZE(left),AOP_SIZE(right));
3404 unsigned long lit = 0L;
3406 /* if the left side is a literal or
3407 if the right is in a pointer register and left
3409 if ((AOP_TYPE(left) == AOP_LIT) ||
3410 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3415 if(AOP_TYPE(right) == AOP_LIT)
3416 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3418 /* if the right side is a literal then anything goes */
3419 if (AOP_TYPE(right) == AOP_LIT &&
3420 AOP_TYPE(left) != AOP_DIR ) {
3422 emitcode("cjne","%s,%s,%05d$",
3423 aopGet(AOP(left),offset,FALSE,FALSE),
3424 aopGet(AOP(right),offset,FALSE,FALSE),
3430 /* if the right side is in a register or in direct space or
3431 if the left is a pointer register & right is not */
3432 else if (AOP_TYPE(right) == AOP_REG ||
3433 AOP_TYPE(right) == AOP_DIR ||
3434 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3435 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3437 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3438 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3439 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
3440 emitcode("jnz","%05d$",lbl->key+100);
3442 emitcode("cjne","a,%s,%05d$",
3443 aopGet(AOP(right),offset,FALSE,TRUE),
3448 /* right is a pointer reg need both a & b */
3450 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
3452 emitcode("mov","b,%s",l);
3453 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3454 emitcode("cjne","a,b,%05d$",lbl->key+100);
3460 /*-----------------------------------------------------------------*/
3461 /* gencjne - compare and jump if not equal */
3462 /*-----------------------------------------------------------------*/
3463 static void gencjne(operand *left, operand *right, symbol *lbl)
3465 symbol *tlbl = newiTempLabel(NULL);
3467 gencjneshort(left, right, lbl);
3469 emitcode("mov","a,%s",one);
3470 emitcode("sjmp","%05d$",tlbl->key+100);
3471 emitcode("","%05d$:",lbl->key+100);
3472 emitcode("clr","a");
3473 emitcode("","%05d$:",tlbl->key+100);
3476 /*-----------------------------------------------------------------*/
3477 /* genCmpEq - generates code for equal to */
3478 /*-----------------------------------------------------------------*/
3479 static void genCmpEq (iCode *ic, iCode *ifx)
3481 operand *left, *right, *result;
3483 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3484 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3485 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3487 /* if literal, literal on the right or
3488 if the right is in a pointer register and left
3490 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
3491 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3492 operand *t = IC_RIGHT(ic);
3493 IC_RIGHT(ic) = IC_LEFT(ic);
3497 if(ifx && !AOP_SIZE(result)){
3499 /* if they are both bit variables */
3500 if (AOP_TYPE(left) == AOP_CRY &&
3501 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3502 if(AOP_TYPE(right) == AOP_LIT){
3503 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3505 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3506 emitcode("cpl","c");
3507 } else if(lit == 1L) {
3508 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3510 emitcode("clr","c");
3512 /* AOP_TYPE(right) == AOP_CRY */
3514 symbol *lbl = newiTempLabel(NULL);
3515 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3516 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3517 emitcode("cpl","c");
3518 emitcode("","%05d$:",(lbl->key+100));
3520 /* if true label then we jump if condition
3522 tlbl = newiTempLabel(NULL);
3523 if ( IC_TRUE(ifx) ) {
3524 emitcode("jnc","%05d$",tlbl->key+100);
3525 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3527 emitcode("jc","%05d$",tlbl->key+100);
3528 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3530 emitcode("","%05d$:",tlbl->key+100);
3532 tlbl = newiTempLabel(NULL);
3533 gencjneshort(left, right, tlbl);
3534 if ( IC_TRUE(ifx) ) {
3535 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3536 emitcode("","%05d$:",tlbl->key+100);
3538 symbol *lbl = newiTempLabel(NULL);
3539 emitcode("sjmp","%05d$",lbl->key+100);
3540 emitcode("","%05d$:",tlbl->key+100);
3541 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3542 emitcode("","%05d$:",lbl->key+100);
3545 /* mark the icode as generated */
3550 /* if they are both bit variables */
3551 if (AOP_TYPE(left) == AOP_CRY &&
3552 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3553 if(AOP_TYPE(right) == AOP_LIT){
3554 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3556 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3557 emitcode("cpl","c");
3558 } else if(lit == 1L) {
3559 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3561 emitcode("clr","c");
3563 /* AOP_TYPE(right) == AOP_CRY */
3565 symbol *lbl = newiTempLabel(NULL);
3566 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3567 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3568 emitcode("cpl","c");
3569 emitcode("","%05d$:",(lbl->key+100));
3572 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
3577 genIfxJump (ifx,"c");
3580 /* if the result is used in an arithmetic operation
3581 then put the result in place */
3584 gencjne(left,right,newiTempLabel(NULL));
3585 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3586 aopPut(AOP(result),"a",0);
3590 genIfxJump (ifx,"a");
3593 /* if the result is used in an arithmetic operation
3594 then put the result in place */
3595 if (AOP_TYPE(result) != AOP_CRY)
3597 /* leave the result in acc */
3601 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3602 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3603 freeAsmop(result,NULL,ic,TRUE);
3606 /*-----------------------------------------------------------------*/
3607 /* ifxForOp - returns the icode containing the ifx for operand */
3608 /*-----------------------------------------------------------------*/
3609 static iCode *ifxForOp ( operand *op, iCode *ic )
3611 /* if true symbol then needs to be assigned */
3612 if (IS_TRUE_SYMOP(op))
3615 /* if this has register type condition and
3616 the next instruction is ifx with the same operand
3617 and live to of the operand is upto the ifx only then */
3619 ic->next->op == IFX &&
3620 IC_COND(ic->next)->key == op->key &&
3621 OP_SYMBOL(op)->liveTo <= ic->next->seq )
3626 /*-----------------------------------------------------------------*/
3627 /* genAndOp - for && operation */
3628 /*-----------------------------------------------------------------*/
3629 static void genAndOp (iCode *ic)
3631 operand *left,*right, *result;
3634 /* note here that && operations that are in an
3635 if statement are taken away by backPatchLabels
3636 only those used in arthmetic operations remain */
3637 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3638 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3639 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3641 /* if both are bit variables */
3642 if (AOP_TYPE(left) == AOP_CRY &&
3643 AOP_TYPE(right) == AOP_CRY ) {
3644 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3645 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3648 tlbl = newiTempLabel(NULL);
3650 emitcode("jz","%05d$",tlbl->key+100);
3652 emitcode("","%05d$:",tlbl->key+100);
3656 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3657 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3658 freeAsmop(result,NULL,ic,TRUE);
3662 /*-----------------------------------------------------------------*/
3663 /* genOrOp - for || operation */
3664 /*-----------------------------------------------------------------*/
3665 static void genOrOp (iCode *ic)
3667 operand *left,*right, *result;
3670 /* note here that || operations that are in an
3671 if statement are taken away by backPatchLabels
3672 only those used in arthmetic operations remain */
3673 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3674 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3675 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3677 /* if both are bit variables */
3678 if (AOP_TYPE(left) == AOP_CRY &&
3679 AOP_TYPE(right) == AOP_CRY ) {
3680 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3681 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
3684 tlbl = newiTempLabel(NULL);
3686 emitcode("jnz","%05d$",tlbl->key+100);
3688 emitcode("","%05d$:",tlbl->key+100);
3692 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3693 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3694 freeAsmop(result,NULL,ic,TRUE);
3697 /*-----------------------------------------------------------------*/
3698 /* isLiteralBit - test if lit == 2^n */
3699 /*-----------------------------------------------------------------*/
3700 static int isLiteralBit(unsigned long lit)
3702 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
3703 0x100L,0x200L,0x400L,0x800L,
3704 0x1000L,0x2000L,0x4000L,0x8000L,
3705 0x10000L,0x20000L,0x40000L,0x80000L,
3706 0x100000L,0x200000L,0x400000L,0x800000L,
3707 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
3708 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
3711 for(idx = 0; idx < 32; idx++)
3717 /*-----------------------------------------------------------------*/
3718 /* continueIfTrue - */
3719 /*-----------------------------------------------------------------*/
3720 static void continueIfTrue (iCode *ic)
3723 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3727 /*-----------------------------------------------------------------*/
3729 /*-----------------------------------------------------------------*/
3730 static void jumpIfTrue (iCode *ic)
3733 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3737 /*-----------------------------------------------------------------*/
3738 /* jmpTrueOrFalse - */
3739 /*-----------------------------------------------------------------*/
3740 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
3742 // ugly but optimized by peephole
3744 symbol *nlbl = newiTempLabel(NULL);
3745 emitcode("sjmp","%05d$",nlbl->key+100);
3746 emitcode("","%05d$:",tlbl->key+100);
3747 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3748 emitcode("","%05d$:",nlbl->key+100);
3751 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3752 emitcode("","%05d$:",tlbl->key+100);
3757 /*-----------------------------------------------------------------*/
3758 /* genAnd - code for and */
3759 /*-----------------------------------------------------------------*/
3760 static void genAnd (iCode *ic, iCode *ifx)
3762 operand *left, *right, *result;
3764 unsigned long lit = 0L;
3768 aopOp((left = IC_LEFT(ic)),ic,FALSE);
3769 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3770 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3773 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3775 AOP_TYPE(left), AOP_TYPE(right));
3776 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3778 AOP_SIZE(left), AOP_SIZE(right));
3781 /* if left is a literal & right is not then exchange them */
3782 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3783 AOP_NEEDSACC(left)) {
3784 operand *tmp = right ;
3789 /* if result = right then exchange them */
3790 if(sameRegs(AOP(result),AOP(right))){
3791 operand *tmp = right ;
3796 /* if right is bit then exchange them */
3797 if (AOP_TYPE(right) == AOP_CRY &&
3798 AOP_TYPE(left) != AOP_CRY){
3799 operand *tmp = right ;
3803 if(AOP_TYPE(right) == AOP_LIT)
3804 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3806 size = AOP_SIZE(result);
3809 // result = bit & yy;
3810 if (AOP_TYPE(left) == AOP_CRY){
3811 // c = bit & literal;
3812 if(AOP_TYPE(right) == AOP_LIT){
3814 if(size && sameRegs(AOP(result),AOP(left)))
3817 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3820 if(size && (AOP_TYPE(result) == AOP_CRY)){
3821 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
3824 if((AOP_TYPE(result) == AOP_CRY) && ifx){
3828 emitcode("clr","c");
3831 if (AOP_TYPE(right) == AOP_CRY){
3833 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3834 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3837 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
3839 emitcode("rrc","a");
3840 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3848 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
3849 genIfxJump(ifx, "c");
3853 // if(val & 0xZZ) - size = 0, ifx != FALSE -
3854 // bit = val & 0xZZ - size = 1, ifx = FALSE -
3855 if((AOP_TYPE(right) == AOP_LIT) &&
3856 (AOP_TYPE(result) == AOP_CRY) &&
3857 (AOP_TYPE(left) != AOP_CRY)){
3858 int posbit = isLiteralBit(lit);
3862 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
3865 emitcode("mov","c,acc.%d",posbit&0x07);
3869 sprintf(buffer,"acc.%d",posbit&0x07);
3870 genIfxJump(ifx, buffer);
3875 symbol *tlbl = newiTempLabel(NULL);
3876 int sizel = AOP_SIZE(left);
3878 emitcode("setb","c");
3880 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
3881 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
3883 if((posbit = isLiteralBit(bytelit)) != 0)
3884 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
3886 if(bytelit != 0x0FFL)
3887 emitcode("anl","a,%s",
3888 aopGet(AOP(right),offset,FALSE,TRUE));
3889 emitcode("jnz","%05d$",tlbl->key+100);
3894 // bit = left & literal
3896 emitcode("clr","c");
3897 emitcode("","%05d$:",tlbl->key+100);
3899 // if(left & literal)
3902 jmpTrueOrFalse(ifx, tlbl);
3910 /* if left is same as result */
3911 if(sameRegs(AOP(result),AOP(left))){
3912 for(;size--; offset++) {
3913 if(AOP_TYPE(right) == AOP_LIT){
3914 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
3918 aopPut(AOP(result),zero,offset);
3920 if (IS_AOP_PREG(result)) {
3921 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3922 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
3923 aopPut(AOP(result),"a",offset);
3925 emitcode("anl","%s,%s",
3926 aopGet(AOP(left),offset,FALSE,TRUE),
3927 aopGet(AOP(right),offset,FALSE,FALSE));
3929 if (AOP_TYPE(left) == AOP_ACC)
3930 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
3932 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3933 if (IS_AOP_PREG(result)) {
3934 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
3935 aopPut(AOP(result),"a",offset);
3938 emitcode("anl","%s,a",
3939 aopGet(AOP(left),offset,FALSE,TRUE));
3944 // left & result in different registers
3945 if(AOP_TYPE(result) == AOP_CRY){
3947 // if(size), result in bit
3948 // if(!size && ifx), conditional oper: if(left & right)
3949 symbol *tlbl = newiTempLabel(NULL);
3950 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
3952 emitcode("setb","c");
3954 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3955 emitcode("anl","a,%s",
3956 aopGet(AOP(left),offset,FALSE,FALSE));
3957 emitcode("jnz","%05d$",tlbl->key+100);
3962 emitcode("","%05d$:",tlbl->key+100);
3965 jmpTrueOrFalse(ifx, tlbl);
3967 for(;(size--);offset++) {
3969 // result = left & right
3970 if(AOP_TYPE(right) == AOP_LIT){
3971 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
3973 aopGet(AOP(left),offset,FALSE,FALSE),
3976 } else if(bytelit == 0){
3977 aopPut(AOP(result),zero,offset);
3981 // faster than result <- left, anl result,right
3982 // and better if result is SFR
3983 if (AOP_TYPE(left) == AOP_ACC)
3984 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
3986 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3987 emitcode("anl","a,%s",
3988 aopGet(AOP(left),offset,FALSE,FALSE));
3990 aopPut(AOP(result),"a",offset);
3996 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3997 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3998 freeAsmop(result,NULL,ic,TRUE);
4001 /*-----------------------------------------------------------------*/
4002 /* genOr - code for or */
4003 /*-----------------------------------------------------------------*/
4004 static void genOr (iCode *ic, iCode *ifx)
4006 operand *left, *right, *result;
4008 unsigned long lit = 0L;
4010 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4011 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4012 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4015 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4017 AOP_TYPE(left), AOP_TYPE(right));
4018 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4020 AOP_SIZE(left), AOP_SIZE(right));
4023 /* if left is a literal & right is not then exchange them */
4024 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4025 AOP_NEEDSACC(left)) {
4026 operand *tmp = right ;
4031 /* if result = right then exchange them */
4032 if(sameRegs(AOP(result),AOP(right))){
4033 operand *tmp = right ;
4038 /* if right is bit then exchange them */
4039 if (AOP_TYPE(right) == AOP_CRY &&
4040 AOP_TYPE(left) != AOP_CRY){
4041 operand *tmp = right ;
4045 if(AOP_TYPE(right) == AOP_LIT)
4046 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4048 size = AOP_SIZE(result);
4052 if (AOP_TYPE(left) == AOP_CRY){
4053 if(AOP_TYPE(right) == AOP_LIT){
4054 // c = bit & literal;
4056 // lit != 0 => result = 1
4057 if(AOP_TYPE(result) == AOP_CRY){
4059 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4061 continueIfTrue(ifx);
4064 emitcode("setb","c");
4066 // lit == 0 => result = left
4067 if(size && sameRegs(AOP(result),AOP(left)))
4069 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4072 if (AOP_TYPE(right) == AOP_CRY){
4074 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4075 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4079 symbol *tlbl = newiTempLabel(NULL);
4080 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4081 emitcode("setb","c");
4082 emitcode("jb","%s,%05d$",
4083 AOP(left)->aopu.aop_dir,tlbl->key+100);
4085 emitcode("jnz","%05d$",tlbl->key+100);
4086 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4087 jmpTrueOrFalse(ifx, tlbl);
4091 emitcode("","%05d$:",tlbl->key+100);
4100 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4101 genIfxJump(ifx, "c");
4105 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4106 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4107 if((AOP_TYPE(right) == AOP_LIT) &&
4108 (AOP_TYPE(result) == AOP_CRY) &&
4109 (AOP_TYPE(left) != AOP_CRY)){
4113 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4115 continueIfTrue(ifx);
4118 // lit = 0, result = boolean(left)
4120 emitcode("setb","c");
4123 symbol *tlbl = newiTempLabel(NULL);
4124 emitcode("jnz","%05d$",tlbl->key+100);
4126 emitcode("","%05d$:",tlbl->key+100);
4128 genIfxJump (ifx,"a");
4136 /* if left is same as result */
4137 if(sameRegs(AOP(result),AOP(left))){
4138 for(;size--; offset++) {
4139 if(AOP_TYPE(right) == AOP_LIT){
4140 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4143 if (IS_AOP_PREG(left)) {
4144 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4145 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4146 aopPut(AOP(result),"a",offset);
4148 emitcode("orl","%s,%s",
4149 aopGet(AOP(left),offset,FALSE,TRUE),
4150 aopGet(AOP(right),offset,FALSE,FALSE));
4152 if (AOP_TYPE(left) == AOP_ACC)
4153 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4155 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4156 if (IS_AOP_PREG(left)) {
4157 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4158 aopPut(AOP(result),"a",offset);
4160 emitcode("orl","%s,a",
4161 aopGet(AOP(left),offset,FALSE,TRUE));
4166 // left & result in different registers
4167 if(AOP_TYPE(result) == AOP_CRY){
4169 // if(size), result in bit
4170 // if(!size && ifx), conditional oper: if(left | right)
4171 symbol *tlbl = newiTempLabel(NULL);
4172 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4174 emitcode("setb","c");
4176 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4177 emitcode("orl","a,%s",
4178 aopGet(AOP(left),offset,FALSE,FALSE));
4179 emitcode("jnz","%05d$",tlbl->key+100);
4184 emitcode("","%05d$:",tlbl->key+100);
4187 jmpTrueOrFalse(ifx, tlbl);
4188 } else for(;(size--);offset++){
4190 // result = left & right
4191 if(AOP_TYPE(right) == AOP_LIT){
4192 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4194 aopGet(AOP(left),offset,FALSE,FALSE),
4199 // faster than result <- left, anl result,right
4200 // and better if result is SFR
4201 if (AOP_TYPE(left) == AOP_ACC)
4202 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4204 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4205 emitcode("orl","a,%s",
4206 aopGet(AOP(left),offset,FALSE,FALSE));
4208 aopPut(AOP(result),"a",offset);
4213 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4214 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4215 freeAsmop(result,NULL,ic,TRUE);
4218 /*-----------------------------------------------------------------*/
4219 /* genXor - code for xclusive or */
4220 /*-----------------------------------------------------------------*/
4221 static void genXor (iCode *ic, iCode *ifx)
4223 operand *left, *right, *result;
4225 unsigned long lit = 0L;
4227 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4228 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4229 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4232 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4234 AOP_TYPE(left), AOP_TYPE(right));
4235 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4237 AOP_SIZE(left), AOP_SIZE(right));
4240 /* if left is a literal & right is not ||
4241 if left needs acc & right does not */
4242 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4243 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4244 operand *tmp = right ;
4249 /* if result = right then exchange them */
4250 if(sameRegs(AOP(result),AOP(right))){
4251 operand *tmp = right ;
4256 /* if right is bit then exchange them */
4257 if (AOP_TYPE(right) == AOP_CRY &&
4258 AOP_TYPE(left) != AOP_CRY){
4259 operand *tmp = right ;
4263 if(AOP_TYPE(right) == AOP_LIT)
4264 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4266 size = AOP_SIZE(result);
4270 if (AOP_TYPE(left) == AOP_CRY){
4271 if(AOP_TYPE(right) == AOP_LIT){
4272 // c = bit & literal;
4274 // lit>>1 != 0 => result = 1
4275 if(AOP_TYPE(result) == AOP_CRY){
4277 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4279 continueIfTrue(ifx);
4282 emitcode("setb","c");
4286 // lit == 0, result = left
4287 if(size && sameRegs(AOP(result),AOP(left)))
4289 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4291 // lit == 1, result = not(left)
4292 if(size && sameRegs(AOP(result),AOP(left))){
4293 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4296 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4297 emitcode("cpl","c");
4304 symbol *tlbl = newiTempLabel(NULL);
4305 if (AOP_TYPE(right) == AOP_CRY){
4307 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4310 int sizer = AOP_SIZE(right);
4312 // if val>>1 != 0, result = 1
4313 emitcode("setb","c");
4315 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
4317 // test the msb of the lsb
4318 emitcode("anl","a,#0xfe");
4319 emitcode("jnz","%05d$",tlbl->key+100);
4323 emitcode("rrc","a");
4325 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4326 emitcode("cpl","c");
4327 emitcode("","%05d$:",(tlbl->key+100));
4334 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4335 genIfxJump(ifx, "c");
4339 if(sameRegs(AOP(result),AOP(left))){
4340 /* if left is same as result */
4341 for(;size--; offset++) {
4342 if(AOP_TYPE(right) == AOP_LIT){
4343 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4346 if (IS_AOP_PREG(left)) {
4347 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4348 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4349 aopPut(AOP(result),"a",offset);
4351 emitcode("xrl","%s,%s",
4352 aopGet(AOP(left),offset,FALSE,TRUE),
4353 aopGet(AOP(right),offset,FALSE,FALSE));
4355 if (AOP_TYPE(left) == AOP_ACC)
4356 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4358 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4359 if (IS_AOP_PREG(left)) {
4360 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4361 aopPut(AOP(result),"a",offset);
4363 emitcode("xrl","%s,a",
4364 aopGet(AOP(left),offset,FALSE,TRUE));
4369 // left & result in different registers
4370 if(AOP_TYPE(result) == AOP_CRY){
4372 // if(size), result in bit
4373 // if(!size && ifx), conditional oper: if(left ^ right)
4374 symbol *tlbl = newiTempLabel(NULL);
4375 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4377 emitcode("setb","c");
4379 if((AOP_TYPE(right) == AOP_LIT) &&
4380 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4381 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4383 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4384 emitcode("xrl","a,%s",
4385 aopGet(AOP(left),offset,FALSE,FALSE));
4387 emitcode("jnz","%05d$",tlbl->key+100);
4392 emitcode("","%05d$:",tlbl->key+100);
4395 jmpTrueOrFalse(ifx, tlbl);
4396 } else for(;(size--);offset++){
4398 // result = left & right
4399 if(AOP_TYPE(right) == AOP_LIT){
4400 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4402 aopGet(AOP(left),offset,FALSE,FALSE),
4407 // faster than result <- left, anl result,right
4408 // and better if result is SFR
4409 if (AOP_TYPE(left) == AOP_ACC)
4410 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4412 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4413 emitcode("xrl","a,%s",
4414 aopGet(AOP(left),offset,FALSE,TRUE));
4416 aopPut(AOP(result),"a",offset);
4421 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4422 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4423 freeAsmop(result,NULL,ic,TRUE);
4426 /*-----------------------------------------------------------------*/
4427 /* genInline - write the inline code out */
4428 /*-----------------------------------------------------------------*/
4429 static void genInline (iCode *ic)
4431 char buffer[MAX_INLINEASM];
4435 _G.inLine += (!options.asmpeep);
4436 strcpy(buffer,IC_INLINE(ic));
4438 /* emit each line as a code */
4457 /* emitcode("",buffer); */
4458 _G.inLine -= (!options.asmpeep);
4461 /*-----------------------------------------------------------------*/
4462 /* genRRC - rotate right with carry */
4463 /*-----------------------------------------------------------------*/
4464 static void genRRC (iCode *ic)
4466 operand *left , *result ;
4467 int size, offset = 0;
4470 /* rotate right with carry */
4472 result=IC_RESULT(ic);
4473 aopOp (left,ic,FALSE);
4474 aopOp (result,ic,FALSE);
4476 /* move it to the result */
4477 size = AOP_SIZE(result);
4481 l = aopGet(AOP(left),offset,FALSE,FALSE);
4483 emitcode("rrc","a");
4484 if (AOP_SIZE(result) > 1)
4485 aopPut(AOP(result),"a",offset--);
4487 /* now we need to put the carry into the
4488 highest order byte of the result */
4489 if (AOP_SIZE(result) > 1) {
4490 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
4493 emitcode("mov","acc.7,c");
4494 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
4495 freeAsmop(left,NULL,ic,TRUE);
4496 freeAsmop(result,NULL,ic,TRUE);
4499 /*-----------------------------------------------------------------*/
4500 /* genRLC - generate code for rotate left with carry */
4501 /*-----------------------------------------------------------------*/
4502 static void genRLC (iCode *ic)
4504 operand *left , *result ;
4505 int size, offset = 0;
4508 /* rotate right with carry */
4510 result=IC_RESULT(ic);
4511 aopOp (left,ic,FALSE);
4512 aopOp (result,ic,FALSE);
4514 /* move it to the result */
4515 size = AOP_SIZE(result);
4518 l = aopGet(AOP(left),offset,FALSE,FALSE);
4520 emitcode("add","a,acc");
4521 if (AOP_SIZE(result) > 1)
4522 aopPut(AOP(result),"a",offset++);
4524 l = aopGet(AOP(left),offset,FALSE,FALSE);
4526 emitcode("rlc","a");
4527 if (AOP_SIZE(result) > 1)
4528 aopPut(AOP(result),"a",offset++);
4531 /* now we need to put the carry into the
4532 highest order byte of the result */
4533 if (AOP_SIZE(result) > 1) {
4534 l = aopGet(AOP(result),0,FALSE,FALSE);
4537 emitcode("mov","acc.0,c");
4538 aopPut(AOP(result),"a",0);
4539 freeAsmop(left,NULL,ic,TRUE);
4540 freeAsmop(result,NULL,ic,TRUE);
4543 /*-----------------------------------------------------------------*/
4544 /* genGetHbit - generates code get highest order bit */
4545 /*-----------------------------------------------------------------*/
4546 static void genGetHbit (iCode *ic)
4548 operand *left, *result;
4550 result=IC_RESULT(ic);
4551 aopOp (left,ic,FALSE);
4552 aopOp (result,ic,FALSE);
4554 /* get the highest order byte into a */
4555 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
4556 if(AOP_TYPE(result) == AOP_CRY){
4557 emitcode("rlc","a");
4562 emitcode("anl","a,#0x01");
4567 freeAsmop(left,NULL,ic,TRUE);
4568 freeAsmop(result,NULL,ic,TRUE);
4571 /*-----------------------------------------------------------------*/
4572 /* AccRol - rotate left accumulator by known count */
4573 /*-----------------------------------------------------------------*/
4574 static void AccRol (int shCount)
4576 shCount &= 0x0007; // shCount : 0..7
4588 emitcode("swap","a");
4592 emitcode("swap","a");
4595 emitcode("swap","a");
4608 /*-----------------------------------------------------------------*/
4609 /* AccLsh - left shift accumulator by known count */
4610 /*-----------------------------------------------------------------*/
4611 static void AccLsh (int shCount)
4615 emitcode("add","a,acc");
4618 emitcode("add","a,acc");
4619 emitcode("add","a,acc");
4621 /* rotate left accumulator */
4623 /* and kill the lower order bits */
4624 emitcode("anl","a,#0x%02x", SLMask[shCount]);
4629 /*-----------------------------------------------------------------*/
4630 /* AccRsh - right shift accumulator by known count */
4631 /*-----------------------------------------------------------------*/
4632 static void AccRsh (int shCount)
4637 emitcode("rrc","a");
4639 /* rotate right accumulator */
4640 AccRol(8 - shCount);
4641 /* and kill the higher order bits */
4642 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4647 /*-----------------------------------------------------------------*/
4648 /* AccSRsh - signed right shift accumulator by known count */
4649 /*-----------------------------------------------------------------*/
4650 static void AccSRsh (int shCount)
4655 emitcode("mov","c,acc.7");
4656 emitcode("rrc","a");
4657 } else if(shCount == 2){
4658 emitcode("mov","c,acc.7");
4659 emitcode("rrc","a");
4660 emitcode("mov","c,acc.7");
4661 emitcode("rrc","a");
4663 tlbl = newiTempLabel(NULL);
4664 /* rotate right accumulator */
4665 AccRol(8 - shCount);
4666 /* and kill the higher order bits */
4667 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4668 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4669 emitcode("orl","a,#0x%02x",
4670 (unsigned char)~SRMask[shCount]);
4671 emitcode("","%05d$:",tlbl->key+100);
4676 /*-----------------------------------------------------------------*/
4677 /* shiftR1Left2Result - shift right one byte from left to result */
4678 /*-----------------------------------------------------------------*/
4679 static void shiftR1Left2Result (operand *left, int offl,
4680 operand *result, int offr,
4681 int shCount, int sign)
4683 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4684 /* shift right accumulator */
4689 aopPut(AOP(result),"a",offr);
4692 /*-----------------------------------------------------------------*/
4693 /* shiftL1Left2Result - shift left one byte from left to result */
4694 /*-----------------------------------------------------------------*/
4695 static void shiftL1Left2Result (operand *left, int offl,
4696 operand *result, int offr, int shCount)
4699 l = aopGet(AOP(left),offl,FALSE,FALSE);
4701 /* shift left accumulator */
4703 aopPut(AOP(result),"a",offr);
4706 /*-----------------------------------------------------------------*/
4707 /* movLeft2Result - move byte from left to result */
4708 /*-----------------------------------------------------------------*/
4709 static void movLeft2Result (operand *left, int offl,
4710 operand *result, int offr, int sign)
4713 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
4714 l = aopGet(AOP(left),offl,FALSE,FALSE);
4716 if (*l == '@' && (IS_AOP_PREG(result))) {
4717 emitcode("mov","a,%s",l);
4718 aopPut(AOP(result),"a",offr);
4721 aopPut(AOP(result),l,offr);
4723 /* MSB sign in acc.7 ! */
4724 if(getDataSize(left) == offl+1){
4725 emitcode("mov","a,%s",l);
4726 aopPut(AOP(result),"a",offr);
4733 /*-----------------------------------------------------------------*/
4734 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
4735 /*-----------------------------------------------------------------*/
4736 static void AccAXRrl1 (char *x)
4738 emitcode("rrc","a");
4739 emitcode("xch","a,%s", x);
4740 emitcode("rrc","a");
4741 emitcode("xch","a,%s", x);
4744 /*-----------------------------------------------------------------*/
4745 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
4746 /*-----------------------------------------------------------------*/
4747 static void AccAXLrl1 (char *x)
4749 emitcode("xch","a,%s",x);
4750 emitcode("rlc","a");
4751 emitcode("xch","a,%s",x);
4752 emitcode("rlc","a");
4755 /*-----------------------------------------------------------------*/
4756 /* AccAXLsh1 - left shift a:x<-0 by 1 */
4757 /*-----------------------------------------------------------------*/
4758 static void AccAXLsh1 (char *x)
4760 emitcode("xch","a,%s",x);
4761 emitcode("add","a,acc");
4762 emitcode("xch","a,%s",x);
4763 emitcode("rlc","a");
4766 /*-----------------------------------------------------------------*/
4767 /* AccAXLsh - left shift a:x by known count (0..7) */
4768 /*-----------------------------------------------------------------*/
4769 static void AccAXLsh (char *x, int shCount)
4783 case 5 : // AAAAABBB:CCCCCDDD
4784 AccRol(shCount); // BBBAAAAA:CCCCCDDD
4785 emitcode("anl","a,#0x%02x",
4786 SLMask[shCount]); // BBB00000:CCCCCDDD
4787 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
4788 AccRol(shCount); // DDDCCCCC:BBB00000
4789 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
4790 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
4791 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
4792 emitcode("anl","a,#0x%02x",
4793 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
4794 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
4795 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
4797 case 6 : // AAAAAABB:CCCCCCDD
4798 emitcode("anl","a,#0x%02x",
4799 SRMask[shCount]); // 000000BB:CCCCCCDD
4800 emitcode("mov","c,acc.0"); // c = B
4801 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
4802 AccAXRrl1(x); // BCCCCCCD:D000000B
4803 AccAXRrl1(x); // BBCCCCCC:DD000000
4805 case 7 : // a:x <<= 7
4806 emitcode("anl","a,#0x%02x",
4807 SRMask[shCount]); // 0000000B:CCCCCCCD
4808 emitcode("mov","c,acc.0"); // c = B
4809 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
4810 AccAXRrl1(x); // BCCCCCCC:D0000000
4817 /*-----------------------------------------------------------------*/
4818 /* AccAXRsh - right shift a:x known count (0..7) */
4819 /*-----------------------------------------------------------------*/
4820 static void AccAXRsh (char *x, int shCount)
4827 AccAXRrl1(x); // 0->a:x
4831 AccAXRrl1(x); // 0->a:x
4833 AccAXRrl1(x); // 0->a:x
4837 case 5 : // AAAAABBB:CCCCCDDD = a:x
4838 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
4839 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
4840 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
4841 emitcode("anl","a,#0x%02x",
4842 SRMask[shCount]); // 000CCCCC:BBBAAAAA
4843 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
4844 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
4845 emitcode("anl","a,#0x%02x",
4846 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
4847 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
4848 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
4849 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
4851 case 6 : // AABBBBBB:CCDDDDDD
4852 emitcode("mov","c,acc.7");
4853 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
4854 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
4855 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
4856 emitcode("anl","a,#0x%02x",
4857 SRMask[shCount]); // 000000AA:BBBBBBCC
4859 case 7 : // ABBBBBBB:CDDDDDDD
4860 emitcode("mov","c,acc.7"); // c = A
4861 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
4862 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
4863 emitcode("anl","a,#0x%02x",
4864 SRMask[shCount]); // 0000000A:BBBBBBBC
4871 /*-----------------------------------------------------------------*/
4872 /* AccAXRshS - right shift signed a:x known count (0..7) */
4873 /*-----------------------------------------------------------------*/
4874 static void AccAXRshS (char *x, int shCount)
4881 emitcode("mov","c,acc.7");
4882 AccAXRrl1(x); // s->a:x
4885 emitcode("mov","c,acc.7");
4886 AccAXRrl1(x); // s->a:x
4887 emitcode("mov","c,acc.7");
4888 AccAXRrl1(x); // s->a:x
4892 case 5 : // AAAAABBB:CCCCCDDD = a:x
4893 tlbl = newiTempLabel(NULL);
4894 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
4895 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
4896 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
4897 emitcode("anl","a,#0x%02x",
4898 SRMask[shCount]); // 000CCCCC:BBBAAAAA
4899 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
4900 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
4901 emitcode("anl","a,#0x%02x",
4902 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
4903 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
4904 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
4905 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
4906 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4907 emitcode("orl","a,#0x%02x",
4908 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
4909 emitcode("","%05d$:",tlbl->key+100);
4910 break; // SSSSAAAA:BBBCCCCC
4911 case 6 : // AABBBBBB:CCDDDDDD
4912 tlbl = newiTempLabel(NULL);
4913 emitcode("mov","c,acc.7");
4914 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
4915 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
4916 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
4917 emitcode("anl","a,#0x%02x",
4918 SRMask[shCount]); // 000000AA:BBBBBBCC
4919 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4920 emitcode("orl","a,#0x%02x",
4921 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
4922 emitcode("","%05d$:",tlbl->key+100);
4924 case 7 : // ABBBBBBB:CDDDDDDD
4925 tlbl = newiTempLabel(NULL);
4926 emitcode("mov","c,acc.7"); // c = A
4927 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
4928 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
4929 emitcode("anl","a,#0x%02x",
4930 SRMask[shCount]); // 0000000A:BBBBBBBC
4931 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4932 emitcode("orl","a,#0x%02x",
4933 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
4934 emitcode("","%05d$:",tlbl->key+100);
4941 /*-----------------------------------------------------------------*/
4942 /* shiftL2Left2Result - shift left two bytes from left to result */
4943 /*-----------------------------------------------------------------*/
4944 static void shiftL2Left2Result (operand *left, int offl,
4945 operand *result, int offr, int shCount)
4947 if(sameRegs(AOP(result), AOP(left)) &&
4948 ((offl + MSB16) == offr)){
4949 /* don't crash result[offr] */
4950 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4951 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4953 movLeft2Result(left,offl, result, offr, 0);
4954 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4956 /* ax << shCount (x = lsb(result))*/
4957 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
4958 aopPut(AOP(result),"a",offr+MSB16);
4962 /*-----------------------------------------------------------------*/
4963 /* shiftR2Left2Result - shift right two bytes from left to result */
4964 /*-----------------------------------------------------------------*/
4965 static void shiftR2Left2Result (operand *left, int offl,
4966 operand *result, int offr,
4967 int shCount, int sign)
4969 if(sameRegs(AOP(result), AOP(left)) &&
4970 ((offl + MSB16) == offr)){
4971 /* don't crash result[offr] */
4972 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4973 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4975 movLeft2Result(left,offl, result, offr, 0);
4976 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4978 /* a:x >> shCount (x = lsb(result))*/
4980 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
4982 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
4983 if(getDataSize(result) > 1)
4984 aopPut(AOP(result),"a",offr+MSB16);
4987 /*-----------------------------------------------------------------*/
4988 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
4989 /*-----------------------------------------------------------------*/
4990 static void shiftLLeftOrResult (operand *left, int offl,
4991 operand *result, int offr, int shCount)
4993 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4994 /* shift left accumulator */
4996 /* or with result */
4997 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
4998 /* back to result */
4999 aopPut(AOP(result),"a",offr);
5002 /*-----------------------------------------------------------------*/
5003 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5004 /*-----------------------------------------------------------------*/
5005 static void shiftRLeftOrResult (operand *left, int offl,
5006 operand *result, int offr, int shCount)
5008 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5009 /* shift right accumulator */
5011 /* or with result */
5012 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5013 /* back to result */
5014 aopPut(AOP(result),"a",offr);
5017 /*-----------------------------------------------------------------*/
5018 /* genlshOne - left shift a one byte quantity by known count */
5019 /*-----------------------------------------------------------------*/
5020 static void genlshOne (operand *result, operand *left, int shCount)
5022 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5025 /*-----------------------------------------------------------------*/
5026 /* genlshTwo - left shift two bytes by known amount != 0 */
5027 /*-----------------------------------------------------------------*/
5028 static void genlshTwo (operand *result,operand *left, int shCount)
5032 size = getDataSize(result);
5034 /* if shCount >= 8 */
5040 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5042 movLeft2Result(left, LSB, result, MSB16, 0);
5044 aopPut(AOP(result),zero,LSB);
5047 /* 1 <= shCount <= 7 */
5050 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5052 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5056 /*-----------------------------------------------------------------*/
5057 /* shiftLLong - shift left one long from left to result */
5058 /* offl = LSB or MSB16 */
5059 /*-----------------------------------------------------------------*/
5060 static void shiftLLong (operand *left, operand *result, int offr )
5063 int size = AOP_SIZE(result);
5065 if(size >= LSB+offr){
5066 l = aopGet(AOP(left),LSB,FALSE,FALSE);
5068 emitcode("add","a,acc");
5069 if (sameRegs(AOP(left),AOP(result)) &&
5070 size >= MSB16+offr && offr != LSB )
5071 emitcode("xch","a,%s",
5072 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
5074 aopPut(AOP(result),"a",LSB+offr);
5077 if(size >= MSB16+offr){
5078 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5079 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
5082 emitcode("rlc","a");
5083 if (sameRegs(AOP(left),AOP(result)) &&
5084 size >= MSB24+offr && offr != LSB)
5085 emitcode("xch","a,%s",
5086 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
5088 aopPut(AOP(result),"a",MSB16+offr);
5091 if(size >= MSB24+offr){
5092 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5093 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
5096 emitcode("rlc","a");
5097 if (sameRegs(AOP(left),AOP(result)) &&
5098 size >= MSB32+offr && offr != LSB )
5099 emitcode("xch","a,%s",
5100 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
5102 aopPut(AOP(result),"a",MSB24+offr);
5105 if(size > MSB32+offr){
5106 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5107 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
5110 emitcode("rlc","a");
5111 aopPut(AOP(result),"a",MSB32+offr);
5114 aopPut(AOP(result),zero,LSB);
5117 /*-----------------------------------------------------------------*/
5118 /* genlshFour - shift four byte by a known amount != 0 */
5119 /*-----------------------------------------------------------------*/
5120 static void genlshFour (operand *result, operand *left, int shCount)
5124 size = AOP_SIZE(result);
5126 /* if shifting more that 3 bytes */
5127 if (shCount >= 24 ) {
5130 /* lowest order of left goes to the highest
5131 order of the destination */
5132 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5134 movLeft2Result(left, LSB, result, MSB32, 0);
5135 aopPut(AOP(result),zero,LSB);
5136 aopPut(AOP(result),zero,MSB16);
5137 aopPut(AOP(result),zero,MSB32);
5141 /* more than two bytes */
5142 else if ( shCount >= 16 ) {
5143 /* lower order two bytes goes to higher order two bytes */
5145 /* if some more remaining */
5147 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5149 movLeft2Result(left, MSB16, result, MSB32, 0);
5150 movLeft2Result(left, LSB, result, MSB24, 0);
5152 aopPut(AOP(result),zero,MSB16);
5153 aopPut(AOP(result),zero,LSB);
5157 /* if more than 1 byte */
5158 else if ( shCount >= 8 ) {
5159 /* lower order three bytes goes to higher order three bytes */
5163 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5165 movLeft2Result(left, LSB, result, MSB16, 0);
5167 else{ /* size = 4 */
5169 movLeft2Result(left, MSB24, result, MSB32, 0);
5170 movLeft2Result(left, MSB16, result, MSB24, 0);
5171 movLeft2Result(left, LSB, result, MSB16, 0);
5172 aopPut(AOP(result),zero,LSB);
5174 else if(shCount == 1)
5175 shiftLLong(left, result, MSB16);
5177 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5178 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5179 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5180 aopPut(AOP(result),zero,LSB);
5185 /* 1 <= shCount <= 7 */
5186 else if(shCount <= 2){
5187 shiftLLong(left, result, LSB);
5189 shiftLLong(result, result, LSB);
5191 /* 3 <= shCount <= 7, optimize */
5193 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5194 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5195 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5199 /*-----------------------------------------------------------------*/
5200 /* genLeftShiftLiteral - left shifting by known count */
5201 /*-----------------------------------------------------------------*/
5202 static void genLeftShiftLiteral (operand *left,
5207 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5210 freeAsmop(right,NULL,ic,TRUE);
5212 aopOp(left,ic,FALSE);
5213 aopOp(result,ic,FALSE);
5215 size = getSize(operandType(result));
5218 emitcode("; shift left ","result %d, left %d",size,
5222 /* I suppose that the left size >= result size */
5225 movLeft2Result(left, size, result, size, 0);
5229 else if(shCount >= (size * 8))
5231 aopPut(AOP(result),zero,size);
5235 genlshOne (result,left,shCount);
5240 genlshTwo (result,left,shCount);
5244 genlshFour (result,left,shCount);
5248 freeAsmop(left,NULL,ic,TRUE);
5249 freeAsmop(result,NULL,ic,TRUE);
5252 /*-----------------------------------------------------------------*/
5253 /* genLeftShift - generates code for left shifting */
5254 /*-----------------------------------------------------------------*/
5255 static void genLeftShift (iCode *ic)
5257 operand *left,*right, *result;
5260 symbol *tlbl , *tlbl1;
5262 right = IC_RIGHT(ic);
5264 result = IC_RESULT(ic);
5266 aopOp(right,ic,FALSE);
5268 /* if the shift count is known then do it
5269 as efficiently as possible */
5270 if (AOP_TYPE(right) == AOP_LIT) {
5271 genLeftShiftLiteral (left,right,result,ic);
5275 /* shift count is unknown then we have to form
5276 a loop get the loop count in B : Note: we take
5277 only the lower order byte since shifting
5278 more that 32 bits make no sense anyway, ( the
5279 largest size of an object can be only 32 bits ) */
5281 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5282 emitcode("inc","b");
5283 freeAsmop (right,NULL,ic,TRUE);
5284 aopOp(left,ic,FALSE);
5285 aopOp(result,ic,FALSE);
5287 /* now move the left to the result if they are not the
5289 if (!sameRegs(AOP(left),AOP(result)) &&
5290 AOP_SIZE(result) > 1) {
5292 size = AOP_SIZE(result);
5295 l = aopGet(AOP(left),offset,FALSE,TRUE);
5296 if (*l == '@' && (IS_AOP_PREG(result))) {
5298 emitcode("mov","a,%s",l);
5299 aopPut(AOP(result),"a",offset);
5301 aopPut(AOP(result),l,offset);
5306 tlbl = newiTempLabel(NULL);
5307 size = AOP_SIZE(result);
5309 tlbl1 = newiTempLabel(NULL);
5311 /* if it is only one byte then */
5313 symbol *tlbl1 = newiTempLabel(NULL);
5315 l = aopGet(AOP(left),0,FALSE,FALSE);
5317 emitcode("sjmp","%05d$",tlbl1->key+100);
5318 emitcode("","%05d$:",tlbl->key+100);
5319 emitcode("add","a,acc");
5320 emitcode("","%05d$:",tlbl1->key+100);
5321 emitcode("djnz","b,%05d$",tlbl->key+100);
5322 aopPut(AOP(result),"a",0);
5326 reAdjustPreg(AOP(result));
5328 emitcode("sjmp","%05d$",tlbl1->key+100);
5329 emitcode("","%05d$:",tlbl->key+100);
5330 l = aopGet(AOP(result),offset,FALSE,FALSE);
5332 emitcode("add","a,acc");
5333 aopPut(AOP(result),"a",offset++);
5335 l = aopGet(AOP(result),offset,FALSE,FALSE);
5337 emitcode("rlc","a");
5338 aopPut(AOP(result),"a",offset++);
5340 reAdjustPreg(AOP(result));
5342 emitcode("","%05d$:",tlbl1->key+100);
5343 emitcode("djnz","b,%05d$",tlbl->key+100);
5345 freeAsmop(left,NULL,ic,TRUE);
5346 freeAsmop(result,NULL,ic,TRUE);
5349 /*-----------------------------------------------------------------*/
5350 /* genrshOne - right shift a one byte quantity by known count */
5351 /*-----------------------------------------------------------------*/
5352 static void genrshOne (operand *result, operand *left,
5353 int shCount, int sign)
5355 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
5358 /*-----------------------------------------------------------------*/
5359 /* genrshTwo - right shift two bytes by known amount != 0 */
5360 /*-----------------------------------------------------------------*/
5361 static void genrshTwo (operand *result,operand *left,
5362 int shCount, int sign)
5364 /* if shCount >= 8 */
5368 shiftR1Left2Result(left, MSB16, result, LSB,
5371 movLeft2Result(left, MSB16, result, LSB, sign);
5372 addSign(result, MSB16, sign);
5375 /* 1 <= shCount <= 7 */
5377 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
5380 /*-----------------------------------------------------------------*/
5381 /* shiftRLong - shift right one long from left to result */
5382 /* offl = LSB or MSB16 */
5383 /*-----------------------------------------------------------------*/
5384 static void shiftRLong (operand *left, int offl,
5385 operand *result, int sign)
5388 emitcode("clr","c");
5389 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
5391 emitcode("mov","c,acc.7");
5392 emitcode("rrc","a");
5393 aopPut(AOP(result),"a",MSB32-offl);
5395 /* add sign of "a" */
5396 addSign(result, MSB32, sign);
5398 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
5399 emitcode("rrc","a");
5400 aopPut(AOP(result),"a",MSB24-offl);
5402 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
5403 emitcode("rrc","a");
5404 aopPut(AOP(result),"a",MSB16-offl);
5407 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
5408 emitcode("rrc","a");
5409 aopPut(AOP(result),"a",LSB);
5413 /*-----------------------------------------------------------------*/
5414 /* genrshFour - shift four byte by a known amount != 0 */
5415 /*-----------------------------------------------------------------*/
5416 static void genrshFour (operand *result, operand *left,
5417 int shCount, int sign)
5419 /* if shifting more that 3 bytes */
5420 if(shCount >= 24 ) {
5423 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
5425 movLeft2Result(left, MSB32, result, LSB, sign);
5426 addSign(result, MSB16, sign);
5428 else if(shCount >= 16){
5431 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
5433 movLeft2Result(left, MSB24, result, LSB, 0);
5434 movLeft2Result(left, MSB32, result, MSB16, sign);
5436 addSign(result, MSB24, sign);
5438 else if(shCount >= 8){
5441 shiftRLong(left, MSB16, result, sign);
5442 else if(shCount == 0){
5443 movLeft2Result(left, MSB16, result, LSB, 0);
5444 movLeft2Result(left, MSB24, result, MSB16, 0);
5445 movLeft2Result(left, MSB32, result, MSB24, sign);
5446 addSign(result, MSB32, sign);
5449 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
5450 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
5451 /* the last shift is signed */
5452 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
5453 addSign(result, MSB32, sign);
5456 else{ /* 1 <= shCount <= 7 */
5458 shiftRLong(left, LSB, result, sign);
5460 shiftRLong(result, LSB, result, sign);
5463 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
5464 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
5465 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
5470 /*-----------------------------------------------------------------*/
5471 /* genRightShiftLiteral - right shifting by known count */
5472 /*-----------------------------------------------------------------*/
5473 static void genRightShiftLiteral (operand *left,
5479 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5482 freeAsmop(right,NULL,ic,TRUE);
5484 aopOp(left,ic,FALSE);
5485 aopOp(result,ic,FALSE);
5488 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
5492 size = getDataSize(left);
5493 /* test the LEFT size !!! */
5495 /* I suppose that the left size >= result size */
5497 size = getDataSize(result);
5499 movLeft2Result(left, size, result, size, 0);
5502 else if(shCount >= (size * 8)){
5504 /* get sign in acc.7 */
5505 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
5506 addSign(result, LSB, sign);
5510 genrshOne (result,left,shCount,sign);
5514 genrshTwo (result,left,shCount,sign);
5518 genrshFour (result,left,shCount,sign);
5524 freeAsmop(left,NULL,ic,TRUE);
5525 freeAsmop(result,NULL,ic,TRUE);
5529 /*-----------------------------------------------------------------*/
5530 /* genSignedRightShift - right shift of signed number */
5531 /*-----------------------------------------------------------------*/
5532 static void genSignedRightShift (iCode *ic)
5534 operand *right, *left, *result;
5537 symbol *tlbl, *tlbl1 ;
5539 /* we do it the hard way put the shift count in b
5540 and loop thru preserving the sign */
5542 right = IC_RIGHT(ic);
5544 result = IC_RESULT(ic);
5546 aopOp(right,ic,FALSE);
5549 if ( AOP_TYPE(right) == AOP_LIT) {
5550 genRightShiftLiteral (left,right,result,ic,1);
5553 /* shift count is unknown then we have to form
5554 a loop get the loop count in B : Note: we take
5555 only the lower order byte since shifting
5556 more that 32 bits make no sense anyway, ( the
5557 largest size of an object can be only 32 bits ) */
5559 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5560 emitcode("inc","b");
5561 freeAsmop (right,NULL,ic,TRUE);
5562 aopOp(left,ic,FALSE);
5563 aopOp(result,ic,FALSE);
5565 /* now move the left to the result if they are not the
5567 if (!sameRegs(AOP(left),AOP(result)) &&
5568 AOP_SIZE(result) > 1) {
5570 size = AOP_SIZE(result);
5573 l = aopGet(AOP(left),offset,FALSE,TRUE);
5574 if (*l == '@' && IS_AOP_PREG(result)) {
5576 emitcode("mov","a,%s",l);
5577 aopPut(AOP(result),"a",offset);
5579 aopPut(AOP(result),l,offset);
5584 /* mov the highest order bit to OVR */
5585 tlbl = newiTempLabel(NULL);
5586 tlbl1= newiTempLabel(NULL);
5588 size = AOP_SIZE(result);
5590 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
5591 emitcode("rlc","a");
5592 emitcode("mov","ov,c");
5593 /* if it is only one byte then */
5595 l = aopGet(AOP(left),0,FALSE,FALSE);
5597 emitcode("sjmp","%05d$",tlbl1->key+100);
5598 emitcode("","%05d$:",tlbl->key+100);
5599 emitcode("mov","c,ov");
5600 emitcode("rrc","a");
5601 emitcode("","%05d$:",tlbl1->key+100);
5602 emitcode("djnz","b,%05d$",tlbl->key+100);
5603 aopPut(AOP(result),"a",0);
5607 reAdjustPreg(AOP(result));
5608 emitcode("sjmp","%05d$",tlbl1->key+100);
5609 emitcode("","%05d$:",tlbl->key+100);
5610 emitcode("mov","c,ov");
5612 l = aopGet(AOP(result),offset,FALSE,FALSE);
5614 emitcode("rrc","a");
5615 aopPut(AOP(result),"a",offset--);
5617 reAdjustPreg(AOP(result));
5618 emitcode("","%05d$:",tlbl1->key+100);
5619 emitcode("djnz","b,%05d$",tlbl->key+100);
5622 freeAsmop(left,NULL,ic,TRUE);
5623 freeAsmop(result,NULL,ic,TRUE);
5626 /*-----------------------------------------------------------------*/
5627 /* genRightShift - generate code for right shifting */
5628 /*-----------------------------------------------------------------*/
5629 static void genRightShift (iCode *ic)
5631 operand *right, *left, *result;
5635 symbol *tlbl, *tlbl1 ;
5637 /* if signed then we do it the hard way preserve the
5638 sign bit moving it inwards */
5639 retype = getSpec(operandType(IC_RESULT(ic)));
5641 if (!SPEC_USIGN(retype)) {
5642 genSignedRightShift (ic);
5646 /* signed & unsigned types are treated the same : i.e. the
5647 signed is NOT propagated inwards : quoting from the
5648 ANSI - standard : "for E1 >> E2, is equivalent to division
5649 by 2**E2 if unsigned or if it has a non-negative value,
5650 otherwise the result is implementation defined ", MY definition
5651 is that the sign does not get propagated */
5653 right = IC_RIGHT(ic);
5655 result = IC_RESULT(ic);
5657 aopOp(right,ic,FALSE);
5659 /* if the shift count is known then do it
5660 as efficiently as possible */
5661 if (AOP_TYPE(right) == AOP_LIT) {
5662 genRightShiftLiteral (left,right,result,ic, 0);
5666 /* shift count is unknown then we have to form
5667 a loop get the loop count in B : Note: we take
5668 only the lower order byte since shifting
5669 more that 32 bits make no sense anyway, ( the
5670 largest size of an object can be only 32 bits ) */
5672 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5673 emitcode("inc","b");
5674 freeAsmop (right,NULL,ic,TRUE);
5675 aopOp(left,ic,FALSE);
5676 aopOp(result,ic,FALSE);
5678 /* now move the left to the result if they are not the
5680 if (!sameRegs(AOP(left),AOP(result)) &&
5681 AOP_SIZE(result) > 1) {
5683 size = AOP_SIZE(result);
5686 l = aopGet(AOP(left),offset,FALSE,TRUE);
5687 if (*l == '@' && IS_AOP_PREG(result)) {
5689 emitcode("mov","a,%s",l);
5690 aopPut(AOP(result),"a",offset);
5692 aopPut(AOP(result),l,offset);
5697 tlbl = newiTempLabel(NULL);
5698 tlbl1= newiTempLabel(NULL);
5699 size = AOP_SIZE(result);
5702 /* if it is only one byte then */
5704 l = aopGet(AOP(left),0,FALSE,FALSE);
5706 emitcode("sjmp","%05d$",tlbl1->key+100);
5707 emitcode("","%05d$:",tlbl->key+100);
5709 emitcode("rrc","a");
5710 emitcode("","%05d$:",tlbl1->key+100);
5711 emitcode("djnz","b,%05d$",tlbl->key+100);
5712 aopPut(AOP(result),"a",0);
5716 reAdjustPreg(AOP(result));
5717 emitcode("sjmp","%05d$",tlbl1->key+100);
5718 emitcode("","%05d$:",tlbl->key+100);
5721 l = aopGet(AOP(result),offset,FALSE,FALSE);
5723 emitcode("rrc","a");
5724 aopPut(AOP(result),"a",offset--);
5726 reAdjustPreg(AOP(result));
5728 emitcode("","%05d$:",tlbl1->key+100);
5729 emitcode("djnz","b,%05d$",tlbl->key+100);
5732 freeAsmop(left,NULL,ic,TRUE);
5733 freeAsmop(result,NULL,ic,TRUE);
5736 /*-----------------------------------------------------------------*/
5737 /* genUnpackBits - generates code for unpacking bits */
5738 /*-----------------------------------------------------------------*/
5739 static void genUnpackBits (operand *result, char *rname, int ptype)
5746 etype = getSpec(operandType(result));
5748 /* read the first byte */
5753 emitcode("mov","a,@%s",rname);
5757 emitcode("movx","a,@%s",rname);
5761 emitcode("movx","a,@dptr");
5765 emitcode("clr","a");
5766 emitcode("movc","a","@a+dptr");
5770 emitcode("lcall","__gptrget");
5774 /* if we have bitdisplacement then it fits */
5775 /* into this byte completely or if length is */
5776 /* less than a byte */
5777 if ((shCnt = SPEC_BSTR(etype)) ||
5778 (SPEC_BLEN(etype) <= 8)) {
5780 /* shift right acc */
5783 emitcode("anl","a,#0x%02x",
5784 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
5785 aopPut(AOP(result),"a",offset);
5789 /* bit field did not fit in a byte */
5790 rlen = SPEC_BLEN(etype) - 8;
5791 aopPut(AOP(result),"a",offset++);
5798 emitcode("inc","%s",rname);
5799 emitcode("mov","a,@%s",rname);
5803 emitcode("inc","%s",rname);
5804 emitcode("movx","a,@%s",rname);
5808 emitcode("inc","dptr");
5809 emitcode("movx","a,@dptr");
5813 emitcode("clr","a");
5814 emitcode("inc","dptr");
5815 emitcode("movc","a","@a+dptr");
5819 emitcode("inc","dptr");
5820 emitcode("lcall","__gptrget");
5825 /* if we are done */
5829 aopPut(AOP(result),"a",offset++);
5834 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
5835 aopPut(AOP(result),"a",offset);
5842 /*-----------------------------------------------------------------*/
5843 /* genDataPointerGet - generates code when ptr offset is known */
5844 /*-----------------------------------------------------------------*/
5845 static void genDataPointerGet (operand *left,
5851 int size , offset = 0;
5852 aopOp(result,ic,TRUE);
5854 /* get the string representation of the name */
5855 l = aopGet(AOP(left),0,FALSE,TRUE);
5856 size = AOP_SIZE(result);
5859 sprintf(buffer,"(%s + %d)",l+1,offset);
5861 sprintf(buffer,"%s",l+1);
5862 aopPut(AOP(result),buffer,offset++);
5865 freeAsmop(left,NULL,ic,TRUE);
5866 freeAsmop(result,NULL,ic,TRUE);
5869 /*-----------------------------------------------------------------*/
5870 /* genNearPointerGet - emitcode for near pointer fetch */
5871 /*-----------------------------------------------------------------*/
5872 static void genNearPointerGet (operand *left,
5879 link *rtype, *retype;
5880 link *ltype = operandType(left);
5883 rtype = operandType(result);
5884 retype= getSpec(rtype);
5886 aopOp(left,ic,FALSE);
5888 /* if left is rematerialisable and
5889 result is not bit variable type and
5890 the left is pointer to data space i.e
5891 lower 128 bytes of space */
5892 if (AOP_TYPE(left) == AOP_IMMD &&
5893 !IS_BITVAR(retype) &&
5894 DCL_TYPE(ltype) == POINTER) {
5895 genDataPointerGet (left,result,ic);
5899 /* if the value is already in a pointer register
5900 then don't need anything more */
5901 if (!AOP_INPREG(AOP(left))) {
5902 /* otherwise get a free pointer register */
5904 preg = getFreePtr(ic,&aop,FALSE);
5905 emitcode("mov","%s,%s",
5907 aopGet(AOP(left),0,FALSE,TRUE));
5908 rname = preg->name ;
5910 rname = aopGet(AOP(left),0,FALSE,FALSE);
5912 freeAsmop(left,NULL,ic,TRUE);
5913 aopOp (result,ic,FALSE);
5915 /* if bitfield then unpack the bits */
5916 if (IS_BITVAR(retype))
5917 genUnpackBits (result,rname,POINTER);
5919 /* we have can just get the values */
5920 int size = AOP_SIZE(result);
5924 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
5926 emitcode("mov","a,@%s",rname);
5927 aopPut(AOP(result),"a",offset);
5929 sprintf(buffer,"@%s",rname);
5930 aopPut(AOP(result),buffer,offset);
5934 emitcode("inc","%s",rname);
5938 /* now some housekeeping stuff */
5940 /* we had to allocate for this iCode */
5941 freeAsmop(NULL,aop,ic,TRUE);
5943 /* we did not allocate which means left
5944 already in a pointer register, then
5945 if size > 0 && this could be used again
5946 we have to point it back to where it
5948 if (AOP_SIZE(result) > 1 &&
5949 !OP_SYMBOL(left)->remat &&
5950 ( OP_SYMBOL(left)->liveTo > ic->seq ||
5952 int size = AOP_SIZE(result) - 1;
5954 emitcode("dec","%s",rname);
5959 freeAsmop(result,NULL,ic,TRUE);
5963 /*-----------------------------------------------------------------*/
5964 /* genPagedPointerGet - emitcode for paged pointer fetch */
5965 /*-----------------------------------------------------------------*/
5966 static void genPagedPointerGet (operand *left,
5973 link *rtype, *retype;
5975 rtype = operandType(result);
5976 retype= getSpec(rtype);
5978 aopOp(left,ic,FALSE);
5980 /* if the value is already in a pointer register
5981 then don't need anything more */
5982 if (!AOP_INPREG(AOP(left))) {
5983 /* otherwise get a free pointer register */
5985 preg = getFreePtr(ic,&aop,FALSE);
5986 emitcode("mov","%s,%s",
5988 aopGet(AOP(left),0,FALSE,TRUE));
5989 rname = preg->name ;
5991 rname = aopGet(AOP(left),0,FALSE,FALSE);
5993 freeAsmop(left,NULL,ic,TRUE);
5994 aopOp (result,ic,FALSE);
5996 /* if bitfield then unpack the bits */
5997 if (IS_BITVAR(retype))
5998 genUnpackBits (result,rname,PPOINTER);
6000 /* we have can just get the values */
6001 int size = AOP_SIZE(result);
6006 emitcode("movx","a,@%s",rname);
6007 aopPut(AOP(result),"a",offset);
6012 emitcode("inc","%s",rname);
6016 /* now some housekeeping stuff */
6018 /* we had to allocate for this iCode */
6019 freeAsmop(NULL,aop,ic,TRUE);
6021 /* we did not allocate which means left
6022 already in a pointer register, then
6023 if size > 0 && this could be used again
6024 we have to point it back to where it
6026 if (AOP_SIZE(result) > 1 &&
6027 !OP_SYMBOL(left)->remat &&
6028 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6030 int size = AOP_SIZE(result) - 1;
6032 emitcode("dec","%s",rname);
6037 freeAsmop(result,NULL,ic,TRUE);
6042 /*-----------------------------------------------------------------*/
6043 /* genFarPointerGet - gget value from far space */
6044 /*-----------------------------------------------------------------*/
6045 static void genFarPointerGet (operand *left,
6046 operand *result, iCode *ic)
6049 link *retype = getSpec(operandType(result));
6051 aopOp(left,ic,FALSE);
6053 /* if the operand is already in dptr
6054 then we do nothing else we move the value to dptr */
6055 if (AOP_TYPE(left) != AOP_STR) {
6056 /* if this is remateriazable */
6057 if (AOP_TYPE(left) == AOP_IMMD)
6058 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6059 else { /* we need to get it byte by byte */
6060 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6061 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6062 if (options.model == MODEL_FLAT24)
6064 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6068 /* so dptr know contains the address */
6069 freeAsmop(left,NULL,ic,TRUE);
6070 aopOp(result,ic,FALSE);
6072 /* if bit then unpack */
6073 if (IS_BITVAR(retype))
6074 genUnpackBits(result,"dptr",FPOINTER);
6076 size = AOP_SIZE(result);
6080 emitcode("movx","a,@dptr");
6081 aopPut(AOP(result),"a",offset++);
6083 emitcode("inc","dptr");
6087 freeAsmop(result,NULL,ic,TRUE);
6090 /*-----------------------------------------------------------------*/
6091 /* emitcodePointerGet - gget value from code space */
6092 /*-----------------------------------------------------------------*/
6093 static void emitcodePointerGet (operand *left,
6094 operand *result, iCode *ic)
6097 link *retype = getSpec(operandType(result));
6099 aopOp(left,ic,FALSE);
6101 /* if the operand is already in dptr
6102 then we do nothing else we move the value to dptr */
6103 if (AOP_TYPE(left) != AOP_STR) {
6104 /* if this is remateriazable */
6105 if (AOP_TYPE(left) == AOP_IMMD)
6106 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6107 else { /* we need to get it byte by byte */
6108 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6109 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6110 if (options.model == MODEL_FLAT24)
6112 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6116 /* so dptr know contains the address */
6117 freeAsmop(left,NULL,ic,TRUE);
6118 aopOp(result,ic,FALSE);
6120 /* if bit then unpack */
6121 if (IS_BITVAR(retype))
6122 genUnpackBits(result,"dptr",CPOINTER);
6124 size = AOP_SIZE(result);
6128 emitcode("clr","a");
6129 emitcode("movc","a,@a+dptr");
6130 aopPut(AOP(result),"a",offset++);
6132 emitcode("inc","dptr");
6136 freeAsmop(result,NULL,ic,TRUE);
6139 /*-----------------------------------------------------------------*/
6140 /* genGenPointerGet - gget value from generic pointer space */
6141 /*-----------------------------------------------------------------*/
6142 static void genGenPointerGet (operand *left,
6143 operand *result, iCode *ic)
6146 link *retype = getSpec(operandType(result));
6148 aopOp(left,ic,FALSE);
6150 /* if the operand is already in dptr
6151 then we do nothing else we move the value to dptr */
6152 if (AOP_TYPE(left) != AOP_STR) {
6153 /* if this is remateriazable */
6154 if (AOP_TYPE(left) == AOP_IMMD) {
6155 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6156 emitcode("mov","b,#%d",pointerCode(retype));
6158 else { /* we need to get it byte by byte */
6159 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6160 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6161 if (options.model == MODEL_FLAT24)
6163 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6164 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
6168 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
6172 /* so dptr know contains the address */
6173 freeAsmop(left,NULL,ic,TRUE);
6174 aopOp(result,ic,FALSE);
6176 /* if bit then unpack */
6177 if (IS_BITVAR(retype))
6178 genUnpackBits(result,"dptr",GPOINTER);
6180 size = AOP_SIZE(result);
6184 emitcode("lcall","__gptrget");
6185 aopPut(AOP(result),"a",offset++);
6187 emitcode("inc","dptr");
6191 freeAsmop(result,NULL,ic,TRUE);
6194 /*-----------------------------------------------------------------*/
6195 /* genPointerGet - generate code for pointer get */
6196 /*-----------------------------------------------------------------*/
6197 static void genPointerGet (iCode *ic)
6199 operand *left, *result ;
6204 result = IC_RESULT(ic) ;
6206 /* depending on the type of pointer we need to
6207 move it to the correct pointer register */
6208 type = operandType(left);
6209 etype = getSpec(type);
6210 /* if left is of type of pointer then it is simple */
6211 if (IS_PTR(type) && !IS_FUNC(type->next))
6212 p_type = DCL_TYPE(type);
6214 /* we have to go by the storage class */
6215 p_type = PTR_TYPE(SPEC_OCLS(etype));
6217 /* if (SPEC_OCLS(etype)->codesp ) { */
6218 /* p_type = CPOINTER ; */
6221 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6222 /* p_type = FPOINTER ; */
6224 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6225 /* p_type = PPOINTER; */
6227 /* if (SPEC_OCLS(etype) == idata ) */
6228 /* p_type = IPOINTER; */
6230 /* p_type = POINTER ; */
6233 /* now that we have the pointer type we assign
6234 the pointer values */
6239 genNearPointerGet (left,result,ic);
6243 genPagedPointerGet(left,result,ic);
6247 genFarPointerGet (left,result,ic);
6251 emitcodePointerGet (left,result,ic);
6255 genGenPointerGet (left,result,ic);
6261 /*-----------------------------------------------------------------*/
6262 /* genPackBits - generates code for packed bit storage */
6263 /*-----------------------------------------------------------------*/
6264 static void genPackBits (link *etype ,
6266 char *rname, int p_type)
6274 blen = SPEC_BLEN(etype);
6275 bstr = SPEC_BSTR(etype);
6277 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6280 /* if the bit lenth is less than or */
6281 /* it exactly fits a byte then */
6282 if (SPEC_BLEN(etype) <= 8 ) {
6283 shCount = SPEC_BSTR(etype) ;
6285 /* shift left acc */
6288 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6293 emitcode ("mov","b,a");
6294 emitcode("mov","a,@%s",rname);
6298 emitcode ("mov","b,a");
6299 emitcode("movx","a,@dptr");
6303 emitcode ("push","b");
6304 emitcode ("push","acc");
6305 emitcode ("lcall","__gptrget");
6306 emitcode ("pop","b");
6310 emitcode ("anl","a,#0x%02x",(unsigned char)
6311 ((unsigned char)(0xFF << (blen+bstr)) |
6312 (unsigned char)(0xFF >> (8-bstr)) ) );
6313 emitcode ("orl","a,b");
6314 if (p_type == GPOINTER)
6315 emitcode("pop","b");
6321 emitcode("mov","@%s,a",rname);
6325 emitcode("movx","@dptr,a");
6329 emitcode("lcall","__gptrput");
6334 if ( SPEC_BLEN(etype) <= 8 )
6337 emitcode("inc","%s",rname);
6338 rLen = SPEC_BLEN(etype) ;
6340 /* now generate for lengths greater than one byte */
6343 l = aopGet(AOP(right),offset++,FALSE,TRUE);
6353 emitcode("mov","@%s,a",rname);
6355 emitcode("mov","@%s,%s",rname,l);
6360 emitcode("movx","@dptr,a");
6365 emitcode("lcall","__gptrput");
6368 emitcode ("inc","%s",rname);
6373 /* last last was not complete */
6375 /* save the byte & read byte */
6378 emitcode ("mov","b,a");
6379 emitcode("mov","a,@%s",rname);
6383 emitcode ("mov","b,a");
6384 emitcode("movx","a,@dptr");
6388 emitcode ("push","b");
6389 emitcode ("push","acc");
6390 emitcode ("lcall","__gptrget");
6391 emitcode ("pop","b");
6395 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
6396 emitcode ("orl","a,b");
6399 if (p_type == GPOINTER)
6400 emitcode("pop","b");
6405 emitcode("mov","@%s,a",rname);
6409 emitcode("movx","@dptr,a");
6413 emitcode("lcall","__gptrput");
6417 /*-----------------------------------------------------------------*/
6418 /* genDataPointerSet - remat pointer to data space */
6419 /*-----------------------------------------------------------------*/
6420 static void genDataPointerSet(operand *right,
6424 int size, offset = 0 ;
6425 char *l, buffer[256];
6427 aopOp(right,ic,FALSE);
6429 l = aopGet(AOP(result),0,FALSE,TRUE);
6430 size = AOP_SIZE(right);
6433 sprintf(buffer,"(%s + %d)",l+1,offset);
6435 sprintf(buffer,"%s",l+1);
6436 emitcode("mov","%s,%s",buffer,
6437 aopGet(AOP(right),offset++,FALSE,FALSE));
6440 freeAsmop(right,NULL,ic,TRUE);
6441 freeAsmop(result,NULL,ic,TRUE);
6444 /*-----------------------------------------------------------------*/
6445 /* genNearPointerSet - emitcode for near pointer put */
6446 /*-----------------------------------------------------------------*/
6447 static void genNearPointerSet (operand *right,
6455 link *ptype = operandType(result);
6457 retype= getSpec(operandType(right));
6459 aopOp(result,ic,FALSE);
6461 /* if the result is rematerializable &
6462 in data space & not a bit variable */
6463 if (AOP_TYPE(result) == AOP_IMMD &&
6464 DCL_TYPE(ptype) == POINTER &&
6465 !IS_BITVAR(retype)) {
6466 genDataPointerSet (right,result,ic);
6470 /* if the value is already in a pointer register
6471 then don't need anything more */
6472 if (!AOP_INPREG(AOP(result))) {
6473 /* otherwise get a free pointer register */
6475 preg = getFreePtr(ic,&aop,FALSE);
6476 emitcode("mov","%s,%s",
6478 aopGet(AOP(result),0,FALSE,TRUE));
6479 rname = preg->name ;
6481 rname = aopGet(AOP(result),0,FALSE,FALSE);
6483 freeAsmop(result,NULL,ic,TRUE);
6484 aopOp (right,ic,FALSE);
6486 /* if bitfield then unpack the bits */
6487 if (IS_BITVAR(retype))
6488 genPackBits (retype,right,rname,POINTER);
6490 /* we have can just get the values */
6491 int size = AOP_SIZE(right);
6495 l = aopGet(AOP(right),offset,FALSE,TRUE);
6498 emitcode("mov","@%s,a",rname);
6500 emitcode("mov","@%s,%s",rname,l);
6502 emitcode("inc","%s",rname);
6507 /* now some housekeeping stuff */
6509 /* we had to allocate for this iCode */
6510 freeAsmop(NULL,aop,ic,TRUE);
6512 /* we did not allocate which means left
6513 already in a pointer register, then
6514 if size > 0 && this could be used again
6515 we have to point it back to where it
6517 if (AOP_SIZE(right) > 1 &&
6518 !OP_SYMBOL(result)->remat &&
6519 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6521 int size = AOP_SIZE(right) - 1;
6523 emitcode("dec","%s",rname);
6528 freeAsmop(right,NULL,ic,TRUE);
6533 /*-----------------------------------------------------------------*/
6534 /* genPagedPointerSet - emitcode for Paged pointer put */
6535 /*-----------------------------------------------------------------*/
6536 static void genPagedPointerSet (operand *right,
6545 retype= getSpec(operandType(right));
6547 aopOp(result,ic,FALSE);
6549 /* if the value is already in a pointer register
6550 then don't need anything more */
6551 if (!AOP_INPREG(AOP(result))) {
6552 /* otherwise get a free pointer register */
6554 preg = getFreePtr(ic,&aop,FALSE);
6555 emitcode("mov","%s,%s",
6557 aopGet(AOP(result),0,FALSE,TRUE));
6558 rname = preg->name ;
6560 rname = aopGet(AOP(result),0,FALSE,FALSE);
6562 freeAsmop(result,NULL,ic,TRUE);
6563 aopOp (right,ic,FALSE);
6565 /* if bitfield then unpack the bits */
6566 if (IS_BITVAR(retype))
6567 genPackBits (retype,right,rname,PPOINTER);
6569 /* we have can just get the values */
6570 int size = AOP_SIZE(right);
6574 l = aopGet(AOP(right),offset,FALSE,TRUE);
6577 emitcode("movx","@%s,a",rname);
6580 emitcode("inc","%s",rname);
6586 /* now some housekeeping stuff */
6588 /* we had to allocate for this iCode */
6589 freeAsmop(NULL,aop,ic,TRUE);
6591 /* we did not allocate which means left
6592 already in a pointer register, then
6593 if size > 0 && this could be used again
6594 we have to point it back to where it
6596 if (AOP_SIZE(right) > 1 &&
6597 !OP_SYMBOL(result)->remat &&
6598 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6600 int size = AOP_SIZE(right) - 1;
6602 emitcode("dec","%s",rname);
6607 freeAsmop(right,NULL,ic,TRUE);
6612 /*-----------------------------------------------------------------*/
6613 /* genFarPointerSet - set value from far space */
6614 /*-----------------------------------------------------------------*/
6615 static void genFarPointerSet (operand *right,
6616 operand *result, iCode *ic)
6619 link *retype = getSpec(operandType(right));
6621 aopOp(result,ic,FALSE);
6623 /* if the operand is already in dptr
6624 then we do nothing else we move the value to dptr */
6625 if (AOP_TYPE(result) != AOP_STR) {
6626 /* if this is remateriazable */
6627 if (AOP_TYPE(result) == AOP_IMMD)
6628 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6629 else { /* we need to get it byte by byte */
6630 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6631 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6632 if (options.model == MODEL_FLAT24)
6634 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6638 /* so dptr know contains the address */
6639 freeAsmop(result,NULL,ic,TRUE);
6640 aopOp(right,ic,FALSE);
6642 /* if bit then unpack */
6643 if (IS_BITVAR(retype))
6644 genPackBits(retype,right,"dptr",FPOINTER);
6646 size = AOP_SIZE(right);
6650 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6652 emitcode("movx","@dptr,a");
6654 emitcode("inc","dptr");
6658 freeAsmop(right,NULL,ic,TRUE);
6661 /*-----------------------------------------------------------------*/
6662 /* genGenPointerSet - set value from generic pointer space */
6663 /*-----------------------------------------------------------------*/
6664 static void genGenPointerSet (operand *right,
6665 operand *result, iCode *ic)
6668 link *retype = getSpec(operandType(right));
6670 aopOp(result,ic,FALSE);
6672 /* if the operand is already in dptr
6673 then we do nothing else we move the value to dptr */
6674 if (AOP_TYPE(result) != AOP_STR) {
6675 /* if this is remateriazable */
6676 if (AOP_TYPE(result) == AOP_IMMD) {
6677 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6678 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
6680 else { /* we need to get it byte by byte */
6681 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6682 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6683 if (options.model == MODEL_FLAT24)
6685 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6686 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
6690 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
6694 /* so dptr know contains the address */
6695 freeAsmop(result,NULL,ic,TRUE);
6696 aopOp(right,ic,FALSE);
6698 /* if bit then unpack */
6699 if (IS_BITVAR(retype))
6700 genPackBits(retype,right,"dptr",GPOINTER);
6702 size = AOP_SIZE(right);
6706 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6708 emitcode("lcall","__gptrput");
6710 emitcode("inc","dptr");
6714 freeAsmop(right,NULL,ic,TRUE);
6717 /*-----------------------------------------------------------------*/
6718 /* genPointerSet - stores the value into a pointer location */
6719 /*-----------------------------------------------------------------*/
6720 static void genPointerSet (iCode *ic)
6722 operand *right, *result ;
6726 right = IC_RIGHT(ic);
6727 result = IC_RESULT(ic) ;
6729 /* depending on the type of pointer we need to
6730 move it to the correct pointer register */
6731 type = operandType(result);
6732 etype = getSpec(type);
6733 /* if left is of type of pointer then it is simple */
6734 if (IS_PTR(type) && !IS_FUNC(type->next)) {
6735 p_type = DCL_TYPE(type);
6738 /* we have to go by the storage class */
6739 p_type = PTR_TYPE(SPEC_OCLS(etype));
6741 /* if (SPEC_OCLS(etype)->codesp ) { */
6742 /* p_type = CPOINTER ; */
6745 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6746 /* p_type = FPOINTER ; */
6748 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6749 /* p_type = PPOINTER ; */
6751 /* if (SPEC_OCLS(etype) == idata ) */
6752 /* p_type = IPOINTER ; */
6754 /* p_type = POINTER ; */
6757 /* now that we have the pointer type we assign
6758 the pointer values */
6763 genNearPointerSet (right,result,ic);
6767 genPagedPointerSet (right,result,ic);
6771 genFarPointerSet (right,result,ic);
6775 genGenPointerSet (right,result,ic);
6781 /*-----------------------------------------------------------------*/
6782 /* genIfx - generate code for Ifx statement */
6783 /*-----------------------------------------------------------------*/
6784 static void genIfx (iCode *ic, iCode *popIc)
6786 operand *cond = IC_COND(ic);
6789 aopOp(cond,ic,FALSE);
6791 /* get the value into acc */
6792 if (AOP_TYPE(cond) != AOP_CRY)
6796 /* the result is now in the accumulator */
6797 freeAsmop(cond,NULL,ic,TRUE);
6799 /* if there was something to be popped then do it */
6803 /* if the condition is a bit variable */
6804 if (isbit && IS_ITEMP(cond) &&
6806 genIfxJump(ic,SPIL_LOC(cond)->rname);
6808 if (isbit && !IS_ITEMP(cond))
6809 genIfxJump(ic,OP_SYMBOL(cond)->rname);
6816 /*-----------------------------------------------------------------*/
6817 /* genAddrOf - generates code for address of */
6818 /*-----------------------------------------------------------------*/
6819 static void genAddrOf (iCode *ic)
6821 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
6824 aopOp(IC_RESULT(ic),ic,FALSE);
6826 /* if the operand is on the stack then we
6827 need to get the stack offset of this
6830 /* if it has an offset then we need to compute
6833 emitcode("mov","a,_bp");
6834 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
6835 aopPut(AOP(IC_RESULT(ic)),"a",0);
6837 /* we can just move _bp */
6838 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
6839 /* fill the result with zero */
6840 size = AOP_SIZE(IC_RESULT(ic)) - 1;
6843 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
6848 /* object not on stack then we need the name */
6849 size = AOP_SIZE(IC_RESULT(ic));
6853 char s[SDCC_NAME_MAX];
6855 sprintf(s,"#(%s >> %d)",
6859 sprintf(s,"#%s",sym->rname);
6860 aopPut(AOP(IC_RESULT(ic)),s,offset++);
6864 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
6868 /*-----------------------------------------------------------------*/
6869 /* genFarFarAssign - assignment when both are in far space */
6870 /*-----------------------------------------------------------------*/
6871 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
6873 int size = AOP_SIZE(right);
6876 /* first push the right side on to the stack */
6878 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6880 emitcode ("push","acc");
6883 freeAsmop(right,NULL,ic,FALSE);
6884 /* now assign DPTR to result */
6885 aopOp(result,ic,FALSE);
6886 size = AOP_SIZE(result);
6888 emitcode ("pop","acc");
6889 aopPut(AOP(result),"a",--offset);
6891 freeAsmop(result,NULL,ic,FALSE);
6895 /*-----------------------------------------------------------------*/
6896 /* genAssign - generate code for assignment */
6897 /*-----------------------------------------------------------------*/
6898 static void genAssign (iCode *ic)
6900 operand *result, *right;
6902 unsigned long lit = 0L;
6904 result = IC_RESULT(ic);
6905 right = IC_RIGHT(ic) ;
6907 /* if they are the same */
6908 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
6911 aopOp(right,ic,FALSE);
6913 /* special case both in far space */
6914 if (AOP_TYPE(right) == AOP_DPTR &&
6915 IS_TRUE_SYMOP(result) &&
6916 isOperandInFarSpace(result)) {
6918 genFarFarAssign (result,right,ic);
6922 aopOp(result,ic,TRUE);
6924 /* if they are the same registers */
6925 if (sameRegs(AOP(right),AOP(result)))
6928 /* if the result is a bit */
6929 if (AOP_TYPE(result) == AOP_CRY) {
6931 /* if the right size is a literal then
6932 we know what the value is */
6933 if (AOP_TYPE(right) == AOP_LIT) {
6934 if (((int) operandLitValue(right)))
6935 aopPut(AOP(result),one,0);
6937 aopPut(AOP(result),zero,0);
6941 /* the right is also a bit variable */
6942 if (AOP_TYPE(right) == AOP_CRY) {
6943 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6944 aopPut(AOP(result),"c",0);
6950 aopPut(AOP(result),"a",0);
6954 /* bit variables done */
6956 size = AOP_SIZE(result);
6958 if(AOP_TYPE(right) == AOP_LIT)
6959 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6961 (AOP_TYPE(result) != AOP_REG) &&
6962 (AOP_TYPE(right) == AOP_LIT) &&
6963 !IS_FLOAT(operandType(right)) &&
6965 emitcode("clr","a");
6967 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
6968 aopPut(AOP(result),"a",size);
6971 aopGet(AOP(right),size,FALSE,FALSE),
6977 aopGet(AOP(right),offset,FALSE,FALSE),
6984 freeAsmop (right,NULL,ic,FALSE);
6985 freeAsmop (result,NULL,ic,TRUE);
6988 /*-----------------------------------------------------------------*/
6989 /* genJumpTab - genrates code for jump table */
6990 /*-----------------------------------------------------------------*/
6991 static void genJumpTab (iCode *ic)
6996 aopOp(IC_JTCOND(ic),ic,FALSE);
6997 /* get the condition into accumulator */
6998 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
7000 /* multiply by three */
7001 emitcode("add","a,acc");
7002 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
7003 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7005 jtab = newiTempLabel(NULL);
7006 emitcode("mov","dptr,#%05d$",jtab->key+100);
7007 emitcode("jmp","@a+dptr");
7008 emitcode("","%05d$:",jtab->key+100);
7009 /* now generate the jump labels */
7010 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
7011 jtab = setNextItem(IC_JTLABELS(ic)))
7012 emitcode("ljmp","%05d$",jtab->key+100);
7016 /*-----------------------------------------------------------------*/
7017 /* genCast - gen code for casting */
7018 /*-----------------------------------------------------------------*/
7019 static void genCast (iCode *ic)
7021 operand *result = IC_RESULT(ic);
7022 link *ctype = operandType(IC_LEFT(ic));
7023 operand *right = IC_RIGHT(ic);
7026 /* if they are equivalent then do nothing */
7027 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
7030 aopOp(right,ic,FALSE) ;
7031 aopOp(result,ic,FALSE);
7033 /* if the result is a bit */
7034 if (AOP_TYPE(result) == AOP_CRY) {
7035 /* if the right size is a literal then
7036 we know what the value is */
7037 if (AOP_TYPE(right) == AOP_LIT) {
7038 if (((int) operandLitValue(right)))
7039 aopPut(AOP(result),one,0);
7041 aopPut(AOP(result),zero,0);
7046 /* the right is also a bit variable */
7047 if (AOP_TYPE(right) == AOP_CRY) {
7048 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7049 aopPut(AOP(result),"c",0);
7055 aopPut(AOP(result),"a",0);
7059 /* if they are the same size : or less */
7060 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
7062 /* if they are in the same place */
7063 if (sameRegs(AOP(right),AOP(result)))
7066 /* if they in different places then copy */
7067 size = AOP_SIZE(result);
7071 aopGet(AOP(right),offset,FALSE,FALSE),
7079 /* if the result is of type pointer */
7080 if (IS_PTR(ctype)) {
7083 link *type = operandType(right);
7084 link *etype = getSpec(type);
7086 /* pointer to generic pointer */
7087 if (IS_GENPTR(ctype)) {
7091 p_type = DCL_TYPE(type);
7093 /* we have to go by the storage class */
7094 p_type = PTR_TYPE(SPEC_OCLS(etype));
7096 /* if (SPEC_OCLS(etype)->codesp ) */
7097 /* p_type = CPOINTER ; */
7099 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7100 /* p_type = FPOINTER ; */
7102 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7103 /* p_type = PPOINTER; */
7105 /* if (SPEC_OCLS(etype) == idata ) */
7106 /* p_type = IPOINTER ; */
7108 /* p_type = POINTER ; */
7111 /* the first two bytes are known */
7112 size = GPTRSIZE - 1;
7116 aopGet(AOP(right),offset,FALSE,FALSE),
7120 /* the last byte depending on type */
7137 /* this should never happen */
7138 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7139 "got unknown pointer type");
7142 aopPut(AOP(result),l, GPTRSIZE - 1);
7146 /* just copy the pointers */
7147 size = AOP_SIZE(result);
7151 aopGet(AOP(right),offset,FALSE,FALSE),
7158 /* so we now know that the size of destination is greater
7159 than the size of the source */
7160 /* we move to result for the size of source */
7161 size = AOP_SIZE(right);
7165 aopGet(AOP(right),offset,FALSE,FALSE),
7170 /* now depending on the sign of the destination */
7171 size = AOP_SIZE(result) - AOP_SIZE(right);
7172 /* if unsigned or not an integral type */
7173 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
7175 aopPut(AOP(result),zero,offset++);
7177 /* we need to extend the sign :{ */
7178 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
7181 emitcode("rlc","a");
7182 emitcode("subb","a,acc");
7184 aopPut(AOP(result),"a",offset++);
7187 /* we are done hurray !!!! */
7190 freeAsmop(right,NULL,ic,TRUE);
7191 freeAsmop(result,NULL,ic,TRUE);
7195 /*-----------------------------------------------------------------*/
7196 /* genDjnz - generate decrement & jump if not zero instrucion */
7197 /*-----------------------------------------------------------------*/
7198 static int genDjnz (iCode *ic, iCode *ifx)
7204 /* if the if condition has a false label
7205 then we cannot save */
7209 /* if the minus is not of the form
7211 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
7212 !IS_OP_LITERAL(IC_RIGHT(ic)))
7215 if (operandLitValue(IC_RIGHT(ic)) != 1)
7218 /* if the size of this greater than one then no
7220 if (getSize(operandType(IC_RESULT(ic))) > 1)
7223 /* otherwise we can save BIG */
7224 lbl = newiTempLabel(NULL);
7225 lbl1= newiTempLabel(NULL);
7227 aopOp(IC_RESULT(ic),ic,FALSE);
7229 if (IS_AOP_PREG(IC_RESULT(ic))) {
7230 emitcode("dec","%s",
7231 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7232 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7233 emitcode("jnz","%05d$",lbl->key+100);
7235 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
7238 emitcode ("sjmp","%05d$",lbl1->key+100);
7239 emitcode ("","%05d$:",lbl->key+100);
7240 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
7241 emitcode ("","%05d$:",lbl1->key+100);
7243 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7248 /*-----------------------------------------------------------------*/
7249 /* genReceive - generate code for a receive iCode */
7250 /*-----------------------------------------------------------------*/
7251 static void genReceive (iCode *ic)
7253 if (isOperandInFarSpace(IC_RESULT(ic)) &&
7254 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
7255 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
7257 int size = getSize(operandType(IC_RESULT(ic)));
7258 int offset = fReturnSize - size;
7260 emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
7261 fReturn[fReturnSize - offset - 1] : "acc"));
7264 aopOp(IC_RESULT(ic),ic,FALSE);
7265 size = AOP_SIZE(IC_RESULT(ic));
7268 emitcode ("pop","acc");
7269 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
7274 aopOp(IC_RESULT(ic),ic,FALSE);
7276 assignResultValue(IC_RESULT(ic));
7279 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7282 /*-----------------------------------------------------------------*/
7283 /* gen51Code - generate code for 8051 based controllers */
7284 /*-----------------------------------------------------------------*/
7285 void gen51Code (iCode *lic)
7290 /* Hack-o-matic: change fReturn based on model. */
7291 if (options.model == MODEL_FLAT24)
7293 fReturn = fReturn390;
7297 lineHead = lineCurr = NULL;
7299 /* if debug information required */
7300 /* if (options.debug && currFunc) { */
7302 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
7304 if (IS_STATIC(currFunc->etype))
7305 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
7307 emitcode("","G$%s$0$0 ==.",currFunc->name);
7310 /* stack pointer name */
7311 if (options.useXstack)
7317 for (ic = lic ; ic ; ic = ic->next ) {
7319 if ( cln != ic->lineno ) {
7320 if ( options.debug ) {
7322 emitcode("","C$%s$%d$%d$%d ==.",
7323 ic->filename,ic->lineno,
7324 ic->level,ic->block);
7327 emitcode(";","%s %d",ic->filename,ic->lineno);
7330 /* if the result is marked as
7331 spilt and rematerializable or code for
7332 this has already been generated then
7334 if (resultRemat(ic) || ic->generated )
7337 /* depending on the operation */
7356 /* IPOP happens only when trying to restore a
7357 spilt live range, if there is an ifx statement
7358 following this pop then the if statement might
7359 be using some of the registers being popped which
7360 would destory the contents of the register so
7361 we need to check for this condition and handle it */
7363 ic->next->op == IFX &&
7364 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
7365 genIfx (ic->next,ic);
7383 genEndFunction (ic);
7403 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
7420 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
7424 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
7431 /* note these two are xlated by algebraic equivalence
7432 during parsing SDCC.y */
7433 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7434 "got '>=' or '<=' shouldn't have come here");
7438 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
7450 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
7454 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
7458 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
7485 case GET_VALUE_AT_ADDRESS:
7490 if (POINTER_SET(ic))
7517 addSet(&_G.sendSet,ic);
7522 /* piCode(ic,stdout); */
7528 /* now we are ready to call the
7529 peep hole optimizer */
7530 if (!options.nopeep)
7531 peepHole (&lineHead);
7533 /* now do the actual printing */
7534 printLine (lineHead,codeOutFile);