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 /* genPlusIncr :- does addition with increment if possible */
2253 /*-----------------------------------------------------------------*/
2254 static bool genPlusIncr (iCode *ic)
2256 unsigned int icount ;
2257 unsigned int size = getDataSize(IC_RESULT(ic));
2259 /* will try to generate an increment */
2260 /* if the right side is not a literal
2262 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2265 /* if the literal value of the right hand side
2266 is greater than 4 then it is not worth it */
2267 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2270 /* if increment 16 bits in register */
2271 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2274 symbol *tlbl = newiTempLabel(NULL);
2275 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2276 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2277 IS_AOP_PREG(IC_RESULT(ic)))
2278 emitcode("cjne","%s,#0x00,%05d$"
2279 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2282 emitcode("clr","a");
2283 emitcode("cjne","a,%s,%05d$"
2284 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2288 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2291 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2292 IS_AOP_PREG(IC_RESULT(ic)))
2293 emitcode("cjne","%s,#0x00,%05d$"
2294 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2297 emitcode("cjne","a,%s,%05d$"
2298 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2301 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2305 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2306 IS_AOP_PREG(IC_RESULT(ic)))
2307 emitcode("cjne","%s,#0x00,%05d$"
2308 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2311 emitcode("cjne","a,%s,%05d$"
2312 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2315 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2317 emitcode("","%05d$:",tlbl->key+100);
2321 /* if the sizes are greater than 1 then we cannot */
2322 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2323 AOP_SIZE(IC_LEFT(ic)) > 1 )
2326 /* we can if the aops of the left & result match or
2327 if they are in registers and the registers are the
2329 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2332 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2333 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2334 aopPut(AOP(IC_RESULT(ic)),"a",0);
2338 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2347 /*-----------------------------------------------------------------*/
2348 /* outBitAcc - output a bit in acc */
2349 /*-----------------------------------------------------------------*/
2350 static void outBitAcc(operand *result)
2352 symbol *tlbl = newiTempLabel(NULL);
2353 /* if the result is a bit */
2354 if (AOP_TYPE(result) == AOP_CRY){
2355 aopPut(AOP(result),"a",0);
2358 emitcode("jz","%05d$",tlbl->key+100);
2359 emitcode("mov","a,%s",one);
2360 emitcode("","%05d$:",tlbl->key+100);
2365 /*-----------------------------------------------------------------*/
2366 /* genPlusBits - generates code for addition of two bits */
2367 /*-----------------------------------------------------------------*/
2368 static void genPlusBits (iCode *ic)
2370 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2371 symbol *lbl = newiTempLabel(NULL);
2372 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2373 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2374 emitcode("cpl","c");
2375 emitcode("","%05d$:",(lbl->key+100));
2376 outBitC(IC_RESULT(ic));
2379 emitcode("clr","a");
2380 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2381 emitcode("rlc","a");
2382 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2383 emitcode("addc","a,#0x00");
2384 outAcc(IC_RESULT(ic));
2389 /* This is the original version of this code.
2391 * This is being kept around for reference,
2392 * because I am not entirely sure I got it right...
2394 static void adjustArithmeticResult(iCode *ic)
2396 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2397 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2398 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2399 aopPut(AOP(IC_RESULT(ic)),
2400 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2403 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2404 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
2405 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2406 aopPut(AOP(IC_RESULT(ic)),
2407 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2410 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2411 AOP_SIZE(IC_LEFT(ic)) < 3 &&
2412 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
2413 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2414 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2416 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2417 aopPut(AOP(IC_RESULT(ic)),buffer,2);
2421 /* This is the pure and virtuous version of this code.
2422 * I'm pretty certain it's right, but not enough to toss the old
2425 static void adjustArithmeticResult(iCode *ic)
2427 if (opIsGptr(IC_RESULT(ic)) &&
2428 opIsGptr(IC_LEFT(ic)) &&
2429 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2431 aopPut(AOP(IC_RESULT(ic)),
2432 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
2436 if (opIsGptr(IC_RESULT(ic)) &&
2437 opIsGptr(IC_RIGHT(ic)) &&
2438 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2440 aopPut(AOP(IC_RESULT(ic)),
2441 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
2445 if (opIsGptr(IC_RESULT(ic)) &&
2446 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2447 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2448 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2449 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2451 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2452 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2457 /*-----------------------------------------------------------------*/
2458 /* genPlus - generates code for addition */
2459 /*-----------------------------------------------------------------*/
2460 static void genPlus (iCode *ic)
2462 int size, offset = 0;
2464 /* special cases :- */
2466 aopOp (IC_LEFT(ic),ic,FALSE);
2467 aopOp (IC_RIGHT(ic),ic,FALSE);
2468 aopOp (IC_RESULT(ic),ic,TRUE);
2470 /* if literal, literal on the right or
2471 if left requires ACC or right is already
2473 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2474 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2475 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2476 operand *t = IC_RIGHT(ic);
2477 IC_RIGHT(ic) = IC_LEFT(ic);
2481 /* if both left & right are in bit
2483 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2484 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2489 /* if left in bit space & right literal */
2490 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2491 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2492 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2493 /* if result in bit space */
2494 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2495 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
2496 emitcode("cpl","c");
2497 outBitC(IC_RESULT(ic));
2499 size = getDataSize(IC_RESULT(ic));
2501 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2502 emitcode("addc","a,#00");
2503 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2509 /* if I can do an increment instead
2510 of add then GOOD for ME */
2511 if (genPlusIncr (ic) == TRUE)
2514 size = getDataSize(IC_RESULT(ic));
2517 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2518 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2520 emitcode("add","a,%s",
2521 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2523 emitcode("addc","a,%s",
2524 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2526 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2528 emitcode("add","a,%s",
2529 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2531 emitcode("addc","a,%s",
2532 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2534 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2537 adjustArithmeticResult(ic);
2540 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2541 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2542 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2545 /*-----------------------------------------------------------------*/
2546 /* genMinusDec :- does subtraction with deccrement if possible */
2547 /*-----------------------------------------------------------------*/
2548 static bool genMinusDec (iCode *ic)
2550 unsigned int icount ;
2551 unsigned int size = getDataSize(IC_RESULT(ic));
2553 /* will try to generate an increment */
2554 /* if the right side is not a literal
2556 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2559 /* if the literal value of the right hand side
2560 is greater than 4 then it is not worth it */
2561 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2564 size = getDataSize(IC_RESULT(ic));
2565 /* if decrement 16 bits in register */
2566 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2569 symbol *tlbl = newiTempLabel(NULL);
2570 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2571 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2572 IS_AOP_PREG(IC_RESULT(ic)))
2573 emitcode("cjne","%s,#0xff,%05d$"
2574 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2577 emitcode("mov","a,#0xff");
2578 emitcode("cjne","a,%s,%05d$"
2579 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2582 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2585 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2586 IS_AOP_PREG(IC_RESULT(ic)))
2587 emitcode("cjne","%s,#0xff,%05d$"
2588 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2591 emitcode("cjne","a,%s,%05d$"
2592 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2595 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2599 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2600 IS_AOP_PREG(IC_RESULT(ic)))
2601 emitcode("cjne","%s,#0xff,%05d$"
2602 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2605 emitcode("cjne","a,%s,%05d$"
2606 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2609 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2611 emitcode("","%05d$:",tlbl->key+100);
2615 /* if the sizes are greater than 1 then we cannot */
2616 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2617 AOP_SIZE(IC_LEFT(ic)) > 1 )
2620 /* we can if the aops of the left & result match or
2621 if they are in registers and the registers are the
2623 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2626 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2634 /*-----------------------------------------------------------------*/
2635 /* addSign - complete with sign */
2636 /*-----------------------------------------------------------------*/
2637 static void addSign(operand *result, int offset, int sign)
2639 int size = (getDataSize(result) - offset);
2642 emitcode("rlc","a");
2643 emitcode("subb","a,acc");
2645 aopPut(AOP(result),"a",offset++);
2648 aopPut(AOP(result),zero,offset++);
2652 /*-----------------------------------------------------------------*/
2653 /* genMinusBits - generates code for subtraction of two bits */
2654 /*-----------------------------------------------------------------*/
2655 static void genMinusBits (iCode *ic)
2657 symbol *lbl = newiTempLabel(NULL);
2658 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2659 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2660 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2661 emitcode("cpl","c");
2662 emitcode("","%05d$:",(lbl->key+100));
2663 outBitC(IC_RESULT(ic));
2666 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2667 emitcode("subb","a,acc");
2668 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
2669 emitcode("inc","a");
2670 emitcode("","%05d$:",(lbl->key+100));
2671 aopPut(AOP(IC_RESULT(ic)),"a",0);
2672 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
2676 /*-----------------------------------------------------------------*/
2677 /* genMinus - generates code for subtraction */
2678 /*-----------------------------------------------------------------*/
2679 static void genMinus (iCode *ic)
2681 int size, offset = 0;
2682 unsigned long lit = 0L;
2684 aopOp (IC_LEFT(ic),ic,FALSE);
2685 aopOp (IC_RIGHT(ic),ic,FALSE);
2686 aopOp (IC_RESULT(ic),ic,TRUE);
2688 /* special cases :- */
2689 /* if both left & right are in bit space */
2690 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2691 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2696 /* if I can do an decrement instead
2697 of subtract then GOOD for ME */
2698 if (genMinusDec (ic) == TRUE)
2701 size = getDataSize(IC_RESULT(ic));
2703 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
2707 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2711 /* if literal, add a,#-lit, else normal subb */
2713 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2714 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2715 emitcode("subb","a,%s",
2716 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2718 /* first add without previous c */
2720 emitcode("add","a,#0x%02x",
2721 (unsigned int)(lit & 0x0FFL));
2723 emitcode("addc","a,#0x%02x",
2724 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
2726 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2729 adjustArithmeticResult(ic);
2732 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2733 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2734 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2738 /*-----------------------------------------------------------------*/
2739 /* genMultbits :- multiplication of bits */
2740 /*-----------------------------------------------------------------*/
2741 static void genMultbits (operand *left,
2745 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2746 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
2751 /*-----------------------------------------------------------------*/
2752 /* genMultOneByte : 8 bit multiplication & division */
2753 /*-----------------------------------------------------------------*/
2754 static void genMultOneByte (operand *left,
2758 link *opetype = operandType(result);
2763 /* (if two literals, the value is computed before) */
2764 /* if one literal, literal on the right */
2765 if (AOP_TYPE(left) == AOP_LIT){
2771 size = AOP_SIZE(result);
2772 /* signed or unsigned */
2773 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2774 l = aopGet(AOP(left),0,FALSE,FALSE);
2776 emitcode("mul","ab");
2777 /* if result size = 1, mul signed = mul unsigned */
2778 aopPut(AOP(result),"a",0);
2780 if (SPEC_USIGN(opetype)){
2781 aopPut(AOP(result),"b",1);
2783 /* for filling the MSBs */
2784 emitcode("clr","a");
2787 emitcode("mov","a,b");
2789 /* adjust the MSB if left or right neg */
2791 /* if one literal */
2792 if (AOP_TYPE(right) == AOP_LIT){
2793 /* AND literal negative */
2794 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
2795 /* adjust MSB (c==0 after mul) */
2796 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2800 lbl = newiTempLabel(NULL);
2801 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2802 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
2803 emitcode("","%05d$:",(lbl->key+100));
2804 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2805 lbl = newiTempLabel(NULL);
2806 emitcode("jc","%05d$",(lbl->key+100));
2807 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2808 emitcode("","%05d$:",(lbl->key+100));
2811 lbl = newiTempLabel(NULL);
2812 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
2813 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
2814 emitcode("","%05d$:",(lbl->key+100));
2815 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
2816 lbl = newiTempLabel(NULL);
2817 emitcode("jc","%05d$",(lbl->key+100));
2818 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
2819 emitcode("","%05d$:",(lbl->key+100));
2821 aopPut(AOP(result),"a",1);
2824 emitcode("rlc","a");
2825 emitcode("subb","a,acc");
2832 aopPut(AOP(result),"a",offset++);
2836 /*-----------------------------------------------------------------*/
2837 /* genMult - generates code for multiplication */
2838 /*-----------------------------------------------------------------*/
2839 static void genMult (iCode *ic)
2841 operand *left = IC_LEFT(ic);
2842 operand *right = IC_RIGHT(ic);
2843 operand *result= IC_RESULT(ic);
2845 /* assign the amsops */
2846 aopOp (left,ic,FALSE);
2847 aopOp (right,ic,FALSE);
2848 aopOp (result,ic,TRUE);
2850 /* special cases first */
2852 if (AOP_TYPE(left) == AOP_CRY &&
2853 AOP_TYPE(right)== AOP_CRY) {
2854 genMultbits(left,right,result);
2858 /* if both are of size == 1 */
2859 if (AOP_SIZE(left) == 1 &&
2860 AOP_SIZE(right) == 1 ) {
2861 genMultOneByte(left,right,result);
2865 /* should have been converted to function call */
2869 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2870 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2871 freeAsmop(result,NULL,ic,TRUE);
2874 /*-----------------------------------------------------------------*/
2875 /* genDivbits :- division of bits */
2876 /*-----------------------------------------------------------------*/
2877 static void genDivbits (operand *left,
2884 /* the result must be bit */
2885 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
2886 l = aopGet(AOP(left),0,FALSE,FALSE);
2890 emitcode("div","ab");
2891 emitcode("rrc","a");
2892 aopPut(AOP(result),"c",0);
2895 /*-----------------------------------------------------------------*/
2896 /* genDivOneByte : 8 bit division */
2897 /*-----------------------------------------------------------------*/
2898 static void genDivOneByte (operand *left,
2902 link *opetype = operandType(result);
2907 size = AOP_SIZE(result) - 1;
2909 /* signed or unsigned */
2910 if (SPEC_USIGN(opetype)) {
2911 /* unsigned is easy */
2912 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2913 l = aopGet(AOP(left),0,FALSE,FALSE);
2915 emitcode("div","ab");
2916 aopPut(AOP(result),"a",0);
2918 aopPut(AOP(result),zero,offset++);
2922 /* signed is a little bit more difficult */
2924 /* save the signs of the operands */
2925 l = aopGet(AOP(left),0,FALSE,FALSE);
2927 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
2928 emitcode("push","acc"); /* save it on the stack */
2930 /* now sign adjust for both left & right */
2931 l = aopGet(AOP(right),0,FALSE,FALSE);
2933 lbl = newiTempLabel(NULL);
2934 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
2935 emitcode("cpl","a");
2936 emitcode("inc","a");
2937 emitcode("","%05d$:",(lbl->key+100));
2938 emitcode("mov","b,a");
2940 /* sign adjust left side */
2941 l = aopGet(AOP(left),0,FALSE,FALSE);
2944 lbl = newiTempLabel(NULL);
2945 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
2946 emitcode("cpl","a");
2947 emitcode("inc","a");
2948 emitcode("","%05d$:",(lbl->key+100));
2950 /* now the division */
2951 emitcode("div","ab");
2952 /* we are interested in the lower order
2954 emitcode("mov","b,a");
2955 lbl = newiTempLabel(NULL);
2956 emitcode("pop","acc");
2957 /* if there was an over flow we don't
2958 adjust the sign of the result */
2959 emitcode("jb","ov,%05d$",(lbl->key+100));
2960 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
2962 emitcode("clr","a");
2963 emitcode("subb","a,b");
2964 emitcode("mov","b,a");
2965 emitcode("","%05d$:",(lbl->key+100));
2967 /* now we are done */
2968 aopPut(AOP(result),"b",0);
2970 emitcode("mov","c,b.7");
2971 emitcode("subb","a,acc");
2974 aopPut(AOP(result),"a",offset++);
2978 /*-----------------------------------------------------------------*/
2979 /* genDiv - generates code for division */
2980 /*-----------------------------------------------------------------*/
2981 static void genDiv (iCode *ic)
2983 operand *left = IC_LEFT(ic);
2984 operand *right = IC_RIGHT(ic);
2985 operand *result= IC_RESULT(ic);
2987 /* assign the amsops */
2988 aopOp (left,ic,FALSE);
2989 aopOp (right,ic,FALSE);
2990 aopOp (result,ic,TRUE);
2992 /* special cases first */
2994 if (AOP_TYPE(left) == AOP_CRY &&
2995 AOP_TYPE(right)== AOP_CRY) {
2996 genDivbits(left,right,result);
3000 /* if both are of size == 1 */
3001 if (AOP_SIZE(left) == 1 &&
3002 AOP_SIZE(right) == 1 ) {
3003 genDivOneByte(left,right,result);
3007 /* should have been converted to function call */
3010 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3011 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3012 freeAsmop(result,NULL,ic,TRUE);
3015 /*-----------------------------------------------------------------*/
3016 /* genModbits :- modulus of bits */
3017 /*-----------------------------------------------------------------*/
3018 static void genModbits (operand *left,
3025 /* the result must be bit */
3026 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3027 l = aopGet(AOP(left),0,FALSE,FALSE);
3031 emitcode("div","ab");
3032 emitcode("mov","a,b");
3033 emitcode("rrc","a");
3034 aopPut(AOP(result),"c",0);
3037 /*-----------------------------------------------------------------*/
3038 /* genModOneByte : 8 bit modulus */
3039 /*-----------------------------------------------------------------*/
3040 static void genModOneByte (operand *left,
3044 link *opetype = operandType(result);
3048 /* signed or unsigned */
3049 if (SPEC_USIGN(opetype)) {
3050 /* unsigned is easy */
3051 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3052 l = aopGet(AOP(left),0,FALSE,FALSE);
3054 emitcode("div","ab");
3055 aopPut(AOP(result),"b",0);
3059 /* signed is a little bit more difficult */
3061 /* save the signs of the operands */
3062 l = aopGet(AOP(left),0,FALSE,FALSE);
3065 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3066 emitcode("push","acc"); /* save it on the stack */
3068 /* now sign adjust for both left & right */
3069 l = aopGet(AOP(right),0,FALSE,FALSE);
3072 lbl = newiTempLabel(NULL);
3073 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3074 emitcode("cpl","a");
3075 emitcode("inc","a");
3076 emitcode("","%05d$:",(lbl->key+100));
3077 emitcode("mov","b,a");
3079 /* sign adjust left side */
3080 l = aopGet(AOP(left),0,FALSE,FALSE);
3083 lbl = newiTempLabel(NULL);
3084 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3085 emitcode("cpl","a");
3086 emitcode("inc","a");
3087 emitcode("","%05d$:",(lbl->key+100));
3089 /* now the multiplication */
3090 emitcode("div","ab");
3091 /* we are interested in the lower order
3093 lbl = newiTempLabel(NULL);
3094 emitcode("pop","acc");
3095 /* if there was an over flow we don't
3096 adjust the sign of the result */
3097 emitcode("jb","ov,%05d$",(lbl->key+100));
3098 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3100 emitcode("clr","a");
3101 emitcode("subb","a,b");
3102 emitcode("mov","b,a");
3103 emitcode("","%05d$:",(lbl->key+100));
3105 /* now we are done */
3106 aopPut(AOP(result),"b",0);
3110 /*-----------------------------------------------------------------*/
3111 /* genMod - generates code for division */
3112 /*-----------------------------------------------------------------*/
3113 static void genMod (iCode *ic)
3115 operand *left = IC_LEFT(ic);
3116 operand *right = IC_RIGHT(ic);
3117 operand *result= IC_RESULT(ic);
3119 /* assign the amsops */
3120 aopOp (left,ic,FALSE);
3121 aopOp (right,ic,FALSE);
3122 aopOp (result,ic,TRUE);
3124 /* special cases first */
3126 if (AOP_TYPE(left) == AOP_CRY &&
3127 AOP_TYPE(right)== AOP_CRY) {
3128 genModbits(left,right,result);
3132 /* if both are of size == 1 */
3133 if (AOP_SIZE(left) == 1 &&
3134 AOP_SIZE(right) == 1 ) {
3135 genModOneByte(left,right,result);
3139 /* should have been converted to function call */
3143 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3144 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3145 freeAsmop(result,NULL,ic,TRUE);
3148 /*-----------------------------------------------------------------*/
3149 /* genIfxJump :- will create a jump depending on the ifx */
3150 /*-----------------------------------------------------------------*/
3151 static void genIfxJump (iCode *ic, char *jval)
3154 symbol *tlbl = newiTempLabel(NULL);
3157 /* if true label then we jump if condition
3159 if ( IC_TRUE(ic) ) {
3161 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3162 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3165 /* false label is present */
3166 jlbl = IC_FALSE(ic) ;
3167 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3168 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3170 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3171 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3173 emitcode(inst,"%05d$",tlbl->key+100);
3174 emitcode("ljmp","%05d$",jlbl->key+100);
3175 emitcode("","%05d$:",tlbl->key+100);
3177 /* mark the icode as generated */
3181 /*-----------------------------------------------------------------*/
3182 /* genCmp :- greater or less than comparison */
3183 /*-----------------------------------------------------------------*/
3184 static void genCmp (operand *left,operand *right,
3185 operand *result, iCode *ifx, int sign)
3187 int size, offset = 0 ;
3188 unsigned long lit = 0L;
3190 /* if left & right are bit variables */
3191 if (AOP_TYPE(left) == AOP_CRY &&
3192 AOP_TYPE(right) == AOP_CRY ) {
3193 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3194 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3196 /* subtract right from left if at the
3197 end the carry flag is set then we know that
3198 left is greater than right */
3199 size = max(AOP_SIZE(left),AOP_SIZE(right));
3201 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3202 if((size == 1) && !sign &&
3203 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3204 symbol *lbl = newiTempLabel(NULL);
3205 emitcode("cjne","%s,%s,%05d$",
3206 aopGet(AOP(left),offset,FALSE,FALSE),
3207 aopGet(AOP(right),offset,FALSE,FALSE),
3209 emitcode("","%05d$:",lbl->key+100);
3211 if(AOP_TYPE(right) == AOP_LIT){
3212 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3213 /* optimize if(x < 0) or if(x >= 0) */
3219 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE));
3220 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3221 genIfxJump (ifx,"acc.7");
3225 emitcode("rlc","a");
3232 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3233 if (sign && size == 0) {
3234 emitcode("xrl","a,#0x80");
3235 if (AOP_TYPE(right) == AOP_LIT){
3236 unsigned long lit = (unsigned long)
3237 floatFromVal(AOP(right)->aopu.aop_lit);
3238 emitcode("subb","a,#0x%02x",
3239 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3241 emitcode("mov","b,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3242 emitcode("xrl","b,#0x80");
3243 emitcode("subb","a,b");
3246 emitcode("subb","a,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3252 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3255 /* if the result is used in the next
3256 ifx conditional branch then generate
3257 code a little differently */
3259 genIfxJump (ifx,"c");
3262 /* leave the result in acc */
3266 /*-----------------------------------------------------------------*/
3267 /* genCmpGt :- greater than comparison */
3268 /*-----------------------------------------------------------------*/
3269 static void genCmpGt (iCode *ic, iCode *ifx)
3271 operand *left, *right, *result;
3272 link *letype , *retype;
3276 right= IC_RIGHT(ic);
3277 result = IC_RESULT(ic);
3279 letype = getSpec(operandType(left));
3280 retype =getSpec(operandType(right));
3281 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3282 /* assign the amsops */
3283 aopOp (left,ic,FALSE);
3284 aopOp (right,ic,FALSE);
3285 aopOp (result,ic,TRUE);
3287 genCmp(right, left, result, ifx, sign);
3289 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3290 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3291 freeAsmop(result,NULL,ic,TRUE);
3294 /*-----------------------------------------------------------------*/
3295 /* genCmpLt - less than comparisons */
3296 /*-----------------------------------------------------------------*/
3297 static void genCmpLt (iCode *ic, iCode *ifx)
3299 operand *left, *right, *result;
3300 link *letype , *retype;
3304 right= IC_RIGHT(ic);
3305 result = IC_RESULT(ic);
3307 letype = getSpec(operandType(left));
3308 retype =getSpec(operandType(right));
3309 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3311 /* assign the amsops */
3312 aopOp (left,ic,FALSE);
3313 aopOp (right,ic,FALSE);
3314 aopOp (result,ic,TRUE);
3316 genCmp(left, right, result, ifx, sign);
3318 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3319 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3320 freeAsmop(result,NULL,ic,TRUE);
3323 /*-----------------------------------------------------------------*/
3324 /* gencjneshort - compare and jump if not equal */
3325 /*-----------------------------------------------------------------*/
3326 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3328 int size = max(AOP_SIZE(left),AOP_SIZE(right));
3330 unsigned long lit = 0L;
3332 /* if the left side is a literal or
3333 if the right is in a pointer register and left
3335 if ((AOP_TYPE(left) == AOP_LIT) ||
3336 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3341 if(AOP_TYPE(right) == AOP_LIT)
3342 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3344 /* if the right side is a literal then anything goes */
3345 if (AOP_TYPE(right) == AOP_LIT &&
3346 AOP_TYPE(left) != AOP_DIR ) {
3348 emitcode("cjne","%s,%s,%05d$",
3349 aopGet(AOP(left),offset,FALSE,FALSE),
3350 aopGet(AOP(right),offset,FALSE,FALSE),
3356 /* if the right side is in a register or in direct space or
3357 if the left is a pointer register & right is not */
3358 else if (AOP_TYPE(right) == AOP_REG ||
3359 AOP_TYPE(right) == AOP_DIR ||
3360 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3361 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3363 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3364 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3365 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
3366 emitcode("jnz","%05d$",lbl->key+100);
3368 emitcode("cjne","a,%s,%05d$",
3369 aopGet(AOP(right),offset,FALSE,TRUE),
3374 /* right is a pointer reg need both a & b */
3376 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
3378 emitcode("mov","b,%s",l);
3379 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3380 emitcode("cjne","a,b,%05d$",lbl->key+100);
3386 /*-----------------------------------------------------------------*/
3387 /* gencjne - compare and jump if not equal */
3388 /*-----------------------------------------------------------------*/
3389 static void gencjne(operand *left, operand *right, symbol *lbl)
3391 symbol *tlbl = newiTempLabel(NULL);
3393 gencjneshort(left, right, lbl);
3395 emitcode("mov","a,%s",one);
3396 emitcode("sjmp","%05d$",tlbl->key+100);
3397 emitcode("","%05d$:",lbl->key+100);
3398 emitcode("clr","a");
3399 emitcode("","%05d$:",tlbl->key+100);
3402 /*-----------------------------------------------------------------*/
3403 /* genCmpEq - generates code for equal to */
3404 /*-----------------------------------------------------------------*/
3405 static void genCmpEq (iCode *ic, iCode *ifx)
3407 operand *left, *right, *result;
3409 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3410 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3411 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3413 /* if literal, literal on the right or
3414 if the right is in a pointer register and left
3416 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
3417 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3418 operand *t = IC_RIGHT(ic);
3419 IC_RIGHT(ic) = IC_LEFT(ic);
3423 if(ifx && !AOP_SIZE(result)){
3425 /* if they are both bit variables */
3426 if (AOP_TYPE(left) == AOP_CRY &&
3427 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3428 if(AOP_TYPE(right) == AOP_LIT){
3429 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3431 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3432 emitcode("cpl","c");
3433 } else if(lit == 1L) {
3434 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3436 emitcode("clr","c");
3438 /* AOP_TYPE(right) == AOP_CRY */
3440 symbol *lbl = newiTempLabel(NULL);
3441 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3442 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3443 emitcode("cpl","c");
3444 emitcode("","%05d$:",(lbl->key+100));
3446 /* if true label then we jump if condition
3448 tlbl = newiTempLabel(NULL);
3449 if ( IC_TRUE(ifx) ) {
3450 emitcode("jnc","%05d$",tlbl->key+100);
3451 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3453 emitcode("jc","%05d$",tlbl->key+100);
3454 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3456 emitcode("","%05d$:",tlbl->key+100);
3458 tlbl = newiTempLabel(NULL);
3459 gencjneshort(left, right, tlbl);
3460 if ( IC_TRUE(ifx) ) {
3461 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3462 emitcode("","%05d$:",tlbl->key+100);
3464 symbol *lbl = newiTempLabel(NULL);
3465 emitcode("sjmp","%05d$",lbl->key+100);
3466 emitcode("","%05d$:",tlbl->key+100);
3467 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3468 emitcode("","%05d$:",lbl->key+100);
3471 /* mark the icode as generated */
3476 /* if they are both bit variables */
3477 if (AOP_TYPE(left) == AOP_CRY &&
3478 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3479 if(AOP_TYPE(right) == AOP_LIT){
3480 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3482 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3483 emitcode("cpl","c");
3484 } else if(lit == 1L) {
3485 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3487 emitcode("clr","c");
3489 /* AOP_TYPE(right) == AOP_CRY */
3491 symbol *lbl = newiTempLabel(NULL);
3492 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3493 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3494 emitcode("cpl","c");
3495 emitcode("","%05d$:",(lbl->key+100));
3498 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
3503 genIfxJump (ifx,"c");
3506 /* if the result is used in an arithmetic operation
3507 then put the result in place */
3510 gencjne(left,right,newiTempLabel(NULL));
3511 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3512 aopPut(AOP(result),"a",0);
3516 genIfxJump (ifx,"a");
3519 /* if the result is used in an arithmetic operation
3520 then put the result in place */
3521 if (AOP_TYPE(result) != AOP_CRY)
3523 /* leave the result in acc */
3527 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3528 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3529 freeAsmop(result,NULL,ic,TRUE);
3532 /*-----------------------------------------------------------------*/
3533 /* ifxForOp - returns the icode containing the ifx for operand */
3534 /*-----------------------------------------------------------------*/
3535 static iCode *ifxForOp ( operand *op, iCode *ic )
3537 /* if true symbol then needs to be assigned */
3538 if (IS_TRUE_SYMOP(op))
3541 /* if this has register type condition and
3542 the next instruction is ifx with the same operand
3543 and live to of the operand is upto the ifx only then */
3545 ic->next->op == IFX &&
3546 IC_COND(ic->next)->key == op->key &&
3547 OP_SYMBOL(op)->liveTo <= ic->next->seq )
3552 /*-----------------------------------------------------------------*/
3553 /* genAndOp - for && operation */
3554 /*-----------------------------------------------------------------*/
3555 static void genAndOp (iCode *ic)
3557 operand *left,*right, *result;
3560 /* note here that && operations that are in an
3561 if statement are taken away by backPatchLabels
3562 only those used in arthmetic operations remain */
3563 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3564 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3565 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3567 /* if both are bit variables */
3568 if (AOP_TYPE(left) == AOP_CRY &&
3569 AOP_TYPE(right) == AOP_CRY ) {
3570 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3571 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3574 tlbl = newiTempLabel(NULL);
3576 emitcode("jz","%05d$",tlbl->key+100);
3578 emitcode("","%05d$:",tlbl->key+100);
3582 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3583 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3584 freeAsmop(result,NULL,ic,TRUE);
3588 /*-----------------------------------------------------------------*/
3589 /* genOrOp - for || operation */
3590 /*-----------------------------------------------------------------*/
3591 static void genOrOp (iCode *ic)
3593 operand *left,*right, *result;
3596 /* note here that || operations that are in an
3597 if statement are taken away by backPatchLabels
3598 only those used in arthmetic operations remain */
3599 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3600 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3601 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3603 /* if both are bit variables */
3604 if (AOP_TYPE(left) == AOP_CRY &&
3605 AOP_TYPE(right) == AOP_CRY ) {
3606 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3607 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
3610 tlbl = newiTempLabel(NULL);
3612 emitcode("jnz","%05d$",tlbl->key+100);
3614 emitcode("","%05d$:",tlbl->key+100);
3618 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3619 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3620 freeAsmop(result,NULL,ic,TRUE);
3623 /*-----------------------------------------------------------------*/
3624 /* isLiteralBit - test if lit == 2^n */
3625 /*-----------------------------------------------------------------*/
3626 static int isLiteralBit(unsigned long lit)
3628 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
3629 0x100L,0x200L,0x400L,0x800L,
3630 0x1000L,0x2000L,0x4000L,0x8000L,
3631 0x10000L,0x20000L,0x40000L,0x80000L,
3632 0x100000L,0x200000L,0x400000L,0x800000L,
3633 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
3634 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
3637 for(idx = 0; idx < 32; idx++)
3643 /*-----------------------------------------------------------------*/
3644 /* continueIfTrue - */
3645 /*-----------------------------------------------------------------*/
3646 static void continueIfTrue (iCode *ic)
3649 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3653 /*-----------------------------------------------------------------*/
3655 /*-----------------------------------------------------------------*/
3656 static void jumpIfTrue (iCode *ic)
3659 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3663 /*-----------------------------------------------------------------*/
3664 /* jmpTrueOrFalse - */
3665 /*-----------------------------------------------------------------*/
3666 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
3668 // ugly but optimized by peephole
3670 symbol *nlbl = newiTempLabel(NULL);
3671 emitcode("sjmp","%05d$",nlbl->key+100);
3672 emitcode("","%05d$:",tlbl->key+100);
3673 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3674 emitcode("","%05d$:",nlbl->key+100);
3677 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3678 emitcode("","%05d$:",tlbl->key+100);
3683 /*-----------------------------------------------------------------*/
3684 /* genAnd - code for and */
3685 /*-----------------------------------------------------------------*/
3686 static void genAnd (iCode *ic, iCode *ifx)
3688 operand *left, *right, *result;
3690 unsigned long lit = 0L;
3694 aopOp((left = IC_LEFT(ic)),ic,FALSE);
3695 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3696 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3699 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3701 AOP_TYPE(left), AOP_TYPE(right));
3702 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3704 AOP_SIZE(left), AOP_SIZE(right));
3707 /* if left is a literal & right is not then exchange them */
3708 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3709 AOP_NEEDSACC(left)) {
3710 operand *tmp = right ;
3715 /* if result = right then exchange them */
3716 if(sameRegs(AOP(result),AOP(right))){
3717 operand *tmp = right ;
3722 /* if right is bit then exchange them */
3723 if (AOP_TYPE(right) == AOP_CRY &&
3724 AOP_TYPE(left) != AOP_CRY){
3725 operand *tmp = right ;
3729 if(AOP_TYPE(right) == AOP_LIT)
3730 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3732 size = AOP_SIZE(result);
3735 // result = bit & yy;
3736 if (AOP_TYPE(left) == AOP_CRY){
3737 // c = bit & literal;
3738 if(AOP_TYPE(right) == AOP_LIT){
3740 if(size && sameRegs(AOP(result),AOP(left)))
3743 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3746 if(size && (AOP_TYPE(result) == AOP_CRY)){
3747 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
3750 if((AOP_TYPE(result) == AOP_CRY) && ifx){
3754 emitcode("clr","c");
3757 if (AOP_TYPE(right) == AOP_CRY){
3759 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3760 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3763 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
3765 emitcode("rrc","a");
3766 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3774 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
3775 genIfxJump(ifx, "c");
3779 // if(val & 0xZZ) - size = 0, ifx != FALSE -
3780 // bit = val & 0xZZ - size = 1, ifx = FALSE -
3781 if((AOP_TYPE(right) == AOP_LIT) &&
3782 (AOP_TYPE(result) == AOP_CRY) &&
3783 (AOP_TYPE(left) != AOP_CRY)){
3784 int posbit = isLiteralBit(lit);
3788 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
3791 emitcode("mov","c,acc.%d",posbit&0x07);
3795 sprintf(buffer,"acc.%d",posbit&0x07);
3796 genIfxJump(ifx, buffer);
3801 symbol *tlbl = newiTempLabel(NULL);
3802 int sizel = AOP_SIZE(left);
3804 emitcode("setb","c");
3806 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
3807 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
3809 if((posbit = isLiteralBit(bytelit)) != 0)
3810 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
3812 if(bytelit != 0x0FFL)
3813 emitcode("anl","a,%s",
3814 aopGet(AOP(right),offset,FALSE,TRUE));
3815 emitcode("jnz","%05d$",tlbl->key+100);
3820 // bit = left & literal
3822 emitcode("clr","c");
3823 emitcode("","%05d$:",tlbl->key+100);
3825 // if(left & literal)
3828 jmpTrueOrFalse(ifx, tlbl);
3836 /* if left is same as result */
3837 if(sameRegs(AOP(result),AOP(left))){
3838 for(;size--; offset++) {
3839 if(AOP_TYPE(right) == AOP_LIT){
3840 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
3844 aopPut(AOP(result),zero,offset);
3846 if (IS_AOP_PREG(result)) {
3847 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3848 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
3849 aopPut(AOP(result),"a",offset);
3851 emitcode("anl","%s,%s",
3852 aopGet(AOP(left),offset,FALSE,TRUE),
3853 aopGet(AOP(right),offset,FALSE,FALSE));
3855 if (AOP_TYPE(left) == AOP_ACC)
3856 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
3858 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3859 if (IS_AOP_PREG(result)) {
3860 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
3861 aopPut(AOP(result),"a",offset);
3864 emitcode("anl","%s,a",
3865 aopGet(AOP(left),offset,FALSE,TRUE));
3870 // left & result in different registers
3871 if(AOP_TYPE(result) == AOP_CRY){
3873 // if(size), result in bit
3874 // if(!size && ifx), conditional oper: if(left & right)
3875 symbol *tlbl = newiTempLabel(NULL);
3876 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
3878 emitcode("setb","c");
3880 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3881 emitcode("anl","a,%s",
3882 aopGet(AOP(left),offset,FALSE,FALSE));
3883 emitcode("jnz","%05d$",tlbl->key+100);
3888 emitcode("","%05d$:",tlbl->key+100);
3891 jmpTrueOrFalse(ifx, tlbl);
3893 for(;(size--);offset++) {
3895 // result = left & right
3896 if(AOP_TYPE(right) == AOP_LIT){
3897 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
3899 aopGet(AOP(left),offset,FALSE,FALSE),
3902 } else if(bytelit == 0){
3903 aopPut(AOP(result),zero,offset);
3907 // faster than result <- left, anl result,right
3908 // and better if result is SFR
3909 if (AOP_TYPE(left) == AOP_ACC)
3910 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
3912 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3913 emitcode("anl","a,%s",
3914 aopGet(AOP(left),offset,FALSE,FALSE));
3916 aopPut(AOP(result),"a",offset);
3922 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3923 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3924 freeAsmop(result,NULL,ic,TRUE);
3927 /*-----------------------------------------------------------------*/
3928 /* genOr - code for or */
3929 /*-----------------------------------------------------------------*/
3930 static void genOr (iCode *ic, iCode *ifx)
3932 operand *left, *right, *result;
3934 unsigned long lit = 0L;
3936 aopOp((left = IC_LEFT(ic)),ic,FALSE);
3937 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3938 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3941 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3943 AOP_TYPE(left), AOP_TYPE(right));
3944 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3946 AOP_SIZE(left), AOP_SIZE(right));
3949 /* if left is a literal & right is not then exchange them */
3950 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3951 AOP_NEEDSACC(left)) {
3952 operand *tmp = right ;
3957 /* if result = right then exchange them */
3958 if(sameRegs(AOP(result),AOP(right))){
3959 operand *tmp = right ;
3964 /* if right is bit then exchange them */
3965 if (AOP_TYPE(right) == AOP_CRY &&
3966 AOP_TYPE(left) != AOP_CRY){
3967 operand *tmp = right ;
3971 if(AOP_TYPE(right) == AOP_LIT)
3972 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3974 size = AOP_SIZE(result);
3978 if (AOP_TYPE(left) == AOP_CRY){
3979 if(AOP_TYPE(right) == AOP_LIT){
3980 // c = bit & literal;
3982 // lit != 0 => result = 1
3983 if(AOP_TYPE(result) == AOP_CRY){
3985 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
3987 continueIfTrue(ifx);
3990 emitcode("setb","c");
3992 // lit == 0 => result = left
3993 if(size && sameRegs(AOP(result),AOP(left)))
3995 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3998 if (AOP_TYPE(right) == AOP_CRY){
4000 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4001 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4005 symbol *tlbl = newiTempLabel(NULL);
4006 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4007 emitcode("setb","c");
4008 emitcode("jb","%s,%05d$",
4009 AOP(left)->aopu.aop_dir,tlbl->key+100);
4011 emitcode("jnz","%05d$",tlbl->key+100);
4012 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4013 jmpTrueOrFalse(ifx, tlbl);
4017 emitcode("","%05d$:",tlbl->key+100);
4026 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4027 genIfxJump(ifx, "c");
4031 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4032 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4033 if((AOP_TYPE(right) == AOP_LIT) &&
4034 (AOP_TYPE(result) == AOP_CRY) &&
4035 (AOP_TYPE(left) != AOP_CRY)){
4039 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4041 continueIfTrue(ifx);
4044 // lit = 0, result = boolean(left)
4046 emitcode("setb","c");
4049 symbol *tlbl = newiTempLabel(NULL);
4050 emitcode("jnz","%05d$",tlbl->key+100);
4052 emitcode("","%05d$:",tlbl->key+100);
4054 genIfxJump (ifx,"a");
4062 /* if left is same as result */
4063 if(sameRegs(AOP(result),AOP(left))){
4064 for(;size--; offset++) {
4065 if(AOP_TYPE(right) == AOP_LIT){
4066 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4069 if (IS_AOP_PREG(left)) {
4070 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4071 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4072 aopPut(AOP(result),"a",offset);
4074 emitcode("orl","%s,%s",
4075 aopGet(AOP(left),offset,FALSE,TRUE),
4076 aopGet(AOP(right),offset,FALSE,FALSE));
4078 if (AOP_TYPE(left) == AOP_ACC)
4079 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4081 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4082 if (IS_AOP_PREG(left)) {
4083 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4084 aopPut(AOP(result),"a",offset);
4086 emitcode("orl","%s,a",
4087 aopGet(AOP(left),offset,FALSE,TRUE));
4092 // left & result in different registers
4093 if(AOP_TYPE(result) == AOP_CRY){
4095 // if(size), result in bit
4096 // if(!size && ifx), conditional oper: if(left | right)
4097 symbol *tlbl = newiTempLabel(NULL);
4098 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4100 emitcode("setb","c");
4102 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4103 emitcode("orl","a,%s",
4104 aopGet(AOP(left),offset,FALSE,FALSE));
4105 emitcode("jnz","%05d$",tlbl->key+100);
4110 emitcode("","%05d$:",tlbl->key+100);
4113 jmpTrueOrFalse(ifx, tlbl);
4114 } else for(;(size--);offset++){
4116 // result = left & right
4117 if(AOP_TYPE(right) == AOP_LIT){
4118 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4120 aopGet(AOP(left),offset,FALSE,FALSE),
4125 // faster than result <- left, anl result,right
4126 // and better if result is SFR
4127 if (AOP_TYPE(left) == AOP_ACC)
4128 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4130 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4131 emitcode("orl","a,%s",
4132 aopGet(AOP(left),offset,FALSE,FALSE));
4134 aopPut(AOP(result),"a",offset);
4139 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4140 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4141 freeAsmop(result,NULL,ic,TRUE);
4144 /*-----------------------------------------------------------------*/
4145 /* genXor - code for xclusive or */
4146 /*-----------------------------------------------------------------*/
4147 static void genXor (iCode *ic, iCode *ifx)
4149 operand *left, *right, *result;
4151 unsigned long lit = 0L;
4153 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4154 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4155 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4158 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4160 AOP_TYPE(left), AOP_TYPE(right));
4161 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4163 AOP_SIZE(left), AOP_SIZE(right));
4166 /* if left is a literal & right is not ||
4167 if left needs acc & right does not */
4168 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4169 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4170 operand *tmp = right ;
4175 /* if result = right then exchange them */
4176 if(sameRegs(AOP(result),AOP(right))){
4177 operand *tmp = right ;
4182 /* if right is bit then exchange them */
4183 if (AOP_TYPE(right) == AOP_CRY &&
4184 AOP_TYPE(left) != AOP_CRY){
4185 operand *tmp = right ;
4189 if(AOP_TYPE(right) == AOP_LIT)
4190 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4192 size = AOP_SIZE(result);
4196 if (AOP_TYPE(left) == AOP_CRY){
4197 if(AOP_TYPE(right) == AOP_LIT){
4198 // c = bit & literal;
4200 // lit>>1 != 0 => result = 1
4201 if(AOP_TYPE(result) == AOP_CRY){
4203 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4205 continueIfTrue(ifx);
4208 emitcode("setb","c");
4212 // lit == 0, result = left
4213 if(size && sameRegs(AOP(result),AOP(left)))
4215 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4217 // lit == 1, result = not(left)
4218 if(size && sameRegs(AOP(result),AOP(left))){
4219 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4222 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4223 emitcode("cpl","c");
4230 symbol *tlbl = newiTempLabel(NULL);
4231 if (AOP_TYPE(right) == AOP_CRY){
4233 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4236 int sizer = AOP_SIZE(right);
4238 // if val>>1 != 0, result = 1
4239 emitcode("setb","c");
4241 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
4243 // test the msb of the lsb
4244 emitcode("anl","a,#0xfe");
4245 emitcode("jnz","%05d$",tlbl->key+100);
4249 emitcode("rrc","a");
4251 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4252 emitcode("cpl","c");
4253 emitcode("","%05d$:",(tlbl->key+100));
4260 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4261 genIfxJump(ifx, "c");
4265 if(sameRegs(AOP(result),AOP(left))){
4266 /* if left is same as result */
4267 for(;size--; offset++) {
4268 if(AOP_TYPE(right) == AOP_LIT){
4269 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4272 if (IS_AOP_PREG(left)) {
4273 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4274 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4275 aopPut(AOP(result),"a",offset);
4277 emitcode("xrl","%s,%s",
4278 aopGet(AOP(left),offset,FALSE,TRUE),
4279 aopGet(AOP(right),offset,FALSE,FALSE));
4281 if (AOP_TYPE(left) == AOP_ACC)
4282 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4284 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4285 if (IS_AOP_PREG(left)) {
4286 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4287 aopPut(AOP(result),"a",offset);
4289 emitcode("xrl","%s,a",
4290 aopGet(AOP(left),offset,FALSE,TRUE));
4295 // left & result in different registers
4296 if(AOP_TYPE(result) == AOP_CRY){
4298 // if(size), result in bit
4299 // if(!size && ifx), conditional oper: if(left ^ right)
4300 symbol *tlbl = newiTempLabel(NULL);
4301 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4303 emitcode("setb","c");
4305 if((AOP_TYPE(right) == AOP_LIT) &&
4306 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4307 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4309 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4310 emitcode("xrl","a,%s",
4311 aopGet(AOP(left),offset,FALSE,FALSE));
4313 emitcode("jnz","%05d$",tlbl->key+100);
4318 emitcode("","%05d$:",tlbl->key+100);
4321 jmpTrueOrFalse(ifx, tlbl);
4322 } else for(;(size--);offset++){
4324 // result = left & right
4325 if(AOP_TYPE(right) == AOP_LIT){
4326 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4328 aopGet(AOP(left),offset,FALSE,FALSE),
4333 // faster than result <- left, anl result,right
4334 // and better if result is SFR
4335 if (AOP_TYPE(left) == AOP_ACC)
4336 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4338 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4339 emitcode("xrl","a,%s",
4340 aopGet(AOP(left),offset,FALSE,TRUE));
4342 aopPut(AOP(result),"a",offset);
4347 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4348 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4349 freeAsmop(result,NULL,ic,TRUE);
4352 /*-----------------------------------------------------------------*/
4353 /* genInline - write the inline code out */
4354 /*-----------------------------------------------------------------*/
4355 static void genInline (iCode *ic)
4357 char buffer[MAX_INLINEASM];
4361 _G.inLine += (!options.asmpeep);
4362 strcpy(buffer,IC_INLINE(ic));
4364 /* emit each line as a code */
4383 /* emitcode("",buffer); */
4384 _G.inLine -= (!options.asmpeep);
4387 /*-----------------------------------------------------------------*/
4388 /* genRRC - rotate right with carry */
4389 /*-----------------------------------------------------------------*/
4390 static void genRRC (iCode *ic)
4392 operand *left , *result ;
4393 int size, offset = 0;
4396 /* rotate right with carry */
4398 result=IC_RESULT(ic);
4399 aopOp (left,ic,FALSE);
4400 aopOp (result,ic,FALSE);
4402 /* move it to the result */
4403 size = AOP_SIZE(result);
4407 l = aopGet(AOP(left),offset,FALSE,FALSE);
4409 emitcode("rrc","a");
4410 if (AOP_SIZE(result) > 1)
4411 aopPut(AOP(result),"a",offset--);
4413 /* now we need to put the carry into the
4414 highest order byte of the result */
4415 if (AOP_SIZE(result) > 1) {
4416 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
4419 emitcode("mov","acc.7,c");
4420 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
4421 freeAsmop(left,NULL,ic,TRUE);
4422 freeAsmop(result,NULL,ic,TRUE);
4425 /*-----------------------------------------------------------------*/
4426 /* genRLC - generate code for rotate left with carry */
4427 /*-----------------------------------------------------------------*/
4428 static void genRLC (iCode *ic)
4430 operand *left , *result ;
4431 int size, offset = 0;
4434 /* rotate right with carry */
4436 result=IC_RESULT(ic);
4437 aopOp (left,ic,FALSE);
4438 aopOp (result,ic,FALSE);
4440 /* move it to the result */
4441 size = AOP_SIZE(result);
4444 l = aopGet(AOP(left),offset,FALSE,FALSE);
4446 emitcode("add","a,acc");
4447 if (AOP_SIZE(result) > 1)
4448 aopPut(AOP(result),"a",offset++);
4450 l = aopGet(AOP(left),offset,FALSE,FALSE);
4452 emitcode("rlc","a");
4453 if (AOP_SIZE(result) > 1)
4454 aopPut(AOP(result),"a",offset++);
4457 /* now we need to put the carry into the
4458 highest order byte of the result */
4459 if (AOP_SIZE(result) > 1) {
4460 l = aopGet(AOP(result),0,FALSE,FALSE);
4463 emitcode("mov","acc.0,c");
4464 aopPut(AOP(result),"a",0);
4465 freeAsmop(left,NULL,ic,TRUE);
4466 freeAsmop(result,NULL,ic,TRUE);
4469 /*-----------------------------------------------------------------*/
4470 /* genGetHbit - generates code get highest order bit */
4471 /*-----------------------------------------------------------------*/
4472 static void genGetHbit (iCode *ic)
4474 operand *left, *result;
4476 result=IC_RESULT(ic);
4477 aopOp (left,ic,FALSE);
4478 aopOp (result,ic,FALSE);
4480 /* get the highest order byte into a */
4481 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
4482 if(AOP_TYPE(result) == AOP_CRY){
4483 emitcode("rlc","a");
4488 emitcode("anl","a,#0x01");
4493 freeAsmop(left,NULL,ic,TRUE);
4494 freeAsmop(result,NULL,ic,TRUE);
4497 /*-----------------------------------------------------------------*/
4498 /* AccRol - rotate left accumulator by known count */
4499 /*-----------------------------------------------------------------*/
4500 static void AccRol (int shCount)
4502 shCount &= 0x0007; // shCount : 0..7
4514 emitcode("swap","a");
4518 emitcode("swap","a");
4521 emitcode("swap","a");
4534 /*-----------------------------------------------------------------*/
4535 /* AccLsh - left shift accumulator by known count */
4536 /*-----------------------------------------------------------------*/
4537 static void AccLsh (int shCount)
4541 emitcode("add","a,acc");
4544 emitcode("add","a,acc");
4545 emitcode("add","a,acc");
4547 /* rotate left accumulator */
4549 /* and kill the lower order bits */
4550 emitcode("anl","a,#0x%02x", SLMask[shCount]);
4555 /*-----------------------------------------------------------------*/
4556 /* AccRsh - right shift accumulator by known count */
4557 /*-----------------------------------------------------------------*/
4558 static void AccRsh (int shCount)
4563 emitcode("rrc","a");
4565 /* rotate right accumulator */
4566 AccRol(8 - shCount);
4567 /* and kill the higher order bits */
4568 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4573 /*-----------------------------------------------------------------*/
4574 /* AccSRsh - signed right shift accumulator by known count */
4575 /*-----------------------------------------------------------------*/
4576 static void AccSRsh (int shCount)
4581 emitcode("mov","c,acc.7");
4582 emitcode("rrc","a");
4583 } else if(shCount == 2){
4584 emitcode("mov","c,acc.7");
4585 emitcode("rrc","a");
4586 emitcode("mov","c,acc.7");
4587 emitcode("rrc","a");
4589 tlbl = newiTempLabel(NULL);
4590 /* rotate right accumulator */
4591 AccRol(8 - shCount);
4592 /* and kill the higher order bits */
4593 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4594 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4595 emitcode("orl","a,#0x%02x",
4596 (unsigned char)~SRMask[shCount]);
4597 emitcode("","%05d$:",tlbl->key+100);
4602 /*-----------------------------------------------------------------*/
4603 /* shiftR1Left2Result - shift right one byte from left to result */
4604 /*-----------------------------------------------------------------*/
4605 static void shiftR1Left2Result (operand *left, int offl,
4606 operand *result, int offr,
4607 int shCount, int sign)
4609 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4610 /* shift right accumulator */
4615 aopPut(AOP(result),"a",offr);
4618 /*-----------------------------------------------------------------*/
4619 /* shiftL1Left2Result - shift left one byte from left to result */
4620 /*-----------------------------------------------------------------*/
4621 static void shiftL1Left2Result (operand *left, int offl,
4622 operand *result, int offr, int shCount)
4625 l = aopGet(AOP(left),offl,FALSE,FALSE);
4627 /* shift left accumulator */
4629 aopPut(AOP(result),"a",offr);
4632 /*-----------------------------------------------------------------*/
4633 /* movLeft2Result - move byte from left to result */
4634 /*-----------------------------------------------------------------*/
4635 static void movLeft2Result (operand *left, int offl,
4636 operand *result, int offr, int sign)
4639 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
4640 l = aopGet(AOP(left),offl,FALSE,FALSE);
4642 if (*l == '@' && (IS_AOP_PREG(result))) {
4643 emitcode("mov","a,%s",l);
4644 aopPut(AOP(result),"a",offr);
4647 aopPut(AOP(result),l,offr);
4649 /* MSB sign in acc.7 ! */
4650 if(getDataSize(left) == offl+1){
4651 emitcode("mov","a,%s",l);
4652 aopPut(AOP(result),"a",offr);
4659 /*-----------------------------------------------------------------*/
4660 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
4661 /*-----------------------------------------------------------------*/
4662 static void AccAXRrl1 (char *x)
4664 emitcode("rrc","a");
4665 emitcode("xch","a,%s", x);
4666 emitcode("rrc","a");
4667 emitcode("xch","a,%s", x);
4670 /*-----------------------------------------------------------------*/
4671 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
4672 /*-----------------------------------------------------------------*/
4673 static void AccAXLrl1 (char *x)
4675 emitcode("xch","a,%s",x);
4676 emitcode("rlc","a");
4677 emitcode("xch","a,%s",x);
4678 emitcode("rlc","a");
4681 /*-----------------------------------------------------------------*/
4682 /* AccAXLsh1 - left shift a:x<-0 by 1 */
4683 /*-----------------------------------------------------------------*/
4684 static void AccAXLsh1 (char *x)
4686 emitcode("xch","a,%s",x);
4687 emitcode("add","a,acc");
4688 emitcode("xch","a,%s",x);
4689 emitcode("rlc","a");
4692 /*-----------------------------------------------------------------*/
4693 /* AccAXLsh - left shift a:x by known count (0..7) */
4694 /*-----------------------------------------------------------------*/
4695 static void AccAXLsh (char *x, int shCount)
4709 case 5 : // AAAAABBB:CCCCCDDD
4710 AccRol(shCount); // BBBAAAAA:CCCCCDDD
4711 emitcode("anl","a,#0x%02x",
4712 SLMask[shCount]); // BBB00000:CCCCCDDD
4713 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
4714 AccRol(shCount); // DDDCCCCC:BBB00000
4715 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
4716 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
4717 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
4718 emitcode("anl","a,#0x%02x",
4719 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
4720 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
4721 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
4723 case 6 : // AAAAAABB:CCCCCCDD
4724 emitcode("anl","a,#0x%02x",
4725 SRMask[shCount]); // 000000BB:CCCCCCDD
4726 emitcode("mov","c,acc.0"); // c = B
4727 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
4728 AccAXRrl1(x); // BCCCCCCD:D000000B
4729 AccAXRrl1(x); // BBCCCCCC:DD000000
4731 case 7 : // a:x <<= 7
4732 emitcode("anl","a,#0x%02x",
4733 SRMask[shCount]); // 0000000B:CCCCCCCD
4734 emitcode("mov","c,acc.0"); // c = B
4735 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
4736 AccAXRrl1(x); // BCCCCCCC:D0000000
4743 /*-----------------------------------------------------------------*/
4744 /* AccAXRsh - right shift a:x known count (0..7) */
4745 /*-----------------------------------------------------------------*/
4746 static void AccAXRsh (char *x, int shCount)
4753 AccAXRrl1(x); // 0->a:x
4757 AccAXRrl1(x); // 0->a:x
4759 AccAXRrl1(x); // 0->a:x
4763 case 5 : // AAAAABBB:CCCCCDDD = a:x
4764 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
4765 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
4766 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
4767 emitcode("anl","a,#0x%02x",
4768 SRMask[shCount]); // 000CCCCC:BBBAAAAA
4769 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
4770 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
4771 emitcode("anl","a,#0x%02x",
4772 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
4773 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
4774 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
4775 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
4777 case 6 : // AABBBBBB:CCDDDDDD
4778 emitcode("mov","c,acc.7");
4779 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
4780 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
4781 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
4782 emitcode("anl","a,#0x%02x",
4783 SRMask[shCount]); // 000000AA:BBBBBBCC
4785 case 7 : // ABBBBBBB:CDDDDDDD
4786 emitcode("mov","c,acc.7"); // c = A
4787 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
4788 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
4789 emitcode("anl","a,#0x%02x",
4790 SRMask[shCount]); // 0000000A:BBBBBBBC
4797 /*-----------------------------------------------------------------*/
4798 /* AccAXRshS - right shift signed a:x known count (0..7) */
4799 /*-----------------------------------------------------------------*/
4800 static void AccAXRshS (char *x, int shCount)
4807 emitcode("mov","c,acc.7");
4808 AccAXRrl1(x); // s->a:x
4811 emitcode("mov","c,acc.7");
4812 AccAXRrl1(x); // s->a:x
4813 emitcode("mov","c,acc.7");
4814 AccAXRrl1(x); // s->a:x
4818 case 5 : // AAAAABBB:CCCCCDDD = a:x
4819 tlbl = newiTempLabel(NULL);
4820 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
4821 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
4822 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
4823 emitcode("anl","a,#0x%02x",
4824 SRMask[shCount]); // 000CCCCC:BBBAAAAA
4825 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
4826 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
4827 emitcode("anl","a,#0x%02x",
4828 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
4829 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
4830 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
4831 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
4832 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4833 emitcode("orl","a,#0x%02x",
4834 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
4835 emitcode("","%05d$:",tlbl->key+100);
4836 break; // SSSSAAAA:BBBCCCCC
4837 case 6 : // AABBBBBB:CCDDDDDD
4838 tlbl = newiTempLabel(NULL);
4839 emitcode("mov","c,acc.7");
4840 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
4841 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
4842 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
4843 emitcode("anl","a,#0x%02x",
4844 SRMask[shCount]); // 000000AA:BBBBBBCC
4845 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4846 emitcode("orl","a,#0x%02x",
4847 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
4848 emitcode("","%05d$:",tlbl->key+100);
4850 case 7 : // ABBBBBBB:CDDDDDDD
4851 tlbl = newiTempLabel(NULL);
4852 emitcode("mov","c,acc.7"); // c = A
4853 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
4854 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
4855 emitcode("anl","a,#0x%02x",
4856 SRMask[shCount]); // 0000000A:BBBBBBBC
4857 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4858 emitcode("orl","a,#0x%02x",
4859 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
4860 emitcode("","%05d$:",tlbl->key+100);
4867 /*-----------------------------------------------------------------*/
4868 /* shiftL2Left2Result - shift left two bytes from left to result */
4869 /*-----------------------------------------------------------------*/
4870 static void shiftL2Left2Result (operand *left, int offl,
4871 operand *result, int offr, int shCount)
4873 if(sameRegs(AOP(result), AOP(left)) &&
4874 ((offl + MSB16) == offr)){
4875 /* don't crash result[offr] */
4876 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4877 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4879 movLeft2Result(left,offl, result, offr, 0);
4880 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4882 /* ax << shCount (x = lsb(result))*/
4883 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
4884 aopPut(AOP(result),"a",offr+MSB16);
4888 /*-----------------------------------------------------------------*/
4889 /* shiftR2Left2Result - shift right two bytes from left to result */
4890 /*-----------------------------------------------------------------*/
4891 static void shiftR2Left2Result (operand *left, int offl,
4892 operand *result, int offr,
4893 int shCount, int sign)
4895 if(sameRegs(AOP(result), AOP(left)) &&
4896 ((offl + MSB16) == offr)){
4897 /* don't crash result[offr] */
4898 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4899 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4901 movLeft2Result(left,offl, result, offr, 0);
4902 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4904 /* a:x >> shCount (x = lsb(result))*/
4906 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
4908 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
4909 if(getDataSize(result) > 1)
4910 aopPut(AOP(result),"a",offr+MSB16);
4913 /*-----------------------------------------------------------------*/
4914 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
4915 /*-----------------------------------------------------------------*/
4916 static void shiftLLeftOrResult (operand *left, int offl,
4917 operand *result, int offr, int shCount)
4919 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4920 /* shift left accumulator */
4922 /* or with result */
4923 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
4924 /* back to result */
4925 aopPut(AOP(result),"a",offr);
4928 /*-----------------------------------------------------------------*/
4929 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
4930 /*-----------------------------------------------------------------*/
4931 static void shiftRLeftOrResult (operand *left, int offl,
4932 operand *result, int offr, int shCount)
4934 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4935 /* shift right accumulator */
4937 /* or with result */
4938 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
4939 /* back to result */
4940 aopPut(AOP(result),"a",offr);
4943 /*-----------------------------------------------------------------*/
4944 /* genlshOne - left shift a one byte quantity by known count */
4945 /*-----------------------------------------------------------------*/
4946 static void genlshOne (operand *result, operand *left, int shCount)
4948 shiftL1Left2Result(left, LSB, result, LSB, shCount);
4951 /*-----------------------------------------------------------------*/
4952 /* genlshTwo - left shift two bytes by known amount != 0 */
4953 /*-----------------------------------------------------------------*/
4954 static void genlshTwo (operand *result,operand *left, int shCount)
4958 size = getDataSize(result);
4960 /* if shCount >= 8 */
4966 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
4968 movLeft2Result(left, LSB, result, MSB16, 0);
4970 aopPut(AOP(result),zero,LSB);
4973 /* 1 <= shCount <= 7 */
4976 shiftL1Left2Result(left, LSB, result, LSB, shCount);
4978 shiftL2Left2Result(left, LSB, result, LSB, shCount);
4982 /*-----------------------------------------------------------------*/
4983 /* shiftLLong - shift left one long from left to result */
4984 /* offl = LSB or MSB16 */
4985 /*-----------------------------------------------------------------*/
4986 static void shiftLLong (operand *left, operand *result, int offr )
4989 int size = AOP_SIZE(result);
4991 if(size >= LSB+offr){
4992 l = aopGet(AOP(left),LSB,FALSE,FALSE);
4994 emitcode("add","a,acc");
4995 if (sameRegs(AOP(left),AOP(result)) &&
4996 size >= MSB16+offr && offr != LSB )
4997 emitcode("xch","a,%s",
4998 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
5000 aopPut(AOP(result),"a",LSB+offr);
5003 if(size >= MSB16+offr){
5004 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5005 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
5008 emitcode("rlc","a");
5009 if (sameRegs(AOP(left),AOP(result)) &&
5010 size >= MSB24+offr && offr != LSB)
5011 emitcode("xch","a,%s",
5012 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
5014 aopPut(AOP(result),"a",MSB16+offr);
5017 if(size >= MSB24+offr){
5018 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5019 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
5022 emitcode("rlc","a");
5023 if (sameRegs(AOP(left),AOP(result)) &&
5024 size >= MSB32+offr && offr != LSB )
5025 emitcode("xch","a,%s",
5026 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
5028 aopPut(AOP(result),"a",MSB24+offr);
5031 if(size > MSB32+offr){
5032 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5033 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
5036 emitcode("rlc","a");
5037 aopPut(AOP(result),"a",MSB32+offr);
5040 aopPut(AOP(result),zero,LSB);
5043 /*-----------------------------------------------------------------*/
5044 /* genlshFour - shift four byte by a known amount != 0 */
5045 /*-----------------------------------------------------------------*/
5046 static void genlshFour (operand *result, operand *left, int shCount)
5050 size = AOP_SIZE(result);
5052 /* if shifting more that 3 bytes */
5053 if (shCount >= 24 ) {
5056 /* lowest order of left goes to the highest
5057 order of the destination */
5058 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5060 movLeft2Result(left, LSB, result, MSB32, 0);
5061 aopPut(AOP(result),zero,LSB);
5062 aopPut(AOP(result),zero,MSB16);
5063 aopPut(AOP(result),zero,MSB32);
5067 /* more than two bytes */
5068 else if ( shCount >= 16 ) {
5069 /* lower order two bytes goes to higher order two bytes */
5071 /* if some more remaining */
5073 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5075 movLeft2Result(left, MSB16, result, MSB32, 0);
5076 movLeft2Result(left, LSB, result, MSB24, 0);
5078 aopPut(AOP(result),zero,MSB16);
5079 aopPut(AOP(result),zero,LSB);
5083 /* if more than 1 byte */
5084 else if ( shCount >= 8 ) {
5085 /* lower order three bytes goes to higher order three bytes */
5089 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5091 movLeft2Result(left, LSB, result, MSB16, 0);
5093 else{ /* size = 4 */
5095 movLeft2Result(left, MSB24, result, MSB32, 0);
5096 movLeft2Result(left, MSB16, result, MSB24, 0);
5097 movLeft2Result(left, LSB, result, MSB16, 0);
5098 aopPut(AOP(result),zero,LSB);
5100 else if(shCount == 1)
5101 shiftLLong(left, result, MSB16);
5103 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5104 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5105 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5106 aopPut(AOP(result),zero,LSB);
5111 /* 1 <= shCount <= 7 */
5112 else if(shCount <= 2){
5113 shiftLLong(left, result, LSB);
5115 shiftLLong(result, result, LSB);
5117 /* 3 <= shCount <= 7, optimize */
5119 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5120 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5121 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5125 /*-----------------------------------------------------------------*/
5126 /* genLeftShiftLiteral - left shifting by known count */
5127 /*-----------------------------------------------------------------*/
5128 static void genLeftShiftLiteral (operand *left,
5133 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5136 freeAsmop(right,NULL,ic,TRUE);
5138 aopOp(left,ic,FALSE);
5139 aopOp(result,ic,FALSE);
5141 size = getSize(operandType(result));
5144 emitcode("; shift left ","result %d, left %d",size,
5148 /* I suppose that the left size >= result size */
5151 movLeft2Result(left, size, result, size, 0);
5155 else if(shCount >= (size * 8))
5157 aopPut(AOP(result),zero,size);
5161 genlshOne (result,left,shCount);
5166 genlshTwo (result,left,shCount);
5170 genlshFour (result,left,shCount);
5174 freeAsmop(left,NULL,ic,TRUE);
5175 freeAsmop(result,NULL,ic,TRUE);
5178 /*-----------------------------------------------------------------*/
5179 /* genLeftShift - generates code for left shifting */
5180 /*-----------------------------------------------------------------*/
5181 static void genLeftShift (iCode *ic)
5183 operand *left,*right, *result;
5186 symbol *tlbl , *tlbl1;
5188 right = IC_RIGHT(ic);
5190 result = IC_RESULT(ic);
5192 aopOp(right,ic,FALSE);
5194 /* if the shift count is known then do it
5195 as efficiently as possible */
5196 if (AOP_TYPE(right) == AOP_LIT) {
5197 genLeftShiftLiteral (left,right,result,ic);
5201 /* shift count is unknown then we have to form
5202 a loop get the loop count in B : Note: we take
5203 only the lower order byte since shifting
5204 more that 32 bits make no sense anyway, ( the
5205 largest size of an object can be only 32 bits ) */
5207 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5208 emitcode("inc","b");
5209 freeAsmop (right,NULL,ic,TRUE);
5210 aopOp(left,ic,FALSE);
5211 aopOp(result,ic,FALSE);
5213 /* now move the left to the result if they are not the
5215 if (!sameRegs(AOP(left),AOP(result)) &&
5216 AOP_SIZE(result) > 1) {
5218 size = AOP_SIZE(result);
5221 l = aopGet(AOP(left),offset,FALSE,TRUE);
5222 if (*l == '@' && (IS_AOP_PREG(result))) {
5224 emitcode("mov","a,%s",l);
5225 aopPut(AOP(result),"a",offset);
5227 aopPut(AOP(result),l,offset);
5232 tlbl = newiTempLabel(NULL);
5233 size = AOP_SIZE(result);
5235 tlbl1 = newiTempLabel(NULL);
5237 /* if it is only one byte then */
5239 symbol *tlbl1 = newiTempLabel(NULL);
5241 l = aopGet(AOP(left),0,FALSE,FALSE);
5243 emitcode("sjmp","%05d$",tlbl1->key+100);
5244 emitcode("","%05d$:",tlbl->key+100);
5245 emitcode("add","a,acc");
5246 emitcode("","%05d$:",tlbl1->key+100);
5247 emitcode("djnz","b,%05d$",tlbl->key+100);
5248 aopPut(AOP(result),"a",0);
5252 reAdjustPreg(AOP(result));
5254 emitcode("sjmp","%05d$",tlbl1->key+100);
5255 emitcode("","%05d$:",tlbl->key+100);
5256 l = aopGet(AOP(result),offset,FALSE,FALSE);
5258 emitcode("add","a,acc");
5259 aopPut(AOP(result),"a",offset++);
5261 l = aopGet(AOP(result),offset,FALSE,FALSE);
5263 emitcode("rlc","a");
5264 aopPut(AOP(result),"a",offset++);
5266 reAdjustPreg(AOP(result));
5268 emitcode("","%05d$:",tlbl1->key+100);
5269 emitcode("djnz","b,%05d$",tlbl->key+100);
5271 freeAsmop(left,NULL,ic,TRUE);
5272 freeAsmop(result,NULL,ic,TRUE);
5275 /*-----------------------------------------------------------------*/
5276 /* genrshOne - right shift a one byte quantity by known count */
5277 /*-----------------------------------------------------------------*/
5278 static void genrshOne (operand *result, operand *left,
5279 int shCount, int sign)
5281 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
5284 /*-----------------------------------------------------------------*/
5285 /* genrshTwo - right shift two bytes by known amount != 0 */
5286 /*-----------------------------------------------------------------*/
5287 static void genrshTwo (operand *result,operand *left,
5288 int shCount, int sign)
5290 /* if shCount >= 8 */
5294 shiftR1Left2Result(left, MSB16, result, LSB,
5297 movLeft2Result(left, MSB16, result, LSB, sign);
5298 addSign(result, MSB16, sign);
5301 /* 1 <= shCount <= 7 */
5303 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
5306 /*-----------------------------------------------------------------*/
5307 /* shiftRLong - shift right one long from left to result */
5308 /* offl = LSB or MSB16 */
5309 /*-----------------------------------------------------------------*/
5310 static void shiftRLong (operand *left, int offl,
5311 operand *result, int sign)
5314 emitcode("clr","c");
5315 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
5317 emitcode("mov","c,acc.7");
5318 emitcode("rrc","a");
5319 aopPut(AOP(result),"a",MSB32-offl);
5321 /* add sign of "a" */
5322 addSign(result, MSB32, sign);
5324 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
5325 emitcode("rrc","a");
5326 aopPut(AOP(result),"a",MSB24-offl);
5328 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
5329 emitcode("rrc","a");
5330 aopPut(AOP(result),"a",MSB16-offl);
5333 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
5334 emitcode("rrc","a");
5335 aopPut(AOP(result),"a",LSB);
5339 /*-----------------------------------------------------------------*/
5340 /* genrshFour - shift four byte by a known amount != 0 */
5341 /*-----------------------------------------------------------------*/
5342 static void genrshFour (operand *result, operand *left,
5343 int shCount, int sign)
5345 /* if shifting more that 3 bytes */
5346 if(shCount >= 24 ) {
5349 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
5351 movLeft2Result(left, MSB32, result, LSB, sign);
5352 addSign(result, MSB16, sign);
5354 else if(shCount >= 16){
5357 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
5359 movLeft2Result(left, MSB24, result, LSB, 0);
5360 movLeft2Result(left, MSB32, result, MSB16, sign);
5362 addSign(result, MSB24, sign);
5364 else if(shCount >= 8){
5367 shiftRLong(left, MSB16, result, sign);
5368 else if(shCount == 0){
5369 movLeft2Result(left, MSB16, result, LSB, 0);
5370 movLeft2Result(left, MSB24, result, MSB16, 0);
5371 movLeft2Result(left, MSB32, result, MSB24, sign);
5372 addSign(result, MSB32, sign);
5375 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
5376 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
5377 /* the last shift is signed */
5378 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
5379 addSign(result, MSB32, sign);
5382 else{ /* 1 <= shCount <= 7 */
5384 shiftRLong(left, LSB, result, sign);
5386 shiftRLong(result, LSB, result, sign);
5389 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
5390 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
5391 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
5396 /*-----------------------------------------------------------------*/
5397 /* genRightShiftLiteral - right shifting by known count */
5398 /*-----------------------------------------------------------------*/
5399 static void genRightShiftLiteral (operand *left,
5405 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5408 freeAsmop(right,NULL,ic,TRUE);
5410 aopOp(left,ic,FALSE);
5411 aopOp(result,ic,FALSE);
5414 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
5418 size = getDataSize(left);
5419 /* test the LEFT size !!! */
5421 /* I suppose that the left size >= result size */
5423 size = getDataSize(result);
5425 movLeft2Result(left, size, result, size, 0);
5428 else if(shCount >= (size * 8)){
5430 /* get sign in acc.7 */
5431 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
5432 addSign(result, LSB, sign);
5436 genrshOne (result,left,shCount,sign);
5440 genrshTwo (result,left,shCount,sign);
5444 genrshFour (result,left,shCount,sign);
5450 freeAsmop(left,NULL,ic,TRUE);
5451 freeAsmop(result,NULL,ic,TRUE);
5455 /*-----------------------------------------------------------------*/
5456 /* genSignedRightShift - right shift of signed number */
5457 /*-----------------------------------------------------------------*/
5458 static void genSignedRightShift (iCode *ic)
5460 operand *right, *left, *result;
5463 symbol *tlbl, *tlbl1 ;
5465 /* we do it the hard way put the shift count in b
5466 and loop thru preserving the sign */
5468 right = IC_RIGHT(ic);
5470 result = IC_RESULT(ic);
5472 aopOp(right,ic,FALSE);
5475 if ( AOP_TYPE(right) == AOP_LIT) {
5476 genRightShiftLiteral (left,right,result,ic,1);
5479 /* shift count is unknown then we have to form
5480 a loop get the loop count in B : Note: we take
5481 only the lower order byte since shifting
5482 more that 32 bits make no sense anyway, ( the
5483 largest size of an object can be only 32 bits ) */
5485 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5486 emitcode("inc","b");
5487 freeAsmop (right,NULL,ic,TRUE);
5488 aopOp(left,ic,FALSE);
5489 aopOp(result,ic,FALSE);
5491 /* now move the left to the result if they are not the
5493 if (!sameRegs(AOP(left),AOP(result)) &&
5494 AOP_SIZE(result) > 1) {
5496 size = AOP_SIZE(result);
5499 l = aopGet(AOP(left),offset,FALSE,TRUE);
5500 if (*l == '@' && IS_AOP_PREG(result)) {
5502 emitcode("mov","a,%s",l);
5503 aopPut(AOP(result),"a",offset);
5505 aopPut(AOP(result),l,offset);
5510 /* mov the highest order bit to OVR */
5511 tlbl = newiTempLabel(NULL);
5512 tlbl1= newiTempLabel(NULL);
5514 size = AOP_SIZE(result);
5516 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
5517 emitcode("rlc","a");
5518 emitcode("mov","ov,c");
5519 /* if it is only one byte then */
5521 l = aopGet(AOP(left),0,FALSE,FALSE);
5523 emitcode("sjmp","%05d$",tlbl1->key+100);
5524 emitcode("","%05d$:",tlbl->key+100);
5525 emitcode("mov","c,ov");
5526 emitcode("rrc","a");
5527 emitcode("","%05d$:",tlbl1->key+100);
5528 emitcode("djnz","b,%05d$",tlbl->key+100);
5529 aopPut(AOP(result),"a",0);
5533 reAdjustPreg(AOP(result));
5534 emitcode("sjmp","%05d$",tlbl1->key+100);
5535 emitcode("","%05d$:",tlbl->key+100);
5536 emitcode("mov","c,ov");
5538 l = aopGet(AOP(result),offset,FALSE,FALSE);
5540 emitcode("rrc","a");
5541 aopPut(AOP(result),"a",offset--);
5543 reAdjustPreg(AOP(result));
5544 emitcode("","%05d$:",tlbl1->key+100);
5545 emitcode("djnz","b,%05d$",tlbl->key+100);
5548 freeAsmop(left,NULL,ic,TRUE);
5549 freeAsmop(result,NULL,ic,TRUE);
5552 /*-----------------------------------------------------------------*/
5553 /* genRightShift - generate code for right shifting */
5554 /*-----------------------------------------------------------------*/
5555 static void genRightShift (iCode *ic)
5557 operand *right, *left, *result;
5561 symbol *tlbl, *tlbl1 ;
5563 /* if signed then we do it the hard way preserve the
5564 sign bit moving it inwards */
5565 retype = getSpec(operandType(IC_RESULT(ic)));
5567 if (!SPEC_USIGN(retype)) {
5568 genSignedRightShift (ic);
5572 /* signed & unsigned types are treated the same : i.e. the
5573 signed is NOT propagated inwards : quoting from the
5574 ANSI - standard : "for E1 >> E2, is equivalent to division
5575 by 2**E2 if unsigned or if it has a non-negative value,
5576 otherwise the result is implementation defined ", MY definition
5577 is that the sign does not get propagated */
5579 right = IC_RIGHT(ic);
5581 result = IC_RESULT(ic);
5583 aopOp(right,ic,FALSE);
5585 /* if the shift count is known then do it
5586 as efficiently as possible */
5587 if (AOP_TYPE(right) == AOP_LIT) {
5588 genRightShiftLiteral (left,right,result,ic, 0);
5592 /* shift count is unknown then we have to form
5593 a loop get the loop count in B : Note: we take
5594 only the lower order byte since shifting
5595 more that 32 bits make no sense anyway, ( the
5596 largest size of an object can be only 32 bits ) */
5598 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5599 emitcode("inc","b");
5600 freeAsmop (right,NULL,ic,TRUE);
5601 aopOp(left,ic,FALSE);
5602 aopOp(result,ic,FALSE);
5604 /* now move the left to the result if they are not the
5606 if (!sameRegs(AOP(left),AOP(result)) &&
5607 AOP_SIZE(result) > 1) {
5609 size = AOP_SIZE(result);
5612 l = aopGet(AOP(left),offset,FALSE,TRUE);
5613 if (*l == '@' && IS_AOP_PREG(result)) {
5615 emitcode("mov","a,%s",l);
5616 aopPut(AOP(result),"a",offset);
5618 aopPut(AOP(result),l,offset);
5623 tlbl = newiTempLabel(NULL);
5624 tlbl1= newiTempLabel(NULL);
5625 size = AOP_SIZE(result);
5628 /* if it is only one byte then */
5630 l = aopGet(AOP(left),0,FALSE,FALSE);
5632 emitcode("sjmp","%05d$",tlbl1->key+100);
5633 emitcode("","%05d$:",tlbl->key+100);
5635 emitcode("rrc","a");
5636 emitcode("","%05d$:",tlbl1->key+100);
5637 emitcode("djnz","b,%05d$",tlbl->key+100);
5638 aopPut(AOP(result),"a",0);
5642 reAdjustPreg(AOP(result));
5643 emitcode("sjmp","%05d$",tlbl1->key+100);
5644 emitcode("","%05d$:",tlbl->key+100);
5647 l = aopGet(AOP(result),offset,FALSE,FALSE);
5649 emitcode("rrc","a");
5650 aopPut(AOP(result),"a",offset--);
5652 reAdjustPreg(AOP(result));
5654 emitcode("","%05d$:",tlbl1->key+100);
5655 emitcode("djnz","b,%05d$",tlbl->key+100);
5658 freeAsmop(left,NULL,ic,TRUE);
5659 freeAsmop(result,NULL,ic,TRUE);
5662 /*-----------------------------------------------------------------*/
5663 /* genUnpackBits - generates code for unpacking bits */
5664 /*-----------------------------------------------------------------*/
5665 static void genUnpackBits (operand *result, char *rname, int ptype)
5672 etype = getSpec(operandType(result));
5674 /* read the first byte */
5679 emitcode("mov","a,@%s",rname);
5683 emitcode("movx","a,@%s",rname);
5687 emitcode("movx","a,@dptr");
5691 emitcode("clr","a");
5692 emitcode("movc","a","@a+dptr");
5696 emitcode("lcall","__gptrget");
5700 /* if we have bitdisplacement then it fits */
5701 /* into this byte completely or if length is */
5702 /* less than a byte */
5703 if ((shCnt = SPEC_BSTR(etype)) ||
5704 (SPEC_BLEN(etype) <= 8)) {
5706 /* shift right acc */
5709 emitcode("anl","a,#0x%02x",
5710 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
5711 aopPut(AOP(result),"a",offset);
5715 /* bit field did not fit in a byte */
5716 rlen = SPEC_BLEN(etype) - 8;
5717 aopPut(AOP(result),"a",offset++);
5724 emitcode("inc","%s",rname);
5725 emitcode("mov","a,@%s",rname);
5729 emitcode("inc","%s",rname);
5730 emitcode("movx","a,@%s",rname);
5734 emitcode("inc","dptr");
5735 emitcode("movx","a,@dptr");
5739 emitcode("clr","a");
5740 emitcode("inc","dptr");
5741 emitcode("movc","a","@a+dptr");
5745 emitcode("inc","dptr");
5746 emitcode("lcall","__gptrget");
5751 /* if we are done */
5755 aopPut(AOP(result),"a",offset++);
5760 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
5761 aopPut(AOP(result),"a",offset);
5768 /*-----------------------------------------------------------------*/
5769 /* genDataPointerGet - generates code when ptr offset is known */
5770 /*-----------------------------------------------------------------*/
5771 static void genDataPointerGet (operand *left,
5777 int size , offset = 0;
5778 aopOp(result,ic,TRUE);
5780 /* get the string representation of the name */
5781 l = aopGet(AOP(left),0,FALSE,TRUE);
5782 size = AOP_SIZE(result);
5785 sprintf(buffer,"(%s + %d)",l+1,offset);
5787 sprintf(buffer,"%s",l+1);
5788 aopPut(AOP(result),buffer,offset++);
5791 freeAsmop(left,NULL,ic,TRUE);
5792 freeAsmop(result,NULL,ic,TRUE);
5795 /*-----------------------------------------------------------------*/
5796 /* genNearPointerGet - emitcode for near pointer fetch */
5797 /*-----------------------------------------------------------------*/
5798 static void genNearPointerGet (operand *left,
5805 link *rtype, *retype;
5806 link *ltype = operandType(left);
5809 rtype = operandType(result);
5810 retype= getSpec(rtype);
5812 aopOp(left,ic,FALSE);
5814 /* if left is rematerialisable and
5815 result is not bit variable type and
5816 the left is pointer to data space i.e
5817 lower 128 bytes of space */
5818 if (AOP_TYPE(left) == AOP_IMMD &&
5819 !IS_BITVAR(retype) &&
5820 DCL_TYPE(ltype) == POINTER) {
5821 genDataPointerGet (left,result,ic);
5825 /* if the value is already in a pointer register
5826 then don't need anything more */
5827 if (!AOP_INPREG(AOP(left))) {
5828 /* otherwise get a free pointer register */
5830 preg = getFreePtr(ic,&aop,FALSE);
5831 emitcode("mov","%s,%s",
5833 aopGet(AOP(left),0,FALSE,TRUE));
5834 rname = preg->name ;
5836 rname = aopGet(AOP(left),0,FALSE,FALSE);
5838 freeAsmop(left,NULL,ic,TRUE);
5839 aopOp (result,ic,FALSE);
5841 /* if bitfield then unpack the bits */
5842 if (IS_BITVAR(retype))
5843 genUnpackBits (result,rname,POINTER);
5845 /* we have can just get the values */
5846 int size = AOP_SIZE(result);
5850 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
5852 emitcode("mov","a,@%s",rname);
5853 aopPut(AOP(result),"a",offset);
5855 sprintf(buffer,"@%s",rname);
5856 aopPut(AOP(result),buffer,offset);
5860 emitcode("inc","%s",rname);
5864 /* now some housekeeping stuff */
5866 /* we had to allocate for this iCode */
5867 freeAsmop(NULL,aop,ic,TRUE);
5869 /* we did not allocate which means left
5870 already in a pointer register, then
5871 if size > 0 && this could be used again
5872 we have to point it back to where it
5874 if (AOP_SIZE(result) > 1 &&
5875 !OP_SYMBOL(left)->remat &&
5876 ( OP_SYMBOL(left)->liveTo > ic->seq ||
5878 int size = AOP_SIZE(result) - 1;
5880 emitcode("dec","%s",rname);
5885 freeAsmop(result,NULL,ic,TRUE);
5889 /*-----------------------------------------------------------------*/
5890 /* genPagedPointerGet - emitcode for paged pointer fetch */
5891 /*-----------------------------------------------------------------*/
5892 static void genPagedPointerGet (operand *left,
5899 link *rtype, *retype;
5901 rtype = operandType(result);
5902 retype= getSpec(rtype);
5904 aopOp(left,ic,FALSE);
5906 /* if the value is already in a pointer register
5907 then don't need anything more */
5908 if (!AOP_INPREG(AOP(left))) {
5909 /* otherwise get a free pointer register */
5911 preg = getFreePtr(ic,&aop,FALSE);
5912 emitcode("mov","%s,%s",
5914 aopGet(AOP(left),0,FALSE,TRUE));
5915 rname = preg->name ;
5917 rname = aopGet(AOP(left),0,FALSE,FALSE);
5919 freeAsmop(left,NULL,ic,TRUE);
5920 aopOp (result,ic,FALSE);
5922 /* if bitfield then unpack the bits */
5923 if (IS_BITVAR(retype))
5924 genUnpackBits (result,rname,PPOINTER);
5926 /* we have can just get the values */
5927 int size = AOP_SIZE(result);
5932 emitcode("movx","a,@%s",rname);
5933 aopPut(AOP(result),"a",offset);
5938 emitcode("inc","%s",rname);
5942 /* now some housekeeping stuff */
5944 /* we had to allocate for this iCode */
5945 freeAsmop(NULL,aop,ic,TRUE);
5947 /* we did not allocate which means left
5948 already in a pointer register, then
5949 if size > 0 && this could be used again
5950 we have to point it back to where it
5952 if (AOP_SIZE(result) > 1 &&
5953 !OP_SYMBOL(left)->remat &&
5954 ( OP_SYMBOL(left)->liveTo > ic->seq ||
5956 int size = AOP_SIZE(result) - 1;
5958 emitcode("dec","%s",rname);
5963 freeAsmop(result,NULL,ic,TRUE);
5968 /*-----------------------------------------------------------------*/
5969 /* genFarPointerGet - gget value from far space */
5970 /*-----------------------------------------------------------------*/
5971 static void genFarPointerGet (operand *left,
5972 operand *result, iCode *ic)
5975 link *retype = getSpec(operandType(result));
5977 aopOp(left,ic,FALSE);
5979 /* if the operand is already in dptr
5980 then we do nothing else we move the value to dptr */
5981 if (AOP_TYPE(left) != AOP_STR) {
5982 /* if this is remateriazable */
5983 if (AOP_TYPE(left) == AOP_IMMD)
5984 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
5985 else { /* we need to get it byte by byte */
5986 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
5987 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
5988 if (options.model == MODEL_FLAT24)
5990 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
5994 /* so dptr know contains the address */
5995 freeAsmop(left,NULL,ic,TRUE);
5996 aopOp(result,ic,FALSE);
5998 /* if bit then unpack */
5999 if (IS_BITVAR(retype))
6000 genUnpackBits(result,"dptr",FPOINTER);
6002 size = AOP_SIZE(result);
6006 emitcode("movx","a,@dptr");
6007 aopPut(AOP(result),"a",offset++);
6009 emitcode("inc","dptr");
6013 freeAsmop(result,NULL,ic,TRUE);
6016 /*-----------------------------------------------------------------*/
6017 /* emitcodePointerGet - gget value from code space */
6018 /*-----------------------------------------------------------------*/
6019 static void emitcodePointerGet (operand *left,
6020 operand *result, iCode *ic)
6023 link *retype = getSpec(operandType(result));
6025 aopOp(left,ic,FALSE);
6027 /* if the operand is already in dptr
6028 then we do nothing else we move the value to dptr */
6029 if (AOP_TYPE(left) != AOP_STR) {
6030 /* if this is remateriazable */
6031 if (AOP_TYPE(left) == AOP_IMMD)
6032 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6033 else { /* we need to get it byte by byte */
6034 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6035 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6036 if (options.model == MODEL_FLAT24)
6038 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6042 /* so dptr know contains the address */
6043 freeAsmop(left,NULL,ic,TRUE);
6044 aopOp(result,ic,FALSE);
6046 /* if bit then unpack */
6047 if (IS_BITVAR(retype))
6048 genUnpackBits(result,"dptr",CPOINTER);
6050 size = AOP_SIZE(result);
6054 emitcode("clr","a");
6055 emitcode("movc","a,@a+dptr");
6056 aopPut(AOP(result),"a",offset++);
6058 emitcode("inc","dptr");
6062 freeAsmop(result,NULL,ic,TRUE);
6065 /*-----------------------------------------------------------------*/
6066 /* genGenPointerGet - gget value from generic pointer space */
6067 /*-----------------------------------------------------------------*/
6068 static void genGenPointerGet (operand *left,
6069 operand *result, iCode *ic)
6072 link *retype = getSpec(operandType(result));
6074 aopOp(left,ic,FALSE);
6076 /* if the operand is already in dptr
6077 then we do nothing else we move the value to dptr */
6078 if (AOP_TYPE(left) != AOP_STR) {
6079 /* if this is remateriazable */
6080 if (AOP_TYPE(left) == AOP_IMMD) {
6081 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6082 emitcode("mov","b,#%d",pointerCode(retype));
6084 else { /* we need to get it byte by byte */
6085 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6086 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6087 if (options.model == MODEL_FLAT24)
6089 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6090 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
6094 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
6098 /* so dptr know contains the address */
6099 freeAsmop(left,NULL,ic,TRUE);
6100 aopOp(result,ic,FALSE);
6102 /* if bit then unpack */
6103 if (IS_BITVAR(retype))
6104 genUnpackBits(result,"dptr",GPOINTER);
6106 size = AOP_SIZE(result);
6110 emitcode("lcall","__gptrget");
6111 aopPut(AOP(result),"a",offset++);
6113 emitcode("inc","dptr");
6117 freeAsmop(result,NULL,ic,TRUE);
6120 /*-----------------------------------------------------------------*/
6121 /* genPointerGet - generate code for pointer get */
6122 /*-----------------------------------------------------------------*/
6123 static void genPointerGet (iCode *ic)
6125 operand *left, *result ;
6130 result = IC_RESULT(ic) ;
6132 /* depending on the type of pointer we need to
6133 move it to the correct pointer register */
6134 type = operandType(left);
6135 etype = getSpec(type);
6136 /* if left is of type of pointer then it is simple */
6137 if (IS_PTR(type) && !IS_FUNC(type->next))
6138 p_type = DCL_TYPE(type);
6140 /* we have to go by the storage class */
6141 p_type = PTR_TYPE(SPEC_OCLS(etype));
6143 /* if (SPEC_OCLS(etype)->codesp ) { */
6144 /* p_type = CPOINTER ; */
6147 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6148 /* p_type = FPOINTER ; */
6150 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6151 /* p_type = PPOINTER; */
6153 /* if (SPEC_OCLS(etype) == idata ) */
6154 /* p_type = IPOINTER; */
6156 /* p_type = POINTER ; */
6159 /* now that we have the pointer type we assign
6160 the pointer values */
6165 genNearPointerGet (left,result,ic);
6169 genPagedPointerGet(left,result,ic);
6173 genFarPointerGet (left,result,ic);
6177 emitcodePointerGet (left,result,ic);
6181 genGenPointerGet (left,result,ic);
6187 /*-----------------------------------------------------------------*/
6188 /* genPackBits - generates code for packed bit storage */
6189 /*-----------------------------------------------------------------*/
6190 static void genPackBits (link *etype ,
6192 char *rname, int p_type)
6200 blen = SPEC_BLEN(etype);
6201 bstr = SPEC_BSTR(etype);
6203 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6206 /* if the bit lenth is less than or */
6207 /* it exactly fits a byte then */
6208 if (SPEC_BLEN(etype) <= 8 ) {
6209 shCount = SPEC_BSTR(etype) ;
6211 /* shift left acc */
6214 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6219 emitcode ("mov","b,a");
6220 emitcode("mov","a,@%s",rname);
6224 emitcode ("mov","b,a");
6225 emitcode("movx","a,@dptr");
6229 emitcode ("push","b");
6230 emitcode ("push","acc");
6231 emitcode ("lcall","__gptrget");
6232 emitcode ("pop","b");
6236 emitcode ("anl","a,#0x%02x",(unsigned char)
6237 ((unsigned char)(0xFF << (blen+bstr)) |
6238 (unsigned char)(0xFF >> (8-bstr)) ) );
6239 emitcode ("orl","a,b");
6240 if (p_type == GPOINTER)
6241 emitcode("pop","b");
6247 emitcode("mov","@%s,a",rname);
6251 emitcode("movx","@dptr,a");
6255 emitcode("lcall","__gptrput");
6260 if ( SPEC_BLEN(etype) <= 8 )
6263 emitcode("inc","%s",rname);
6264 rLen = SPEC_BLEN(etype) ;
6266 /* now generate for lengths greater than one byte */
6269 l = aopGet(AOP(right),offset++,FALSE,TRUE);
6279 emitcode("mov","@%s,a",rname);
6281 emitcode("mov","@%s,%s",rname,l);
6286 emitcode("movx","@dptr,a");
6291 emitcode("lcall","__gptrput");
6294 emitcode ("inc","%s",rname);
6299 /* last last was not complete */
6301 /* save the byte & read byte */
6304 emitcode ("mov","b,a");
6305 emitcode("mov","a,@%s",rname);
6309 emitcode ("mov","b,a");
6310 emitcode("movx","a,@dptr");
6314 emitcode ("push","b");
6315 emitcode ("push","acc");
6316 emitcode ("lcall","__gptrget");
6317 emitcode ("pop","b");
6321 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
6322 emitcode ("orl","a,b");
6325 if (p_type == GPOINTER)
6326 emitcode("pop","b");
6331 emitcode("mov","@%s,a",rname);
6335 emitcode("movx","@dptr,a");
6339 emitcode("lcall","__gptrput");
6343 /*-----------------------------------------------------------------*/
6344 /* genDataPointerSet - remat pointer to data space */
6345 /*-----------------------------------------------------------------*/
6346 static void genDataPointerSet(operand *right,
6350 int size, offset = 0 ;
6351 char *l, buffer[256];
6353 aopOp(right,ic,FALSE);
6355 l = aopGet(AOP(result),0,FALSE,TRUE);
6356 size = AOP_SIZE(right);
6359 sprintf(buffer,"(%s + %d)",l+1,offset);
6361 sprintf(buffer,"%s",l+1);
6362 emitcode("mov","%s,%s",buffer,
6363 aopGet(AOP(right),offset++,FALSE,FALSE));
6366 freeAsmop(right,NULL,ic,TRUE);
6367 freeAsmop(result,NULL,ic,TRUE);
6370 /*-----------------------------------------------------------------*/
6371 /* genNearPointerSet - emitcode for near pointer put */
6372 /*-----------------------------------------------------------------*/
6373 static void genNearPointerSet (operand *right,
6381 link *ptype = operandType(result);
6383 retype= getSpec(operandType(right));
6385 aopOp(result,ic,FALSE);
6387 /* if the result is rematerializable &
6388 in data space & not a bit variable */
6389 if (AOP_TYPE(result) == AOP_IMMD &&
6390 DCL_TYPE(ptype) == POINTER &&
6391 !IS_BITVAR(retype)) {
6392 genDataPointerSet (right,result,ic);
6396 /* if the value is already in a pointer register
6397 then don't need anything more */
6398 if (!AOP_INPREG(AOP(result))) {
6399 /* otherwise get a free pointer register */
6401 preg = getFreePtr(ic,&aop,FALSE);
6402 emitcode("mov","%s,%s",
6404 aopGet(AOP(result),0,FALSE,TRUE));
6405 rname = preg->name ;
6407 rname = aopGet(AOP(result),0,FALSE,FALSE);
6409 freeAsmop(result,NULL,ic,TRUE);
6410 aopOp (right,ic,FALSE);
6412 /* if bitfield then unpack the bits */
6413 if (IS_BITVAR(retype))
6414 genPackBits (retype,right,rname,POINTER);
6416 /* we have can just get the values */
6417 int size = AOP_SIZE(right);
6421 l = aopGet(AOP(right),offset,FALSE,TRUE);
6424 emitcode("mov","@%s,a",rname);
6426 emitcode("mov","@%s,%s",rname,l);
6428 emitcode("inc","%s",rname);
6433 /* now some housekeeping stuff */
6435 /* we had to allocate for this iCode */
6436 freeAsmop(NULL,aop,ic,TRUE);
6438 /* we did not allocate which means left
6439 already in a pointer register, then
6440 if size > 0 && this could be used again
6441 we have to point it back to where it
6443 if (AOP_SIZE(right) > 1 &&
6444 !OP_SYMBOL(result)->remat &&
6445 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6447 int size = AOP_SIZE(right) - 1;
6449 emitcode("dec","%s",rname);
6454 freeAsmop(right,NULL,ic,TRUE);
6459 /*-----------------------------------------------------------------*/
6460 /* genPagedPointerSet - emitcode for Paged pointer put */
6461 /*-----------------------------------------------------------------*/
6462 static void genPagedPointerSet (operand *right,
6471 retype= getSpec(operandType(right));
6473 aopOp(result,ic,FALSE);
6475 /* if the value is already in a pointer register
6476 then don't need anything more */
6477 if (!AOP_INPREG(AOP(result))) {
6478 /* otherwise get a free pointer register */
6480 preg = getFreePtr(ic,&aop,FALSE);
6481 emitcode("mov","%s,%s",
6483 aopGet(AOP(result),0,FALSE,TRUE));
6484 rname = preg->name ;
6486 rname = aopGet(AOP(result),0,FALSE,FALSE);
6488 freeAsmop(result,NULL,ic,TRUE);
6489 aopOp (right,ic,FALSE);
6491 /* if bitfield then unpack the bits */
6492 if (IS_BITVAR(retype))
6493 genPackBits (retype,right,rname,PPOINTER);
6495 /* we have can just get the values */
6496 int size = AOP_SIZE(right);
6500 l = aopGet(AOP(right),offset,FALSE,TRUE);
6503 emitcode("movx","@%s,a",rname);
6506 emitcode("inc","%s",rname);
6512 /* now some housekeeping stuff */
6514 /* we had to allocate for this iCode */
6515 freeAsmop(NULL,aop,ic,TRUE);
6517 /* we did not allocate which means left
6518 already in a pointer register, then
6519 if size > 0 && this could be used again
6520 we have to point it back to where it
6522 if (AOP_SIZE(right) > 1 &&
6523 !OP_SYMBOL(result)->remat &&
6524 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6526 int size = AOP_SIZE(right) - 1;
6528 emitcode("dec","%s",rname);
6533 freeAsmop(right,NULL,ic,TRUE);
6538 /*-----------------------------------------------------------------*/
6539 /* genFarPointerSet - set value from far space */
6540 /*-----------------------------------------------------------------*/
6541 static void genFarPointerSet (operand *right,
6542 operand *result, iCode *ic)
6545 link *retype = getSpec(operandType(right));
6547 aopOp(result,ic,FALSE);
6549 /* if the operand is already in dptr
6550 then we do nothing else we move the value to dptr */
6551 if (AOP_TYPE(result) != AOP_STR) {
6552 /* if this is remateriazable */
6553 if (AOP_TYPE(result) == AOP_IMMD)
6554 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6555 else { /* we need to get it byte by byte */
6556 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6557 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6558 if (options.model == MODEL_FLAT24)
6560 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6564 /* so dptr know contains the address */
6565 freeAsmop(result,NULL,ic,TRUE);
6566 aopOp(right,ic,FALSE);
6568 /* if bit then unpack */
6569 if (IS_BITVAR(retype))
6570 genPackBits(retype,right,"dptr",FPOINTER);
6572 size = AOP_SIZE(right);
6576 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6578 emitcode("movx","@dptr,a");
6580 emitcode("inc","dptr");
6584 freeAsmop(right,NULL,ic,TRUE);
6587 /*-----------------------------------------------------------------*/
6588 /* genGenPointerSet - set value from generic pointer space */
6589 /*-----------------------------------------------------------------*/
6590 static void genGenPointerSet (operand *right,
6591 operand *result, iCode *ic)
6594 link *retype = getSpec(operandType(right));
6596 aopOp(result,ic,FALSE);
6598 /* if the operand is already in dptr
6599 then we do nothing else we move the value to dptr */
6600 if (AOP_TYPE(result) != AOP_STR) {
6601 /* if this is remateriazable */
6602 if (AOP_TYPE(result) == AOP_IMMD) {
6603 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6604 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
6606 else { /* we need to get it byte by byte */
6607 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6608 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6609 if (options.model == MODEL_FLAT24)
6611 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6612 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
6616 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
6620 /* so dptr know contains the address */
6621 freeAsmop(result,NULL,ic,TRUE);
6622 aopOp(right,ic,FALSE);
6624 /* if bit then unpack */
6625 if (IS_BITVAR(retype))
6626 genPackBits(retype,right,"dptr",GPOINTER);
6628 size = AOP_SIZE(right);
6632 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6634 emitcode("lcall","__gptrput");
6636 emitcode("inc","dptr");
6640 freeAsmop(right,NULL,ic,TRUE);
6643 /*-----------------------------------------------------------------*/
6644 /* genPointerSet - stores the value into a pointer location */
6645 /*-----------------------------------------------------------------*/
6646 static void genPointerSet (iCode *ic)
6648 operand *right, *result ;
6652 right = IC_RIGHT(ic);
6653 result = IC_RESULT(ic) ;
6655 /* depending on the type of pointer we need to
6656 move it to the correct pointer register */
6657 type = operandType(result);
6658 etype = getSpec(type);
6659 /* if left is of type of pointer then it is simple */
6660 if (IS_PTR(type) && !IS_FUNC(type->next)) {
6661 p_type = DCL_TYPE(type);
6664 /* we have to go by the storage class */
6665 p_type = PTR_TYPE(SPEC_OCLS(etype));
6667 /* if (SPEC_OCLS(etype)->codesp ) { */
6668 /* p_type = CPOINTER ; */
6671 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6672 /* p_type = FPOINTER ; */
6674 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6675 /* p_type = PPOINTER ; */
6677 /* if (SPEC_OCLS(etype) == idata ) */
6678 /* p_type = IPOINTER ; */
6680 /* p_type = POINTER ; */
6683 /* now that we have the pointer type we assign
6684 the pointer values */
6689 genNearPointerSet (right,result,ic);
6693 genPagedPointerSet (right,result,ic);
6697 genFarPointerSet (right,result,ic);
6701 genGenPointerSet (right,result,ic);
6707 /*-----------------------------------------------------------------*/
6708 /* genIfx - generate code for Ifx statement */
6709 /*-----------------------------------------------------------------*/
6710 static void genIfx (iCode *ic, iCode *popIc)
6712 operand *cond = IC_COND(ic);
6715 aopOp(cond,ic,FALSE);
6717 /* get the value into acc */
6718 if (AOP_TYPE(cond) != AOP_CRY)
6722 /* the result is now in the accumulator */
6723 freeAsmop(cond,NULL,ic,TRUE);
6725 /* if there was something to be popped then do it */
6729 /* if the condition is a bit variable */
6730 if (isbit && IS_ITEMP(cond) &&
6732 genIfxJump(ic,SPIL_LOC(cond)->rname);
6734 if (isbit && !IS_ITEMP(cond))
6735 genIfxJump(ic,OP_SYMBOL(cond)->rname);
6742 /*-----------------------------------------------------------------*/
6743 /* genAddrOf - generates code for address of */
6744 /*-----------------------------------------------------------------*/
6745 static void genAddrOf (iCode *ic)
6747 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
6750 aopOp(IC_RESULT(ic),ic,FALSE);
6752 /* if the operand is on the stack then we
6753 need to get the stack offset of this
6756 /* if it has an offset then we need to compute
6759 emitcode("mov","a,_bp");
6760 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
6761 aopPut(AOP(IC_RESULT(ic)),"a",0);
6763 /* we can just move _bp */
6764 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
6765 /* fill the result with zero */
6766 size = AOP_SIZE(IC_RESULT(ic)) - 1;
6769 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
6774 /* object not on stack then we need the name */
6775 size = AOP_SIZE(IC_RESULT(ic));
6779 char s[SDCC_NAME_MAX];
6781 sprintf(s,"#(%s >> %d)",
6785 sprintf(s,"#%s",sym->rname);
6786 aopPut(AOP(IC_RESULT(ic)),s,offset++);
6790 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
6794 /*-----------------------------------------------------------------*/
6795 /* genFarFarAssign - assignment when both are in far space */
6796 /*-----------------------------------------------------------------*/
6797 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
6799 int size = AOP_SIZE(right);
6802 /* first push the right side on to the stack */
6804 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6806 emitcode ("push","acc");
6809 freeAsmop(right,NULL,ic,FALSE);
6810 /* now assign DPTR to result */
6811 aopOp(result,ic,FALSE);
6812 size = AOP_SIZE(result);
6814 emitcode ("pop","acc");
6815 aopPut(AOP(result),"a",--offset);
6817 freeAsmop(result,NULL,ic,FALSE);
6821 /*-----------------------------------------------------------------*/
6822 /* genAssign - generate code for assignment */
6823 /*-----------------------------------------------------------------*/
6824 static void genAssign (iCode *ic)
6826 operand *result, *right;
6828 unsigned long lit = 0L;
6830 result = IC_RESULT(ic);
6831 right = IC_RIGHT(ic) ;
6833 /* if they are the same */
6834 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
6837 aopOp(right,ic,FALSE);
6839 /* special case both in far space */
6840 if (AOP_TYPE(right) == AOP_DPTR &&
6841 IS_TRUE_SYMOP(result) &&
6842 isOperandInFarSpace(result)) {
6844 genFarFarAssign (result,right,ic);
6848 aopOp(result,ic,TRUE);
6850 /* if they are the same registers */
6851 if (sameRegs(AOP(right),AOP(result)))
6854 /* if the result is a bit */
6855 if (AOP_TYPE(result) == AOP_CRY) {
6857 /* if the right size is a literal then
6858 we know what the value is */
6859 if (AOP_TYPE(right) == AOP_LIT) {
6860 if (((int) operandLitValue(right)))
6861 aopPut(AOP(result),one,0);
6863 aopPut(AOP(result),zero,0);
6867 /* the right is also a bit variable */
6868 if (AOP_TYPE(right) == AOP_CRY) {
6869 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6870 aopPut(AOP(result),"c",0);
6876 aopPut(AOP(result),"a",0);
6880 /* bit variables done */
6882 size = AOP_SIZE(result);
6884 if(AOP_TYPE(right) == AOP_LIT)
6885 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6887 (AOP_TYPE(result) != AOP_REG) &&
6888 (AOP_TYPE(right) == AOP_LIT) &&
6889 !IS_FLOAT(operandType(right)) &&
6891 emitcode("clr","a");
6893 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
6894 aopPut(AOP(result),"a",size);
6897 aopGet(AOP(right),size,FALSE,FALSE),
6903 aopGet(AOP(right),offset,FALSE,FALSE),
6910 freeAsmop (right,NULL,ic,FALSE);
6911 freeAsmop (result,NULL,ic,TRUE);
6914 /*-----------------------------------------------------------------*/
6915 /* genJumpTab - genrates code for jump table */
6916 /*-----------------------------------------------------------------*/
6917 static void genJumpTab (iCode *ic)
6922 aopOp(IC_JTCOND(ic),ic,FALSE);
6923 /* get the condition into accumulator */
6924 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
6926 /* multiply by three */
6927 emitcode("add","a,acc");
6928 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
6929 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
6931 jtab = newiTempLabel(NULL);
6932 emitcode("mov","dptr,#%05d$",jtab->key+100);
6933 emitcode("jmp","@a+dptr");
6934 emitcode("","%05d$:",jtab->key+100);
6935 /* now generate the jump labels */
6936 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
6937 jtab = setNextItem(IC_JTLABELS(ic)))
6938 emitcode("ljmp","%05d$",jtab->key+100);
6942 /*-----------------------------------------------------------------*/
6943 /* genCast - gen code for casting */
6944 /*-----------------------------------------------------------------*/
6945 static void genCast (iCode *ic)
6947 operand *result = IC_RESULT(ic);
6948 link *ctype = operandType(IC_LEFT(ic));
6949 operand *right = IC_RIGHT(ic);
6952 /* if they are equivalent then do nothing */
6953 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
6956 aopOp(right,ic,FALSE) ;
6957 aopOp(result,ic,FALSE);
6959 /* if the result is a bit */
6960 if (AOP_TYPE(result) == AOP_CRY) {
6961 /* if the right size is a literal then
6962 we know what the value is */
6963 if (AOP_TYPE(right) == AOP_LIT) {
6964 if (((int) operandLitValue(right)))
6965 aopPut(AOP(result),one,0);
6967 aopPut(AOP(result),zero,0);
6972 /* the right is also a bit variable */
6973 if (AOP_TYPE(right) == AOP_CRY) {
6974 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6975 aopPut(AOP(result),"c",0);
6981 aopPut(AOP(result),"a",0);
6985 /* if they are the same size : or less */
6986 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
6988 /* if they are in the same place */
6989 if (sameRegs(AOP(right),AOP(result)))
6992 /* if they in different places then copy */
6993 size = AOP_SIZE(result);
6997 aopGet(AOP(right),offset,FALSE,FALSE),
7005 /* if the result is of type pointer */
7006 if (IS_PTR(ctype)) {
7009 link *type = operandType(right);
7010 link *etype = getSpec(type);
7012 /* pointer to generic pointer */
7013 if (IS_GENPTR(ctype)) {
7017 p_type = DCL_TYPE(type);
7019 /* we have to go by the storage class */
7020 p_type = PTR_TYPE(SPEC_OCLS(etype));
7022 /* if (SPEC_OCLS(etype)->codesp ) */
7023 /* p_type = CPOINTER ; */
7025 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7026 /* p_type = FPOINTER ; */
7028 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7029 /* p_type = PPOINTER; */
7031 /* if (SPEC_OCLS(etype) == idata ) */
7032 /* p_type = IPOINTER ; */
7034 /* p_type = POINTER ; */
7037 /* the first two bytes are known */
7038 size = GPTRSIZE - 1;
7042 aopGet(AOP(right),offset,FALSE,FALSE),
7046 /* the last byte depending on type */
7063 /* this should never happen */
7064 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7065 "got unknown pointer type");
7068 aopPut(AOP(result),l, GPTRSIZE - 1);
7072 /* just copy the pointers */
7073 size = AOP_SIZE(result);
7077 aopGet(AOP(right),offset,FALSE,FALSE),
7084 /* so we now know that the size of destination is greater
7085 than the size of the source */
7086 /* we move to result for the size of source */
7087 size = AOP_SIZE(right);
7091 aopGet(AOP(right),offset,FALSE,FALSE),
7096 /* now depending on the sign of the destination */
7097 size = AOP_SIZE(result) - AOP_SIZE(right);
7098 /* if unsigned or not an integral type */
7099 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
7101 aopPut(AOP(result),zero,offset++);
7103 /* we need to extend the sign :{ */
7104 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
7107 emitcode("rlc","a");
7108 emitcode("subb","a,acc");
7110 aopPut(AOP(result),"a",offset++);
7113 /* we are done hurray !!!! */
7116 freeAsmop(right,NULL,ic,TRUE);
7117 freeAsmop(result,NULL,ic,TRUE);
7121 /*-----------------------------------------------------------------*/
7122 /* genDjnz - generate decrement & jump if not zero instrucion */
7123 /*-----------------------------------------------------------------*/
7124 static int genDjnz (iCode *ic, iCode *ifx)
7130 /* if the if condition has a false label
7131 then we cannot save */
7135 /* if the minus is not of the form
7137 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
7138 !IS_OP_LITERAL(IC_RIGHT(ic)))
7141 if (operandLitValue(IC_RIGHT(ic)) != 1)
7144 /* if the size of this greater than one then no
7146 if (getSize(operandType(IC_RESULT(ic))) > 1)
7149 /* otherwise we can save BIG */
7150 lbl = newiTempLabel(NULL);
7151 lbl1= newiTempLabel(NULL);
7153 aopOp(IC_RESULT(ic),ic,FALSE);
7155 if (IS_AOP_PREG(IC_RESULT(ic))) {
7156 emitcode("dec","%s",
7157 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7158 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7159 emitcode("jnz","%05d$",lbl->key+100);
7161 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
7164 emitcode ("sjmp","%05d$",lbl1->key+100);
7165 emitcode ("","%05d$:",lbl->key+100);
7166 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
7167 emitcode ("","%05d$:",lbl1->key+100);
7169 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7174 /*-----------------------------------------------------------------*/
7175 /* genReceive - generate code for a receive iCode */
7176 /*-----------------------------------------------------------------*/
7177 static void genReceive (iCode *ic)
7179 if (isOperandInFarSpace(IC_RESULT(ic)) &&
7180 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
7181 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
7183 int size = getSize(operandType(IC_RESULT(ic)));
7184 int offset = fReturnSize - size;
7186 emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
7187 fReturn[fReturnSize - offset - 1] : "acc"));
7190 aopOp(IC_RESULT(ic),ic,FALSE);
7191 size = AOP_SIZE(IC_RESULT(ic));
7194 emitcode ("pop","acc");
7195 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
7200 aopOp(IC_RESULT(ic),ic,FALSE);
7202 assignResultValue(IC_RESULT(ic));
7205 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7208 /*-----------------------------------------------------------------*/
7209 /* gen51Code - generate code for 8051 based controllers */
7210 /*-----------------------------------------------------------------*/
7211 void gen51Code (iCode *lic)
7216 /* Hack-o-matic: change fReturn based on model. */
7217 if (options.model == MODEL_FLAT24)
7219 fReturn = fReturn390;
7223 lineHead = lineCurr = NULL;
7225 /* if debug information required */
7226 /* if (options.debug && currFunc) { */
7228 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
7230 if (IS_STATIC(currFunc->etype))
7231 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
7233 emitcode("","G$%s$0$0 ==.",currFunc->name);
7236 /* stack pointer name */
7237 if (options.useXstack)
7243 for (ic = lic ; ic ; ic = ic->next ) {
7245 if ( cln != ic->lineno ) {
7246 if ( options.debug ) {
7248 emitcode("","C$%s$%d$%d$%d ==.",
7249 ic->filename,ic->lineno,
7250 ic->level,ic->block);
7253 emitcode(";","%s %d",ic->filename,ic->lineno);
7256 /* if the result is marked as
7257 spilt and rematerializable or code for
7258 this has already been generated then
7260 if (resultRemat(ic) || ic->generated )
7263 /* depending on the operation */
7282 /* IPOP happens only when trying to restore a
7283 spilt live range, if there is an ifx statement
7284 following this pop then the if statement might
7285 be using some of the registers being popped which
7286 would destory the contents of the register so
7287 we need to check for this condition and handle it */
7289 ic->next->op == IFX &&
7290 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
7291 genIfx (ic->next,ic);
7309 genEndFunction (ic);
7329 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
7346 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
7350 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
7357 /* note these two are xlated by algebraic equivalence
7358 during parsing SDCC.y */
7359 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7360 "got '>=' or '<=' shouldn't have come here");
7364 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
7376 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
7380 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
7384 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
7411 case GET_VALUE_AT_ADDRESS:
7416 if (POINTER_SET(ic))
7443 addSet(&_G.sendSet,ic);
7448 /* piCode(ic,stdout); */
7454 /* now we are ready to call the
7455 peep hole optimizer */
7456 if (!options.nopeep)
7457 peepHole (&lineHead);
7459 /* now do the actual printing */
7460 printLine (lineHead,codeOutFile);