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)
239 if (SPEC_OCLS(etype)->codesp ) {
243 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
246 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
249 if (SPEC_OCLS(etype) == idata )
256 /*-----------------------------------------------------------------*/
257 /* aopForSym - for a true symbol */
258 /*-----------------------------------------------------------------*/
259 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
262 memmap *space= SPEC_OCLS(sym->etype);
264 /* if already has one */
268 /* assign depending on the storage class */
269 /* if it is on the stack or indirectly addressable */
270 /* space we need to assign either r0 or r1 to it */
271 if (sym->onStack || sym->iaccess) {
272 sym->aop = aop = newAsmop(0);
273 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
274 aop->size = getSize(sym->type);
276 /* now assign the address of the variable to
277 the pointer register */
278 if (aop->type != AOP_STK) {
283 emitcode("push","acc");
285 emitcode("mov","a,_bp");
286 emitcode("add","a,#0x%02x",
288 ((char)(sym->stack - _G.nRegsSaved )) :
289 ((char)sym->stack)) & 0xff);
290 emitcode("mov","%s,a",
291 aop->aopu.aop_ptr->name);
294 emitcode("pop","acc");
297 emitcode("mov","%s,#%s",
298 aop->aopu.aop_ptr->name,
300 aop->paged = space->paged;
302 aop->aopu.aop_stk = sym->stack;
306 /* if in bit space */
307 if (IN_BITSPACE(space)) {
308 sym->aop = aop = newAsmop (AOP_CRY);
309 aop->aopu.aop_dir = sym->rname ;
310 aop->size = getSize(sym->type);
313 /* if it is in direct space */
314 if (IN_DIRSPACE(space)) {
315 sym->aop = aop = newAsmop (AOP_DIR);
316 aop->aopu.aop_dir = sym->rname ;
317 aop->size = getSize(sym->type);
321 /* special case for a function */
322 if (IS_FUNC(sym->type)) {
323 sym->aop = aop = newAsmop(AOP_IMMD);
324 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
325 strcpy(aop->aopu.aop_immd,sym->rname);
326 aop->size = FPTRSIZE;
330 /* only remaining is far space */
331 /* in which case DPTR gets the address */
332 sym->aop = aop = newAsmop(AOP_DPTR);
333 emitcode ("mov","dptr,#%s", sym->rname);
334 aop->size = getSize(sym->type);
336 /* if it is in code space */
337 if (IN_CODESPACE(space))
343 /*-----------------------------------------------------------------*/
344 /* aopForRemat - rematerialzes an object */
345 /*-----------------------------------------------------------------*/
346 static asmop *aopForRemat (symbol *sym)
349 iCode *ic = sym->rematiCode;
350 asmop *aop = newAsmop(AOP_IMMD);
354 /* if plus or minus print the right hand side */
355 if (ic->op == '+' || ic->op == '-') {
356 sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
359 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
363 /* we reached the end */
364 sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
368 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
369 strcpy(aop->aopu.aop_immd,buffer);
373 /*-----------------------------------------------------------------*/
374 /* regsInCommon - two operands have some registers in common */
375 /*-----------------------------------------------------------------*/
376 static bool regsInCommon (operand *op1, operand *op2)
381 /* if they have registers in common */
382 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
385 sym1 = OP_SYMBOL(op1);
386 sym2 = OP_SYMBOL(op2);
388 if (sym1->nRegs == 0 || sym2->nRegs == 0)
391 for (i = 0 ; i < sym1->nRegs ; i++) {
396 for (j = 0 ; j < sym2->nRegs ;j++ ) {
400 if (sym2->regs[j] == sym1->regs[i])
408 /*-----------------------------------------------------------------*/
409 /* operandsEqu - equivalent */
410 /*-----------------------------------------------------------------*/
411 static bool operandsEqu ( operand *op1, operand *op2)
415 /* if they not symbols */
416 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
419 sym1 = OP_SYMBOL(op1);
420 sym2 = OP_SYMBOL(op2);
422 /* if both are itemps & one is spilt
423 and the other is not then false */
424 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
425 sym1->isspilt != sym2->isspilt )
428 /* if they are the same */
432 if (strcmp(sym1->rname,sym2->rname) == 0)
436 /* if left is a tmp & right is not */
440 (sym1->usl.spillLoc == sym2))
447 (sym2->usl.spillLoc == sym1))
453 /*-----------------------------------------------------------------*/
454 /* sameRegs - two asmops have the same registers */
455 /*-----------------------------------------------------------------*/
456 static bool sameRegs (asmop *aop1, asmop *aop2 )
463 if (aop1->type != AOP_REG ||
464 aop2->type != AOP_REG )
467 if (aop1->size != aop2->size )
470 for (i = 0 ; i < aop1->size ; i++ )
471 if (aop1->aopu.aop_reg[i] !=
472 aop2->aopu.aop_reg[i] )
478 /*-----------------------------------------------------------------*/
479 /* aopOp - allocates an asmop for an operand : */
480 /*-----------------------------------------------------------------*/
481 static void aopOp (operand *op, iCode *ic, bool result)
490 /* if this a literal */
491 if (IS_OP_LITERAL(op)) {
492 op->aop = aop = newAsmop(AOP_LIT);
493 aop->aopu.aop_lit = op->operand.valOperand;
494 aop->size = getSize(operandType(op));
498 /* if already has a asmop then continue */
502 /* if the underlying symbol has a aop */
503 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
504 op->aop = OP_SYMBOL(op)->aop;
508 /* if this is a true symbol */
509 if (IS_TRUE_SYMOP(op)) {
510 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
514 /* this is a temporary : this has
520 e) can be a return use only */
525 /* if the type is a conditional */
526 if (sym->regType == REG_CND) {
527 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
532 /* if it is spilt then two situations
534 b) has a spill location */
535 if (sym->isspilt || sym->nRegs == 0) {
537 /* rematerialize it NOW */
539 sym->aop = op->aop = aop =
541 aop->size = getSize(sym->type);
547 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
548 aop->size = getSize(sym->type);
549 for ( i = 0 ; i < 2 ; i++ )
550 aop->aopu.aop_str[i] = accUse[i];
556 aop = op->aop = sym->aop = newAsmop(AOP_STR);
557 aop->size = getSize(sym->type);
558 for ( i = 0 ; i < fReturnSize ; i++ )
559 aop->aopu.aop_str[i] = fReturn[i];
563 /* else spill location */
564 sym->aop = op->aop = aop =
565 aopForSym(ic,sym->usl.spillLoc,result);
566 aop->size = getSize(sym->type);
570 /* must be in a register */
571 sym->aop = op->aop = aop = newAsmop(AOP_REG);
572 aop->size = sym->nRegs;
573 for ( i = 0 ; i < sym->nRegs ;i++)
574 aop->aopu.aop_reg[i] = sym->regs[i];
577 /*-----------------------------------------------------------------*/
578 /* freeAsmop - free up the asmop given to an operand */
579 /*----------------------------------------------------------------*/
580 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
597 /* depending on the asmop type only three cases need work AOP_RO
598 , AOP_R1 && AOP_STK */
603 emitcode ("pop","ar0");
607 bitVectUnSetBit(ic->rUsed,R0_IDX);
613 emitcode ("pop","ar1");
617 bitVectUnSetBit(ic->rUsed,R1_IDX);
623 int stk = aop->aopu.aop_stk + aop->size;
624 bitVectUnSetBit(ic->rUsed,R0_IDX);
625 bitVectUnSetBit(ic->rUsed,R1_IDX);
627 getFreePtr(ic,&aop,FALSE);
629 emitcode ("mov","a,_bp");
630 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
631 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
633 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
636 emitcode("pop","acc");
637 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
639 emitcode("dec","%s",aop->aopu.aop_ptr->name);
642 freeAsmop(op,NULL,ic,TRUE);
644 emitcode("pop","ar0");
649 emitcode("pop","ar1");
656 /* all other cases just dealloc */
660 OP_SYMBOL(op)->aop = NULL;
661 /* if the symbol has a spill */
663 SPIL_LOC(op)->aop = NULL;
668 /*-----------------------------------------------------------------*/
669 /* aopGet - for fetching value of the aop */
670 /*-----------------------------------------------------------------*/
671 static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
676 /* offset is greater than
678 if (offset > (aop->size - 1) &&
679 aop->type != AOP_LIT)
682 /* depending on type */
687 /* if we need to increment it */
688 while (offset > aop->coff) {
689 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
693 while (offset < aop->coff) {
694 emitcode("dec","%s",aop->aopu.aop_ptr->name);
700 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
701 return (dname ? "acc" : "a");
703 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
704 ALLOC_ATOMIC(rs,strlen(s)+1);
709 while (offset > aop->coff) {
710 emitcode ("inc","dptr");
714 while (offset < aop->coff) {
715 emitcode("lcall","__decdptr");
722 emitcode("movc","a,@a+dptr");
725 emitcode("movx","a,@dptr");
726 return (dname ? "acc" : "a");
731 sprintf (s,"#(%s)",aop->aopu.aop_immd);
734 sprintf(s,"#(%s >> %d)",
740 ALLOC_ATOMIC(rs,strlen(s)+1);
746 sprintf(s,"(%s + %d)",
750 sprintf(s,"%s",aop->aopu.aop_dir);
751 ALLOC_ATOMIC(rs,strlen(s)+1);
757 return aop->aopu.aop_reg[offset]->dname;
759 return aop->aopu.aop_reg[offset]->name;
763 emitcode("mov","c,%s",aop->aopu.aop_dir);
764 emitcode("rlc","a") ;
765 return (dname ? "acc" : "a");
768 if (!offset && dname)
770 return aop->aopu.aop_str[offset];
773 return aopLiteral (aop->aopu.aop_lit,offset);
777 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
781 return aop->aopu.aop_str[offset];
785 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
786 "aopget got unsupported aop->type");
789 /*-----------------------------------------------------------------*/
790 /* aopPut - puts a string for a aop */
791 /*-----------------------------------------------------------------*/
792 static void aopPut (asmop *aop, char *s, int offset)
797 if (aop->size && offset > ( aop->size - 1)) {
798 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
799 "aopPut got offset > aop->size");
803 /* will assign value to value */
804 /* depending on where it is ofcourse */
808 sprintf(d,"(%s + %d)",
809 aop->aopu.aop_dir,offset);
811 sprintf(d,"%s",aop->aopu.aop_dir);
814 emitcode("mov","%s,%s",d,s);
819 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
820 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
822 strcmp(s,"r0") == 0 ||
823 strcmp(s,"r1") == 0 ||
824 strcmp(s,"r2") == 0 ||
825 strcmp(s,"r3") == 0 ||
826 strcmp(s,"r4") == 0 ||
827 strcmp(s,"r5") == 0 ||
828 strcmp(s,"r6") == 0 ||
829 strcmp(s,"r7") == 0 )
830 emitcode("mov","%s,%s",
831 aop->aopu.aop_reg[offset]->dname,s);
833 emitcode("mov","%s,%s",
834 aop->aopu.aop_reg[offset]->name,s);
840 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
841 "aopPut writting to code space");
845 while (offset > aop->coff) {
847 emitcode ("inc","dptr");
850 while (offset < aop->coff) {
852 emitcode("lcall","__decdptr");
857 /* if not in accumulater */
860 emitcode ("movx","@dptr,a");
865 while (offset > aop->coff) {
867 emitcode("inc","%s",aop->aopu.aop_ptr->name);
869 while (offset < aop->coff) {
871 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
877 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
882 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
884 if (strcmp(s,"r0") == 0 ||
885 strcmp(s,"r1") == 0 ||
886 strcmp(s,"r2") == 0 ||
887 strcmp(s,"r3") == 0 ||
888 strcmp(s,"r4") == 0 ||
889 strcmp(s,"r5") == 0 ||
890 strcmp(s,"r6") == 0 ||
891 strcmp(s,"r7") == 0 ) {
893 sprintf(buffer,"a%s",s);
894 emitcode("mov","@%s,%s",
895 aop->aopu.aop_ptr->name,buffer);
897 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
902 if (strcmp(s,"a") == 0)
903 emitcode("push","acc");
905 emitcode("push","%s",s);
910 /* if bit variable */
911 if (!aop->aopu.aop_dir) {
916 emitcode("clr","%s",aop->aopu.aop_dir);
919 emitcode("setb","%s",aop->aopu.aop_dir);
922 emitcode("mov","%s,c",aop->aopu.aop_dir);
924 lbl = newiTempLabel(NULL);
929 emitcode("cjne","a,#0x01,%05d$",lbl->key+100);
930 emitcode("","%05d$:",lbl->key+100);
932 emitcode("mov","%s,c",aop->aopu.aop_dir);
939 if (strcmp(aop->aopu.aop_str[offset],s))
940 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
945 if (!offset && (strcmp(s,"acc") == 0))
948 if (strcmp(aop->aopu.aop_str[offset],s))
949 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
953 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
954 "aopPut got unsupported aop->type");
962 /*-----------------------------------------------------------------*/
963 /* pointToEnd :- points to the last byte of the operand */
964 /*-----------------------------------------------------------------*/
965 static void pointToEnd (asmop *aop)
971 aop->coff = count = (aop->size - 1);
976 emitcode("inc","%s",aop->aopu.aop_ptr->name);
980 emitcode("inc","dptr");
987 /*-----------------------------------------------------------------*/
988 /* reAdjustPreg - points a register back to where it should */
989 /*-----------------------------------------------------------------*/
990 static void reAdjustPreg (asmop *aop)
995 if ((size = aop->size) <= 1)
1002 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1006 emitcode("lcall","__decdptr");
1013 #define AOP(op) op->aop
1014 #define AOP_TYPE(op) AOP(op)->type
1015 #define AOP_SIZE(op) AOP(op)->size
1016 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1017 AOP_TYPE(x) == AOP_R0))
1019 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1020 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1022 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1023 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1024 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1026 /*-----------------------------------------------------------------*/
1027 /* genNotFloat - generates not for float operations */
1028 /*-----------------------------------------------------------------*/
1029 static void genNotFloat (operand *op, operand *res)
1035 /* we will put 127 in the first byte of
1037 aopPut(AOP(res),"#127",0);
1038 size = AOP_SIZE(op) - 1;
1041 l = aopGet(op->aop,offset++,FALSE,FALSE);
1045 emitcode("orl","a,%s",
1047 offset++,FALSE,FALSE));
1049 tlbl = newiTempLabel(NULL);
1051 tlbl = newiTempLabel(NULL);
1052 aopPut(res->aop,one,1);
1053 emitcode("jz","%05d$",(tlbl->key+100));
1054 aopPut(res->aop,zero,1);
1055 emitcode("","%05d$:",(tlbl->key+100));
1057 size = res->aop->size - 2;
1059 /* put zeros in the rest */
1061 aopPut(res->aop,zero,offset++);
1064 /*-----------------------------------------------------------------*/
1065 /* opIsGptr: returns non-zero if the passed operand is */
1066 /* a generic pointer type. */
1067 /*-----------------------------------------------------------------*/
1068 static int opIsGptr(operand *op)
1070 link *type = operandType(op);
1072 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1079 /*-----------------------------------------------------------------*/
1080 /* getDataSize - get the operand data size */
1081 /*-----------------------------------------------------------------*/
1082 static int getDataSize(operand *op)
1085 size = AOP_SIZE(op);
1086 if (size == GPTRSIZE)
1088 link *type = operandType(op);
1089 if (IS_GENPTR(type))
1091 /* generic pointer; arithmetic operations
1092 * should ignore the high byte (pointer type).
1100 /*-----------------------------------------------------------------*/
1101 /* outAcc - output Acc */
1102 /*-----------------------------------------------------------------*/
1103 static void outAcc(operand *result)
1106 size = getDataSize(result);
1108 aopPut(AOP(result),"a",0);
1111 /* unsigned or positive */
1113 aopPut(AOP(result),zero,offset++);
1118 /*-----------------------------------------------------------------*/
1119 /* outBitC - output a bit C */
1120 /*-----------------------------------------------------------------*/
1121 static void outBitC(operand *result)
1123 /* if the result is bit */
1124 if (AOP_TYPE(result) == AOP_CRY)
1125 aopPut(AOP(result),"c",0);
1127 emitcode("clr","a");
1128 emitcode("rlc","a");
1133 /*-----------------------------------------------------------------*/
1134 /* toBoolean - emit code for orl a,operator(sizeop) */
1135 /*-----------------------------------------------------------------*/
1136 static void toBoolean(operand *oper)
1138 int size = AOP_SIZE(oper) - 1;
1140 MOVA(aopGet(AOP(oper),0,FALSE,FALSE));
1142 emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE));
1146 /*-----------------------------------------------------------------*/
1147 /* genNot - generate code for ! operation */
1148 /*-----------------------------------------------------------------*/
1149 static void genNot (iCode *ic)
1152 link *optype = operandType(IC_LEFT(ic));
1154 /* assign asmOps to operand & result */
1155 aopOp (IC_LEFT(ic),ic,FALSE);
1156 aopOp (IC_RESULT(ic),ic,TRUE);
1158 /* if in bit space then a special case */
1159 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1160 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1161 emitcode("cpl","c");
1162 outBitC(IC_RESULT(ic));
1166 /* if type float then do float */
1167 if (IS_FLOAT(optype)) {
1168 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1172 toBoolean(IC_LEFT(ic));
1174 tlbl = newiTempLabel(NULL);
1175 emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1176 emitcode("","%05d$:",tlbl->key+100);
1177 outBitC(IC_RESULT(ic));
1180 /* release the aops */
1181 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1182 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1186 /*-----------------------------------------------------------------*/
1187 /* genCpl - generate code for complement */
1188 /*-----------------------------------------------------------------*/
1189 static void genCpl (iCode *ic)
1195 /* assign asmOps to operand & result */
1196 aopOp (IC_LEFT(ic),ic,FALSE);
1197 aopOp (IC_RESULT(ic),ic,TRUE);
1199 /* if both are in bit space then
1201 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1202 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1204 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1205 emitcode("cpl","c");
1206 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1210 size = AOP_SIZE(IC_RESULT(ic));
1212 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1214 emitcode("cpl","a");
1215 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1220 /* release the aops */
1221 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1222 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1225 /*-----------------------------------------------------------------*/
1226 /* genUminusFloat - unary minus for floating points */
1227 /*-----------------------------------------------------------------*/
1228 static void genUminusFloat(operand *op,operand *result)
1230 int size ,offset =0 ;
1232 /* for this we just need to flip the
1233 first it then copy the rest in place */
1234 size = AOP_SIZE(op) - 1;
1235 l = aopGet(AOP(op),3,FALSE,FALSE);
1239 emitcode("cpl","acc.7");
1240 aopPut(AOP(result),"a",3);
1244 aopGet(AOP(op),offset,FALSE,FALSE),
1250 /*-----------------------------------------------------------------*/
1251 /* genUminus - unary minus code generation */
1252 /*-----------------------------------------------------------------*/
1253 static void genUminus (iCode *ic)
1256 link *optype, *rtype;
1260 aopOp(IC_LEFT(ic),ic,FALSE);
1261 aopOp(IC_RESULT(ic),ic,TRUE);
1263 /* if both in bit space then special
1265 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1266 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1268 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1269 emitcode("cpl","c");
1270 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1274 optype = operandType(IC_LEFT(ic));
1275 rtype = operandType(IC_RESULT(ic));
1277 /* if float then do float stuff */
1278 if (IS_FLOAT(optype)) {
1279 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1283 /* otherwise subtract from zero */
1284 size = AOP_SIZE(IC_LEFT(ic));
1288 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1289 if (!strcmp(l,"a")) {
1290 emitcode("cpl","a");
1291 emitcode("inc","a");
1293 emitcode("clr","a");
1294 emitcode("subb","a,%s",l);
1296 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1299 /* if any remaining bytes in the result */
1300 /* we just need to propagate the sign */
1301 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1302 emitcode("rlc","a");
1303 emitcode("subb","a,acc");
1305 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1309 /* release the aops */
1310 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1311 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1314 /*-----------------------------------------------------------------*/
1315 /* saveRegisters - will look for a call and save the registers */
1316 /*-----------------------------------------------------------------*/
1317 static void saveRegisters(iCode *lic)
1325 for (ic = lic ; ic ; ic = ic->next)
1326 if (ic->op == CALL || ic->op == PCALL)
1330 fprintf(stderr,"found parameter push with no function call\n");
1334 /* if the registers have been saved already then
1336 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1339 /* find the registers in use at this time
1340 and push them away to safety */
1341 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1345 if (options.useXstack) {
1346 if (bitVectBitValue(rsave,R0_IDX))
1347 emitcode("mov","b,r0");
1348 emitcode("mov","r0,%s",spname);
1349 for (i = 0 ; i < mcs51_nRegs ; i++) {
1350 if (bitVectBitValue(rsave,i)) {
1352 emitcode("mov","a,b");
1354 emitcode("mov","a,%s",mcs51_regWithIdx(i)->name);
1355 emitcode("movx","@r0,a");
1356 emitcode("inc","r0");
1359 emitcode("mov","%s,r0",spname);
1360 if (bitVectBitValue(rsave,R0_IDX))
1361 emitcode("mov","r0,b");
1363 for (i = 0 ; i < mcs51_nRegs ; i++) {
1364 if (bitVectBitValue(rsave,i))
1365 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
1368 detype = getSpec(operandType(IC_LEFT(ic)));
1370 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1371 IS_ISR(currFunc->etype) &&
1374 saverbank(SPEC_BANK(detype),ic,TRUE);
1377 /*-----------------------------------------------------------------*/
1378 /* unsaveRegisters - pop the pushed registers */
1379 /*-----------------------------------------------------------------*/
1380 static void unsaveRegisters (iCode *ic)
1384 /* find the registers in use at this time
1385 and push them away to safety */
1386 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1389 if (options.useXstack) {
1390 emitcode("mov","r0,%s",spname);
1391 for (i = mcs51_nRegs ; i >= 0 ; i--) {
1392 if (bitVectBitValue(rsave,i)) {
1393 emitcode("dec","r0");
1394 emitcode("movx","a,@r0");
1396 emitcode("mov","b,a");
1398 emitcode("mov","%s,a",mcs51_regWithIdx(i)->name);
1402 emitcode("mov","%s,r0",spname);
1403 if (bitVectBitValue(rsave,R0_IDX))
1404 emitcode("mov","r0,b");
1406 for (i = mcs51_nRegs ; i >= 0 ; i--) {
1407 if (bitVectBitValue(rsave,i))
1408 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
1414 /*-----------------------------------------------------------------*/
1416 /*-----------------------------------------------------------------*/
1417 static void pushSide(operand * oper, int size)
1421 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1422 if (AOP_TYPE(oper) != AOP_REG &&
1423 AOP_TYPE(oper) != AOP_DIR &&
1425 emitcode("mov","a,%s",l);
1426 emitcode("push","acc");
1428 emitcode("push","%s",l);
1432 /*-----------------------------------------------------------------*/
1433 /* assignResultValue - */
1434 /*-----------------------------------------------------------------*/
1435 static void assignResultValue(operand * oper)
1438 int size = AOP_SIZE(oper);
1440 aopPut(AOP(oper),fReturn[offset],offset);
1446 /*-----------------------------------------------------------------*/
1447 /* genXpush - pushes onto the external stack */
1448 /*-----------------------------------------------------------------*/
1449 static void genXpush (iCode *ic)
1451 asmop *aop = newAsmop(0);
1453 int size,offset = 0;
1455 aopOp(IC_LEFT(ic),ic,FALSE);
1456 r = getFreePtr(ic,&aop,FALSE);
1459 emitcode("mov","%s,_spx",r->name);
1461 size = AOP_SIZE(IC_LEFT(ic));
1464 char *l = aopGet(AOP(IC_LEFT(ic)),
1465 offset++,FALSE,FALSE);
1467 emitcode("movx","@%s,a",r->name);
1468 emitcode("inc","%s",r->name);
1473 emitcode("mov","_spx,%s",r->name);
1475 freeAsmop(NULL,aop,ic,TRUE);
1476 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1479 /*-----------------------------------------------------------------*/
1480 /* genIpush - genrate code for pushing this gets a little complex */
1481 /*-----------------------------------------------------------------*/
1482 static void genIpush (iCode *ic)
1484 int size, offset = 0 ;
1488 /* if this is not a parm push : ie. it is spill push
1489 and spill push is always done on the local stack */
1490 if (!ic->parmPush) {
1492 /* and the item is spilt then do nothing */
1493 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1496 aopOp(IC_LEFT(ic),ic,FALSE);
1497 size = AOP_SIZE(IC_LEFT(ic));
1498 /* push it on the stack */
1500 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1505 emitcode("push","%s",l);
1510 /* this is a paramter push: in this case we call
1511 the routine to find the call and save those
1512 registers that need to be saved */
1515 /* if use external stack then call the external
1516 stack pushing routine */
1517 if (options.useXstack) {
1522 /* then do the push */
1523 aopOp(IC_LEFT(ic),ic,FALSE);
1526 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1527 size = AOP_SIZE(IC_LEFT(ic));
1530 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1531 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1532 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1534 emitcode("mov","a,%s",l);
1535 emitcode("push","acc");
1537 emitcode("push","%s",l);
1540 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1543 /*-----------------------------------------------------------------*/
1544 /* genIpop - recover the registers: can happen only for spilling */
1545 /*-----------------------------------------------------------------*/
1546 static void genIpop (iCode *ic)
1551 /* if the temp was not pushed then */
1552 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1555 aopOp(IC_LEFT(ic),ic,FALSE);
1556 size = AOP_SIZE(IC_LEFT(ic));
1559 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1562 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1565 /*-----------------------------------------------------------------*/
1566 /* unsaverbank - restores the resgister bank from stack */
1567 /*-----------------------------------------------------------------*/
1568 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1575 if (options.useXstack) {
1577 r = getFreePtr(ic,&aop,FALSE);
1580 emitcode("mov","%s,_spx",r->name);
1581 emitcode("movx","a,@%s",r->name);
1582 emitcode("mov","psw,a");
1583 emitcode("dec","%s",r->name);
1586 emitcode ("pop","psw");
1589 for (i = (mcs51_nRegs - 1) ; i >= 0 ;i--) {
1590 if (options.useXstack) {
1591 emitcode("movx","a,@%s",r->name);
1592 emitcode("mov","(%s+%d),a",
1593 regs8051[i].base,8*bank+regs8051[i].offset);
1594 emitcode("dec","%s",r->name);
1597 emitcode("pop","(%s+%d)",
1598 regs8051[i].base,8*bank+regs8051[i].offset);
1601 if (options.useXstack) {
1603 emitcode("mov","_spx,%s",r->name);
1604 freeAsmop(NULL,aop,ic,TRUE);
1609 /*-----------------------------------------------------------------*/
1610 /* saverbank - saves an entire register bank on the stack */
1611 /*-----------------------------------------------------------------*/
1612 static void saverbank (int bank, iCode *ic, bool pushPsw)
1618 if (options.useXstack) {
1621 r = getFreePtr(ic,&aop,FALSE);
1622 emitcode("mov","%s,_spx",r->name);
1626 for (i = 0 ; i < mcs51_nRegs ;i++) {
1627 if (options.useXstack) {
1628 emitcode("inc","%s",r->name);
1629 emitcode("mov","a,(%s+%d)",
1630 regs8051[i].base,8*bank+regs8051[i].offset);
1631 emitcode("movx","@%s,a",r->name);
1633 emitcode("push","(%s+%d)",
1634 regs8051[i].base,8*bank+regs8051[i].offset);
1638 if (options.useXstack) {
1639 emitcode("mov","a,psw");
1640 emitcode("movx","@%s,a",r->name);
1641 emitcode("inc","%s",r->name);
1642 emitcode("mov","_spx,%s",r->name);
1643 freeAsmop (NULL,aop,ic,TRUE);
1646 emitcode("push","psw");
1648 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1654 /*-----------------------------------------------------------------*/
1655 /* genCall - generates a call statement */
1656 /*-----------------------------------------------------------------*/
1657 static void genCall (iCode *ic)
1661 /* if caller saves & we have not saved then */
1665 /* if we are calling a function that is not using
1666 the same register bank then we need to save the
1667 destination registers on the stack */
1668 detype = getSpec(operandType(IC_LEFT(ic)));
1670 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1671 IS_ISR(currFunc->etype) &&
1674 saverbank(SPEC_BANK(detype),ic,TRUE);
1676 /* if send set is not empty the assign */
1680 for (sic = setFirstItem(_G.sendSet) ; sic ;
1681 sic = setNextItem(_G.sendSet)) {
1682 int size, offset = 0;
1683 aopOp(IC_LEFT(sic),sic,FALSE);
1684 size = AOP_SIZE(IC_LEFT(sic));
1686 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1688 if (strcmp(l,fReturn[offset]))
1689 emitcode("mov","%s,%s",
1694 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1699 emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1700 OP_SYMBOL(IC_LEFT(ic))->rname :
1701 OP_SYMBOL(IC_LEFT(ic))->name));
1703 /* if we need assign a result value */
1704 if ((IS_ITEMP(IC_RESULT(ic)) &&
1705 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1706 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1707 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1710 aopOp(IC_RESULT(ic),ic,FALSE);
1713 assignResultValue(IC_RESULT(ic));
1715 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1718 /* adjust the stack for parameters if
1720 if (IC_LEFT(ic)->parmBytes) {
1722 if (IC_LEFT(ic)->parmBytes > 3) {
1723 emitcode("mov","a,%s",spname);
1724 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1725 emitcode("mov","%s,a",spname);
1727 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1728 emitcode("dec","%s",spname);
1732 /* if register bank was saved then pop them */
1734 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1736 /* if we hade saved some registers then unsave them */
1737 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1738 unsaveRegisters (ic);
1743 /*-----------------------------------------------------------------*/
1744 /* genPcall - generates a call by pointer statement */
1745 /*-----------------------------------------------------------------*/
1746 static void genPcall (iCode *ic)
1749 symbol *rlbl = newiTempLabel(NULL);
1752 /* if caller saves & we have not saved then */
1756 /* if we are calling a function that is not using
1757 the same register bank then we need to save the
1758 destination registers on the stack */
1759 detype = getSpec(operandType(IC_LEFT(ic)));
1761 IS_ISR(currFunc->etype) &&
1762 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
1763 saverbank(SPEC_BANK(detype),ic,TRUE);
1766 /* push the return address on to the stack */
1767 emitcode("mov","a,#%05d$",(rlbl->key+100));
1768 emitcode("push","acc");
1769 emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
1770 emitcode("push","acc");
1772 if (options.model == MODEL_FLAT24)
1774 emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
1775 emitcode("push","acc");
1778 /* now push the calling address */
1779 aopOp(IC_LEFT(ic),ic,FALSE);
1781 pushSide(IC_LEFT(ic), FPTRSIZE);
1783 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1785 /* if send set is not empty the assign */
1789 for (sic = setFirstItem(_G.sendSet) ; sic ;
1790 sic = setNextItem(_G.sendSet)) {
1791 int size, offset = 0;
1792 aopOp(IC_LEFT(sic),sic,FALSE);
1793 size = AOP_SIZE(IC_LEFT(sic));
1795 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1797 if (strcmp(l,fReturn[offset]))
1798 emitcode("mov","%s,%s",
1803 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1809 emitcode("","%05d$:",(rlbl->key+100));
1812 /* if we need assign a result value */
1813 if ((IS_ITEMP(IC_RESULT(ic)) &&
1814 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1815 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
1816 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1819 aopOp(IC_RESULT(ic),ic,FALSE);
1822 assignResultValue(IC_RESULT(ic));
1824 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1827 /* adjust the stack for parameters if
1829 if (IC_LEFT(ic)->parmBytes) {
1831 if (IC_LEFT(ic)->parmBytes > 3) {
1832 emitcode("mov","a,%s",spname);
1833 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1834 emitcode("mov","%s,a",spname);
1836 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1837 emitcode("dec","%s",spname);
1841 /* if register bank was saved then unsave them */
1843 (SPEC_BANK(currFunc->etype) !=
1845 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1847 /* if we hade saved some registers then
1850 unsaveRegisters (ic);
1854 /*-----------------------------------------------------------------*/
1855 /* resultRemat - result is rematerializable */
1856 /*-----------------------------------------------------------------*/
1857 static int resultRemat (iCode *ic)
1859 if (SKIP_IC(ic) || ic->op == IFX)
1862 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1863 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1864 if (sym->remat && !POINTER_SET(ic))
1871 /*-----------------------------------------------------------------*/
1872 /* inExcludeList - return 1 if the string is in exclude Reg list */
1873 /*-----------------------------------------------------------------*/
1874 static bool inExcludeList(char *s)
1878 if (options.excludeRegs[i] &&
1879 strcasecmp(options.excludeRegs[i],"none") == 0)
1882 for ( i = 0 ; options.excludeRegs[i]; i++) {
1883 if (options.excludeRegs[i] &&
1884 strcasecmp(s,options.excludeRegs[i]) == 0)
1890 /*-----------------------------------------------------------------*/
1891 /* genFunction - generated code for function entry */
1892 /*-----------------------------------------------------------------*/
1893 static void genFunction (iCode *ic)
1899 /* create the function header */
1900 emitcode(";","-----------------------------------------");
1901 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1902 emitcode(";","-----------------------------------------");
1904 emitcode("","%s:",sym->rname);
1905 fetype = getSpec(operandType(IC_LEFT(ic)));
1907 /* if critical function then turn interrupts off */
1908 if (SPEC_CRTCL(fetype))
1909 emitcode("clr","ea");
1911 /* here we need to generate the equates for the
1912 register bank if required */
1913 if (SPEC_BANK(fetype) != rbank) {
1916 rbank = SPEC_BANK(fetype);
1917 for ( i = 0 ; i < mcs51_nRegs ; i++ ) {
1918 if (strcmp(regs8051[i].base,"0") == 0)
1919 emitcode("","%s = 0x%02x",
1921 8*rbank+regs8051[i].offset);
1923 emitcode ("","%s = %s + 0x%02x",
1926 8*rbank+regs8051[i].offset);
1930 /* if this is an interrupt service routine then
1931 save acc, b, dpl, dph */
1932 if (IS_ISR(sym->etype)) {
1934 if (!inExcludeList("acc"))
1935 emitcode ("push","acc");
1936 if (!inExcludeList("b"))
1937 emitcode ("push","b");
1938 if (!inExcludeList("dpl"))
1939 emitcode ("push","dpl");
1940 if (!inExcludeList("dph"))
1941 emitcode ("push","dph");
1942 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
1943 emitcode ("push", "dpx");
1944 /* if this isr has no bank i.e. is going to
1945 run with bank 0 , then we need to save more
1947 if (!SPEC_BANK(sym->etype)) {
1949 /* if this function does not call any other
1950 function then we can be economical and
1951 save only those registers that are used */
1952 if (! sym->hasFcall) {
1955 /* if any registers used */
1956 if (sym->regsUsed) {
1957 /* save the registers used */
1958 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
1959 if (bitVectBitValue(sym->regsUsed,i) ||
1960 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
1961 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
1966 /* this function has a function call cannot
1967 determines register usage so we will have the
1969 saverbank(0,ic,FALSE);
1973 /* if callee-save to be used for this function
1974 then save the registers being used in this function */
1975 if (sym->calleeSave) {
1978 /* if any registers used */
1979 if (sym->regsUsed) {
1980 /* save the registers used */
1981 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
1982 if (bitVectBitValue(sym->regsUsed,i) ||
1983 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
1984 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
1992 /* set the register bank to the desired value */
1993 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
1994 emitcode("push","psw");
1995 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
1998 if (IS_RENT(sym->etype) || options.stackAuto) {
2000 if (options.useXstack) {
2001 emitcode("mov","r0,%s",spname);
2002 emitcode("mov","a,_bp");
2003 emitcode("movx","@r0,a");
2004 emitcode("inc","%s",spname);
2007 /* set up the stack */
2008 emitcode ("push","_bp"); /* save the callers stack */
2009 emitcode ("mov","_bp,%s",spname);
2012 /* adjust the stack for the function */
2017 werror(W_STACK_OVERFLOW,sym->name);
2019 if (i > 3 && sym->recvSize < 4) {
2021 emitcode ("mov","a,sp");
2022 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2023 emitcode ("mov","sp,a");
2028 emitcode("inc","sp");
2033 emitcode ("mov","a,_spx");
2034 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2035 emitcode ("mov","_spx,a");
2040 /*-----------------------------------------------------------------*/
2041 /* genEndFunction - generates epilogue for functions */
2042 /*-----------------------------------------------------------------*/
2043 static void genEndFunction (iCode *ic)
2045 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2047 if (IS_RENT(sym->etype) || options.stackAuto)
2048 emitcode ("mov","%s,_bp",spname);
2050 /* if use external stack but some variables were
2051 added to the local stack then decrement the
2053 if (options.useXstack && sym->stack) {
2054 emitcode("mov","a,sp");
2055 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2056 emitcode("mov","sp,a");
2060 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2061 if (options.useXstack) {
2062 emitcode("mov","r0,%s",spname);
2063 emitcode("movx","a,@r0");
2064 emitcode("mov","_bp,a");
2065 emitcode("dec","%s",spname);
2068 emitcode ("pop","_bp");
2071 /* restore the register bank */
2072 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2073 emitcode ("pop","psw");
2075 if (IS_ISR(sym->etype)) {
2077 /* now we need to restore the registers */
2078 /* if this isr has no bank i.e. is going to
2079 run with bank 0 , then we need to save more
2081 if (!SPEC_BANK(sym->etype)) {
2083 /* if this function does not call any other
2084 function then we can be economical and
2085 save only those registers that are used */
2086 if (! sym->hasFcall) {
2089 /* if any registers used */
2090 if (sym->regsUsed) {
2091 /* save the registers used */
2092 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2093 if (bitVectBitValue(sym->regsUsed,i) ||
2094 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2095 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
2100 /* this function has a function call cannot
2101 determines register usage so we will have the
2103 unsaverbank(0,ic,FALSE);
2107 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2108 emitcode ("pop", "dpx");
2109 if (!inExcludeList("dph"))
2110 emitcode ("pop","dph");
2111 if (!inExcludeList("dpl"))
2112 emitcode ("pop","dpl");
2113 if (!inExcludeList("b"))
2114 emitcode ("pop","b");
2115 if (!inExcludeList("acc"))
2116 emitcode ("pop","acc");
2118 if (SPEC_CRTCL(sym->etype))
2119 emitcode("setb","ea");
2121 /* if debug then send end of function */
2122 /* if (options.debug && currFunc) { */
2125 emitcode("","C$%s$%d$%d$%d ==.",
2126 ic->filename,currFunc->lastLine,
2127 ic->level,ic->block);
2128 if (IS_STATIC(currFunc->etype))
2129 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2131 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2135 emitcode ("reti","");
2138 if (SPEC_CRTCL(sym->etype))
2139 emitcode("setb","ea");
2141 if (sym->calleeSave) {
2144 /* if any registers used */
2145 if (sym->regsUsed) {
2146 /* save the registers used */
2147 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2148 if (bitVectBitValue(sym->regsUsed,i) ||
2149 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2150 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
2156 /* if debug then send end of function */
2157 /* if (options.debug && currFunc) { */
2160 emitcode("","C$%s$%d$%d$%d ==.",
2161 ic->filename,currFunc->lastLine,
2162 ic->level,ic->block);
2163 if (IS_STATIC(currFunc->etype))
2164 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2166 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2170 emitcode ("ret","");
2175 /*-----------------------------------------------------------------*/
2176 /* genRet - generate code for return statement */
2177 /*-----------------------------------------------------------------*/
2178 static void genRet (iCode *ic)
2180 int size,offset = 0 , pushed = 0;
2182 /* if we have no return value then
2183 just generate the "ret" */
2187 /* we have something to return then
2188 move the return value into place */
2189 aopOp(IC_LEFT(ic),ic,FALSE);
2190 size = AOP_SIZE(IC_LEFT(ic));
2194 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2195 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2197 emitcode("push","%s",l);
2200 l = aopGet(AOP(IC_LEFT(ic)),offset,
2202 if (strcmp(fReturn[offset],l))
2203 emitcode("mov","%s,%s",fReturn[offset++],l);
2210 if (strcmp(fReturn[pushed],"a"))
2211 emitcode("pop",fReturn[pushed]);
2213 emitcode("pop","acc");
2216 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2219 /* generate a jump to the return label
2220 if the next is not the return statement */
2221 if (!(ic->next && ic->next->op == LABEL &&
2222 IC_LABEL(ic->next) == returnLabel))
2224 emitcode("ljmp","%05d$",(returnLabel->key+100));
2228 /*-----------------------------------------------------------------*/
2229 /* genLabel - generates a label */
2230 /*-----------------------------------------------------------------*/
2231 static void genLabel (iCode *ic)
2233 /* special case never generate */
2234 if (IC_LABEL(ic) == entryLabel)
2237 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2240 /*-----------------------------------------------------------------*/
2241 /* genGoto - generates a ljmp */
2242 /*-----------------------------------------------------------------*/
2243 static void genGoto (iCode *ic)
2245 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2248 /*-----------------------------------------------------------------*/
2249 /* genPlusIncr :- does addition with increment if possible */
2250 /*-----------------------------------------------------------------*/
2251 static bool genPlusIncr (iCode *ic)
2253 unsigned int icount ;
2254 unsigned int size = getDataSize(IC_RESULT(ic));
2256 /* will try to generate an increment */
2257 /* if the right side is not a literal
2259 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2262 /* if the literal value of the right hand side
2263 is greater than 4 then it is not worth it */
2264 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2267 /* if increment 16 bits in register */
2268 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2271 symbol *tlbl = newiTempLabel(NULL);
2272 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2273 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2274 IS_AOP_PREG(IC_RESULT(ic)))
2275 emitcode("cjne","%s,#0x00,%05d$"
2276 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2279 emitcode("clr","a");
2280 emitcode("cjne","a,%s,%05d$"
2281 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2285 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2288 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2289 IS_AOP_PREG(IC_RESULT(ic)))
2290 emitcode("cjne","%s,#0x00,%05d$"
2291 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2294 emitcode("cjne","a,%s,%05d$"
2295 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2298 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2302 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2303 IS_AOP_PREG(IC_RESULT(ic)))
2304 emitcode("cjne","%s,#0x00,%05d$"
2305 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2308 emitcode("cjne","a,%s,%05d$"
2309 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2312 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2314 emitcode("","%05d$:",tlbl->key+100);
2318 /* if the sizes are greater than 1 then we cannot */
2319 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2320 AOP_SIZE(IC_LEFT(ic)) > 1 )
2323 /* we can if the aops of the left & result match or
2324 if they are in registers and the registers are the
2326 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2329 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2330 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2331 aopPut(AOP(IC_RESULT(ic)),"a",0);
2335 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2344 /*-----------------------------------------------------------------*/
2345 /* outBitAcc - output a bit in acc */
2346 /*-----------------------------------------------------------------*/
2347 static void outBitAcc(operand *result)
2349 symbol *tlbl = newiTempLabel(NULL);
2350 /* if the result is a bit */
2351 if (AOP_TYPE(result) == AOP_CRY){
2352 aopPut(AOP(result),"a",0);
2355 emitcode("jz","%05d$",tlbl->key+100);
2356 emitcode("mov","a,%s",one);
2357 emitcode("","%05d$:",tlbl->key+100);
2362 /*-----------------------------------------------------------------*/
2363 /* genPlusBits - generates code for addition of two bits */
2364 /*-----------------------------------------------------------------*/
2365 static void genPlusBits (iCode *ic)
2367 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2368 symbol *lbl = newiTempLabel(NULL);
2369 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2370 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2371 emitcode("cpl","c");
2372 emitcode("","%05d$:",(lbl->key+100));
2373 outBitC(IC_RESULT(ic));
2376 emitcode("clr","a");
2377 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2378 emitcode("rlc","a");
2379 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2380 emitcode("addc","a,#0x00");
2381 outAcc(IC_RESULT(ic));
2386 /* This is the original version of this code.
2388 * This is being kept around for reference,
2389 * because I am not entirely sure I got it right...
2391 static void adjustArithmeticResult(iCode *ic)
2393 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2394 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2395 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2396 aopPut(AOP(IC_RESULT(ic)),
2397 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2400 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2401 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
2402 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2403 aopPut(AOP(IC_RESULT(ic)),
2404 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2407 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2408 AOP_SIZE(IC_LEFT(ic)) < 3 &&
2409 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
2410 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2411 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2413 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2414 aopPut(AOP(IC_RESULT(ic)),buffer,2);
2418 /* This is the pure and virtuous version of this code.
2419 * I'm pretty certain it's right, but not enough to toss the old
2422 static void adjustArithmeticResult(iCode *ic)
2424 if (opIsGptr(IC_RESULT(ic)) &&
2425 opIsGptr(IC_LEFT(ic)) &&
2426 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2428 aopPut(AOP(IC_RESULT(ic)),
2429 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
2433 if (opIsGptr(IC_RESULT(ic)) &&
2434 opIsGptr(IC_RIGHT(ic)) &&
2435 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2437 aopPut(AOP(IC_RESULT(ic)),
2438 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
2442 if (opIsGptr(IC_RESULT(ic)) &&
2443 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2444 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2445 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2446 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2448 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2449 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2454 /*-----------------------------------------------------------------*/
2455 /* genPlus - generates code for addition */
2456 /*-----------------------------------------------------------------*/
2457 static void genPlus (iCode *ic)
2459 int size, offset = 0;
2461 /* special cases :- */
2463 aopOp (IC_LEFT(ic),ic,FALSE);
2464 aopOp (IC_RIGHT(ic),ic,FALSE);
2465 aopOp (IC_RESULT(ic),ic,TRUE);
2467 /* if literal, literal on the right or
2468 if left requires ACC or right is already
2470 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2471 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2472 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2473 operand *t = IC_RIGHT(ic);
2474 IC_RIGHT(ic) = IC_LEFT(ic);
2478 /* if both left & right are in bit
2480 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2481 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2486 /* if left in bit space & right literal */
2487 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2488 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2489 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2490 /* if result in bit space */
2491 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2492 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
2493 emitcode("cpl","c");
2494 outBitC(IC_RESULT(ic));
2496 size = getDataSize(IC_RESULT(ic));
2498 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2499 emitcode("addc","a,#00");
2500 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2506 /* if I can do an increment instead
2507 of add then GOOD for ME */
2508 if (genPlusIncr (ic) == TRUE)
2511 size = getDataSize(IC_RESULT(ic));
2514 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2515 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2517 emitcode("add","a,%s",
2518 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2520 emitcode("addc","a,%s",
2521 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2523 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2525 emitcode("add","a,%s",
2526 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2528 emitcode("addc","a,%s",
2529 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2531 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2534 adjustArithmeticResult(ic);
2537 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2538 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2539 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2542 /*-----------------------------------------------------------------*/
2543 /* genMinusDec :- does subtraction with deccrement if possible */
2544 /*-----------------------------------------------------------------*/
2545 static bool genMinusDec (iCode *ic)
2547 unsigned int icount ;
2548 unsigned int size = getDataSize(IC_RESULT(ic));
2550 /* will try to generate an increment */
2551 /* if the right side is not a literal
2553 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2556 /* if the literal value of the right hand side
2557 is greater than 4 then it is not worth it */
2558 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2561 size = getDataSize(IC_RESULT(ic));
2562 /* if decrement 16 bits in register */
2563 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2566 symbol *tlbl = newiTempLabel(NULL);
2567 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2568 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2569 IS_AOP_PREG(IC_RESULT(ic)))
2570 emitcode("cjne","%s,#0xff,%05d$"
2571 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2574 emitcode("mov","a,#0xff");
2575 emitcode("cjne","a,%s,%05d$"
2576 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2579 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2582 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2583 IS_AOP_PREG(IC_RESULT(ic)))
2584 emitcode("cjne","%s,#0xff,%05d$"
2585 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2588 emitcode("cjne","a,%s,%05d$"
2589 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2592 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2596 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2597 IS_AOP_PREG(IC_RESULT(ic)))
2598 emitcode("cjne","%s,#0xff,%05d$"
2599 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2602 emitcode("cjne","a,%s,%05d$"
2603 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2606 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2608 emitcode("","%05d$:",tlbl->key+100);
2612 /* if the sizes are greater than 1 then we cannot */
2613 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2614 AOP_SIZE(IC_LEFT(ic)) > 1 )
2617 /* we can if the aops of the left & result match or
2618 if they are in registers and the registers are the
2620 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2623 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2631 /*-----------------------------------------------------------------*/
2632 /* addSign - complete with sign */
2633 /*-----------------------------------------------------------------*/
2634 static void addSign(operand *result, int offset, int sign)
2636 int size = (getDataSize(result) - offset);
2639 emitcode("rlc","a");
2640 emitcode("subb","a,acc");
2642 aopPut(AOP(result),"a",offset++);
2645 aopPut(AOP(result),zero,offset++);
2649 /*-----------------------------------------------------------------*/
2650 /* genMinusBits - generates code for subtraction of two bits */
2651 /*-----------------------------------------------------------------*/
2652 static void genMinusBits (iCode *ic)
2654 symbol *lbl = newiTempLabel(NULL);
2655 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2656 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2657 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2658 emitcode("cpl","c");
2659 emitcode("","%05d$:",(lbl->key+100));
2660 outBitC(IC_RESULT(ic));
2663 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2664 emitcode("subb","a,acc");
2665 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
2666 emitcode("inc","a");
2667 emitcode("","%05d$:",(lbl->key+100));
2668 aopPut(AOP(IC_RESULT(ic)),"a",0);
2669 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
2673 /*-----------------------------------------------------------------*/
2674 /* genMinus - generates code for subtraction */
2675 /*-----------------------------------------------------------------*/
2676 static void genMinus (iCode *ic)
2678 int size, offset = 0;
2679 unsigned long lit = 0L;
2681 aopOp (IC_LEFT(ic),ic,FALSE);
2682 aopOp (IC_RIGHT(ic),ic,FALSE);
2683 aopOp (IC_RESULT(ic),ic,TRUE);
2685 /* special cases :- */
2686 /* if both left & right are in bit space */
2687 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2688 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2693 /* if I can do an decrement instead
2694 of subtract then GOOD for ME */
2695 if (genMinusDec (ic) == TRUE)
2698 size = getDataSize(IC_RESULT(ic));
2700 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
2704 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2708 /* if literal, add a,#-lit, else normal subb */
2710 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2711 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2712 emitcode("subb","a,%s",
2713 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2715 /* first add without previous c */
2717 emitcode("add","a,#0x%02x",
2718 (unsigned int)(lit & 0x0FFL));
2720 emitcode("addc","a,#0x%02x",
2721 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
2723 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2726 adjustArithmeticResult(ic);
2729 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2730 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2731 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2735 /*-----------------------------------------------------------------*/
2736 /* genMultbits :- multiplication of bits */
2737 /*-----------------------------------------------------------------*/
2738 static void genMultbits (operand *left,
2742 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2743 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
2748 /*-----------------------------------------------------------------*/
2749 /* genMultOneByte : 8 bit multiplication & division */
2750 /*-----------------------------------------------------------------*/
2751 static void genMultOneByte (operand *left,
2755 link *opetype = operandType(result);
2760 /* (if two literals, the value is computed before) */
2761 /* if one literal, literal on the right */
2762 if (AOP_TYPE(left) == AOP_LIT){
2768 size = AOP_SIZE(result);
2769 /* signed or unsigned */
2770 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2771 l = aopGet(AOP(left),0,FALSE,FALSE);
2773 emitcode("mul","ab");
2774 /* if result size = 1, mul signed = mul unsigned */
2775 aopPut(AOP(result),"a",0);
2777 if (SPEC_USIGN(opetype)){
2778 aopPut(AOP(result),"b",1);
2780 /* for filling the MSBs */
2781 emitcode("clr","a");
2784 emitcode("mov","a,b");
2786 /* adjust the MSB if left or right neg */
2788 /* if one literal */
2789 if (AOP_TYPE(right) == AOP_LIT){
2790 /* AND literal negative */
2791 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
2792 /* adjust MSB (c==0 after mul) */
2793 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2797 lbl = newiTempLabel(NULL);
2798 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2799 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
2800 emitcode("","%05d$:",(lbl->key+100));
2801 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2802 lbl = newiTempLabel(NULL);
2803 emitcode("jc","%05d$",(lbl->key+100));
2804 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2805 emitcode("","%05d$:",(lbl->key+100));
2808 lbl = newiTempLabel(NULL);
2809 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
2810 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
2811 emitcode("","%05d$:",(lbl->key+100));
2812 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
2813 lbl = newiTempLabel(NULL);
2814 emitcode("jc","%05d$",(lbl->key+100));
2815 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
2816 emitcode("","%05d$:",(lbl->key+100));
2818 aopPut(AOP(result),"a",1);
2821 emitcode("rlc","a");
2822 emitcode("subb","a,acc");
2829 aopPut(AOP(result),"a",offset++);
2833 /*-----------------------------------------------------------------*/
2834 /* genMult - generates code for multiplication */
2835 /*-----------------------------------------------------------------*/
2836 static void genMult (iCode *ic)
2838 operand *left = IC_LEFT(ic);
2839 operand *right = IC_RIGHT(ic);
2840 operand *result= IC_RESULT(ic);
2842 /* assign the amsops */
2843 aopOp (left,ic,FALSE);
2844 aopOp (right,ic,FALSE);
2845 aopOp (result,ic,TRUE);
2847 /* special cases first */
2849 if (AOP_TYPE(left) == AOP_CRY &&
2850 AOP_TYPE(right)== AOP_CRY) {
2851 genMultbits(left,right,result);
2855 /* if both are of size == 1 */
2856 if (AOP_SIZE(left) == 1 &&
2857 AOP_SIZE(right) == 1 ) {
2858 genMultOneByte(left,right,result);
2862 /* should have been converted to function call */
2866 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2867 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2868 freeAsmop(result,NULL,ic,TRUE);
2871 /*-----------------------------------------------------------------*/
2872 /* genDivbits :- division of bits */
2873 /*-----------------------------------------------------------------*/
2874 static void genDivbits (operand *left,
2881 /* the result must be bit */
2882 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
2883 l = aopGet(AOP(left),0,FALSE,FALSE);
2887 emitcode("div","ab");
2888 emitcode("rrc","a");
2889 aopPut(AOP(result),"c",0);
2892 /*-----------------------------------------------------------------*/
2893 /* genDivOneByte : 8 bit division */
2894 /*-----------------------------------------------------------------*/
2895 static void genDivOneByte (operand *left,
2899 link *opetype = operandType(result);
2904 size = AOP_SIZE(result) - 1;
2906 /* signed or unsigned */
2907 if (SPEC_USIGN(opetype)) {
2908 /* unsigned is easy */
2909 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2910 l = aopGet(AOP(left),0,FALSE,FALSE);
2912 emitcode("div","ab");
2913 aopPut(AOP(result),"a",0);
2915 aopPut(AOP(result),zero,offset++);
2919 /* signed is a little bit more difficult */
2921 /* save the signs of the operands */
2922 l = aopGet(AOP(left),0,FALSE,FALSE);
2924 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
2925 emitcode("push","acc"); /* save it on the stack */
2927 /* now sign adjust for both left & right */
2928 l = aopGet(AOP(right),0,FALSE,FALSE);
2930 lbl = newiTempLabel(NULL);
2931 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
2932 emitcode("cpl","a");
2933 emitcode("inc","a");
2934 emitcode("","%05d$:",(lbl->key+100));
2935 emitcode("mov","b,a");
2937 /* sign adjust left side */
2938 l = aopGet(AOP(left),0,FALSE,FALSE);
2941 lbl = newiTempLabel(NULL);
2942 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
2943 emitcode("cpl","a");
2944 emitcode("inc","a");
2945 emitcode("","%05d$:",(lbl->key+100));
2947 /* now the division */
2948 emitcode("div","ab");
2949 /* we are interested in the lower order
2951 emitcode("mov","b,a");
2952 lbl = newiTempLabel(NULL);
2953 emitcode("pop","acc");
2954 /* if there was an over flow we don't
2955 adjust the sign of the result */
2956 emitcode("jb","ov,%05d$",(lbl->key+100));
2957 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
2959 emitcode("clr","a");
2960 emitcode("subb","a,b");
2961 emitcode("mov","b,a");
2962 emitcode("","%05d$:",(lbl->key+100));
2964 /* now we are done */
2965 aopPut(AOP(result),"b",0);
2967 emitcode("mov","c,b.7");
2968 emitcode("subb","a,acc");
2971 aopPut(AOP(result),"a",offset++);
2975 /*-----------------------------------------------------------------*/
2976 /* genDiv - generates code for division */
2977 /*-----------------------------------------------------------------*/
2978 static void genDiv (iCode *ic)
2980 operand *left = IC_LEFT(ic);
2981 operand *right = IC_RIGHT(ic);
2982 operand *result= IC_RESULT(ic);
2984 /* assign the amsops */
2985 aopOp (left,ic,FALSE);
2986 aopOp (right,ic,FALSE);
2987 aopOp (result,ic,TRUE);
2989 /* special cases first */
2991 if (AOP_TYPE(left) == AOP_CRY &&
2992 AOP_TYPE(right)== AOP_CRY) {
2993 genDivbits(left,right,result);
2997 /* if both are of size == 1 */
2998 if (AOP_SIZE(left) == 1 &&
2999 AOP_SIZE(right) == 1 ) {
3000 genDivOneByte(left,right,result);
3004 /* should have been converted to function call */
3007 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3008 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3009 freeAsmop(result,NULL,ic,TRUE);
3012 /*-----------------------------------------------------------------*/
3013 /* genModbits :- modulus of bits */
3014 /*-----------------------------------------------------------------*/
3015 static void genModbits (operand *left,
3022 /* the result must be bit */
3023 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3024 l = aopGet(AOP(left),0,FALSE,FALSE);
3028 emitcode("div","ab");
3029 emitcode("mov","a,b");
3030 emitcode("rrc","a");
3031 aopPut(AOP(result),"c",0);
3034 /*-----------------------------------------------------------------*/
3035 /* genModOneByte : 8 bit modulus */
3036 /*-----------------------------------------------------------------*/
3037 static void genModOneByte (operand *left,
3041 link *opetype = operandType(result);
3045 /* signed or unsigned */
3046 if (SPEC_USIGN(opetype)) {
3047 /* unsigned is easy */
3048 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3049 l = aopGet(AOP(left),0,FALSE,FALSE);
3051 emitcode("div","ab");
3052 aopPut(AOP(result),"b",0);
3056 /* signed is a little bit more difficult */
3058 /* save the signs of the operands */
3059 l = aopGet(AOP(left),0,FALSE,FALSE);
3062 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3063 emitcode("push","acc"); /* save it on the stack */
3065 /* now sign adjust for both left & right */
3066 l = aopGet(AOP(right),0,FALSE,FALSE);
3069 lbl = newiTempLabel(NULL);
3070 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3071 emitcode("cpl","a");
3072 emitcode("inc","a");
3073 emitcode("","%05d$:",(lbl->key+100));
3074 emitcode("mov","b,a");
3076 /* sign adjust left side */
3077 l = aopGet(AOP(left),0,FALSE,FALSE);
3080 lbl = newiTempLabel(NULL);
3081 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3082 emitcode("cpl","a");
3083 emitcode("inc","a");
3084 emitcode("","%05d$:",(lbl->key+100));
3086 /* now the multiplication */
3087 emitcode("div","ab");
3088 /* we are interested in the lower order
3090 lbl = newiTempLabel(NULL);
3091 emitcode("pop","acc");
3092 /* if there was an over flow we don't
3093 adjust the sign of the result */
3094 emitcode("jb","ov,%05d$",(lbl->key+100));
3095 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3097 emitcode("clr","a");
3098 emitcode("subb","a,b");
3099 emitcode("mov","b,a");
3100 emitcode("","%05d$:",(lbl->key+100));
3102 /* now we are done */
3103 aopPut(AOP(result),"b",0);
3107 /*-----------------------------------------------------------------*/
3108 /* genMod - generates code for division */
3109 /*-----------------------------------------------------------------*/
3110 static void genMod (iCode *ic)
3112 operand *left = IC_LEFT(ic);
3113 operand *right = IC_RIGHT(ic);
3114 operand *result= IC_RESULT(ic);
3116 /* assign the amsops */
3117 aopOp (left,ic,FALSE);
3118 aopOp (right,ic,FALSE);
3119 aopOp (result,ic,TRUE);
3121 /* special cases first */
3123 if (AOP_TYPE(left) == AOP_CRY &&
3124 AOP_TYPE(right)== AOP_CRY) {
3125 genModbits(left,right,result);
3129 /* if both are of size == 1 */
3130 if (AOP_SIZE(left) == 1 &&
3131 AOP_SIZE(right) == 1 ) {
3132 genModOneByte(left,right,result);
3136 /* should have been converted to function call */
3140 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3141 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3142 freeAsmop(result,NULL,ic,TRUE);
3145 /*-----------------------------------------------------------------*/
3146 /* genIfxJump :- will create a jump depending on the ifx */
3147 /*-----------------------------------------------------------------*/
3148 static void genIfxJump (iCode *ic, char *jval)
3151 symbol *tlbl = newiTempLabel(NULL);
3154 /* if true label then we jump if condition
3156 if ( IC_TRUE(ic) ) {
3158 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3159 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3162 /* false label is present */
3163 jlbl = IC_FALSE(ic) ;
3164 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3165 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3167 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3168 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3170 emitcode(inst,"%05d$",tlbl->key+100);
3171 emitcode("ljmp","%05d$",jlbl->key+100);
3172 emitcode("","%05d$:",tlbl->key+100);
3174 /* mark the icode as generated */
3178 /*-----------------------------------------------------------------*/
3179 /* genCmp :- greater or less than comparison */
3180 /*-----------------------------------------------------------------*/
3181 static void genCmp (operand *left,operand *right,
3182 operand *result, iCode *ifx, int sign)
3184 int size, offset = 0 ;
3185 unsigned long lit = 0L;
3187 /* if left & right are bit variables */
3188 if (AOP_TYPE(left) == AOP_CRY &&
3189 AOP_TYPE(right) == AOP_CRY ) {
3190 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3191 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3193 /* subtract right from left if at the
3194 end the carry flag is set then we know that
3195 left is greater than right */
3196 size = max(AOP_SIZE(left),AOP_SIZE(right));
3198 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3199 if((size == 1) && !sign &&
3200 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3201 symbol *lbl = newiTempLabel(NULL);
3202 emitcode("cjne","%s,%s,%05d$",
3203 aopGet(AOP(left),offset,FALSE,FALSE),
3204 aopGet(AOP(right),offset,FALSE,FALSE),
3206 emitcode("","%05d$:",lbl->key+100);
3208 if(AOP_TYPE(right) == AOP_LIT){
3209 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3210 /* optimize if(x < 0) or if(x >= 0) */
3216 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE));
3217 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3218 genIfxJump (ifx,"acc.7");
3222 emitcode("rlc","a");
3229 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3230 if (sign && size == 0) {
3231 emitcode("xrl","a,#0x80");
3232 if (AOP_TYPE(right) == AOP_LIT){
3233 unsigned long lit = (unsigned long)
3234 floatFromVal(AOP(right)->aopu.aop_lit);
3235 emitcode("subb","a,#0x%02x",
3236 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3238 emitcode("mov","b,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3239 emitcode("xrl","b,#0x80");
3240 emitcode("subb","a,b");
3243 emitcode("subb","a,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3249 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3252 /* if the result is used in the next
3253 ifx conditional branch then generate
3254 code a little differently */
3256 genIfxJump (ifx,"c");
3259 /* leave the result in acc */
3263 /*-----------------------------------------------------------------*/
3264 /* genCmpGt :- greater than comparison */
3265 /*-----------------------------------------------------------------*/
3266 static void genCmpGt (iCode *ic, iCode *ifx)
3268 operand *left, *right, *result;
3269 link *letype , *retype;
3273 right= IC_RIGHT(ic);
3274 result = IC_RESULT(ic);
3276 letype = getSpec(operandType(left));
3277 retype =getSpec(operandType(right));
3278 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3279 /* assign the amsops */
3280 aopOp (left,ic,FALSE);
3281 aopOp (right,ic,FALSE);
3282 aopOp (result,ic,TRUE);
3284 genCmp(right, left, result, ifx, sign);
3286 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3287 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3288 freeAsmop(result,NULL,ic,TRUE);
3291 /*-----------------------------------------------------------------*/
3292 /* genCmpLt - less than comparisons */
3293 /*-----------------------------------------------------------------*/
3294 static void genCmpLt (iCode *ic, iCode *ifx)
3296 operand *left, *right, *result;
3297 link *letype , *retype;
3301 right= IC_RIGHT(ic);
3302 result = IC_RESULT(ic);
3304 letype = getSpec(operandType(left));
3305 retype =getSpec(operandType(right));
3306 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3308 /* assign the amsops */
3309 aopOp (left,ic,FALSE);
3310 aopOp (right,ic,FALSE);
3311 aopOp (result,ic,TRUE);
3313 genCmp(left, right, result, ifx, sign);
3315 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3316 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3317 freeAsmop(result,NULL,ic,TRUE);
3320 /*-----------------------------------------------------------------*/
3321 /* gencjneshort - compare and jump if not equal */
3322 /*-----------------------------------------------------------------*/
3323 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3325 int size = max(AOP_SIZE(left),AOP_SIZE(right));
3327 unsigned long lit = 0L;
3329 /* if the left side is a literal or
3330 if the right is in a pointer register and left
3332 if ((AOP_TYPE(left) == AOP_LIT) ||
3333 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3338 if(AOP_TYPE(right) == AOP_LIT)
3339 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3341 /* if the right side is a literal then anything goes */
3342 if (AOP_TYPE(right) == AOP_LIT &&
3343 AOP_TYPE(left) != AOP_DIR ) {
3345 emitcode("cjne","%s,%s,%05d$",
3346 aopGet(AOP(left),offset,FALSE,FALSE),
3347 aopGet(AOP(right),offset,FALSE,FALSE),
3353 /* if the right side is in a register or in direct space or
3354 if the left is a pointer register & right is not */
3355 else if (AOP_TYPE(right) == AOP_REG ||
3356 AOP_TYPE(right) == AOP_DIR ||
3357 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3358 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3360 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3361 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3362 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
3363 emitcode("jnz","%05d$",lbl->key+100);
3365 emitcode("cjne","a,%s,%05d$",
3366 aopGet(AOP(right),offset,FALSE,TRUE),
3371 /* right is a pointer reg need both a & b */
3373 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
3375 emitcode("mov","b,%s",l);
3376 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3377 emitcode("cjne","a,b,%05d$",lbl->key+100);
3383 /*-----------------------------------------------------------------*/
3384 /* gencjne - compare and jump if not equal */
3385 /*-----------------------------------------------------------------*/
3386 static void gencjne(operand *left, operand *right, symbol *lbl)
3388 symbol *tlbl = newiTempLabel(NULL);
3390 gencjneshort(left, right, lbl);
3392 emitcode("mov","a,%s",one);
3393 emitcode("sjmp","%05d$",tlbl->key+100);
3394 emitcode("","%05d$:",lbl->key+100);
3395 emitcode("clr","a");
3396 emitcode("","%05d$:",tlbl->key+100);
3399 /*-----------------------------------------------------------------*/
3400 /* genCmpEq - generates code for equal to */
3401 /*-----------------------------------------------------------------*/
3402 static void genCmpEq (iCode *ic, iCode *ifx)
3404 operand *left, *right, *result;
3406 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3407 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3408 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3410 /* if literal, literal on the right or
3411 if the right is in a pointer register and left
3413 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
3414 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3415 operand *t = IC_RIGHT(ic);
3416 IC_RIGHT(ic) = IC_LEFT(ic);
3420 if(ifx && !AOP_SIZE(result)){
3422 /* if they are both bit variables */
3423 if (AOP_TYPE(left) == AOP_CRY &&
3424 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3425 if(AOP_TYPE(right) == AOP_LIT){
3426 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3428 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3429 emitcode("cpl","c");
3430 } else if(lit == 1L) {
3431 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3433 emitcode("clr","c");
3435 /* AOP_TYPE(right) == AOP_CRY */
3437 symbol *lbl = newiTempLabel(NULL);
3438 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3439 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3440 emitcode("cpl","c");
3441 emitcode("","%05d$:",(lbl->key+100));
3443 /* if true label then we jump if condition
3445 tlbl = newiTempLabel(NULL);
3446 if ( IC_TRUE(ifx) ) {
3447 emitcode("jnc","%05d$",tlbl->key+100);
3448 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3450 emitcode("jc","%05d$",tlbl->key+100);
3451 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3453 emitcode("","%05d$:",tlbl->key+100);
3455 tlbl = newiTempLabel(NULL);
3456 gencjneshort(left, right, tlbl);
3457 if ( IC_TRUE(ifx) ) {
3458 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3459 emitcode("","%05d$:",tlbl->key+100);
3461 symbol *lbl = newiTempLabel(NULL);
3462 emitcode("sjmp","%05d$",lbl->key+100);
3463 emitcode("","%05d$:",tlbl->key+100);
3464 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3465 emitcode("","%05d$:",lbl->key+100);
3468 /* mark the icode as generated */
3473 /* if they are both bit variables */
3474 if (AOP_TYPE(left) == AOP_CRY &&
3475 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3476 if(AOP_TYPE(right) == AOP_LIT){
3477 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3479 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3480 emitcode("cpl","c");
3481 } else if(lit == 1L) {
3482 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3484 emitcode("clr","c");
3486 /* AOP_TYPE(right) == AOP_CRY */
3488 symbol *lbl = newiTempLabel(NULL);
3489 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3490 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3491 emitcode("cpl","c");
3492 emitcode("","%05d$:",(lbl->key+100));
3495 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
3500 genIfxJump (ifx,"c");
3503 /* if the result is used in an arithmetic operation
3504 then put the result in place */
3507 gencjne(left,right,newiTempLabel(NULL));
3508 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3509 aopPut(AOP(result),"a",0);
3513 genIfxJump (ifx,"a");
3516 /* if the result is used in an arithmetic operation
3517 then put the result in place */
3518 if (AOP_TYPE(result) != AOP_CRY)
3520 /* leave the result in acc */
3524 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3525 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3526 freeAsmop(result,NULL,ic,TRUE);
3529 /*-----------------------------------------------------------------*/
3530 /* ifxForOp - returns the icode containing the ifx for operand */
3531 /*-----------------------------------------------------------------*/
3532 static iCode *ifxForOp ( operand *op, iCode *ic )
3534 /* if true symbol then needs to be assigned */
3535 if (IS_TRUE_SYMOP(op))
3538 /* if this has register type condition and
3539 the next instruction is ifx with the same operand
3540 and live to of the operand is upto the ifx only then */
3542 ic->next->op == IFX &&
3543 IC_COND(ic->next)->key == op->key &&
3544 OP_SYMBOL(op)->liveTo <= ic->next->seq )
3549 /*-----------------------------------------------------------------*/
3550 /* genAndOp - for && operation */
3551 /*-----------------------------------------------------------------*/
3552 static void genAndOp (iCode *ic)
3554 operand *left,*right, *result;
3557 /* note here that && operations that are in an
3558 if statement are taken away by backPatchLabels
3559 only those used in arthmetic operations remain */
3560 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3561 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3562 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3564 /* if both are bit variables */
3565 if (AOP_TYPE(left) == AOP_CRY &&
3566 AOP_TYPE(right) == AOP_CRY ) {
3567 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3568 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3571 tlbl = newiTempLabel(NULL);
3573 emitcode("jz","%05d$",tlbl->key+100);
3575 emitcode("","%05d$:",tlbl->key+100);
3579 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3580 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3581 freeAsmop(result,NULL,ic,TRUE);
3585 /*-----------------------------------------------------------------*/
3586 /* genOrOp - for || operation */
3587 /*-----------------------------------------------------------------*/
3588 static void genOrOp (iCode *ic)
3590 operand *left,*right, *result;
3593 /* note here that || operations that are in an
3594 if statement are taken away by backPatchLabels
3595 only those used in arthmetic operations remain */
3596 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3597 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3598 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3600 /* if both are bit variables */
3601 if (AOP_TYPE(left) == AOP_CRY &&
3602 AOP_TYPE(right) == AOP_CRY ) {
3603 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3604 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
3607 tlbl = newiTempLabel(NULL);
3609 emitcode("jnz","%05d$",tlbl->key+100);
3611 emitcode("","%05d$:",tlbl->key+100);
3615 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3616 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3617 freeAsmop(result,NULL,ic,TRUE);
3620 /*-----------------------------------------------------------------*/
3621 /* isLiteralBit - test if lit == 2^n */
3622 /*-----------------------------------------------------------------*/
3623 static int isLiteralBit(unsigned long lit)
3625 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
3626 0x100L,0x200L,0x400L,0x800L,
3627 0x1000L,0x2000L,0x4000L,0x8000L,
3628 0x10000L,0x20000L,0x40000L,0x80000L,
3629 0x100000L,0x200000L,0x400000L,0x800000L,
3630 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
3631 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
3634 for(idx = 0; idx < 32; idx++)
3640 /*-----------------------------------------------------------------*/
3641 /* continueIfTrue - */
3642 /*-----------------------------------------------------------------*/
3643 static void continueIfTrue (iCode *ic)
3646 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3650 /*-----------------------------------------------------------------*/
3652 /*-----------------------------------------------------------------*/
3653 static void jumpIfTrue (iCode *ic)
3656 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3660 /*-----------------------------------------------------------------*/
3661 /* jmpTrueOrFalse - */
3662 /*-----------------------------------------------------------------*/
3663 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
3665 // ugly but optimized by peephole
3667 symbol *nlbl = newiTempLabel(NULL);
3668 emitcode("sjmp","%05d$",nlbl->key+100);
3669 emitcode("","%05d$:",tlbl->key+100);
3670 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3671 emitcode("","%05d$:",nlbl->key+100);
3674 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3675 emitcode("","%05d$:",tlbl->key+100);
3680 /*-----------------------------------------------------------------*/
3681 /* genAnd - code for and */
3682 /*-----------------------------------------------------------------*/
3683 static void genAnd (iCode *ic, iCode *ifx)
3685 operand *left, *right, *result;
3687 unsigned long lit = 0L;
3691 aopOp((left = IC_LEFT(ic)),ic,FALSE);
3692 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3693 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3696 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3698 AOP_TYPE(left), AOP_TYPE(right));
3699 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3701 AOP_SIZE(left), AOP_SIZE(right));
3704 /* if left is a literal & right is not then exchange them */
3705 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3706 AOP_NEEDSACC(left)) {
3707 operand *tmp = right ;
3712 /* if result = right then exchange them */
3713 if(sameRegs(AOP(result),AOP(right))){
3714 operand *tmp = right ;
3719 /* if right is bit then exchange them */
3720 if (AOP_TYPE(right) == AOP_CRY &&
3721 AOP_TYPE(left) != AOP_CRY){
3722 operand *tmp = right ;
3726 if(AOP_TYPE(right) == AOP_LIT)
3727 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3729 size = AOP_SIZE(result);
3732 // result = bit & yy;
3733 if (AOP_TYPE(left) == AOP_CRY){
3734 // c = bit & literal;
3735 if(AOP_TYPE(right) == AOP_LIT){
3737 if(size && sameRegs(AOP(result),AOP(left)))
3740 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3743 if(size && (AOP_TYPE(result) == AOP_CRY)){
3744 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
3747 if((AOP_TYPE(result) == AOP_CRY) && ifx){
3751 emitcode("clr","c");
3754 if (AOP_TYPE(right) == AOP_CRY){
3756 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3757 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3760 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
3762 emitcode("rrc","a");
3763 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3771 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
3772 genIfxJump(ifx, "c");
3776 // if(val & 0xZZ) - size = 0, ifx != FALSE -
3777 // bit = val & 0xZZ - size = 1, ifx = FALSE -
3778 if((AOP_TYPE(right) == AOP_LIT) &&
3779 (AOP_TYPE(result) == AOP_CRY) &&
3780 (AOP_TYPE(left) != AOP_CRY)){
3781 int posbit = isLiteralBit(lit);
3785 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
3788 emitcode("mov","c,acc.%d",posbit&0x07);
3792 sprintf(buffer,"acc.%d",posbit&0x07);
3793 genIfxJump(ifx, buffer);
3798 symbol *tlbl = newiTempLabel(NULL);
3799 int sizel = AOP_SIZE(left);
3801 emitcode("setb","c");
3803 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
3804 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
3806 if((posbit = isLiteralBit(bytelit)) != 0)
3807 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
3809 if(bytelit != 0x0FFL)
3810 emitcode("anl","a,%s",
3811 aopGet(AOP(right),offset,FALSE,TRUE));
3812 emitcode("jnz","%05d$",tlbl->key+100);
3817 // bit = left & literal
3819 emitcode("clr","c");
3820 emitcode("","%05d$:",tlbl->key+100);
3822 // if(left & literal)
3825 jmpTrueOrFalse(ifx, tlbl);
3833 /* if left is same as result */
3834 if(sameRegs(AOP(result),AOP(left))){
3835 for(;size--; offset++) {
3836 if(AOP_TYPE(right) == AOP_LIT){
3837 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
3841 aopPut(AOP(result),zero,offset);
3843 if (IS_AOP_PREG(result)) {
3844 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3845 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
3846 aopPut(AOP(result),"a",offset);
3848 emitcode("anl","%s,%s",
3849 aopGet(AOP(left),offset,FALSE,TRUE),
3850 aopGet(AOP(right),offset,FALSE,FALSE));
3852 if (AOP_TYPE(left) == AOP_ACC)
3853 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
3855 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3856 if (IS_AOP_PREG(result)) {
3857 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
3858 aopPut(AOP(result),"a",offset);
3861 emitcode("anl","%s,a",
3862 aopGet(AOP(left),offset,FALSE,TRUE));
3867 // left & result in different registers
3868 if(AOP_TYPE(result) == AOP_CRY){
3870 // if(size), result in bit
3871 // if(!size && ifx), conditional oper: if(left & right)
3872 symbol *tlbl = newiTempLabel(NULL);
3873 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
3875 emitcode("setb","c");
3877 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3878 emitcode("anl","a,%s",
3879 aopGet(AOP(left),offset,FALSE,FALSE));
3880 emitcode("jnz","%05d$",tlbl->key+100);
3885 emitcode("","%05d$:",tlbl->key+100);
3888 jmpTrueOrFalse(ifx, tlbl);
3890 for(;(size--);offset++) {
3892 // result = left & right
3893 if(AOP_TYPE(right) == AOP_LIT){
3894 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
3896 aopGet(AOP(left),offset,FALSE,FALSE),
3899 } else if(bytelit == 0){
3900 aopPut(AOP(result),zero,offset);
3904 // faster than result <- left, anl result,right
3905 // and better if result is SFR
3906 if (AOP_TYPE(left) == AOP_ACC)
3907 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
3909 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3910 emitcode("anl","a,%s",
3911 aopGet(AOP(left),offset,FALSE,FALSE));
3913 aopPut(AOP(result),"a",offset);
3919 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3920 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3921 freeAsmop(result,NULL,ic,TRUE);
3924 /*-----------------------------------------------------------------*/
3925 /* genOr - code for or */
3926 /*-----------------------------------------------------------------*/
3927 static void genOr (iCode *ic, iCode *ifx)
3929 operand *left, *right, *result;
3931 unsigned long lit = 0L;
3933 aopOp((left = IC_LEFT(ic)),ic,FALSE);
3934 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3935 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3938 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3940 AOP_TYPE(left), AOP_TYPE(right));
3941 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3943 AOP_SIZE(left), AOP_SIZE(right));
3946 /* if left is a literal & right is not then exchange them */
3947 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3948 AOP_NEEDSACC(left)) {
3949 operand *tmp = right ;
3954 /* if result = right then exchange them */
3955 if(sameRegs(AOP(result),AOP(right))){
3956 operand *tmp = right ;
3961 /* if right is bit then exchange them */
3962 if (AOP_TYPE(right) == AOP_CRY &&
3963 AOP_TYPE(left) != AOP_CRY){
3964 operand *tmp = right ;
3968 if(AOP_TYPE(right) == AOP_LIT)
3969 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3971 size = AOP_SIZE(result);
3975 if (AOP_TYPE(left) == AOP_CRY){
3976 if(AOP_TYPE(right) == AOP_LIT){
3977 // c = bit & literal;
3979 // lit != 0 => result = 1
3980 if(AOP_TYPE(result) == AOP_CRY){
3982 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
3984 continueIfTrue(ifx);
3987 emitcode("setb","c");
3989 // lit == 0 => result = left
3990 if(size && sameRegs(AOP(result),AOP(left)))
3992 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3995 if (AOP_TYPE(right) == AOP_CRY){
3997 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3998 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4002 symbol *tlbl = newiTempLabel(NULL);
4003 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4004 emitcode("setb","c");
4005 emitcode("jb","%s,%05d$",
4006 AOP(left)->aopu.aop_dir,tlbl->key+100);
4008 emitcode("jnz","%05d$",tlbl->key+100);
4009 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4010 jmpTrueOrFalse(ifx, tlbl);
4014 emitcode("","%05d$:",tlbl->key+100);
4023 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4024 genIfxJump(ifx, "c");
4028 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4029 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4030 if((AOP_TYPE(right) == AOP_LIT) &&
4031 (AOP_TYPE(result) == AOP_CRY) &&
4032 (AOP_TYPE(left) != AOP_CRY)){
4036 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4038 continueIfTrue(ifx);
4041 // lit = 0, result = boolean(left)
4043 emitcode("setb","c");
4046 symbol *tlbl = newiTempLabel(NULL);
4047 emitcode("jnz","%05d$",tlbl->key+100);
4049 emitcode("","%05d$:",tlbl->key+100);
4051 genIfxJump (ifx,"a");
4059 /* if left is same as result */
4060 if(sameRegs(AOP(result),AOP(left))){
4061 for(;size--; offset++) {
4062 if(AOP_TYPE(right) == AOP_LIT){
4063 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4066 if (IS_AOP_PREG(left)) {
4067 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4068 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4069 aopPut(AOP(result),"a",offset);
4071 emitcode("orl","%s,%s",
4072 aopGet(AOP(left),offset,FALSE,TRUE),
4073 aopGet(AOP(right),offset,FALSE,FALSE));
4075 if (AOP_TYPE(left) == AOP_ACC)
4076 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4078 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4079 if (IS_AOP_PREG(left)) {
4080 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4081 aopPut(AOP(result),"a",offset);
4083 emitcode("orl","%s,a",
4084 aopGet(AOP(left),offset,FALSE,TRUE));
4089 // left & result in different registers
4090 if(AOP_TYPE(result) == AOP_CRY){
4092 // if(size), result in bit
4093 // if(!size && ifx), conditional oper: if(left | right)
4094 symbol *tlbl = newiTempLabel(NULL);
4095 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4097 emitcode("setb","c");
4099 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4100 emitcode("orl","a,%s",
4101 aopGet(AOP(left),offset,FALSE,FALSE));
4102 emitcode("jnz","%05d$",tlbl->key+100);
4107 emitcode("","%05d$:",tlbl->key+100);
4110 jmpTrueOrFalse(ifx, tlbl);
4111 } else for(;(size--);offset++){
4113 // result = left & right
4114 if(AOP_TYPE(right) == AOP_LIT){
4115 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4117 aopGet(AOP(left),offset,FALSE,FALSE),
4122 // faster than result <- left, anl result,right
4123 // and better if result is SFR
4124 if (AOP_TYPE(left) == AOP_ACC)
4125 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4127 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4128 emitcode("orl","a,%s",
4129 aopGet(AOP(left),offset,FALSE,FALSE));
4131 aopPut(AOP(result),"a",offset);
4136 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4137 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4138 freeAsmop(result,NULL,ic,TRUE);
4141 /*-----------------------------------------------------------------*/
4142 /* genXor - code for xclusive or */
4143 /*-----------------------------------------------------------------*/
4144 static void genXor (iCode *ic, iCode *ifx)
4146 operand *left, *right, *result;
4148 unsigned long lit = 0L;
4150 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4151 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4152 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4155 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4157 AOP_TYPE(left), AOP_TYPE(right));
4158 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4160 AOP_SIZE(left), AOP_SIZE(right));
4163 /* if left is a literal & right is not ||
4164 if left needs acc & right does not */
4165 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4166 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4167 operand *tmp = right ;
4172 /* if result = right then exchange them */
4173 if(sameRegs(AOP(result),AOP(right))){
4174 operand *tmp = right ;
4179 /* if right is bit then exchange them */
4180 if (AOP_TYPE(right) == AOP_CRY &&
4181 AOP_TYPE(left) != AOP_CRY){
4182 operand *tmp = right ;
4186 if(AOP_TYPE(right) == AOP_LIT)
4187 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4189 size = AOP_SIZE(result);
4193 if (AOP_TYPE(left) == AOP_CRY){
4194 if(AOP_TYPE(right) == AOP_LIT){
4195 // c = bit & literal;
4197 // lit>>1 != 0 => result = 1
4198 if(AOP_TYPE(result) == AOP_CRY){
4200 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4202 continueIfTrue(ifx);
4205 emitcode("setb","c");
4209 // lit == 0, result = left
4210 if(size && sameRegs(AOP(result),AOP(left)))
4212 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4214 // lit == 1, result = not(left)
4215 if(size && sameRegs(AOP(result),AOP(left))){
4216 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4219 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4220 emitcode("cpl","c");
4227 symbol *tlbl = newiTempLabel(NULL);
4228 if (AOP_TYPE(right) == AOP_CRY){
4230 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4233 int sizer = AOP_SIZE(right);
4235 // if val>>1 != 0, result = 1
4236 emitcode("setb","c");
4238 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
4240 // test the msb of the lsb
4241 emitcode("anl","a,#0xfe");
4242 emitcode("jnz","%05d$",tlbl->key+100);
4246 emitcode("rrc","a");
4248 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4249 emitcode("cpl","c");
4250 emitcode("","%05d$:",(tlbl->key+100));
4257 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4258 genIfxJump(ifx, "c");
4262 if(sameRegs(AOP(result),AOP(left))){
4263 /* if left is same as result */
4264 for(;size--; offset++) {
4265 if(AOP_TYPE(right) == AOP_LIT){
4266 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4269 if (IS_AOP_PREG(left)) {
4270 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4271 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4272 aopPut(AOP(result),"a",offset);
4274 emitcode("xrl","%s,%s",
4275 aopGet(AOP(left),offset,FALSE,TRUE),
4276 aopGet(AOP(right),offset,FALSE,FALSE));
4278 if (AOP_TYPE(left) == AOP_ACC)
4279 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4281 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4282 if (IS_AOP_PREG(left)) {
4283 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4284 aopPut(AOP(result),"a",offset);
4286 emitcode("xrl","%s,a",
4287 aopGet(AOP(left),offset,FALSE,TRUE));
4292 // left & result in different registers
4293 if(AOP_TYPE(result) == AOP_CRY){
4295 // if(size), result in bit
4296 // if(!size && ifx), conditional oper: if(left ^ right)
4297 symbol *tlbl = newiTempLabel(NULL);
4298 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4300 emitcode("setb","c");
4302 if((AOP_TYPE(right) == AOP_LIT) &&
4303 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4304 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4306 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4307 emitcode("xrl","a,%s",
4308 aopGet(AOP(left),offset,FALSE,FALSE));
4310 emitcode("jnz","%05d$",tlbl->key+100);
4315 emitcode("","%05d$:",tlbl->key+100);
4318 jmpTrueOrFalse(ifx, tlbl);
4319 } else for(;(size--);offset++){
4321 // result = left & right
4322 if(AOP_TYPE(right) == AOP_LIT){
4323 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4325 aopGet(AOP(left),offset,FALSE,FALSE),
4330 // faster than result <- left, anl result,right
4331 // and better if result is SFR
4332 if (AOP_TYPE(left) == AOP_ACC)
4333 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4335 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4336 emitcode("xrl","a,%s",
4337 aopGet(AOP(left),offset,FALSE,TRUE));
4339 aopPut(AOP(result),"a",offset);
4344 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4345 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4346 freeAsmop(result,NULL,ic,TRUE);
4349 /*-----------------------------------------------------------------*/
4350 /* genInline - write the inline code out */
4351 /*-----------------------------------------------------------------*/
4352 static void genInline (iCode *ic)
4354 char buffer[MAX_INLINEASM];
4358 _G.inLine += (!options.asmpeep);
4359 strcpy(buffer,IC_INLINE(ic));
4361 /* emit each line as a code */
4380 /* emitcode("",buffer); */
4381 _G.inLine -= (!options.asmpeep);
4384 /*-----------------------------------------------------------------*/
4385 /* genRRC - rotate right with carry */
4386 /*-----------------------------------------------------------------*/
4387 static void genRRC (iCode *ic)
4389 operand *left , *result ;
4390 int size, offset = 0;
4393 /* rotate right with carry */
4395 result=IC_RESULT(ic);
4396 aopOp (left,ic,FALSE);
4397 aopOp (result,ic,FALSE);
4399 /* move it to the result */
4400 size = AOP_SIZE(result);
4404 l = aopGet(AOP(left),offset,FALSE,FALSE);
4406 emitcode("rrc","a");
4407 if (AOP_SIZE(result) > 1)
4408 aopPut(AOP(result),"a",offset--);
4410 /* now we need to put the carry into the
4411 highest order byte of the result */
4412 if (AOP_SIZE(result) > 1) {
4413 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
4416 emitcode("mov","acc.7,c");
4417 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
4418 freeAsmop(left,NULL,ic,TRUE);
4419 freeAsmop(result,NULL,ic,TRUE);
4422 /*-----------------------------------------------------------------*/
4423 /* genRLC - generate code for rotate left with carry */
4424 /*-----------------------------------------------------------------*/
4425 static void genRLC (iCode *ic)
4427 operand *left , *result ;
4428 int size, offset = 0;
4431 /* rotate right with carry */
4433 result=IC_RESULT(ic);
4434 aopOp (left,ic,FALSE);
4435 aopOp (result,ic,FALSE);
4437 /* move it to the result */
4438 size = AOP_SIZE(result);
4441 l = aopGet(AOP(left),offset,FALSE,FALSE);
4443 emitcode("add","a,acc");
4444 if (AOP_SIZE(result) > 1)
4445 aopPut(AOP(result),"a",offset++);
4447 l = aopGet(AOP(left),offset,FALSE,FALSE);
4449 emitcode("rlc","a");
4450 if (AOP_SIZE(result) > 1)
4451 aopPut(AOP(result),"a",offset++);
4454 /* now we need to put the carry into the
4455 highest order byte of the result */
4456 if (AOP_SIZE(result) > 1) {
4457 l = aopGet(AOP(result),0,FALSE,FALSE);
4460 emitcode("mov","acc.0,c");
4461 aopPut(AOP(result),"a",0);
4462 freeAsmop(left,NULL,ic,TRUE);
4463 freeAsmop(result,NULL,ic,TRUE);
4466 /*-----------------------------------------------------------------*/
4467 /* genGetHbit - generates code get highest order bit */
4468 /*-----------------------------------------------------------------*/
4469 static void genGetHbit (iCode *ic)
4471 operand *left, *result;
4473 result=IC_RESULT(ic);
4474 aopOp (left,ic,FALSE);
4475 aopOp (result,ic,FALSE);
4477 /* get the highest order byte into a */
4478 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
4479 if(AOP_TYPE(result) == AOP_CRY){
4480 emitcode("rlc","a");
4485 emitcode("anl","a,#0x01");
4490 freeAsmop(left,NULL,ic,TRUE);
4491 freeAsmop(result,NULL,ic,TRUE);
4494 /*-----------------------------------------------------------------*/
4495 /* AccRol - rotate left accumulator by known count */
4496 /*-----------------------------------------------------------------*/
4497 static void AccRol (int shCount)
4499 shCount &= 0x0007; // shCount : 0..7
4511 emitcode("swap","a");
4515 emitcode("swap","a");
4518 emitcode("swap","a");
4531 /*-----------------------------------------------------------------*/
4532 /* AccLsh - left shift accumulator by known count */
4533 /*-----------------------------------------------------------------*/
4534 static void AccLsh (int shCount)
4538 emitcode("add","a,acc");
4541 emitcode("add","a,acc");
4542 emitcode("add","a,acc");
4544 /* rotate left accumulator */
4546 /* and kill the lower order bits */
4547 emitcode("anl","a,#0x%02x", SLMask[shCount]);
4552 /*-----------------------------------------------------------------*/
4553 /* AccRsh - right shift accumulator by known count */
4554 /*-----------------------------------------------------------------*/
4555 static void AccRsh (int shCount)
4560 emitcode("rrc","a");
4562 /* rotate right accumulator */
4563 AccRol(8 - shCount);
4564 /* and kill the higher order bits */
4565 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4570 /*-----------------------------------------------------------------*/
4571 /* AccSRsh - signed right shift accumulator by known count */
4572 /*-----------------------------------------------------------------*/
4573 static void AccSRsh (int shCount)
4578 emitcode("mov","c,acc.7");
4579 emitcode("rrc","a");
4580 } else if(shCount == 2){
4581 emitcode("mov","c,acc.7");
4582 emitcode("rrc","a");
4583 emitcode("mov","c,acc.7");
4584 emitcode("rrc","a");
4586 tlbl = newiTempLabel(NULL);
4587 /* rotate right accumulator */
4588 AccRol(8 - shCount);
4589 /* and kill the higher order bits */
4590 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4591 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4592 emitcode("orl","a,#0x%02x",
4593 (unsigned char)~SRMask[shCount]);
4594 emitcode("","%05d$:",tlbl->key+100);
4599 /*-----------------------------------------------------------------*/
4600 /* shiftR1Left2Result - shift right one byte from left to result */
4601 /*-----------------------------------------------------------------*/
4602 static void shiftR1Left2Result (operand *left, int offl,
4603 operand *result, int offr,
4604 int shCount, int sign)
4606 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4607 /* shift right accumulator */
4612 aopPut(AOP(result),"a",offr);
4615 /*-----------------------------------------------------------------*/
4616 /* shiftL1Left2Result - shift left one byte from left to result */
4617 /*-----------------------------------------------------------------*/
4618 static void shiftL1Left2Result (operand *left, int offl,
4619 operand *result, int offr, int shCount)
4622 l = aopGet(AOP(left),offl,FALSE,FALSE);
4624 /* shift left accumulator */
4626 aopPut(AOP(result),"a",offr);
4629 /*-----------------------------------------------------------------*/
4630 /* movLeft2Result - move byte from left to result */
4631 /*-----------------------------------------------------------------*/
4632 static void movLeft2Result (operand *left, int offl,
4633 operand *result, int offr, int sign)
4636 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
4637 l = aopGet(AOP(left),offl,FALSE,FALSE);
4639 if (*l == '@' && (IS_AOP_PREG(result))) {
4640 emitcode("mov","a,%s",l);
4641 aopPut(AOP(result),"a",offr);
4644 aopPut(AOP(result),l,offr);
4646 /* MSB sign in acc.7 ! */
4647 if(getDataSize(left) == offl+1){
4648 emitcode("mov","a,%s",l);
4649 aopPut(AOP(result),"a",offr);
4656 /*-----------------------------------------------------------------*/
4657 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
4658 /*-----------------------------------------------------------------*/
4659 static void AccAXRrl1 (char *x)
4661 emitcode("rrc","a");
4662 emitcode("xch","a,%s", x);
4663 emitcode("rrc","a");
4664 emitcode("xch","a,%s", x);
4667 /*-----------------------------------------------------------------*/
4668 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
4669 /*-----------------------------------------------------------------*/
4670 static void AccAXLrl1 (char *x)
4672 emitcode("xch","a,%s",x);
4673 emitcode("rlc","a");
4674 emitcode("xch","a,%s",x);
4675 emitcode("rlc","a");
4678 /*-----------------------------------------------------------------*/
4679 /* AccAXLsh1 - left shift a:x<-0 by 1 */
4680 /*-----------------------------------------------------------------*/
4681 static void AccAXLsh1 (char *x)
4683 emitcode("xch","a,%s",x);
4684 emitcode("add","a,acc");
4685 emitcode("xch","a,%s",x);
4686 emitcode("rlc","a");
4689 /*-----------------------------------------------------------------*/
4690 /* AccAXLsh - left shift a:x by known count (0..7) */
4691 /*-----------------------------------------------------------------*/
4692 static void AccAXLsh (char *x, int shCount)
4706 case 5 : // AAAAABBB:CCCCCDDD
4707 AccRol(shCount); // BBBAAAAA:CCCCCDDD
4708 emitcode("anl","a,#0x%02x",
4709 SLMask[shCount]); // BBB00000:CCCCCDDD
4710 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
4711 AccRol(shCount); // DDDCCCCC:BBB00000
4712 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
4713 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
4714 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
4715 emitcode("anl","a,#0x%02x",
4716 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
4717 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
4718 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
4720 case 6 : // AAAAAABB:CCCCCCDD
4721 emitcode("anl","a,#0x%02x",
4722 SRMask[shCount]); // 000000BB:CCCCCCDD
4723 emitcode("mov","c,acc.0"); // c = B
4724 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
4725 AccAXRrl1(x); // BCCCCCCD:D000000B
4726 AccAXRrl1(x); // BBCCCCCC:DD000000
4728 case 7 : // a:x <<= 7
4729 emitcode("anl","a,#0x%02x",
4730 SRMask[shCount]); // 0000000B:CCCCCCCD
4731 emitcode("mov","c,acc.0"); // c = B
4732 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
4733 AccAXRrl1(x); // BCCCCCCC:D0000000
4740 /*-----------------------------------------------------------------*/
4741 /* AccAXRsh - right shift a:x known count (0..7) */
4742 /*-----------------------------------------------------------------*/
4743 static void AccAXRsh (char *x, int shCount)
4750 AccAXRrl1(x); // 0->a:x
4754 AccAXRrl1(x); // 0->a:x
4756 AccAXRrl1(x); // 0->a:x
4760 case 5 : // AAAAABBB:CCCCCDDD = a:x
4761 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
4762 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
4763 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
4764 emitcode("anl","a,#0x%02x",
4765 SRMask[shCount]); // 000CCCCC:BBBAAAAA
4766 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
4767 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
4768 emitcode("anl","a,#0x%02x",
4769 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
4770 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
4771 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
4772 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
4774 case 6 : // AABBBBBB:CCDDDDDD
4775 emitcode("mov","c,acc.7");
4776 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
4777 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
4778 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
4779 emitcode("anl","a,#0x%02x",
4780 SRMask[shCount]); // 000000AA:BBBBBBCC
4782 case 7 : // ABBBBBBB:CDDDDDDD
4783 emitcode("mov","c,acc.7"); // c = A
4784 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
4785 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
4786 emitcode("anl","a,#0x%02x",
4787 SRMask[shCount]); // 0000000A:BBBBBBBC
4794 /*-----------------------------------------------------------------*/
4795 /* AccAXRshS - right shift signed a:x known count (0..7) */
4796 /*-----------------------------------------------------------------*/
4797 static void AccAXRshS (char *x, int shCount)
4804 emitcode("mov","c,acc.7");
4805 AccAXRrl1(x); // s->a:x
4808 emitcode("mov","c,acc.7");
4809 AccAXRrl1(x); // s->a:x
4810 emitcode("mov","c,acc.7");
4811 AccAXRrl1(x); // s->a:x
4815 case 5 : // AAAAABBB:CCCCCDDD = a:x
4816 tlbl = newiTempLabel(NULL);
4817 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
4818 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
4819 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
4820 emitcode("anl","a,#0x%02x",
4821 SRMask[shCount]); // 000CCCCC:BBBAAAAA
4822 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
4823 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
4824 emitcode("anl","a,#0x%02x",
4825 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
4826 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
4827 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
4828 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
4829 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4830 emitcode("orl","a,#0x%02x",
4831 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
4832 emitcode("","%05d$:",tlbl->key+100);
4833 break; // SSSSAAAA:BBBCCCCC
4834 case 6 : // AABBBBBB:CCDDDDDD
4835 tlbl = newiTempLabel(NULL);
4836 emitcode("mov","c,acc.7");
4837 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
4838 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
4839 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
4840 emitcode("anl","a,#0x%02x",
4841 SRMask[shCount]); // 000000AA:BBBBBBCC
4842 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4843 emitcode("orl","a,#0x%02x",
4844 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
4845 emitcode("","%05d$:",tlbl->key+100);
4847 case 7 : // ABBBBBBB:CDDDDDDD
4848 tlbl = newiTempLabel(NULL);
4849 emitcode("mov","c,acc.7"); // c = A
4850 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
4851 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
4852 emitcode("anl","a,#0x%02x",
4853 SRMask[shCount]); // 0000000A:BBBBBBBC
4854 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4855 emitcode("orl","a,#0x%02x",
4856 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
4857 emitcode("","%05d$:",tlbl->key+100);
4864 /*-----------------------------------------------------------------*/
4865 /* shiftL2Left2Result - shift left two bytes from left to result */
4866 /*-----------------------------------------------------------------*/
4867 static void shiftL2Left2Result (operand *left, int offl,
4868 operand *result, int offr, int shCount)
4870 if(sameRegs(AOP(result), AOP(left)) &&
4871 ((offl + MSB16) == offr)){
4872 /* don't crash result[offr] */
4873 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4874 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4876 movLeft2Result(left,offl, result, offr, 0);
4877 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4879 /* ax << shCount (x = lsb(result))*/
4880 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
4881 aopPut(AOP(result),"a",offr+MSB16);
4885 /*-----------------------------------------------------------------*/
4886 /* shiftR2Left2Result - shift right two bytes from left to result */
4887 /*-----------------------------------------------------------------*/
4888 static void shiftR2Left2Result (operand *left, int offl,
4889 operand *result, int offr,
4890 int shCount, int sign)
4892 if(sameRegs(AOP(result), AOP(left)) &&
4893 ((offl + MSB16) == offr)){
4894 /* don't crash result[offr] */
4895 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4896 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4898 movLeft2Result(left,offl, result, offr, 0);
4899 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4901 /* a:x >> shCount (x = lsb(result))*/
4903 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
4905 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
4906 if(getDataSize(result) > 1)
4907 aopPut(AOP(result),"a",offr+MSB16);
4910 /*-----------------------------------------------------------------*/
4911 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
4912 /*-----------------------------------------------------------------*/
4913 static void shiftLLeftOrResult (operand *left, int offl,
4914 operand *result, int offr, int shCount)
4916 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4917 /* shift left accumulator */
4919 /* or with result */
4920 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
4921 /* back to result */
4922 aopPut(AOP(result),"a",offr);
4925 /*-----------------------------------------------------------------*/
4926 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
4927 /*-----------------------------------------------------------------*/
4928 static void shiftRLeftOrResult (operand *left, int offl,
4929 operand *result, int offr, int shCount)
4931 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4932 /* shift right accumulator */
4934 /* or with result */
4935 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
4936 /* back to result */
4937 aopPut(AOP(result),"a",offr);
4940 /*-----------------------------------------------------------------*/
4941 /* genlshOne - left shift a one byte quantity by known count */
4942 /*-----------------------------------------------------------------*/
4943 static void genlshOne (operand *result, operand *left, int shCount)
4945 shiftL1Left2Result(left, LSB, result, LSB, shCount);
4948 /*-----------------------------------------------------------------*/
4949 /* genlshTwo - left shift two bytes by known amount != 0 */
4950 /*-----------------------------------------------------------------*/
4951 static void genlshTwo (operand *result,operand *left, int shCount)
4955 size = getDataSize(result);
4957 /* if shCount >= 8 */
4963 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
4965 movLeft2Result(left, LSB, result, MSB16, 0);
4967 aopPut(AOP(result),zero,LSB);
4970 /* 1 <= shCount <= 7 */
4973 shiftL1Left2Result(left, LSB, result, LSB, shCount);
4975 shiftL2Left2Result(left, LSB, result, LSB, shCount);
4979 /*-----------------------------------------------------------------*/
4980 /* shiftLLong - shift left one long from left to result */
4981 /* offl = LSB or MSB16 */
4982 /*-----------------------------------------------------------------*/
4983 static void shiftLLong (operand *left, operand *result, int offr )
4986 int size = AOP_SIZE(result);
4988 if(size >= LSB+offr){
4989 l = aopGet(AOP(left),LSB,FALSE,FALSE);
4991 emitcode("add","a,acc");
4992 if (sameRegs(AOP(left),AOP(result)) &&
4993 size >= MSB16+offr && offr != LSB )
4994 emitcode("xch","a,%s",
4995 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
4997 aopPut(AOP(result),"a",LSB+offr);
5000 if(size >= MSB16+offr){
5001 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5002 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
5005 emitcode("rlc","a");
5006 if (sameRegs(AOP(left),AOP(result)) &&
5007 size >= MSB24+offr && offr != LSB)
5008 emitcode("xch","a,%s",
5009 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
5011 aopPut(AOP(result),"a",MSB16+offr);
5014 if(size >= MSB24+offr){
5015 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5016 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
5019 emitcode("rlc","a");
5020 if (sameRegs(AOP(left),AOP(result)) &&
5021 size >= MSB32+offr && offr != LSB )
5022 emitcode("xch","a,%s",
5023 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
5025 aopPut(AOP(result),"a",MSB24+offr);
5028 if(size > MSB32+offr){
5029 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5030 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
5033 emitcode("rlc","a");
5034 aopPut(AOP(result),"a",MSB32+offr);
5037 aopPut(AOP(result),zero,LSB);
5040 /*-----------------------------------------------------------------*/
5041 /* genlshFour - shift four byte by a known amount != 0 */
5042 /*-----------------------------------------------------------------*/
5043 static void genlshFour (operand *result, operand *left, int shCount)
5047 size = AOP_SIZE(result);
5049 /* if shifting more that 3 bytes */
5050 if (shCount >= 24 ) {
5053 /* lowest order of left goes to the highest
5054 order of the destination */
5055 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5057 movLeft2Result(left, LSB, result, MSB32, 0);
5058 aopPut(AOP(result),zero,LSB);
5059 aopPut(AOP(result),zero,MSB16);
5060 aopPut(AOP(result),zero,MSB32);
5064 /* more than two bytes */
5065 else if ( shCount >= 16 ) {
5066 /* lower order two bytes goes to higher order two bytes */
5068 /* if some more remaining */
5070 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5072 movLeft2Result(left, MSB16, result, MSB32, 0);
5073 movLeft2Result(left, LSB, result, MSB24, 0);
5075 aopPut(AOP(result),zero,MSB16);
5076 aopPut(AOP(result),zero,LSB);
5080 /* if more than 1 byte */
5081 else if ( shCount >= 8 ) {
5082 /* lower order three bytes goes to higher order three bytes */
5086 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5088 movLeft2Result(left, LSB, result, MSB16, 0);
5090 else{ /* size = 4 */
5092 movLeft2Result(left, MSB24, result, MSB32, 0);
5093 movLeft2Result(left, MSB16, result, MSB24, 0);
5094 movLeft2Result(left, LSB, result, MSB16, 0);
5095 aopPut(AOP(result),zero,LSB);
5097 else if(shCount == 1)
5098 shiftLLong(left, result, MSB16);
5100 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5101 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5102 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5103 aopPut(AOP(result),zero,LSB);
5108 /* 1 <= shCount <= 7 */
5109 else if(shCount <= 2){
5110 shiftLLong(left, result, LSB);
5112 shiftLLong(result, result, LSB);
5114 /* 3 <= shCount <= 7, optimize */
5116 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5117 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5118 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5122 /*-----------------------------------------------------------------*/
5123 /* genLeftShiftLiteral - left shifting by known count */
5124 /*-----------------------------------------------------------------*/
5125 static void genLeftShiftLiteral (operand *left,
5130 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5133 freeAsmop(right,NULL,ic,TRUE);
5135 aopOp(left,ic,FALSE);
5136 aopOp(result,ic,FALSE);
5138 size = getSize(operandType(result));
5141 emitcode("; shift left ","result %d, left %d",size,
5145 /* I suppose that the left size >= result size */
5148 movLeft2Result(left, size, result, size, 0);
5152 else if(shCount >= (size * 8))
5154 aopPut(AOP(result),zero,size);
5158 genlshOne (result,left,shCount);
5163 genlshTwo (result,left,shCount);
5167 genlshFour (result,left,shCount);
5171 freeAsmop(left,NULL,ic,TRUE);
5172 freeAsmop(result,NULL,ic,TRUE);
5175 /*-----------------------------------------------------------------*/
5176 /* genLeftShift - generates code for left shifting */
5177 /*-----------------------------------------------------------------*/
5178 static void genLeftShift (iCode *ic)
5180 operand *left,*right, *result;
5183 symbol *tlbl , *tlbl1;
5185 right = IC_RIGHT(ic);
5187 result = IC_RESULT(ic);
5189 aopOp(right,ic,FALSE);
5191 /* if the shift count is known then do it
5192 as efficiently as possible */
5193 if (AOP_TYPE(right) == AOP_LIT) {
5194 genLeftShiftLiteral (left,right,result,ic);
5198 /* shift count is unknown then we have to form
5199 a loop get the loop count in B : Note: we take
5200 only the lower order byte since shifting
5201 more that 32 bits make no sense anyway, ( the
5202 largest size of an object can be only 32 bits ) */
5204 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5205 emitcode("inc","b");
5206 freeAsmop (right,NULL,ic,TRUE);
5207 aopOp(left,ic,FALSE);
5208 aopOp(result,ic,FALSE);
5210 /* now move the left to the result if they are not the
5212 if (!sameRegs(AOP(left),AOP(result)) &&
5213 AOP_SIZE(result) > 1) {
5215 size = AOP_SIZE(result);
5218 l = aopGet(AOP(left),offset,FALSE,TRUE);
5219 if (*l == '@' && (IS_AOP_PREG(result))) {
5221 emitcode("mov","a,%s",l);
5222 aopPut(AOP(result),"a",offset);
5224 aopPut(AOP(result),l,offset);
5229 tlbl = newiTempLabel(NULL);
5230 size = AOP_SIZE(result);
5232 tlbl1 = newiTempLabel(NULL);
5234 /* if it is only one byte then */
5236 symbol *tlbl1 = newiTempLabel(NULL);
5238 l = aopGet(AOP(left),0,FALSE,FALSE);
5240 emitcode("sjmp","%05d$",tlbl1->key+100);
5241 emitcode("","%05d$:",tlbl->key+100);
5242 emitcode("add","a,acc");
5243 emitcode("","%05d$:",tlbl1->key+100);
5244 emitcode("djnz","b,%05d$",tlbl->key+100);
5245 aopPut(AOP(result),"a",0);
5249 reAdjustPreg(AOP(result));
5251 emitcode("sjmp","%05d$",tlbl1->key+100);
5252 emitcode("","%05d$:",tlbl->key+100);
5253 l = aopGet(AOP(result),offset,FALSE,FALSE);
5255 emitcode("add","a,acc");
5256 aopPut(AOP(result),"a",offset++);
5258 l = aopGet(AOP(result),offset,FALSE,FALSE);
5260 emitcode("rlc","a");
5261 aopPut(AOP(result),"a",offset++);
5263 reAdjustPreg(AOP(result));
5265 emitcode("","%05d$:",tlbl1->key+100);
5266 emitcode("djnz","b,%05d$",tlbl->key+100);
5268 freeAsmop(left,NULL,ic,TRUE);
5269 freeAsmop(result,NULL,ic,TRUE);
5272 /*-----------------------------------------------------------------*/
5273 /* genrshOne - right shift a one byte quantity by known count */
5274 /*-----------------------------------------------------------------*/
5275 static void genrshOne (operand *result, operand *left,
5276 int shCount, int sign)
5278 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
5281 /*-----------------------------------------------------------------*/
5282 /* genrshTwo - right shift two bytes by known amount != 0 */
5283 /*-----------------------------------------------------------------*/
5284 static void genrshTwo (operand *result,operand *left,
5285 int shCount, int sign)
5287 /* if shCount >= 8 */
5291 shiftR1Left2Result(left, MSB16, result, LSB,
5294 movLeft2Result(left, MSB16, result, LSB, sign);
5295 addSign(result, MSB16, sign);
5298 /* 1 <= shCount <= 7 */
5300 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
5303 /*-----------------------------------------------------------------*/
5304 /* shiftRLong - shift right one long from left to result */
5305 /* offl = LSB or MSB16 */
5306 /*-----------------------------------------------------------------*/
5307 static void shiftRLong (operand *left, int offl,
5308 operand *result, int sign)
5311 emitcode("clr","c");
5312 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
5314 emitcode("mov","c,acc.7");
5315 emitcode("rrc","a");
5316 aopPut(AOP(result),"a",MSB32-offl);
5318 /* add sign of "a" */
5319 addSign(result, MSB32, sign);
5321 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
5322 emitcode("rrc","a");
5323 aopPut(AOP(result),"a",MSB24-offl);
5325 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
5326 emitcode("rrc","a");
5327 aopPut(AOP(result),"a",MSB16-offl);
5330 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
5331 emitcode("rrc","a");
5332 aopPut(AOP(result),"a",LSB);
5336 /*-----------------------------------------------------------------*/
5337 /* genrshFour - shift four byte by a known amount != 0 */
5338 /*-----------------------------------------------------------------*/
5339 static void genrshFour (operand *result, operand *left,
5340 int shCount, int sign)
5342 /* if shifting more that 3 bytes */
5343 if(shCount >= 24 ) {
5346 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
5348 movLeft2Result(left, MSB32, result, LSB, sign);
5349 addSign(result, MSB16, sign);
5351 else if(shCount >= 16){
5354 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
5356 movLeft2Result(left, MSB24, result, LSB, 0);
5357 movLeft2Result(left, MSB32, result, MSB16, sign);
5359 addSign(result, MSB24, sign);
5361 else if(shCount >= 8){
5364 shiftRLong(left, MSB16, result, sign);
5365 else if(shCount == 0){
5366 movLeft2Result(left, MSB16, result, LSB, 0);
5367 movLeft2Result(left, MSB24, result, MSB16, 0);
5368 movLeft2Result(left, MSB32, result, MSB24, sign);
5369 addSign(result, MSB32, sign);
5372 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
5373 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
5374 /* the last shift is signed */
5375 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
5376 addSign(result, MSB32, sign);
5379 else{ /* 1 <= shCount <= 7 */
5381 shiftRLong(left, LSB, result, sign);
5383 shiftRLong(result, LSB, result, sign);
5386 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
5387 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
5388 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
5393 /*-----------------------------------------------------------------*/
5394 /* genRightShiftLiteral - right shifting by known count */
5395 /*-----------------------------------------------------------------*/
5396 static void genRightShiftLiteral (operand *left,
5402 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5405 freeAsmop(right,NULL,ic,TRUE);
5407 aopOp(left,ic,FALSE);
5408 aopOp(result,ic,FALSE);
5411 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
5415 size = getDataSize(left);
5416 /* test the LEFT size !!! */
5418 /* I suppose that the left size >= result size */
5420 size = getDataSize(result);
5422 movLeft2Result(left, size, result, size, 0);
5425 else if(shCount >= (size * 8)){
5427 /* get sign in acc.7 */
5428 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
5429 addSign(result, LSB, sign);
5433 genrshOne (result,left,shCount,sign);
5437 genrshTwo (result,left,shCount,sign);
5441 genrshFour (result,left,shCount,sign);
5447 freeAsmop(left,NULL,ic,TRUE);
5448 freeAsmop(result,NULL,ic,TRUE);
5452 /*-----------------------------------------------------------------*/
5453 /* genSignedRightShift - right shift of signed number */
5454 /*-----------------------------------------------------------------*/
5455 static void genSignedRightShift (iCode *ic)
5457 operand *right, *left, *result;
5460 symbol *tlbl, *tlbl1 ;
5462 /* we do it the hard way put the shift count in b
5463 and loop thru preserving the sign */
5465 right = IC_RIGHT(ic);
5467 result = IC_RESULT(ic);
5469 aopOp(right,ic,FALSE);
5472 if ( AOP_TYPE(right) == AOP_LIT) {
5473 genRightShiftLiteral (left,right,result,ic,1);
5476 /* shift count is unknown then we have to form
5477 a loop get the loop count in B : Note: we take
5478 only the lower order byte since shifting
5479 more that 32 bits make no sense anyway, ( the
5480 largest size of an object can be only 32 bits ) */
5482 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5483 emitcode("inc","b");
5484 freeAsmop (right,NULL,ic,TRUE);
5485 aopOp(left,ic,FALSE);
5486 aopOp(result,ic,FALSE);
5488 /* now move the left to the result if they are not the
5490 if (!sameRegs(AOP(left),AOP(result)) &&
5491 AOP_SIZE(result) > 1) {
5493 size = AOP_SIZE(result);
5496 l = aopGet(AOP(left),offset,FALSE,TRUE);
5497 if (*l == '@' && IS_AOP_PREG(result)) {
5499 emitcode("mov","a,%s",l);
5500 aopPut(AOP(result),"a",offset);
5502 aopPut(AOP(result),l,offset);
5507 /* mov the highest order bit to OVR */
5508 tlbl = newiTempLabel(NULL);
5509 tlbl1= newiTempLabel(NULL);
5511 size = AOP_SIZE(result);
5513 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
5514 emitcode("rlc","a");
5515 emitcode("mov","ov,c");
5516 /* if it is only one byte then */
5518 l = aopGet(AOP(left),0,FALSE,FALSE);
5520 emitcode("sjmp","%05d$",tlbl1->key+100);
5521 emitcode("","%05d$:",tlbl->key+100);
5522 emitcode("mov","c,ov");
5523 emitcode("rrc","a");
5524 emitcode("","%05d$:",tlbl1->key+100);
5525 emitcode("djnz","b,%05d$",tlbl->key+100);
5526 aopPut(AOP(result),"a",0);
5530 reAdjustPreg(AOP(result));
5531 emitcode("sjmp","%05d$",tlbl1->key+100);
5532 emitcode("","%05d$:",tlbl->key+100);
5533 emitcode("mov","c,ov");
5535 l = aopGet(AOP(result),offset,FALSE,FALSE);
5537 emitcode("rrc","a");
5538 aopPut(AOP(result),"a",offset--);
5540 reAdjustPreg(AOP(result));
5541 emitcode("","%05d$:",tlbl1->key+100);
5542 emitcode("djnz","b,%05d$",tlbl->key+100);
5545 freeAsmop(left,NULL,ic,TRUE);
5546 freeAsmop(result,NULL,ic,TRUE);
5549 /*-----------------------------------------------------------------*/
5550 /* genRightShift - generate code for right shifting */
5551 /*-----------------------------------------------------------------*/
5552 static void genRightShift (iCode *ic)
5554 operand *right, *left, *result;
5558 symbol *tlbl, *tlbl1 ;
5560 /* if signed then we do it the hard way preserve the
5561 sign bit moving it inwards */
5562 retype = getSpec(operandType(IC_RESULT(ic)));
5564 if (!SPEC_USIGN(retype)) {
5565 genSignedRightShift (ic);
5569 /* signed & unsigned types are treated the same : i.e. the
5570 signed is NOT propagated inwards : quoting from the
5571 ANSI - standard : "for E1 >> E2, is equivalent to division
5572 by 2**E2 if unsigned or if it has a non-negative value,
5573 otherwise the result is implementation defined ", MY definition
5574 is that the sign does not get propagated */
5576 right = IC_RIGHT(ic);
5578 result = IC_RESULT(ic);
5580 aopOp(right,ic,FALSE);
5582 /* if the shift count is known then do it
5583 as efficiently as possible */
5584 if (AOP_TYPE(right) == AOP_LIT) {
5585 genRightShiftLiteral (left,right,result,ic, 0);
5589 /* shift count is unknown then we have to form
5590 a loop get the loop count in B : Note: we take
5591 only the lower order byte since shifting
5592 more that 32 bits make no sense anyway, ( the
5593 largest size of an object can be only 32 bits ) */
5595 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5596 emitcode("inc","b");
5597 freeAsmop (right,NULL,ic,TRUE);
5598 aopOp(left,ic,FALSE);
5599 aopOp(result,ic,FALSE);
5601 /* now move the left to the result if they are not the
5603 if (!sameRegs(AOP(left),AOP(result)) &&
5604 AOP_SIZE(result) > 1) {
5606 size = AOP_SIZE(result);
5609 l = aopGet(AOP(left),offset,FALSE,TRUE);
5610 if (*l == '@' && IS_AOP_PREG(result)) {
5612 emitcode("mov","a,%s",l);
5613 aopPut(AOP(result),"a",offset);
5615 aopPut(AOP(result),l,offset);
5620 tlbl = newiTempLabel(NULL);
5621 tlbl1= newiTempLabel(NULL);
5622 size = AOP_SIZE(result);
5625 /* if it is only one byte then */
5627 l = aopGet(AOP(left),0,FALSE,FALSE);
5629 emitcode("sjmp","%05d$",tlbl1->key+100);
5630 emitcode("","%05d$:",tlbl->key+100);
5632 emitcode("rrc","a");
5633 emitcode("","%05d$:",tlbl1->key+100);
5634 emitcode("djnz","b,%05d$",tlbl->key+100);
5635 aopPut(AOP(result),"a",0);
5639 reAdjustPreg(AOP(result));
5640 emitcode("sjmp","%05d$",tlbl1->key+100);
5641 emitcode("","%05d$:",tlbl->key+100);
5644 l = aopGet(AOP(result),offset,FALSE,FALSE);
5646 emitcode("rrc","a");
5647 aopPut(AOP(result),"a",offset--);
5649 reAdjustPreg(AOP(result));
5651 emitcode("","%05d$:",tlbl1->key+100);
5652 emitcode("djnz","b,%05d$",tlbl->key+100);
5655 freeAsmop(left,NULL,ic,TRUE);
5656 freeAsmop(result,NULL,ic,TRUE);
5659 /*-----------------------------------------------------------------*/
5660 /* genUnpackBits - generates code for unpacking bits */
5661 /*-----------------------------------------------------------------*/
5662 static void genUnpackBits (operand *result, char *rname, int ptype)
5669 etype = getSpec(operandType(result));
5671 /* read the first byte */
5676 emitcode("mov","a,@%s",rname);
5680 emitcode("movx","a,@%s",rname);
5684 emitcode("movx","a,@dptr");
5688 emitcode("clr","a");
5689 emitcode("movc","a","@a+dptr");
5693 emitcode("lcall","__gptrget");
5697 /* if we have bitdisplacement then it fits */
5698 /* into this byte completely or if length is */
5699 /* less than a byte */
5700 if ((shCnt = SPEC_BSTR(etype)) ||
5701 (SPEC_BLEN(etype) <= 8)) {
5703 /* shift right acc */
5706 emitcode("anl","a,#0x%02x",
5707 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
5708 aopPut(AOP(result),"a",offset);
5712 /* bit field did not fit in a byte */
5713 rlen = SPEC_BLEN(etype) - 8;
5714 aopPut(AOP(result),"a",offset++);
5721 emitcode("inc","%s",rname);
5722 emitcode("mov","a,@%s",rname);
5726 emitcode("inc","%s",rname);
5727 emitcode("movx","a,@%s",rname);
5731 emitcode("inc","dptr");
5732 emitcode("movx","a,@dptr");
5736 emitcode("clr","a");
5737 emitcode("inc","dptr");
5738 emitcode("movc","a","@a+dptr");
5742 emitcode("inc","dptr");
5743 emitcode("lcall","__gptrget");
5748 /* if we are done */
5752 aopPut(AOP(result),"a",offset++);
5757 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
5758 aopPut(AOP(result),"a",offset);
5765 /*-----------------------------------------------------------------*/
5766 /* genDataPointerGet - generates code when ptr offset is known */
5767 /*-----------------------------------------------------------------*/
5768 static void genDataPointerGet (operand *left,
5774 int size , offset = 0;
5775 aopOp(result,ic,TRUE);
5777 /* get the string representation of the name */
5778 l = aopGet(AOP(left),0,FALSE,TRUE);
5779 size = AOP_SIZE(result);
5782 sprintf(buffer,"(%s + %d)",l+1,offset);
5784 sprintf(buffer,"%s",l+1);
5785 aopPut(AOP(result),buffer,offset++);
5788 freeAsmop(left,NULL,ic,TRUE);
5789 freeAsmop(result,NULL,ic,TRUE);
5792 /*-----------------------------------------------------------------*/
5793 /* genNearPointerGet - emitcode for near pointer fetch */
5794 /*-----------------------------------------------------------------*/
5795 static void genNearPointerGet (operand *left,
5802 link *rtype, *retype;
5803 link *ltype = operandType(left);
5806 rtype = operandType(result);
5807 retype= getSpec(rtype);
5809 aopOp(left,ic,FALSE);
5811 /* if left is rematerialisable and
5812 result is not bit variable type and
5813 the left is pointer to data space i.e
5814 lower 128 bytes of space */
5815 if (AOP_TYPE(left) == AOP_IMMD &&
5816 !IS_BITVAR(retype) &&
5817 DCL_TYPE(ltype) == POINTER) {
5818 genDataPointerGet (left,result,ic);
5822 /* if the value is already in a pointer register
5823 then don't need anything more */
5824 if (!AOP_INPREG(AOP(left))) {
5825 /* otherwise get a free pointer register */
5827 preg = getFreePtr(ic,&aop,FALSE);
5828 emitcode("mov","%s,%s",
5830 aopGet(AOP(left),0,FALSE,TRUE));
5831 rname = preg->name ;
5833 rname = aopGet(AOP(left),0,FALSE,FALSE);
5835 freeAsmop(left,NULL,ic,TRUE);
5836 aopOp (result,ic,FALSE);
5838 /* if bitfield then unpack the bits */
5839 if (IS_BITVAR(retype))
5840 genUnpackBits (result,rname,POINTER);
5842 /* we have can just get the values */
5843 int size = AOP_SIZE(result);
5847 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
5849 emitcode("mov","a,@%s",rname);
5850 aopPut(AOP(result),"a",offset);
5852 sprintf(buffer,"@%s",rname);
5853 aopPut(AOP(result),buffer,offset);
5857 emitcode("inc","%s",rname);
5861 /* now some housekeeping stuff */
5863 /* we had to allocate for this iCode */
5864 freeAsmop(NULL,aop,ic,TRUE);
5866 /* we did not allocate which means left
5867 already in a pointer register, then
5868 if size > 0 && this could be used again
5869 we have to point it back to where it
5871 if (AOP_SIZE(result) > 1 &&
5872 !OP_SYMBOL(left)->remat &&
5873 ( OP_SYMBOL(left)->liveTo > ic->seq ||
5875 int size = AOP_SIZE(result) - 1;
5877 emitcode("dec","%s",rname);
5882 freeAsmop(result,NULL,ic,TRUE);
5886 /*-----------------------------------------------------------------*/
5887 /* genPagedPointerGet - emitcode for paged pointer fetch */
5888 /*-----------------------------------------------------------------*/
5889 static void genPagedPointerGet (operand *left,
5896 link *rtype, *retype;
5898 rtype = operandType(result);
5899 retype= getSpec(rtype);
5901 aopOp(left,ic,FALSE);
5903 /* if the value is already in a pointer register
5904 then don't need anything more */
5905 if (!AOP_INPREG(AOP(left))) {
5906 /* otherwise get a free pointer register */
5908 preg = getFreePtr(ic,&aop,FALSE);
5909 emitcode("mov","%s,%s",
5911 aopGet(AOP(left),0,FALSE,TRUE));
5912 rname = preg->name ;
5914 rname = aopGet(AOP(left),0,FALSE,FALSE);
5916 freeAsmop(left,NULL,ic,TRUE);
5917 aopOp (result,ic,FALSE);
5919 /* if bitfield then unpack the bits */
5920 if (IS_BITVAR(retype))
5921 genUnpackBits (result,rname,PPOINTER);
5923 /* we have can just get the values */
5924 int size = AOP_SIZE(result);
5929 emitcode("movx","a,@%s",rname);
5930 aopPut(AOP(result),"a",offset);
5935 emitcode("inc","%s",rname);
5939 /* now some housekeeping stuff */
5941 /* we had to allocate for this iCode */
5942 freeAsmop(NULL,aop,ic,TRUE);
5944 /* we did not allocate which means left
5945 already in a pointer register, then
5946 if size > 0 && this could be used again
5947 we have to point it back to where it
5949 if (AOP_SIZE(result) > 1 &&
5950 !OP_SYMBOL(left)->remat &&
5951 ( OP_SYMBOL(left)->liveTo > ic->seq ||
5953 int size = AOP_SIZE(result) - 1;
5955 emitcode("dec","%s",rname);
5960 freeAsmop(result,NULL,ic,TRUE);
5965 /*-----------------------------------------------------------------*/
5966 /* genFarPointerGet - gget value from far space */
5967 /*-----------------------------------------------------------------*/
5968 static void genFarPointerGet (operand *left,
5969 operand *result, iCode *ic)
5972 link *retype = getSpec(operandType(result));
5974 aopOp(left,ic,FALSE);
5976 /* if the operand is already in dptr
5977 then we do nothing else we move the value to dptr */
5978 if (AOP_TYPE(left) != AOP_STR) {
5979 /* if this is remateriazable */
5980 if (AOP_TYPE(left) == AOP_IMMD)
5981 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
5982 else { /* we need to get it byte by byte */
5983 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
5984 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
5985 if (options.model == MODEL_FLAT24)
5987 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
5991 /* so dptr know contains the address */
5992 freeAsmop(left,NULL,ic,TRUE);
5993 aopOp(result,ic,FALSE);
5995 /* if bit then unpack */
5996 if (IS_BITVAR(retype))
5997 genUnpackBits(result,"dptr",FPOINTER);
5999 size = AOP_SIZE(result);
6003 emitcode("movx","a,@dptr");
6004 aopPut(AOP(result),"a",offset++);
6006 emitcode("inc","dptr");
6010 freeAsmop(result,NULL,ic,TRUE);
6013 /*-----------------------------------------------------------------*/
6014 /* emitcodePointerGet - gget value from code space */
6015 /*-----------------------------------------------------------------*/
6016 static void emitcodePointerGet (operand *left,
6017 operand *result, iCode *ic)
6020 link *retype = getSpec(operandType(result));
6022 aopOp(left,ic,FALSE);
6024 /* if the operand is already in dptr
6025 then we do nothing else we move the value to dptr */
6026 if (AOP_TYPE(left) != AOP_STR) {
6027 /* if this is remateriazable */
6028 if (AOP_TYPE(left) == AOP_IMMD)
6029 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6030 else { /* we need to get it byte by byte */
6031 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6032 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6033 if (options.model == MODEL_FLAT24)
6035 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6039 /* so dptr know contains the address */
6040 freeAsmop(left,NULL,ic,TRUE);
6041 aopOp(result,ic,FALSE);
6043 /* if bit then unpack */
6044 if (IS_BITVAR(retype))
6045 genUnpackBits(result,"dptr",CPOINTER);
6047 size = AOP_SIZE(result);
6051 emitcode("clr","a");
6052 emitcode("movc","a,@a+dptr");
6053 aopPut(AOP(result),"a",offset++);
6055 emitcode("inc","dptr");
6059 freeAsmop(result,NULL,ic,TRUE);
6062 /*-----------------------------------------------------------------*/
6063 /* genGenPointerGet - gget value from generic pointer space */
6064 /*-----------------------------------------------------------------*/
6065 static void genGenPointerGet (operand *left,
6066 operand *result, iCode *ic)
6069 link *retype = getSpec(operandType(result));
6071 aopOp(left,ic,FALSE);
6073 /* if the operand is already in dptr
6074 then we do nothing else we move the value to dptr */
6075 if (AOP_TYPE(left) != AOP_STR) {
6076 /* if this is remateriazable */
6077 if (AOP_TYPE(left) == AOP_IMMD) {
6078 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6079 emitcode("mov","b,#%d",pointerCode(retype));
6081 else { /* we need to get it byte by byte */
6082 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6083 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6084 if (options.model == MODEL_FLAT24)
6086 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6087 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
6091 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
6095 /* so dptr know contains the address */
6096 freeAsmop(left,NULL,ic,TRUE);
6097 aopOp(result,ic,FALSE);
6099 /* if bit then unpack */
6100 if (IS_BITVAR(retype))
6101 genUnpackBits(result,"dptr",GPOINTER);
6103 size = AOP_SIZE(result);
6107 emitcode("lcall","__gptrget");
6108 aopPut(AOP(result),"a",offset++);
6110 emitcode("inc","dptr");
6114 freeAsmop(result,NULL,ic,TRUE);
6117 /*-----------------------------------------------------------------*/
6118 /* genPointerGet - generate code for pointer get */
6119 /*-----------------------------------------------------------------*/
6120 static void genPointerGet (iCode *ic)
6122 operand *left, *result ;
6127 result = IC_RESULT(ic) ;
6129 /* depending on the type of pointer we need to
6130 move it to the correct pointer register */
6131 type = operandType(left);
6132 etype = getSpec(type);
6133 /* if left is of type of pointer then it is simple */
6134 if (IS_PTR(type) && !IS_FUNC(type->next))
6135 p_type = DCL_TYPE(type);
6138 /* we have to go by the storage class */
6139 if (SPEC_OCLS(etype)->codesp ) {
6143 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
6146 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
6149 if (SPEC_OCLS(etype) == idata )
6155 /* now that we have the pointer type we assign
6156 the pointer values */
6161 genNearPointerGet (left,result,ic);
6165 genPagedPointerGet(left,result,ic);
6169 genFarPointerGet (left,result,ic);
6173 emitcodePointerGet (left,result,ic);
6177 genGenPointerGet (left,result,ic);
6183 /*-----------------------------------------------------------------*/
6184 /* genPackBits - generates code for packed bit storage */
6185 /*-----------------------------------------------------------------*/
6186 static void genPackBits (link *etype ,
6188 char *rname, int p_type)
6196 blen = SPEC_BLEN(etype);
6197 bstr = SPEC_BSTR(etype);
6199 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6202 /* if the bit lenth is less than or */
6203 /* it exactly fits a byte then */
6204 if (SPEC_BLEN(etype) <= 8 ) {
6205 shCount = SPEC_BSTR(etype) ;
6207 /* shift left acc */
6210 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6215 emitcode ("mov","b,a");
6216 emitcode("mov","a,@%s",rname);
6220 emitcode ("mov","b,a");
6221 emitcode("movx","a,@dptr");
6225 emitcode ("push","b");
6226 emitcode ("push","acc");
6227 emitcode ("lcall","__gptrget");
6228 emitcode ("pop","b");
6232 emitcode ("anl","a,#0x%02x",(unsigned char)
6233 ((unsigned char)(0xFF << (blen+bstr)) |
6234 (unsigned char)(0xFF >> (8-bstr)) ) );
6235 emitcode ("orl","a,b");
6236 if (p_type == GPOINTER)
6237 emitcode("pop","b");
6243 emitcode("mov","@%s,a",rname);
6247 emitcode("movx","@dptr,a");
6251 emitcode("lcall","__gptrput");
6256 if ( SPEC_BLEN(etype) <= 8 )
6259 emitcode("inc","%s",rname);
6260 rLen = SPEC_BLEN(etype) ;
6262 /* now generate for lengths greater than one byte */
6265 l = aopGet(AOP(right),offset++,FALSE,TRUE);
6275 emitcode("mov","@%s,a",rname);
6277 emitcode("mov","@%s,%s",rname,l);
6282 emitcode("movx","@dptr,a");
6287 emitcode("lcall","__gptrput");
6290 emitcode ("inc","%s",rname);
6295 /* last last was not complete */
6297 /* save the byte & read byte */
6300 emitcode ("mov","b,a");
6301 emitcode("mov","a,@%s",rname);
6305 emitcode ("mov","b,a");
6306 emitcode("movx","a,@dptr");
6310 emitcode ("push","b");
6311 emitcode ("push","acc");
6312 emitcode ("lcall","__gptrget");
6313 emitcode ("pop","b");
6317 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
6318 emitcode ("orl","a,b");
6321 if (p_type == GPOINTER)
6322 emitcode("pop","b");
6327 emitcode("mov","@%s,a",rname);
6331 emitcode("movx","@dptr,a");
6335 emitcode("lcall","__gptrput");
6339 /*-----------------------------------------------------------------*/
6340 /* genDataPointerSet - remat pointer to data space */
6341 /*-----------------------------------------------------------------*/
6342 static void genDataPointerSet(operand *right,
6346 int size, offset = 0 ;
6347 char *l, buffer[256];
6349 aopOp(right,ic,FALSE);
6351 l = aopGet(AOP(result),0,FALSE,TRUE);
6352 size = AOP_SIZE(right);
6355 sprintf(buffer,"(%s + %d)",l+1,offset);
6357 sprintf(buffer,"%s",l+1);
6358 emitcode("mov","%s,%s",buffer,
6359 aopGet(AOP(right),offset++,FALSE,FALSE));
6362 freeAsmop(right,NULL,ic,TRUE);
6363 freeAsmop(result,NULL,ic,TRUE);
6366 /*-----------------------------------------------------------------*/
6367 /* genNearPointerSet - emitcode for near pointer put */
6368 /*-----------------------------------------------------------------*/
6369 static void genNearPointerSet (operand *right,
6377 link *ptype = operandType(result);
6379 retype= getSpec(operandType(right));
6381 aopOp(result,ic,FALSE);
6383 /* if the result is rematerializable &
6384 in data space & not a bit variable */
6385 if (AOP_TYPE(result) == AOP_IMMD &&
6386 DCL_TYPE(ptype) == POINTER &&
6387 !IS_BITVAR(retype)) {
6388 genDataPointerSet (right,result,ic);
6392 /* if the value is already in a pointer register
6393 then don't need anything more */
6394 if (!AOP_INPREG(AOP(result))) {
6395 /* otherwise get a free pointer register */
6397 preg = getFreePtr(ic,&aop,FALSE);
6398 emitcode("mov","%s,%s",
6400 aopGet(AOP(result),0,FALSE,TRUE));
6401 rname = preg->name ;
6403 rname = aopGet(AOP(result),0,FALSE,FALSE);
6405 freeAsmop(result,NULL,ic,TRUE);
6406 aopOp (right,ic,FALSE);
6408 /* if bitfield then unpack the bits */
6409 if (IS_BITVAR(retype))
6410 genPackBits (retype,right,rname,POINTER);
6412 /* we have can just get the values */
6413 int size = AOP_SIZE(right);
6417 l = aopGet(AOP(right),offset,FALSE,TRUE);
6420 emitcode("mov","@%s,a",rname);
6422 emitcode("mov","@%s,%s",rname,l);
6424 emitcode("inc","%s",rname);
6429 /* now some housekeeping stuff */
6431 /* we had to allocate for this iCode */
6432 freeAsmop(NULL,aop,ic,TRUE);
6434 /* we did not allocate which means left
6435 already in a pointer register, then
6436 if size > 0 && this could be used again
6437 we have to point it back to where it
6439 if (AOP_SIZE(right) > 1 &&
6440 !OP_SYMBOL(result)->remat &&
6441 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6443 int size = AOP_SIZE(right) - 1;
6445 emitcode("dec","%s",rname);
6450 freeAsmop(right,NULL,ic,TRUE);
6455 /*-----------------------------------------------------------------*/
6456 /* genPagedPointerSet - emitcode for Paged pointer put */
6457 /*-----------------------------------------------------------------*/
6458 static void genPagedPointerSet (operand *right,
6467 retype= getSpec(operandType(right));
6469 aopOp(result,ic,FALSE);
6471 /* if the value is already in a pointer register
6472 then don't need anything more */
6473 if (!AOP_INPREG(AOP(result))) {
6474 /* otherwise get a free pointer register */
6476 preg = getFreePtr(ic,&aop,FALSE);
6477 emitcode("mov","%s,%s",
6479 aopGet(AOP(result),0,FALSE,TRUE));
6480 rname = preg->name ;
6482 rname = aopGet(AOP(result),0,FALSE,FALSE);
6484 freeAsmop(result,NULL,ic,TRUE);
6485 aopOp (right,ic,FALSE);
6487 /* if bitfield then unpack the bits */
6488 if (IS_BITVAR(retype))
6489 genPackBits (retype,right,rname,PPOINTER);
6491 /* we have can just get the values */
6492 int size = AOP_SIZE(right);
6496 l = aopGet(AOP(right),offset,FALSE,TRUE);
6499 emitcode("movx","@%s,a",rname);
6502 emitcode("inc","%s",rname);
6508 /* now some housekeeping stuff */
6510 /* we had to allocate for this iCode */
6511 freeAsmop(NULL,aop,ic,TRUE);
6513 /* we did not allocate which means left
6514 already in a pointer register, then
6515 if size > 0 && this could be used again
6516 we have to point it back to where it
6518 if (AOP_SIZE(right) > 1 &&
6519 !OP_SYMBOL(result)->remat &&
6520 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6522 int size = AOP_SIZE(right) - 1;
6524 emitcode("dec","%s",rname);
6529 freeAsmop(right,NULL,ic,TRUE);
6534 /*-----------------------------------------------------------------*/
6535 /* genFarPointerSet - set value from far space */
6536 /*-----------------------------------------------------------------*/
6537 static void genFarPointerSet (operand *right,
6538 operand *result, iCode *ic)
6541 link *retype = getSpec(operandType(right));
6543 aopOp(result,ic,FALSE);
6545 /* if the operand is already in dptr
6546 then we do nothing else we move the value to dptr */
6547 if (AOP_TYPE(result) != AOP_STR) {
6548 /* if this is remateriazable */
6549 if (AOP_TYPE(result) == AOP_IMMD)
6550 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6551 else { /* we need to get it byte by byte */
6552 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6553 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6554 if (options.model == MODEL_FLAT24)
6556 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6560 /* so dptr know contains the address */
6561 freeAsmop(result,NULL,ic,TRUE);
6562 aopOp(right,ic,FALSE);
6564 /* if bit then unpack */
6565 if (IS_BITVAR(retype))
6566 genPackBits(retype,right,"dptr",FPOINTER);
6568 size = AOP_SIZE(right);
6572 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6574 emitcode("movx","@dptr,a");
6576 emitcode("inc","dptr");
6580 freeAsmop(right,NULL,ic,TRUE);
6583 /*-----------------------------------------------------------------*/
6584 /* genGenPointerSet - set value from generic pointer space */
6585 /*-----------------------------------------------------------------*/
6586 static void genGenPointerSet (operand *right,
6587 operand *result, iCode *ic)
6590 link *retype = getSpec(operandType(right));
6592 aopOp(result,ic,FALSE);
6594 /* if the operand is already in dptr
6595 then we do nothing else we move the value to dptr */
6596 if (AOP_TYPE(result) != AOP_STR) {
6597 /* if this is remateriazable */
6598 if (AOP_TYPE(result) == AOP_IMMD) {
6599 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6600 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
6602 else { /* we need to get it byte by byte */
6603 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6604 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6605 if (options.model == MODEL_FLAT24)
6607 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6608 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
6612 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
6616 /* so dptr know contains the address */
6617 freeAsmop(result,NULL,ic,TRUE);
6618 aopOp(right,ic,FALSE);
6620 /* if bit then unpack */
6621 if (IS_BITVAR(retype))
6622 genPackBits(retype,right,"dptr",GPOINTER);
6624 size = AOP_SIZE(right);
6628 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6630 emitcode("lcall","__gptrput");
6632 emitcode("inc","dptr");
6636 freeAsmop(right,NULL,ic,TRUE);
6639 /*-----------------------------------------------------------------*/
6640 /* genPointerSet - stores the value into a pointer location */
6641 /*-----------------------------------------------------------------*/
6642 static void genPointerSet (iCode *ic)
6644 operand *right, *result ;
6648 right = IC_RIGHT(ic);
6649 result = IC_RESULT(ic) ;
6651 /* depending on the type of pointer we need to
6652 move it to the correct pointer register */
6653 type = operandType(result);
6654 etype = getSpec(type);
6655 /* if left is of type of pointer then it is simple */
6656 if (IS_PTR(type) && !IS_FUNC(type->next)) {
6657 p_type = DCL_TYPE(type);
6661 /* we have to go by the storage class */
6662 if (SPEC_OCLS(etype)->codesp ) {
6666 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
6669 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
6672 if (SPEC_OCLS(etype) == idata )
6678 /* now that we have the pointer type we assign
6679 the pointer values */
6684 genNearPointerSet (right,result,ic);
6688 genPagedPointerSet (right,result,ic);
6692 genFarPointerSet (right,result,ic);
6696 genGenPointerSet (right,result,ic);
6702 /*-----------------------------------------------------------------*/
6703 /* genIfx - generate code for Ifx statement */
6704 /*-----------------------------------------------------------------*/
6705 static void genIfx (iCode *ic, iCode *popIc)
6707 operand *cond = IC_COND(ic);
6710 aopOp(cond,ic,FALSE);
6712 /* get the value into acc */
6713 if (AOP_TYPE(cond) != AOP_CRY)
6717 /* the result is now in the accumulator */
6718 freeAsmop(cond,NULL,ic,TRUE);
6720 /* if there was something to be popped then do it */
6724 /* if the condition is a bit variable */
6725 if (isbit && IS_ITEMP(cond) &&
6727 genIfxJump(ic,SPIL_LOC(cond)->rname);
6729 if (isbit && !IS_ITEMP(cond))
6730 genIfxJump(ic,OP_SYMBOL(cond)->rname);
6737 /*-----------------------------------------------------------------*/
6738 /* genAddrOf - generates code for address of */
6739 /*-----------------------------------------------------------------*/
6740 static void genAddrOf (iCode *ic)
6742 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
6745 aopOp(IC_RESULT(ic),ic,FALSE);
6747 /* if the operand is on the stack then we
6748 need to get the stack offset of this
6751 /* if it has an offset then we need to compute
6754 emitcode("mov","a,_bp");
6755 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
6756 aopPut(AOP(IC_RESULT(ic)),"a",0);
6758 /* we can just move _bp */
6759 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
6760 /* fill the result with zero */
6761 size = AOP_SIZE(IC_RESULT(ic)) - 1;
6764 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
6769 /* object not on stack then we need the name */
6770 size = AOP_SIZE(IC_RESULT(ic));
6774 char s[SDCC_NAME_MAX];
6776 sprintf(s,"#(%s >> %d)",
6780 sprintf(s,"#%s",sym->rname);
6781 aopPut(AOP(IC_RESULT(ic)),s,offset++);
6785 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
6789 /*-----------------------------------------------------------------*/
6790 /* genFarFarAssign - assignment when both are in far space */
6791 /*-----------------------------------------------------------------*/
6792 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
6794 int size = AOP_SIZE(right);
6797 /* first push the right side on to the stack */
6799 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6801 emitcode ("push","acc");
6804 freeAsmop(right,NULL,ic,FALSE);
6805 /* now assign DPTR to result */
6806 aopOp(result,ic,FALSE);
6807 size = AOP_SIZE(result);
6809 emitcode ("pop","acc");
6810 aopPut(AOP(result),"a",--offset);
6812 freeAsmop(result,NULL,ic,FALSE);
6816 /*-----------------------------------------------------------------*/
6817 /* genAssign - generate code for assignment */
6818 /*-----------------------------------------------------------------*/
6819 static void genAssign (iCode *ic)
6821 operand *result, *right;
6823 unsigned long lit = 0L;
6825 result = IC_RESULT(ic);
6826 right = IC_RIGHT(ic) ;
6828 /* if they are the same */
6829 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
6832 aopOp(right,ic,FALSE);
6834 /* special case both in far space */
6835 if (AOP_TYPE(right) == AOP_DPTR &&
6836 IS_TRUE_SYMOP(result) &&
6837 isOperandInFarSpace(result)) {
6839 genFarFarAssign (result,right,ic);
6843 aopOp(result,ic,TRUE);
6845 /* if they are the same registers */
6846 if (sameRegs(AOP(right),AOP(result)))
6849 /* if the result is a bit */
6850 if (AOP_TYPE(result) == AOP_CRY) {
6852 /* if the right size is a literal then
6853 we know what the value is */
6854 if (AOP_TYPE(right) == AOP_LIT) {
6855 if (((int) operandLitValue(right)))
6856 aopPut(AOP(result),one,0);
6858 aopPut(AOP(result),zero,0);
6862 /* the right is also a bit variable */
6863 if (AOP_TYPE(right) == AOP_CRY) {
6864 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6865 aopPut(AOP(result),"c",0);
6871 aopPut(AOP(result),"a",0);
6875 /* bit variables done */
6877 size = AOP_SIZE(result);
6879 if(AOP_TYPE(right) == AOP_LIT)
6880 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6882 (AOP_TYPE(result) != AOP_REG) &&
6883 (AOP_TYPE(right) == AOP_LIT) &&
6884 !IS_FLOAT(operandType(right)) &&
6886 emitcode("clr","a");
6888 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
6889 aopPut(AOP(result),"a",size);
6892 aopGet(AOP(right),size,FALSE,FALSE),
6898 aopGet(AOP(right),offset,FALSE,FALSE),
6905 freeAsmop (right,NULL,ic,FALSE);
6906 freeAsmop (result,NULL,ic,TRUE);
6909 /*-----------------------------------------------------------------*/
6910 /* genJumpTab - genrates code for jump table */
6911 /*-----------------------------------------------------------------*/
6912 static void genJumpTab (iCode *ic)
6917 aopOp(IC_JTCOND(ic),ic,FALSE);
6918 /* get the condition into accumulator */
6919 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
6921 /* multiply by three */
6922 emitcode("add","a,acc");
6923 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
6924 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
6926 jtab = newiTempLabel(NULL);
6927 emitcode("mov","dptr,#%05d$",jtab->key+100);
6928 emitcode("jmp","@a+dptr");
6929 emitcode("","%05d$:",jtab->key+100);
6930 /* now generate the jump labels */
6931 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
6932 jtab = setNextItem(IC_JTLABELS(ic)))
6933 emitcode("ljmp","%05d$",jtab->key+100);
6937 /*-----------------------------------------------------------------*/
6938 /* genCast - gen code for casting */
6939 /*-----------------------------------------------------------------*/
6940 static void genCast (iCode *ic)
6942 operand *result = IC_RESULT(ic);
6943 link *ctype = operandType(IC_LEFT(ic));
6944 operand *right = IC_RIGHT(ic);
6947 /* if they are equivalent then do nothing */
6948 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
6951 aopOp(right,ic,FALSE) ;
6952 aopOp(result,ic,FALSE);
6954 /* if the result is a bit */
6955 if (AOP_TYPE(result) == AOP_CRY) {
6956 /* if the right size is a literal then
6957 we know what the value is */
6958 if (AOP_TYPE(right) == AOP_LIT) {
6959 if (((int) operandLitValue(right)))
6960 aopPut(AOP(result),one,0);
6962 aopPut(AOP(result),zero,0);
6967 /* the right is also a bit variable */
6968 if (AOP_TYPE(right) == AOP_CRY) {
6969 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6970 aopPut(AOP(result),"c",0);
6976 aopPut(AOP(result),"a",0);
6980 /* if they are the same size : or less */
6981 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
6983 /* if they are in the same place */
6984 if (sameRegs(AOP(right),AOP(result)))
6987 /* if they in different places then copy */
6988 size = AOP_SIZE(result);
6992 aopGet(AOP(right),offset,FALSE,FALSE),
7000 /* if the result is of type pointer */
7001 if (IS_PTR(ctype)) {
7004 link *type = operandType(right);
7005 link *etype = getSpec(type);
7007 /* pointer to generic pointer */
7008 if (IS_GENPTR(ctype)) {
7012 p_type = DCL_TYPE(type);
7014 /* we have to go by the storage class */
7015 if (SPEC_OCLS(etype)->codesp )
7018 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
7021 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
7024 if (SPEC_OCLS(etype) == idata )
7030 /* the first two bytes are known */
7031 size = GPTRSIZE - 1;
7035 aopGet(AOP(right),offset,FALSE,FALSE),
7039 /* the last byte depending on type */
7056 /* this should never happen */
7057 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7058 "got unknown pointer type");
7061 aopPut(AOP(result),l, GPTRSIZE - 1);
7065 /* just copy the pointers */
7066 size = AOP_SIZE(result);
7070 aopGet(AOP(right),offset,FALSE,FALSE),
7077 /* so we now know that the size of destination is greater
7078 than the size of the source */
7079 /* we move to result for the size of source */
7080 size = AOP_SIZE(right);
7084 aopGet(AOP(right),offset,FALSE,FALSE),
7089 /* now depending on the sign of the destination */
7090 size = AOP_SIZE(result) - AOP_SIZE(right);
7091 /* if unsigned or not an integral type */
7092 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
7094 aopPut(AOP(result),zero,offset++);
7096 /* we need to extend the sign :{ */
7097 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
7100 emitcode("rlc","a");
7101 emitcode("subb","a,acc");
7103 aopPut(AOP(result),"a",offset++);
7106 /* we are done hurray !!!! */
7109 freeAsmop(right,NULL,ic,TRUE);
7110 freeAsmop(result,NULL,ic,TRUE);
7114 /*-----------------------------------------------------------------*/
7115 /* genDjnz - generate decrement & jump if not zero instrucion */
7116 /*-----------------------------------------------------------------*/
7117 static int genDjnz (iCode *ic, iCode *ifx)
7123 /* if the if condition has a false label
7124 then we cannot save */
7128 /* if the minus is not of the form
7130 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
7131 !IS_OP_LITERAL(IC_RIGHT(ic)))
7134 if (operandLitValue(IC_RIGHT(ic)) != 1)
7137 /* if the size of this greater than one then no
7139 if (getSize(operandType(IC_RESULT(ic))) > 1)
7142 /* otherwise we can save BIG */
7143 lbl = newiTempLabel(NULL);
7144 lbl1= newiTempLabel(NULL);
7146 aopOp(IC_RESULT(ic),ic,FALSE);
7148 if (IS_AOP_PREG(IC_RESULT(ic))) {
7149 emitcode("dec","%s",
7150 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7151 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7152 emitcode("jnz","%05d$",lbl->key+100);
7154 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
7157 emitcode ("sjmp","%05d$",lbl1->key+100);
7158 emitcode ("","%05d$:",lbl->key+100);
7159 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
7160 emitcode ("","%05d$:",lbl1->key+100);
7162 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7167 /*-----------------------------------------------------------------*/
7168 /* genReceive - generate code for a receive iCode */
7169 /*-----------------------------------------------------------------*/
7170 static void genReceive (iCode *ic)
7172 if (isOperandInFarSpace(IC_RESULT(ic)) &&
7173 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
7174 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
7176 int size = getSize(operandType(IC_RESULT(ic)));
7177 int offset = fReturnSize - size;
7179 emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
7180 fReturn[fReturnSize - offset - 1] : "acc"));
7183 aopOp(IC_RESULT(ic),ic,FALSE);
7184 size = AOP_SIZE(IC_RESULT(ic));
7187 emitcode ("pop","acc");
7188 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
7193 aopOp(IC_RESULT(ic),ic,FALSE);
7195 assignResultValue(IC_RESULT(ic));
7198 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7201 /*-----------------------------------------------------------------*/
7202 /* gen51Code - generate code for 8051 based controllers */
7203 /*-----------------------------------------------------------------*/
7204 void gen51Code (iCode *lic)
7209 /* Hack-o-matic: change fReturn based on model. */
7210 if (options.model == MODEL_FLAT24)
7212 fReturn = fReturn390;
7216 lineHead = lineCurr = NULL;
7218 /* if debug information required */
7219 /* if (options.debug && currFunc) { */
7221 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
7223 if (IS_STATIC(currFunc->etype))
7224 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
7226 emitcode("","G$%s$0$0 ==.",currFunc->name);
7229 /* stack pointer name */
7230 if (options.useXstack)
7236 for (ic = lic ; ic ; ic = ic->next ) {
7238 if ( cln != ic->lineno ) {
7239 if ( options.debug ) {
7241 emitcode("","C$%s$%d$%d$%d ==.",
7242 ic->filename,ic->lineno,
7243 ic->level,ic->block);
7246 emitcode(";","%s %d",ic->filename,ic->lineno);
7249 /* if the result is marked as
7250 spilt and rematerializable or code for
7251 this has already been generated then
7253 if (resultRemat(ic) || ic->generated )
7256 /* depending on the operation */
7275 /* IPOP happens only when trying to restore a
7276 spilt live range, if there is an ifx statement
7277 following this pop then the if statement might
7278 be using some of the registers being popped which
7279 would destory the contents of the register so
7280 we need to check for this condition and handle it */
7282 ic->next->op == IFX &&
7283 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
7284 genIfx (ic->next,ic);
7302 genEndFunction (ic);
7322 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
7339 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
7343 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
7350 /* note these two are xlated by algebraic equivalence
7351 during parsing SDCC.y */
7352 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7353 "got '>=' or '<=' shouldn't have come here");
7357 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
7369 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
7373 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
7377 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
7404 case GET_VALUE_AT_ADDRESS:
7409 if (POINTER_SET(ic))
7436 addSet(&_G.sendSet,ic);
7441 /* piCode(ic,stdout); */
7447 /* now we are ready to call the
7448 peep hole optimizer */
7449 if (!options.nopeep)
7450 peepHole (&lineHead);
7452 /* now do the actual printing */
7453 printLine (lineHead,codeOutFile);