1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
35 #include "SDCCglobl.h"
37 #ifdef HAVE_SYS_ISA_DEFS_H
38 #include <sys/isa_defs.h>
43 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
44 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
49 #include "SDCCpeeph.h"
53 char *aopLiteral (value *val, int offset);
55 /* this is the down and dirty file with all kinds of
56 kludgy & hacky stuff. This is what it is all about
57 CODE GENERATION for a specific MCU . some of the
58 routines may be reusable, will have to see */
60 static char *zero = "#0x00";
61 static char *one = "#0x01";
63 static char *fReturn[] = {"dpl","dph","b","a" };
64 static char *accUse[] = {"a","b"};
66 static short rbank = -1;
78 extern int mcs51_ptrRegReq ;
79 extern int mcs51_nRegs;
80 extern FILE *codeOutFile;
81 static void saverbank (int, iCode *,bool);
82 #define RESULTONSTACK(x) \
83 (IC_RESULT(x) && IC_RESULT(x)->aop && \
84 IC_RESULT(x)->aop->type == AOP_STK )
86 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x);
87 #define CLRC emitcode("clr","c");
89 static lineNode *lineHead = NULL;
90 static lineNode *lineCurr = NULL;
92 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
93 0xE0, 0xC0, 0x80, 0x00};
94 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
95 0x07, 0x03, 0x01, 0x00};
102 /*-----------------------------------------------------------------*/
103 /* emitcode - writes the code into a file : for now it is simple */
104 /*-----------------------------------------------------------------*/
105 static void emitcode (char *inst,char *fmt, ...)
108 char lb[MAX_INLINEASM];
115 sprintf(lb,"%s\t",inst);
117 sprintf(lb,"%s",inst);
118 vsprintf(lb+(strlen(lb)),fmt,ap);
122 while (isspace(*lbp)) lbp++;
125 lineCurr = (lineCurr ?
126 connectLine(lineCurr,newLineNode(lb)) :
127 (lineHead = newLineNode(lb)));
128 lineCurr->isInline = _G.inLine;
129 lineCurr->isDebug = _G.debugLine;
133 /*-----------------------------------------------------------------*/
134 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
135 /*-----------------------------------------------------------------*/
136 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
138 bool r0iu = FALSE , r1iu = FALSE;
139 bool r0ou = FALSE , r1ou = FALSE;
141 /* the logic: if r0 & r1 used in the instruction
142 then we are in trouble otherwise */
144 /* first check if r0 & r1 are used by this
145 instruction, in which case we are in trouble */
146 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
147 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
152 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
153 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
155 /* if no usage of r0 then return it */
156 if (!r0iu && !r0ou) {
157 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
158 (*aopp)->type = AOP_R0;
160 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R0_IDX);
163 /* if no usage of r1 then return it */
164 if (!r1iu && !r1ou) {
165 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
166 (*aopp)->type = AOP_R1;
168 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R1_IDX);
171 /* now we know they both have usage */
172 /* if r0 not used in this instruction */
174 /* push it if not already pushed */
176 emitcode ("push","%s",
177 mcs51_regWithIdx(R0_IDX)->dname);
181 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
182 (*aopp)->type = AOP_R0;
184 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R0_IDX);
187 /* if r1 not used then */
190 /* push it if not already pushed */
192 emitcode ("push","%s",
193 mcs51_regWithIdx(R1_IDX)->dname);
197 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
198 (*aopp)->type = AOP_R1;
199 return mcs51_regWithIdx(R1_IDX);
203 /* I said end of world but not quite end of world yet */
204 /* if this is a result then we can push it on the stack*/
206 (*aopp)->type = AOP_STK;
211 /* other wise this is true end of the world */
212 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
213 "getFreePtr should never reach here");
217 /*-----------------------------------------------------------------*/
218 /* newAsmop - creates a new asmOp */
219 /*-----------------------------------------------------------------*/
220 static asmop *newAsmop (short type)
224 ALLOC(aop,sizeof(asmop));
229 /*-----------------------------------------------------------------*/
230 /* pointerCode - returns the code for a pointer type */
231 /*-----------------------------------------------------------------*/
232 static int pointerCode (link *etype)
235 if (SPEC_OCLS(etype)->codesp ) {
239 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
242 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
245 if (SPEC_OCLS(etype) == idata )
252 /*-----------------------------------------------------------------*/
253 /* aopForSym - for a true symbol */
254 /*-----------------------------------------------------------------*/
255 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
258 memmap *space= SPEC_OCLS(sym->etype);
260 /* if already has one */
264 /* assign depending on the storage class */
265 /* if it is on the stack or indirectly addressable */
266 /* space we need to assign either r0 or r1 to it */
267 if (sym->onStack || sym->iaccess) {
268 sym->aop = aop = newAsmop(0);
269 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
270 aop->size = getSize(sym->type);
272 /* now assign the address of the variable to
273 the pointer register */
274 if (aop->type != AOP_STK) {
279 emitcode("push","acc");
281 emitcode("mov","a,_bp");
282 emitcode("add","a,#0x%02x",
284 ((char)(sym->stack - _G.nRegsSaved )) :
285 ((char)sym->stack)) & 0xff);
286 emitcode("mov","%s,a",
287 aop->aopu.aop_ptr->name);
290 emitcode("pop","acc");
293 emitcode("mov","%s,#%s",
294 aop->aopu.aop_ptr->name,
296 aop->paged = space->paged;
298 aop->aopu.aop_stk = sym->stack;
302 /* if in bit space */
303 if (IN_BITSPACE(space)) {
304 sym->aop = aop = newAsmop (AOP_CRY);
305 aop->aopu.aop_dir = sym->rname ;
306 aop->size = getSize(sym->type);
309 /* if it is in direct space */
310 if (IN_DIRSPACE(space)) {
311 sym->aop = aop = newAsmop (AOP_DIR);
312 aop->aopu.aop_dir = sym->rname ;
313 aop->size = getSize(sym->type);
317 /* special case for a function */
318 if (IS_FUNC(sym->type)) {
319 sym->aop = aop = newAsmop(AOP_IMMD);
320 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
321 strcpy(aop->aopu.aop_immd,sym->rname);
322 aop->size = FPTRSIZE;
326 /* only remaining is far space */
327 /* in which case DPTR gets the address */
328 sym->aop = aop = newAsmop(AOP_DPTR);
329 emitcode ("mov","dptr,#%s", sym->rname);
330 aop->size = getSize(sym->type);
332 /* if it is in code space */
333 if (IN_CODESPACE(space))
339 /*-----------------------------------------------------------------*/
340 /* aopForRemat - rematerialzes an object */
341 /*-----------------------------------------------------------------*/
342 static asmop *aopForRemat (symbol *sym)
345 iCode *ic = sym->rematiCode;
346 asmop *aop = newAsmop(AOP_IMMD);
350 /* if plus or minus print the right hand side */
351 if (ic->op == '+' || ic->op == '-') {
352 sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
355 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
359 /* we reached the end */
360 sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
364 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
365 strcpy(aop->aopu.aop_immd,buffer);
369 /*-----------------------------------------------------------------*/
370 /* regsInCommon - two operands have some registers in common */
371 /*-----------------------------------------------------------------*/
372 static bool regsInCommon (operand *op1, operand *op2)
377 /* if they have registers in common */
378 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
381 sym1 = OP_SYMBOL(op1);
382 sym2 = OP_SYMBOL(op2);
384 if (sym1->nRegs == 0 || sym2->nRegs == 0)
387 for (i = 0 ; i < sym1->nRegs ; i++) {
392 for (j = 0 ; j < sym2->nRegs ;j++ ) {
396 if (sym2->regs[j] == sym1->regs[i])
404 /*-----------------------------------------------------------------*/
405 /* operandsEqu - equivalent */
406 /*-----------------------------------------------------------------*/
407 static bool operandsEqu ( operand *op1, operand *op2)
411 /* if they not symbols */
412 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
415 sym1 = OP_SYMBOL(op1);
416 sym2 = OP_SYMBOL(op2);
418 /* if both are itemps & one is spilt
419 and the other is not then false */
420 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
421 sym1->isspilt != sym2->isspilt )
424 /* if they are the same */
428 if (strcmp(sym1->rname,sym2->rname) == 0)
432 /* if left is a tmp & right is not */
436 (sym1->usl.spillLoc == sym2))
443 (sym2->usl.spillLoc == sym1))
449 /*-----------------------------------------------------------------*/
450 /* sameRegs - two asmops have the same registers */
451 /*-----------------------------------------------------------------*/
452 static bool sameRegs (asmop *aop1, asmop *aop2 )
459 if (aop1->type != AOP_REG ||
460 aop2->type != AOP_REG )
463 if (aop1->size != aop2->size )
466 for (i = 0 ; i < aop1->size ; i++ )
467 if (aop1->aopu.aop_reg[i] !=
468 aop2->aopu.aop_reg[i] )
474 /*-----------------------------------------------------------------*/
475 /* aopOp - allocates an asmop for an operand : */
476 /*-----------------------------------------------------------------*/
477 static void aopOp (operand *op, iCode *ic, bool result)
486 /* if this a literal */
487 if (IS_OP_LITERAL(op)) {
488 op->aop = aop = newAsmop(AOP_LIT);
489 aop->aopu.aop_lit = op->operand.valOperand;
490 aop->size = getSize(operandType(op));
494 /* if already has a asmop then continue */
498 /* if the underlying symbol has a aop */
499 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
500 op->aop = OP_SYMBOL(op)->aop;
504 /* if this is a true symbol */
505 if (IS_TRUE_SYMOP(op)) {
506 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
510 /* this is a temporary : this has
516 e) can be a return use only */
521 /* if the type is a conditional */
522 if (sym->regType == REG_CND) {
523 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
528 /* if it is spilt then two situations
530 b) has a spill location */
531 if (sym->isspilt || sym->nRegs == 0) {
533 /* rematerialize it NOW */
535 sym->aop = op->aop = aop =
537 aop->size = getSize(sym->type);
543 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
544 aop->size = getSize(sym->type);
545 for ( i = 0 ; i < 2 ; i++ )
546 aop->aopu.aop_str[i] = accUse[i];
552 aop = op->aop = sym->aop = newAsmop(AOP_STR);
553 aop->size = getSize(sym->type);
554 for ( i = 0 ; i < 4 ; i++ )
555 aop->aopu.aop_str[i] = fReturn[i];
559 /* else spill location */
560 sym->aop = op->aop = aop =
561 aopForSym(ic,sym->usl.spillLoc,result);
562 aop->size = getSize(sym->type);
566 /* must be in a register */
567 sym->aop = op->aop = aop = newAsmop(AOP_REG);
568 aop->size = sym->nRegs;
569 for ( i = 0 ; i < sym->nRegs ;i++)
570 aop->aopu.aop_reg[i] = sym->regs[i];
573 /*-----------------------------------------------------------------*/
574 /* freeAsmop - free up the asmop given to an operand */
575 /*----------------------------------------------------------------*/
576 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
593 /* depending on the asmop type only three cases need work AOP_RO
594 , AOP_R1 && AOP_STK */
599 emitcode ("pop","ar0");
603 bitVectUnSetBit(ic->rUsed,R0_IDX);
609 emitcode ("pop","ar1");
613 bitVectUnSetBit(ic->rUsed,R1_IDX);
619 int stk = aop->aopu.aop_stk + aop->size;
620 bitVectUnSetBit(ic->rUsed,R0_IDX);
621 bitVectUnSetBit(ic->rUsed,R1_IDX);
623 getFreePtr(ic,&aop,FALSE);
625 emitcode ("mov","a,_bp");
626 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
627 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
629 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
632 emitcode("pop","acc");
633 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
635 emitcode("dec","%s",aop->aopu.aop_ptr->name);
638 freeAsmop(op,NULL,ic,TRUE);
640 emitcode("pop","ar0");
645 emitcode("pop","ar1");
652 /* all other cases just dealloc */
656 OP_SYMBOL(op)->aop = NULL;
657 /* if the symbol has a spill */
659 SPIL_LOC(op)->aop = NULL;
664 /*-----------------------------------------------------------------*/
665 /* aopGet - for fetching value of the aop */
666 /*-----------------------------------------------------------------*/
667 static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
672 /* offset is greater than
674 if (offset > (aop->size - 1) &&
675 aop->type != AOP_LIT)
678 /* depending on type */
683 /* if we need to increment it */
684 while (offset > aop->coff) {
685 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
689 while (offset < aop->coff) {
690 emitcode("dec","%s",aop->aopu.aop_ptr->name);
696 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
697 return (dname ? "acc" : "a");
699 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
700 ALLOC_ATOMIC(rs,strlen(s)+1);
705 while (offset > aop->coff) {
706 emitcode ("inc","dptr");
710 while (offset < aop->coff) {
711 emitcode("lcall","__decdptr");
718 emitcode("movc","a,@a+dptr");
721 emitcode("movx","a,@dptr");
722 return (dname ? "acc" : "a");
727 sprintf (s,"#(%s)",aop->aopu.aop_immd);
730 sprintf(s,"#(%s >> %d)",
736 ALLOC_ATOMIC(rs,strlen(s)+1);
742 sprintf(s,"(%s + %d)",
746 sprintf(s,"%s",aop->aopu.aop_dir);
747 ALLOC_ATOMIC(rs,strlen(s)+1);
753 return aop->aopu.aop_reg[offset]->dname;
755 return aop->aopu.aop_reg[offset]->name;
759 emitcode("mov","c,%s",aop->aopu.aop_dir);
760 emitcode("rlc","a") ;
761 return (dname ? "acc" : "a");
764 if (!offset && dname)
766 return aop->aopu.aop_str[offset];
769 return aopLiteral (aop->aopu.aop_lit,offset);
773 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
777 return aop->aopu.aop_str[offset];
781 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
782 "aopget got unsupported aop->type");
785 /*-----------------------------------------------------------------*/
786 /* aopPut - puts a string for a aop */
787 /*-----------------------------------------------------------------*/
788 static void aopPut (asmop *aop, char *s, int offset)
793 if (aop->size && offset > ( aop->size - 1)) {
794 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
795 "aopPut got offset > aop->size");
799 /* will assign value to value */
800 /* depending on where it is ofcourse */
804 sprintf(d,"(%s + %d)",
805 aop->aopu.aop_dir,offset);
807 sprintf(d,"%s",aop->aopu.aop_dir);
810 emitcode("mov","%s,%s",d,s);
815 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
816 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
818 strcmp(s,"r0") == 0 ||
819 strcmp(s,"r1") == 0 ||
820 strcmp(s,"r2") == 0 ||
821 strcmp(s,"r3") == 0 ||
822 strcmp(s,"r4") == 0 ||
823 strcmp(s,"r5") == 0 ||
824 strcmp(s,"r6") == 0 ||
825 strcmp(s,"r7") == 0 )
826 emitcode("mov","%s,%s",
827 aop->aopu.aop_reg[offset]->dname,s);
829 emitcode("mov","%s,%s",
830 aop->aopu.aop_reg[offset]->name,s);
836 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
837 "aopPut writting to code space");
841 while (offset > aop->coff) {
843 emitcode ("inc","dptr");
846 while (offset < aop->coff) {
848 emitcode("lcall","__decdptr");
853 /* if not in accumulater */
856 emitcode ("movx","@dptr,a");
861 while (offset > aop->coff) {
863 emitcode("inc","%s",aop->aopu.aop_ptr->name);
865 while (offset < aop->coff) {
867 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
873 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
878 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
880 if (strcmp(s,"r0") == 0 ||
881 strcmp(s,"r1") == 0 ||
882 strcmp(s,"r2") == 0 ||
883 strcmp(s,"r3") == 0 ||
884 strcmp(s,"r4") == 0 ||
885 strcmp(s,"r5") == 0 ||
886 strcmp(s,"r6") == 0 ||
887 strcmp(s,"r7") == 0 ) {
889 sprintf(buffer,"a%s",s);
890 emitcode("mov","@%s,%s",
891 aop->aopu.aop_ptr->name,buffer);
893 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
898 if (strcmp(s,"a") == 0)
899 emitcode("push","acc");
901 emitcode("push","%s",s);
906 /* if bit variable */
907 if (!aop->aopu.aop_dir) {
912 emitcode("clr","%s",aop->aopu.aop_dir);
915 emitcode("setb","%s",aop->aopu.aop_dir);
918 emitcode("mov","%s,c",aop->aopu.aop_dir);
920 lbl = newiTempLabel(NULL);
925 emitcode("cjne","a,#0x01,%05d$",lbl->key+100);
926 emitcode("","%05d$:",lbl->key+100);
928 emitcode("mov","%s,c",aop->aopu.aop_dir);
935 if (strcmp(aop->aopu.aop_str[offset],s))
936 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
941 if (!offset && (strcmp(s,"acc") == 0))
944 if (strcmp(aop->aopu.aop_str[offset],s))
945 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
949 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
950 "aopPut got unsupported aop->type");
958 /*-----------------------------------------------------------------*/
959 /* pointToEnd :- points to the last byte of the operand */
960 /*-----------------------------------------------------------------*/
961 static void pointToEnd (asmop *aop)
967 aop->coff = count = (aop->size - 1);
972 emitcode("inc","%s",aop->aopu.aop_ptr->name);
976 emitcode("inc","dptr");
983 /*-----------------------------------------------------------------*/
984 /* reAdjustPreg - points a register back to where it should */
985 /*-----------------------------------------------------------------*/
986 static void reAdjustPreg (asmop *aop)
991 if ((size = aop->size) <= 1)
998 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1002 emitcode("lcall","__decdptr");
1009 #define AOP(op) op->aop
1010 #define AOP_TYPE(op) AOP(op)->type
1011 #define AOP_SIZE(op) AOP(op)->size
1012 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1013 AOP_TYPE(x) == AOP_R0))
1015 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1016 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1018 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1019 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1020 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1022 /*-----------------------------------------------------------------*/
1023 /* genNotFloat - generates not for float operations */
1024 /*-----------------------------------------------------------------*/
1025 static void genNotFloat (operand *op, operand *res)
1031 /* we will put 127 in the first byte of
1033 aopPut(AOP(res),"#127",0);
1034 size = AOP_SIZE(op) - 1;
1037 l = aopGet(op->aop,offset++,FALSE,FALSE);
1041 emitcode("orl","a,%s",
1043 offset++,FALSE,FALSE));
1045 tlbl = newiTempLabel(NULL);
1047 tlbl = newiTempLabel(NULL);
1048 aopPut(res->aop,one,1);
1049 emitcode("jz","%05d$",(tlbl->key+100));
1050 aopPut(res->aop,zero,1);
1051 emitcode("","%05d$:",(tlbl->key+100));
1053 size = res->aop->size - 2;
1055 /* put zeros in the rest */
1057 aopPut(res->aop,zero,offset++);
1060 /*-----------------------------------------------------------------*/
1061 /* opIsGptr: returns non-zero if the passed operand is */
1062 /* a generic pointer type. */
1063 /*-----------------------------------------------------------------*/
1064 static int opIsGptr(operand *op)
1066 link *type = operandType(op);
1068 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1075 /*-----------------------------------------------------------------*/
1076 /* getDataSize - get the operand data size */
1077 /*-----------------------------------------------------------------*/
1078 static int getDataSize(operand *op)
1081 size = AOP_SIZE(op);
1082 if (size == GPTRSIZE)
1084 link *type = operandType(op);
1085 if (IS_GENPTR(type))
1087 /* generic pointer; arithmetic operations
1088 * should ignore the high byte (pointer type).
1096 /*-----------------------------------------------------------------*/
1097 /* outAcc - output Acc */
1098 /*-----------------------------------------------------------------*/
1099 static void outAcc(operand *result)
1102 size = getDataSize(result);
1104 aopPut(AOP(result),"a",0);
1107 /* unsigned or positive */
1109 aopPut(AOP(result),zero,offset++);
1114 /*-----------------------------------------------------------------*/
1115 /* outBitC - output a bit C */
1116 /*-----------------------------------------------------------------*/
1117 static void outBitC(operand *result)
1119 /* if the result is bit */
1120 if (AOP_TYPE(result) == AOP_CRY)
1121 aopPut(AOP(result),"c",0);
1123 emitcode("clr","a");
1124 emitcode("rlc","a");
1129 /*-----------------------------------------------------------------*/
1130 /* toBoolean - emit code for orl a,operator(sizeop) */
1131 /*-----------------------------------------------------------------*/
1132 static void toBoolean(operand *oper)
1134 int size = AOP_SIZE(oper) - 1;
1136 MOVA(aopGet(AOP(oper),0,FALSE,FALSE));
1138 emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE));
1142 /*-----------------------------------------------------------------*/
1143 /* genNot - generate code for ! operation */
1144 /*-----------------------------------------------------------------*/
1145 static void genNot (iCode *ic)
1148 link *optype = operandType(IC_LEFT(ic));
1150 /* assign asmOps to operand & result */
1151 aopOp (IC_LEFT(ic),ic,FALSE);
1152 aopOp (IC_RESULT(ic),ic,TRUE);
1154 /* if in bit space then a special case */
1155 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1156 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1157 emitcode("cpl","c");
1158 outBitC(IC_RESULT(ic));
1162 /* if type float then do float */
1163 if (IS_FLOAT(optype)) {
1164 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1168 toBoolean(IC_LEFT(ic));
1170 tlbl = newiTempLabel(NULL);
1171 emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1172 emitcode("","%05d$:",tlbl->key+100);
1173 outBitC(IC_RESULT(ic));
1176 /* release the aops */
1177 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1178 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1182 /*-----------------------------------------------------------------*/
1183 /* genCpl - generate code for complement */
1184 /*-----------------------------------------------------------------*/
1185 static void genCpl (iCode *ic)
1191 /* assign asmOps to operand & result */
1192 aopOp (IC_LEFT(ic),ic,FALSE);
1193 aopOp (IC_RESULT(ic),ic,TRUE);
1195 /* if both are in bit space then
1197 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1198 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1200 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1201 emitcode("cpl","c");
1202 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1206 size = AOP_SIZE(IC_RESULT(ic));
1208 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1210 emitcode("cpl","a");
1211 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1216 /* release the aops */
1217 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1218 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1221 /*-----------------------------------------------------------------*/
1222 /* genUminusFloat - unary minus for floating points */
1223 /*-----------------------------------------------------------------*/
1224 static void genUminusFloat(operand *op,operand *result)
1226 int size ,offset =0 ;
1228 /* for this we just need to flip the
1229 first it then copy the rest in place */
1230 size = AOP_SIZE(op) - 1;
1231 l = aopGet(AOP(op),3,FALSE,FALSE);
1235 emitcode("cpl","acc.7");
1236 aopPut(AOP(result),"a",3);
1240 aopGet(AOP(op),offset,FALSE,FALSE),
1246 /*-----------------------------------------------------------------*/
1247 /* genUminus - unary minus code generation */
1248 /*-----------------------------------------------------------------*/
1249 static void genUminus (iCode *ic)
1252 link *optype, *rtype;
1256 aopOp(IC_LEFT(ic),ic,FALSE);
1257 aopOp(IC_RESULT(ic),ic,TRUE);
1259 /* if both in bit space then special
1261 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1262 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1264 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1265 emitcode("cpl","c");
1266 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1270 optype = operandType(IC_LEFT(ic));
1271 rtype = operandType(IC_RESULT(ic));
1273 /* if float then do float stuff */
1274 if (IS_FLOAT(optype)) {
1275 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1279 /* otherwise subtract from zero */
1280 size = AOP_SIZE(IC_LEFT(ic));
1284 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1285 if (!strcmp(l,"a")) {
1286 emitcode("cpl","a");
1287 emitcode("inc","a");
1289 emitcode("clr","a");
1290 emitcode("subb","a,%s",l);
1292 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1295 /* if any remaining bytes in the result */
1296 /* we just need to propagate the sign */
1297 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1298 emitcode("rlc","a");
1299 emitcode("subb","a,acc");
1301 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1305 /* release the aops */
1306 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1307 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1310 /*-----------------------------------------------------------------*/
1311 /* saveRegisters - will look for a call and save the registers */
1312 /*-----------------------------------------------------------------*/
1313 static void saveRegisters(iCode *lic)
1321 for (ic = lic ; ic ; ic = ic->next)
1322 if (ic->op == CALL || ic->op == PCALL)
1326 fprintf(stderr,"found parameter push with no function call\n");
1330 /* if the registers have been saved already then
1332 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1335 /* find the registers in use at this time
1336 and push them away to safety */
1337 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1341 if (options.useXstack) {
1342 if (bitVectBitValue(rsave,R0_IDX))
1343 emitcode("mov","b,r0");
1344 emitcode("mov","r0,%s",spname);
1345 for (i = 0 ; i < mcs51_nRegs ; i++) {
1346 if (bitVectBitValue(rsave,i)) {
1348 emitcode("mov","a,b");
1350 emitcode("mov","a,%s",mcs51_regWithIdx(i)->name);
1351 emitcode("movx","@r0,a");
1352 emitcode("inc","r0");
1355 emitcode("mov","%s,r0",spname);
1356 if (bitVectBitValue(rsave,R0_IDX))
1357 emitcode("mov","r0,b");
1359 for (i = 0 ; i < mcs51_nRegs ; i++) {
1360 if (bitVectBitValue(rsave,i))
1361 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
1364 detype = getSpec(operandType(IC_LEFT(ic)));
1366 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1367 IS_ISR(currFunc->etype) &&
1370 saverbank(SPEC_BANK(detype),ic,TRUE);
1373 /*-----------------------------------------------------------------*/
1374 /* unsaveRegisters - pop the pushed registers */
1375 /*-----------------------------------------------------------------*/
1376 static void unsaveRegisters (iCode *ic)
1380 /* find the registers in use at this time
1381 and push them away to safety */
1382 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1385 if (options.useXstack) {
1386 emitcode("mov","r0,%s",spname);
1387 for (i = mcs51_nRegs ; i >= 0 ; i--) {
1388 if (bitVectBitValue(rsave,i)) {
1389 emitcode("dec","r0");
1390 emitcode("movx","a,@r0");
1392 emitcode("mov","b,a");
1394 emitcode("mov","%s,a",mcs51_regWithIdx(i)->name);
1398 emitcode("mov","%s,r0",spname);
1399 if (bitVectBitValue(rsave,R0_IDX))
1400 emitcode("mov","r0,b");
1402 for (i = mcs51_nRegs ; i >= 0 ; i--) {
1403 if (bitVectBitValue(rsave,i))
1404 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
1410 /*-----------------------------------------------------------------*/
1412 /*-----------------------------------------------------------------*/
1413 static void pushSide(operand * oper, int size)
1417 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1418 if (AOP_TYPE(oper) != AOP_REG &&
1419 AOP_TYPE(oper) != AOP_DIR &&
1421 emitcode("mov","a,%s",l);
1422 emitcode("push","acc");
1424 emitcode("push","%s",l);
1428 /*-----------------------------------------------------------------*/
1429 /* assignResultValue - */
1430 /*-----------------------------------------------------------------*/
1431 static void assignResultValue(operand * oper)
1434 int size = AOP_SIZE(oper);
1436 aopPut(AOP(oper),fReturn[offset],offset);
1442 /*-----------------------------------------------------------------*/
1443 /* genXpush - pushes onto the external stack */
1444 /*-----------------------------------------------------------------*/
1445 static void genXpush (iCode *ic)
1447 asmop *aop = newAsmop(0);
1449 int size,offset = 0;
1451 aopOp(IC_LEFT(ic),ic,FALSE);
1452 r = getFreePtr(ic,&aop,FALSE);
1455 emitcode("mov","%s,_spx",r->name);
1457 size = AOP_SIZE(IC_LEFT(ic));
1460 char *l = aopGet(AOP(IC_LEFT(ic)),
1461 offset++,FALSE,FALSE);
1463 emitcode("movx","@%s,a",r->name);
1464 emitcode("inc","%s",r->name);
1469 emitcode("mov","_spx,%s",r->name);
1471 freeAsmop(NULL,aop,ic,TRUE);
1472 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1475 /*-----------------------------------------------------------------*/
1476 /* genIpush - genrate code for pushing this gets a little complex */
1477 /*-----------------------------------------------------------------*/
1478 static void genIpush (iCode *ic)
1480 int size, offset = 0 ;
1484 /* if this is not a parm push : ie. it is spill push
1485 and spill push is always done on the local stack */
1486 if (!ic->parmPush) {
1488 /* and the item is spilt then do nothing */
1489 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1492 aopOp(IC_LEFT(ic),ic,FALSE);
1493 size = AOP_SIZE(IC_LEFT(ic));
1494 /* push it on the stack */
1496 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1501 emitcode("push","%s",l);
1506 /* this is a paramter push: in this case we call
1507 the routine to find the call and save those
1508 registers that need to be saved */
1511 /* if use external stack then call the external
1512 stack pushing routine */
1513 if (options.useXstack) {
1518 /* then do the push */
1519 aopOp(IC_LEFT(ic),ic,FALSE);
1522 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1523 size = AOP_SIZE(IC_LEFT(ic));
1526 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1527 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1528 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1530 emitcode("mov","a,%s",l);
1531 emitcode("push","acc");
1533 emitcode("push","%s",l);
1536 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1539 /*-----------------------------------------------------------------*/
1540 /* genIpop - recover the registers: can happen only for spilling */
1541 /*-----------------------------------------------------------------*/
1542 static void genIpop (iCode *ic)
1547 /* if the temp was not pushed then */
1548 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1551 aopOp(IC_LEFT(ic),ic,FALSE);
1552 size = AOP_SIZE(IC_LEFT(ic));
1555 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1558 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1561 /*-----------------------------------------------------------------*/
1562 /* unsaverbank - restores the resgister bank from stack */
1563 /*-----------------------------------------------------------------*/
1564 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1571 if (options.useXstack) {
1573 r = getFreePtr(ic,&aop,FALSE);
1576 emitcode("mov","%s,_spx",r->name);
1577 emitcode("movx","a,@%s",r->name);
1578 emitcode("mov","psw,a");
1579 emitcode("dec","%s",r->name);
1582 emitcode ("pop","psw");
1585 for (i = (mcs51_nRegs - 1) ; i >= 0 ;i--) {
1586 if (options.useXstack) {
1587 emitcode("movx","a,@%s",r->name);
1588 emitcode("mov","(%s+%d),a",
1589 regs8051[i].base,8*bank+regs8051[i].offset);
1590 emitcode("dec","%s",r->name);
1593 emitcode("pop","(%s+%d)",
1594 regs8051[i].base,8*bank+regs8051[i].offset);
1597 if (options.useXstack) {
1599 emitcode("mov","_spx,%s",r->name);
1600 freeAsmop(NULL,aop,ic,TRUE);
1605 /*-----------------------------------------------------------------*/
1606 /* saverbank - saves an entire register bank on the stack */
1607 /*-----------------------------------------------------------------*/
1608 static void saverbank (int bank, iCode *ic, bool pushPsw)
1614 if (options.useXstack) {
1617 r = getFreePtr(ic,&aop,FALSE);
1618 emitcode("mov","%s,_spx",r->name);
1622 for (i = 0 ; i < mcs51_nRegs ;i++) {
1623 if (options.useXstack) {
1624 emitcode("inc","%s",r->name);
1625 emitcode("mov","a,(%s+%d)",
1626 regs8051[i].base,8*bank+regs8051[i].offset);
1627 emitcode("movx","@%s,a",r->name);
1629 emitcode("push","(%s+%d)",
1630 regs8051[i].base,8*bank+regs8051[i].offset);
1634 if (options.useXstack) {
1635 emitcode("mov","a,psw");
1636 emitcode("movx","@%s,a",r->name);
1637 emitcode("inc","%s",r->name);
1638 emitcode("mov","_spx,%s",r->name);
1639 freeAsmop (NULL,aop,ic,TRUE);
1642 emitcode("push","psw");
1644 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1650 /*-----------------------------------------------------------------*/
1651 /* genCall - generates a call statement */
1652 /*-----------------------------------------------------------------*/
1653 static void genCall (iCode *ic)
1657 /* if caller saves & we have not saved then */
1661 /* if we are calling a function that is not using
1662 the same register bank then we need to save the
1663 destination registers on the stack */
1664 detype = getSpec(operandType(IC_LEFT(ic)));
1666 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1667 IS_ISR(currFunc->etype) &&
1670 saverbank(SPEC_BANK(detype),ic,TRUE);
1672 /* if send set is not empty the assign */
1676 for (sic = setFirstItem(_G.sendSet) ; sic ;
1677 sic = setNextItem(_G.sendSet)) {
1678 int size, offset = 0;
1679 aopOp(IC_LEFT(sic),sic,FALSE);
1680 size = AOP_SIZE(IC_LEFT(sic));
1682 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1684 if (strcmp(l,fReturn[offset]))
1685 emitcode("mov","%s,%s",
1690 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1695 emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1696 OP_SYMBOL(IC_LEFT(ic))->rname :
1697 OP_SYMBOL(IC_LEFT(ic))->name));
1699 /* if we need assign a result value */
1700 if ((IS_ITEMP(IC_RESULT(ic)) &&
1701 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1702 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1703 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1706 aopOp(IC_RESULT(ic),ic,FALSE);
1709 assignResultValue(IC_RESULT(ic));
1711 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1714 /* adjust the stack for parameters if
1716 if (IC_LEFT(ic)->parmBytes) {
1718 if (IC_LEFT(ic)->parmBytes > 3) {
1719 emitcode("mov","a,%s",spname);
1720 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1721 emitcode("mov","%s,a",spname);
1723 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1724 emitcode("dec","%s",spname);
1728 /* if register bank was saved then pop them */
1730 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1732 /* if we hade saved some registers then unsave them */
1733 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1734 unsaveRegisters (ic);
1739 /*-----------------------------------------------------------------*/
1740 /* genPcall - generates a call by pointer statement */
1741 /*-----------------------------------------------------------------*/
1742 static void genPcall (iCode *ic)
1745 symbol *rlbl = newiTempLabel(NULL);
1748 /* if caller saves & we have not saved then */
1752 /* if we are calling a function that is not using
1753 the same register bank then we need to save the
1754 destination registers on the stack */
1755 detype = getSpec(operandType(IC_LEFT(ic)));
1757 IS_ISR(currFunc->etype) &&
1758 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
1759 saverbank(SPEC_BANK(detype),ic,TRUE);
1762 /* push the return address on to the stack */
1763 emitcode("mov","a,#%05d$",(rlbl->key+100));
1764 emitcode("push","acc");
1765 emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
1766 emitcode("push","acc");
1768 if (options.model == MODEL_FLAT24)
1770 emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
1771 emitcode("push","acc");
1774 /* now push the calling address */
1775 aopOp(IC_LEFT(ic),ic,FALSE);
1777 pushSide(IC_LEFT(ic), FPTRSIZE);
1779 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1781 /* if send set is not empty the assign */
1785 for (sic = setFirstItem(_G.sendSet) ; sic ;
1786 sic = setNextItem(_G.sendSet)) {
1787 int size, offset = 0;
1788 aopOp(IC_LEFT(sic),sic,FALSE);
1789 size = AOP_SIZE(IC_LEFT(sic));
1791 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1793 if (strcmp(l,fReturn[offset]))
1794 emitcode("mov","%s,%s",
1799 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1805 emitcode("","%05d$:",(rlbl->key+100));
1808 /* if we need assign a result value */
1809 if ((IS_ITEMP(IC_RESULT(ic)) &&
1810 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1811 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
1812 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1815 aopOp(IC_RESULT(ic),ic,FALSE);
1818 assignResultValue(IC_RESULT(ic));
1820 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1823 /* adjust the stack for parameters if
1825 if (IC_LEFT(ic)->parmBytes) {
1827 if (IC_LEFT(ic)->parmBytes > 3) {
1828 emitcode("mov","a,%s",spname);
1829 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1830 emitcode("mov","%s,a",spname);
1832 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1833 emitcode("dec","%s",spname);
1837 /* if register bank was saved then unsave them */
1839 (SPEC_BANK(currFunc->etype) !=
1841 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1843 /* if we hade saved some registers then
1846 unsaveRegisters (ic);
1850 /*-----------------------------------------------------------------*/
1851 /* resultRemat - result is rematerializable */
1852 /*-----------------------------------------------------------------*/
1853 static int resultRemat (iCode *ic)
1855 if (SKIP_IC(ic) || ic->op == IFX)
1858 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1859 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1860 if (sym->remat && !POINTER_SET(ic))
1867 /*-----------------------------------------------------------------*/
1868 /* inExcludeList - return 1 if the string is in exclude Reg list */
1869 /*-----------------------------------------------------------------*/
1870 static bool inExcludeList(char *s)
1874 if (options.excludeRegs[i] &&
1875 strcasecmp(options.excludeRegs[i],"none") == 0)
1878 for ( i = 0 ; options.excludeRegs[i]; i++) {
1879 if (options.excludeRegs[i] &&
1880 strcasecmp(s,options.excludeRegs[i]) == 0)
1886 /*-----------------------------------------------------------------*/
1887 /* genFunction - generated code for function entry */
1888 /*-----------------------------------------------------------------*/
1889 static void genFunction (iCode *ic)
1895 /* create the function header */
1896 emitcode(";","-----------------------------------------");
1897 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1898 emitcode(";","-----------------------------------------");
1900 emitcode("","%s:",sym->rname);
1901 fetype = getSpec(operandType(IC_LEFT(ic)));
1903 /* if critical function then turn interrupts off */
1904 if (SPEC_CRTCL(fetype))
1905 emitcode("clr","ea");
1907 /* here we need to generate the equates for the
1908 register bank if required */
1909 if (SPEC_BANK(fetype) != rbank) {
1912 rbank = SPEC_BANK(fetype);
1913 for ( i = 0 ; i < mcs51_nRegs ; i++ ) {
1914 if (strcmp(regs8051[i].base,"0") == 0)
1915 emitcode("","%s = 0x%02x",
1917 8*rbank+regs8051[i].offset);
1919 emitcode ("","%s = %s + 0x%02x",
1922 8*rbank+regs8051[i].offset);
1926 /* if this is an interrupt service routine then
1927 save acc, b, dpl, dph */
1928 if (IS_ISR(sym->etype)) {
1930 if (!inExcludeList("acc"))
1931 emitcode ("push","acc");
1932 if (!inExcludeList("b"))
1933 emitcode ("push","b");
1934 if (!inExcludeList("dpl"))
1935 emitcode ("push","dpl");
1936 if (!inExcludeList("dph"))
1937 emitcode ("push","dph");
1938 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
1939 emitcode ("push", "dpx");
1940 /* if this isr has no bank i.e. is going to
1941 run with bank 0 , then we need to save more
1943 if (!SPEC_BANK(sym->etype)) {
1945 /* if this function does not call any other
1946 function then we can be economical and
1947 save only those registers that are used */
1948 if (! sym->hasFcall) {
1951 /* if any registers used */
1952 if (sym->regsUsed) {
1953 /* save the registers used */
1954 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
1955 if (bitVectBitValue(sym->regsUsed,i) ||
1956 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
1957 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
1962 /* this function has a function call cannot
1963 determines register usage so we will have the
1965 saverbank(0,ic,FALSE);
1969 /* if callee-save to be used for this function
1970 then save the registers being used in this function */
1971 if (sym->calleeSave) {
1974 /* if any registers used */
1975 if (sym->regsUsed) {
1976 /* save the registers used */
1977 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
1978 if (bitVectBitValue(sym->regsUsed,i) ||
1979 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
1980 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
1988 /* set the register bank to the desired value */
1989 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
1990 emitcode("push","psw");
1991 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
1994 if (IS_RENT(sym->etype) || options.stackAuto) {
1996 if (options.useXstack) {
1997 emitcode("mov","r0,%s",spname);
1998 emitcode("mov","a,_bp");
1999 emitcode("movx","@r0,a");
2000 emitcode("inc","%s",spname);
2003 /* set up the stack */
2004 emitcode ("push","_bp"); /* save the callers stack */
2005 emitcode ("mov","_bp,%s",spname);
2008 /* adjust the stack for the function */
2013 werror(W_STACK_OVERFLOW,sym->name);
2015 if (i > 3 && sym->recvSize < 4) {
2017 emitcode ("mov","a,sp");
2018 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2019 emitcode ("mov","sp,a");
2024 emitcode("inc","sp");
2029 emitcode ("mov","a,_spx");
2030 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2031 emitcode ("mov","_spx,a");
2036 /*-----------------------------------------------------------------*/
2037 /* genEndFunction - generates epilogue for functions */
2038 /*-----------------------------------------------------------------*/
2039 static void genEndFunction (iCode *ic)
2041 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2043 if (IS_RENT(sym->etype) || options.stackAuto)
2044 emitcode ("mov","%s,_bp",spname);
2046 /* if use external stack but some variables were
2047 added to the local stack then decrement the
2049 if (options.useXstack && sym->stack) {
2050 emitcode("mov","a,sp");
2051 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2052 emitcode("mov","sp,a");
2056 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2057 if (options.useXstack) {
2058 emitcode("mov","r0,%s",spname);
2059 emitcode("movx","a,@r0");
2060 emitcode("mov","_bp,a");
2061 emitcode("dec","%s",spname);
2064 emitcode ("pop","_bp");
2067 /* restore the register bank */
2068 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2069 emitcode ("pop","psw");
2071 if (IS_ISR(sym->etype)) {
2073 /* now we need to restore the registers */
2074 /* if this isr has no bank i.e. is going to
2075 run with bank 0 , then we need to save more
2077 if (!SPEC_BANK(sym->etype)) {
2079 /* if this function does not call any other
2080 function then we can be economical and
2081 save only those registers that are used */
2082 if (! sym->hasFcall) {
2085 /* if any registers used */
2086 if (sym->regsUsed) {
2087 /* save the registers used */
2088 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2089 if (bitVectBitValue(sym->regsUsed,i) ||
2090 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2091 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
2096 /* this function has a function call cannot
2097 determines register usage so we will have the
2099 unsaverbank(0,ic,FALSE);
2103 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2104 emitcode ("pop", "dpx");
2105 if (!inExcludeList("dph"))
2106 emitcode ("pop","dph");
2107 if (!inExcludeList("dpl"))
2108 emitcode ("pop","dpl");
2109 if (!inExcludeList("b"))
2110 emitcode ("pop","b");
2111 if (!inExcludeList("acc"))
2112 emitcode ("pop","acc");
2114 if (SPEC_CRTCL(sym->etype))
2115 emitcode("setb","ea");
2117 /* if debug then send end of function */
2118 /* if (options.debug && currFunc) { */
2121 emitcode("","C$%s$%d$%d$%d ==.",
2122 ic->filename,currFunc->lastLine,
2123 ic->level,ic->block);
2124 if (IS_STATIC(currFunc->etype))
2125 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2127 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2131 emitcode ("reti","");
2134 if (SPEC_CRTCL(sym->etype))
2135 emitcode("setb","ea");
2137 if (sym->calleeSave) {
2140 /* if any registers used */
2141 if (sym->regsUsed) {
2142 /* save the registers used */
2143 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2144 if (bitVectBitValue(sym->regsUsed,i) ||
2145 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2146 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
2152 /* if debug then send end of function */
2153 /* if (options.debug && currFunc) { */
2156 emitcode("","C$%s$%d$%d$%d ==.",
2157 ic->filename,currFunc->lastLine,
2158 ic->level,ic->block);
2159 if (IS_STATIC(currFunc->etype))
2160 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2162 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2166 emitcode ("ret","");
2171 /*-----------------------------------------------------------------*/
2172 /* genRet - generate code for return statement */
2173 /*-----------------------------------------------------------------*/
2174 static void genRet (iCode *ic)
2176 int size,offset = 0 , pushed = 0;
2178 /* if we have no return value then
2179 just generate the "ret" */
2183 /* we have something to return then
2184 move the return value into place */
2185 aopOp(IC_LEFT(ic),ic,FALSE);
2186 size = AOP_SIZE(IC_LEFT(ic));
2190 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2191 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2193 emitcode("push","%s",l);
2196 l = aopGet(AOP(IC_LEFT(ic)),offset,
2198 if (strcmp(fReturn[offset],l))
2199 emitcode("mov","%s,%s",fReturn[offset++],l);
2206 if (strcmp(fReturn[pushed],"a"))
2207 emitcode("pop",fReturn[pushed]);
2209 emitcode("pop","acc");
2212 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2215 /* generate a jump to the return label
2216 if the next is not the return statement */
2217 if (!(ic->next && ic->next->op == LABEL &&
2218 IC_LABEL(ic->next) == returnLabel))
2220 emitcode("ljmp","%05d$",(returnLabel->key+100));
2224 /*-----------------------------------------------------------------*/
2225 /* genLabel - generates a label */
2226 /*-----------------------------------------------------------------*/
2227 static void genLabel (iCode *ic)
2229 /* special case never generate */
2230 if (IC_LABEL(ic) == entryLabel)
2233 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2236 /*-----------------------------------------------------------------*/
2237 /* genGoto - generates a ljmp */
2238 /*-----------------------------------------------------------------*/
2239 static void genGoto (iCode *ic)
2241 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2244 /*-----------------------------------------------------------------*/
2245 /* genPlusIncr :- does addition with increment if possible */
2246 /*-----------------------------------------------------------------*/
2247 static bool genPlusIncr (iCode *ic)
2249 unsigned int icount ;
2250 unsigned int size = getDataSize(IC_RESULT(ic));
2252 /* will try to generate an increment */
2253 /* if the right side is not a literal
2255 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2258 /* if the literal value of the right hand side
2259 is greater than 4 then it is not worth it */
2260 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2263 /* if increment 16 bits in register */
2264 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2267 symbol *tlbl = newiTempLabel(NULL);
2268 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2269 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2270 IS_AOP_PREG(IC_RESULT(ic)))
2271 emitcode("cjne","%s,#0x00,%05d$"
2272 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2275 emitcode("clr","a");
2276 emitcode("cjne","a,%s,%05d$"
2277 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2281 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2284 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2285 IS_AOP_PREG(IC_RESULT(ic)))
2286 emitcode("cjne","%s,#0x00,%05d$"
2287 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2290 emitcode("cjne","a,%s,%05d$"
2291 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2294 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2298 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2299 IS_AOP_PREG(IC_RESULT(ic)))
2300 emitcode("cjne","%s,#0x00,%05d$"
2301 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2304 emitcode("cjne","a,%s,%05d$"
2305 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2308 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2310 emitcode("","%05d$:",tlbl->key+100);
2314 /* if the sizes are greater than 1 then we cannot */
2315 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2316 AOP_SIZE(IC_LEFT(ic)) > 1 )
2319 /* we can if the aops of the left & result match or
2320 if they are in registers and the registers are the
2322 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2325 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2326 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2327 aopPut(AOP(IC_RESULT(ic)),"a",0);
2331 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2340 /*-----------------------------------------------------------------*/
2341 /* outBitAcc - output a bit in acc */
2342 /*-----------------------------------------------------------------*/
2343 static void outBitAcc(operand *result)
2345 symbol *tlbl = newiTempLabel(NULL);
2346 /* if the result is a bit */
2347 if (AOP_TYPE(result) == AOP_CRY){
2348 aopPut(AOP(result),"a",0);
2351 emitcode("jz","%05d$",tlbl->key+100);
2352 emitcode("mov","a,%s",one);
2353 emitcode("","%05d$:",tlbl->key+100);
2358 /*-----------------------------------------------------------------*/
2359 /* genPlusBits - generates code for addition of two bits */
2360 /*-----------------------------------------------------------------*/
2361 static void genPlusBits (iCode *ic)
2363 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2364 symbol *lbl = newiTempLabel(NULL);
2365 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2366 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2367 emitcode("cpl","c");
2368 emitcode("","%05d$:",(lbl->key+100));
2369 outBitC(IC_RESULT(ic));
2372 emitcode("clr","a");
2373 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2374 emitcode("rlc","a");
2375 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2376 emitcode("addc","a,#0x00");
2377 outAcc(IC_RESULT(ic));
2382 /* This is the original version of this code.
2384 * This is being kept around for reference,
2385 * because I am not entirely sure I got it right...
2387 static void adjustArithmeticResult(iCode *ic)
2389 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2390 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2391 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2392 aopPut(AOP(IC_RESULT(ic)),
2393 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2396 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2397 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
2398 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2399 aopPut(AOP(IC_RESULT(ic)),
2400 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2403 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2404 AOP_SIZE(IC_LEFT(ic)) < 3 &&
2405 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
2406 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2407 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2409 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2410 aopPut(AOP(IC_RESULT(ic)),buffer,2);
2414 /* This is the pure and virtuous version of this code.
2415 * I'm pretty certain it's right, but not enough to toss the old
2418 static void adjustArithmeticResult(iCode *ic)
2420 if (opIsGptr(IC_RESULT(ic)) &&
2421 opIsGptr(IC_LEFT(ic)) &&
2422 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2424 aopPut(AOP(IC_RESULT(ic)),
2425 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
2429 if (opIsGptr(IC_RESULT(ic)) &&
2430 opIsGptr(IC_RIGHT(ic)) &&
2431 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2433 aopPut(AOP(IC_RESULT(ic)),
2434 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
2438 if (opIsGptr(IC_RESULT(ic)) &&
2439 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2440 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2441 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2442 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2444 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2445 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2450 /*-----------------------------------------------------------------*/
2451 /* genPlus - generates code for addition */
2452 /*-----------------------------------------------------------------*/
2453 static void genPlus (iCode *ic)
2455 int size, offset = 0;
2457 /* special cases :- */
2459 aopOp (IC_LEFT(ic),ic,FALSE);
2460 aopOp (IC_RIGHT(ic),ic,FALSE);
2461 aopOp (IC_RESULT(ic),ic,TRUE);
2463 /* if literal, literal on the right or
2464 if left requires ACC or right is already
2466 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2467 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2468 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2469 operand *t = IC_RIGHT(ic);
2470 IC_RIGHT(ic) = IC_LEFT(ic);
2474 /* if both left & right are in bit
2476 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2477 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2482 /* if left in bit space & right literal */
2483 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2484 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2485 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2486 /* if result in bit space */
2487 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2488 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
2489 emitcode("cpl","c");
2490 outBitC(IC_RESULT(ic));
2492 size = getDataSize(IC_RESULT(ic));
2494 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2495 emitcode("addc","a,#00");
2496 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2502 /* if I can do an increment instead
2503 of add then GOOD for ME */
2504 if (genPlusIncr (ic) == TRUE)
2507 size = getDataSize(IC_RESULT(ic));
2510 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2511 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2513 emitcode("add","a,%s",
2514 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2516 emitcode("addc","a,%s",
2517 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2519 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2521 emitcode("add","a,%s",
2522 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2524 emitcode("addc","a,%s",
2525 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2527 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2530 adjustArithmeticResult(ic);
2533 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2534 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2535 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2538 /*-----------------------------------------------------------------*/
2539 /* genMinusDec :- does subtraction with deccrement if possible */
2540 /*-----------------------------------------------------------------*/
2541 static bool genMinusDec (iCode *ic)
2543 unsigned int icount ;
2544 unsigned int size = getDataSize(IC_RESULT(ic));
2546 /* will try to generate an increment */
2547 /* if the right side is not a literal
2549 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2552 /* if the literal value of the right hand side
2553 is greater than 4 then it is not worth it */
2554 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2557 size = getDataSize(IC_RESULT(ic));
2558 /* if decrement 16 bits in register */
2559 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2562 symbol *tlbl = newiTempLabel(NULL);
2563 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2564 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2565 IS_AOP_PREG(IC_RESULT(ic)))
2566 emitcode("cjne","%s,#0xff,%05d$"
2567 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2570 emitcode("mov","a,#0xff");
2571 emitcode("cjne","a,%s,%05d$"
2572 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2575 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2578 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2579 IS_AOP_PREG(IC_RESULT(ic)))
2580 emitcode("cjne","%s,#0xff,%05d$"
2581 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2584 emitcode("cjne","a,%s,%05d$"
2585 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2588 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2592 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2593 IS_AOP_PREG(IC_RESULT(ic)))
2594 emitcode("cjne","%s,#0xff,%05d$"
2595 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2598 emitcode("cjne","a,%s,%05d$"
2599 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2602 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2604 emitcode("","%05d$:",tlbl->key+100);
2608 /* if the sizes are greater than 1 then we cannot */
2609 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2610 AOP_SIZE(IC_LEFT(ic)) > 1 )
2613 /* we can if the aops of the left & result match or
2614 if they are in registers and the registers are the
2616 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2619 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2627 /*-----------------------------------------------------------------*/
2628 /* addSign - complete with sign */
2629 /*-----------------------------------------------------------------*/
2630 static void addSign(operand *result, int offset, int sign)
2632 int size = (getDataSize(result) - offset);
2635 emitcode("rlc","a");
2636 emitcode("subb","a,acc");
2638 aopPut(AOP(result),"a",offset++);
2641 aopPut(AOP(result),zero,offset++);
2645 /*-----------------------------------------------------------------*/
2646 /* genMinusBits - generates code for subtraction of two bits */
2647 /*-----------------------------------------------------------------*/
2648 static void genMinusBits (iCode *ic)
2650 symbol *lbl = newiTempLabel(NULL);
2651 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2652 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2653 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2654 emitcode("cpl","c");
2655 emitcode("","%05d$:",(lbl->key+100));
2656 outBitC(IC_RESULT(ic));
2659 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2660 emitcode("subb","a,acc");
2661 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
2662 emitcode("inc","a");
2663 emitcode("","%05d$:",(lbl->key+100));
2664 aopPut(AOP(IC_RESULT(ic)),"a",0);
2665 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
2669 /*-----------------------------------------------------------------*/
2670 /* genMinus - generates code for subtraction */
2671 /*-----------------------------------------------------------------*/
2672 static void genMinus (iCode *ic)
2674 int size, offset = 0;
2675 unsigned long lit = 0L;
2677 aopOp (IC_LEFT(ic),ic,FALSE);
2678 aopOp (IC_RIGHT(ic),ic,FALSE);
2679 aopOp (IC_RESULT(ic),ic,TRUE);
2681 /* special cases :- */
2682 /* if both left & right are in bit space */
2683 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2684 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2689 /* if I can do an decrement instead
2690 of subtract then GOOD for ME */
2691 if (genMinusDec (ic) == TRUE)
2694 size = getDataSize(IC_RESULT(ic));
2696 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
2700 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2704 /* if literal, add a,#-lit, else normal subb */
2706 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2707 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2708 emitcode("subb","a,%s",
2709 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2711 /* first add without previous c */
2713 emitcode("add","a,#0x%02x",
2714 (unsigned int)(lit & 0x0FFL));
2716 emitcode("addc","a,#0x%02x",
2717 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
2719 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2722 adjustArithmeticResult(ic);
2725 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2726 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2727 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2731 /*-----------------------------------------------------------------*/
2732 /* genMultbits :- multiplication of bits */
2733 /*-----------------------------------------------------------------*/
2734 static void genMultbits (operand *left,
2738 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2739 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
2744 /*-----------------------------------------------------------------*/
2745 /* genMultOneByte : 8 bit multiplication & division */
2746 /*-----------------------------------------------------------------*/
2747 static void genMultOneByte (operand *left,
2751 link *opetype = operandType(result);
2756 /* (if two literals, the value is computed before) */
2757 /* if one literal, literal on the right */
2758 if (AOP_TYPE(left) == AOP_LIT){
2764 size = AOP_SIZE(result);
2765 /* signed or unsigned */
2766 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2767 l = aopGet(AOP(left),0,FALSE,FALSE);
2769 emitcode("mul","ab");
2770 /* if result size = 1, mul signed = mul unsigned */
2771 aopPut(AOP(result),"a",0);
2773 if (SPEC_USIGN(opetype)){
2774 aopPut(AOP(result),"b",1);
2776 /* for filling the MSBs */
2777 emitcode("clr","a");
2780 emitcode("mov","a,b");
2782 /* adjust the MSB if left or right neg */
2784 /* if one literal */
2785 if (AOP_TYPE(right) == AOP_LIT){
2786 /* AND literal negative */
2787 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
2788 /* adjust MSB (c==0 after mul) */
2789 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2793 lbl = newiTempLabel(NULL);
2794 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2795 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
2796 emitcode("","%05d$:",(lbl->key+100));
2797 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2798 lbl = newiTempLabel(NULL);
2799 emitcode("jc","%05d$",(lbl->key+100));
2800 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2801 emitcode("","%05d$:",(lbl->key+100));
2804 lbl = newiTempLabel(NULL);
2805 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
2806 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
2807 emitcode("","%05d$:",(lbl->key+100));
2808 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
2809 lbl = newiTempLabel(NULL);
2810 emitcode("jc","%05d$",(lbl->key+100));
2811 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
2812 emitcode("","%05d$:",(lbl->key+100));
2814 aopPut(AOP(result),"a",1);
2817 emitcode("rlc","a");
2818 emitcode("subb","a,acc");
2825 aopPut(AOP(result),"a",offset++);
2829 /*-----------------------------------------------------------------*/
2830 /* genMult - generates code for multiplication */
2831 /*-----------------------------------------------------------------*/
2832 static void genMult (iCode *ic)
2834 operand *left = IC_LEFT(ic);
2835 operand *right = IC_RIGHT(ic);
2836 operand *result= IC_RESULT(ic);
2838 /* assign the amsops */
2839 aopOp (left,ic,FALSE);
2840 aopOp (right,ic,FALSE);
2841 aopOp (result,ic,TRUE);
2843 /* special cases first */
2845 if (AOP_TYPE(left) == AOP_CRY &&
2846 AOP_TYPE(right)== AOP_CRY) {
2847 genMultbits(left,right,result);
2851 /* if both are of size == 1 */
2852 if (AOP_SIZE(left) == 1 &&
2853 AOP_SIZE(right) == 1 ) {
2854 genMultOneByte(left,right,result);
2858 /* should have been converted to function call */
2862 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2863 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2864 freeAsmop(result,NULL,ic,TRUE);
2867 /*-----------------------------------------------------------------*/
2868 /* genDivbits :- division of bits */
2869 /*-----------------------------------------------------------------*/
2870 static void genDivbits (operand *left,
2877 /* the result must be bit */
2878 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
2879 l = aopGet(AOP(left),0,FALSE,FALSE);
2883 emitcode("div","ab");
2884 emitcode("rrc","a");
2885 aopPut(AOP(result),"c",0);
2888 /*-----------------------------------------------------------------*/
2889 /* genDivOneByte : 8 bit division */
2890 /*-----------------------------------------------------------------*/
2891 static void genDivOneByte (operand *left,
2895 link *opetype = operandType(result);
2900 size = AOP_SIZE(result) - 1;
2902 /* signed or unsigned */
2903 if (SPEC_USIGN(opetype)) {
2904 /* unsigned is easy */
2905 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2906 l = aopGet(AOP(left),0,FALSE,FALSE);
2908 emitcode("div","ab");
2909 aopPut(AOP(result),"a",0);
2911 aopPut(AOP(result),zero,offset++);
2915 /* signed is a little bit more difficult */
2917 /* save the signs of the operands */
2918 l = aopGet(AOP(left),0,FALSE,FALSE);
2920 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
2921 emitcode("push","acc"); /* save it on the stack */
2923 /* now sign adjust for both left & right */
2924 l = aopGet(AOP(right),0,FALSE,FALSE);
2926 lbl = newiTempLabel(NULL);
2927 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
2928 emitcode("cpl","a");
2929 emitcode("inc","a");
2930 emitcode("","%05d$:",(lbl->key+100));
2931 emitcode("mov","b,a");
2933 /* sign adjust left side */
2934 l = aopGet(AOP(left),0,FALSE,FALSE);
2937 lbl = newiTempLabel(NULL);
2938 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
2939 emitcode("cpl","a");
2940 emitcode("inc","a");
2941 emitcode("","%05d$:",(lbl->key+100));
2943 /* now the division */
2944 emitcode("div","ab");
2945 /* we are interested in the lower order
2947 emitcode("mov","b,a");
2948 lbl = newiTempLabel(NULL);
2949 emitcode("pop","acc");
2950 /* if there was an over flow we don't
2951 adjust the sign of the result */
2952 emitcode("jb","ov,%05d$",(lbl->key+100));
2953 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
2955 emitcode("clr","a");
2956 emitcode("subb","a,b");
2957 emitcode("mov","b,a");
2958 emitcode("","%05d$:",(lbl->key+100));
2960 /* now we are done */
2961 aopPut(AOP(result),"b",0);
2963 emitcode("mov","c,b.7");
2964 emitcode("subb","a,acc");
2967 aopPut(AOP(result),"a",offset++);
2971 /*-----------------------------------------------------------------*/
2972 /* genDiv - generates code for division */
2973 /*-----------------------------------------------------------------*/
2974 static void genDiv (iCode *ic)
2976 operand *left = IC_LEFT(ic);
2977 operand *right = IC_RIGHT(ic);
2978 operand *result= IC_RESULT(ic);
2980 /* assign the amsops */
2981 aopOp (left,ic,FALSE);
2982 aopOp (right,ic,FALSE);
2983 aopOp (result,ic,TRUE);
2985 /* special cases first */
2987 if (AOP_TYPE(left) == AOP_CRY &&
2988 AOP_TYPE(right)== AOP_CRY) {
2989 genDivbits(left,right,result);
2993 /* if both are of size == 1 */
2994 if (AOP_SIZE(left) == 1 &&
2995 AOP_SIZE(right) == 1 ) {
2996 genDivOneByte(left,right,result);
3000 /* should have been converted to function call */
3003 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3004 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3005 freeAsmop(result,NULL,ic,TRUE);
3008 /*-----------------------------------------------------------------*/
3009 /* genModbits :- modulus of bits */
3010 /*-----------------------------------------------------------------*/
3011 static void genModbits (operand *left,
3018 /* the result must be bit */
3019 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3020 l = aopGet(AOP(left),0,FALSE,FALSE);
3024 emitcode("div","ab");
3025 emitcode("mov","a,b");
3026 emitcode("rrc","a");
3027 aopPut(AOP(result),"c",0);
3030 /*-----------------------------------------------------------------*/
3031 /* genModOneByte : 8 bit modulus */
3032 /*-----------------------------------------------------------------*/
3033 static void genModOneByte (operand *left,
3037 link *opetype = operandType(result);
3041 /* signed or unsigned */
3042 if (SPEC_USIGN(opetype)) {
3043 /* unsigned is easy */
3044 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3045 l = aopGet(AOP(left),0,FALSE,FALSE);
3047 emitcode("div","ab");
3048 aopPut(AOP(result),"b",0);
3052 /* signed is a little bit more difficult */
3054 /* save the signs of the operands */
3055 l = aopGet(AOP(left),0,FALSE,FALSE);
3058 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3059 emitcode("push","acc"); /* save it on the stack */
3061 /* now sign adjust for both left & right */
3062 l = aopGet(AOP(right),0,FALSE,FALSE);
3065 lbl = newiTempLabel(NULL);
3066 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3067 emitcode("cpl","a");
3068 emitcode("inc","a");
3069 emitcode("","%05d$:",(lbl->key+100));
3070 emitcode("mov","b,a");
3072 /* sign adjust left side */
3073 l = aopGet(AOP(left),0,FALSE,FALSE);
3076 lbl = newiTempLabel(NULL);
3077 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3078 emitcode("cpl","a");
3079 emitcode("inc","a");
3080 emitcode("","%05d$:",(lbl->key+100));
3082 /* now the multiplication */
3083 emitcode("div","ab");
3084 /* we are interested in the lower order
3086 lbl = newiTempLabel(NULL);
3087 emitcode("pop","acc");
3088 /* if there was an over flow we don't
3089 adjust the sign of the result */
3090 emitcode("jb","ov,%05d$",(lbl->key+100));
3091 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3093 emitcode("clr","a");
3094 emitcode("subb","a,b");
3095 emitcode("mov","b,a");
3096 emitcode("","%05d$:",(lbl->key+100));
3098 /* now we are done */
3099 aopPut(AOP(result),"b",0);
3103 /*-----------------------------------------------------------------*/
3104 /* genMod - generates code for division */
3105 /*-----------------------------------------------------------------*/
3106 static void genMod (iCode *ic)
3108 operand *left = IC_LEFT(ic);
3109 operand *right = IC_RIGHT(ic);
3110 operand *result= IC_RESULT(ic);
3112 /* assign the amsops */
3113 aopOp (left,ic,FALSE);
3114 aopOp (right,ic,FALSE);
3115 aopOp (result,ic,TRUE);
3117 /* special cases first */
3119 if (AOP_TYPE(left) == AOP_CRY &&
3120 AOP_TYPE(right)== AOP_CRY) {
3121 genModbits(left,right,result);
3125 /* if both are of size == 1 */
3126 if (AOP_SIZE(left) == 1 &&
3127 AOP_SIZE(right) == 1 ) {
3128 genModOneByte(left,right,result);
3132 /* should have been converted to function call */
3136 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3137 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3138 freeAsmop(result,NULL,ic,TRUE);
3141 /*-----------------------------------------------------------------*/
3142 /* genIfxJump :- will create a jump depending on the ifx */
3143 /*-----------------------------------------------------------------*/
3144 static void genIfxJump (iCode *ic, char *jval)
3147 symbol *tlbl = newiTempLabel(NULL);
3150 /* if true label then we jump if condition
3152 if ( IC_TRUE(ic) ) {
3154 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3155 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3158 /* false label is present */
3159 jlbl = IC_FALSE(ic) ;
3160 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3161 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3163 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3164 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3166 emitcode(inst,"%05d$",tlbl->key+100);
3167 emitcode("ljmp","%05d$",jlbl->key+100);
3168 emitcode("","%05d$:",tlbl->key+100);
3170 /* mark the icode as generated */
3174 /*-----------------------------------------------------------------*/
3175 /* genCmp :- greater or less than comparison */
3176 /*-----------------------------------------------------------------*/
3177 static void genCmp (operand *left,operand *right,
3178 operand *result, iCode *ifx, int sign)
3180 int size, offset = 0 ;
3181 unsigned long lit = 0L;
3183 /* if left & right are bit variables */
3184 if (AOP_TYPE(left) == AOP_CRY &&
3185 AOP_TYPE(right) == AOP_CRY ) {
3186 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3187 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3189 /* subtract right from left if at the
3190 end the carry flag is set then we know that
3191 left is greater than right */
3192 size = max(AOP_SIZE(left),AOP_SIZE(right));
3194 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3195 if((size == 1) && !sign &&
3196 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3197 symbol *lbl = newiTempLabel(NULL);
3198 emitcode("cjne","%s,%s,%05d$",
3199 aopGet(AOP(left),offset,FALSE,FALSE),
3200 aopGet(AOP(right),offset,FALSE,FALSE),
3202 emitcode("","%05d$:",lbl->key+100);
3204 if(AOP_TYPE(right) == AOP_LIT){
3205 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3206 /* optimize if(x < 0) or if(x >= 0) */
3212 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE));
3213 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3214 genIfxJump (ifx,"acc.7");
3218 emitcode("rlc","a");
3225 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3226 if (sign && size == 0) {
3227 emitcode("xrl","a,#0x80");
3228 if (AOP_TYPE(right) == AOP_LIT){
3229 unsigned long lit = (unsigned long)
3230 floatFromVal(AOP(right)->aopu.aop_lit);
3231 emitcode("subb","a,#0x%02x",
3232 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3234 emitcode("mov","b,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3235 emitcode("xrl","b,#0x80");
3236 emitcode("subb","a,b");
3239 emitcode("subb","a,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3245 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3248 /* if the result is used in the next
3249 ifx conditional branch then generate
3250 code a little differently */
3252 genIfxJump (ifx,"c");
3255 /* leave the result in acc */
3259 /*-----------------------------------------------------------------*/
3260 /* genCmpGt :- greater than comparison */
3261 /*-----------------------------------------------------------------*/
3262 static void genCmpGt (iCode *ic, iCode *ifx)
3264 operand *left, *right, *result;
3265 link *letype , *retype;
3269 right= IC_RIGHT(ic);
3270 result = IC_RESULT(ic);
3272 letype = getSpec(operandType(left));
3273 retype =getSpec(operandType(right));
3274 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3275 /* assign the amsops */
3276 aopOp (left,ic,FALSE);
3277 aopOp (right,ic,FALSE);
3278 aopOp (result,ic,TRUE);
3280 genCmp(right, left, result, ifx, sign);
3282 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3283 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3284 freeAsmop(result,NULL,ic,TRUE);
3287 /*-----------------------------------------------------------------*/
3288 /* genCmpLt - less than comparisons */
3289 /*-----------------------------------------------------------------*/
3290 static void genCmpLt (iCode *ic, iCode *ifx)
3292 operand *left, *right, *result;
3293 link *letype , *retype;
3297 right= IC_RIGHT(ic);
3298 result = IC_RESULT(ic);
3300 letype = getSpec(operandType(left));
3301 retype =getSpec(operandType(right));
3302 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3304 /* assign the amsops */
3305 aopOp (left,ic,FALSE);
3306 aopOp (right,ic,FALSE);
3307 aopOp (result,ic,TRUE);
3309 genCmp(left, right, result, ifx, sign);
3311 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3312 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3313 freeAsmop(result,NULL,ic,TRUE);
3316 /*-----------------------------------------------------------------*/
3317 /* gencjneshort - compare and jump if not equal */
3318 /*-----------------------------------------------------------------*/
3319 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3321 int size = max(AOP_SIZE(left),AOP_SIZE(right));
3323 unsigned long lit = 0L;
3325 /* if the left side is a literal or
3326 if the right is in a pointer register and left
3328 if ((AOP_TYPE(left) == AOP_LIT) ||
3329 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3334 if(AOP_TYPE(right) == AOP_LIT)
3335 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3337 /* if the right side is a literal then anything goes */
3338 if (AOP_TYPE(right) == AOP_LIT &&
3339 AOP_TYPE(left) != AOP_DIR ) {
3341 emitcode("cjne","%s,%s,%05d$",
3342 aopGet(AOP(left),offset,FALSE,FALSE),
3343 aopGet(AOP(right),offset,FALSE,FALSE),
3349 /* if the right side is in a register or in direct space or
3350 if the left is a pointer register & right is not */
3351 else if (AOP_TYPE(right) == AOP_REG ||
3352 AOP_TYPE(right) == AOP_DIR ||
3353 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3354 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3356 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3357 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3358 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
3359 emitcode("jnz","%05d$",lbl->key+100);
3361 emitcode("cjne","a,%s,%05d$",
3362 aopGet(AOP(right),offset,FALSE,TRUE),
3367 /* right is a pointer reg need both a & b */
3369 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
3371 emitcode("mov","b,%s",l);
3372 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3373 emitcode("cjne","a,b,%05d$",lbl->key+100);
3379 /*-----------------------------------------------------------------*/
3380 /* gencjne - compare and jump if not equal */
3381 /*-----------------------------------------------------------------*/
3382 static void gencjne(operand *left, operand *right, symbol *lbl)
3384 symbol *tlbl = newiTempLabel(NULL);
3386 gencjneshort(left, right, lbl);
3388 emitcode("mov","a,%s",one);
3389 emitcode("sjmp","%05d$",tlbl->key+100);
3390 emitcode("","%05d$:",lbl->key+100);
3391 emitcode("clr","a");
3392 emitcode("","%05d$:",tlbl->key+100);
3395 /*-----------------------------------------------------------------*/
3396 /* genCmpEq - generates code for equal to */
3397 /*-----------------------------------------------------------------*/
3398 static void genCmpEq (iCode *ic, iCode *ifx)
3400 operand *left, *right, *result;
3402 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3403 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3404 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3406 /* if literal, literal on the right or
3407 if the right is in a pointer register and left
3409 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
3410 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3411 operand *t = IC_RIGHT(ic);
3412 IC_RIGHT(ic) = IC_LEFT(ic);
3416 if(ifx && !AOP_SIZE(result)){
3418 /* if they are both bit variables */
3419 if (AOP_TYPE(left) == AOP_CRY &&
3420 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3421 if(AOP_TYPE(right) == AOP_LIT){
3422 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3424 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3425 emitcode("cpl","c");
3426 } else if(lit == 1L) {
3427 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3429 emitcode("clr","c");
3431 /* AOP_TYPE(right) == AOP_CRY */
3433 symbol *lbl = newiTempLabel(NULL);
3434 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3435 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3436 emitcode("cpl","c");
3437 emitcode("","%05d$:",(lbl->key+100));
3439 /* if true label then we jump if condition
3441 tlbl = newiTempLabel(NULL);
3442 if ( IC_TRUE(ifx) ) {
3443 emitcode("jnc","%05d$",tlbl->key+100);
3444 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3446 emitcode("jc","%05d$",tlbl->key+100);
3447 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3449 emitcode("","%05d$:",tlbl->key+100);
3451 tlbl = newiTempLabel(NULL);
3452 gencjneshort(left, right, tlbl);
3453 if ( IC_TRUE(ifx) ) {
3454 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3455 emitcode("","%05d$:",tlbl->key+100);
3457 symbol *lbl = newiTempLabel(NULL);
3458 emitcode("sjmp","%05d$",lbl->key+100);
3459 emitcode("","%05d$:",tlbl->key+100);
3460 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3461 emitcode("","%05d$:",lbl->key+100);
3464 /* mark the icode as generated */
3469 /* if they are both bit variables */
3470 if (AOP_TYPE(left) == AOP_CRY &&
3471 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3472 if(AOP_TYPE(right) == AOP_LIT){
3473 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3475 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3476 emitcode("cpl","c");
3477 } else if(lit == 1L) {
3478 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3480 emitcode("clr","c");
3482 /* AOP_TYPE(right) == AOP_CRY */
3484 symbol *lbl = newiTempLabel(NULL);
3485 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3486 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3487 emitcode("cpl","c");
3488 emitcode("","%05d$:",(lbl->key+100));
3491 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
3496 genIfxJump (ifx,"c");
3499 /* if the result is used in an arithmetic operation
3500 then put the result in place */
3503 gencjne(left,right,newiTempLabel(NULL));
3504 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3505 aopPut(AOP(result),"a",0);
3509 genIfxJump (ifx,"a");
3512 /* if the result is used in an arithmetic operation
3513 then put the result in place */
3514 if (AOP_TYPE(result) != AOP_CRY)
3516 /* leave the result in acc */
3520 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3521 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3522 freeAsmop(result,NULL,ic,TRUE);
3525 /*-----------------------------------------------------------------*/
3526 /* ifxForOp - returns the icode containing the ifx for operand */
3527 /*-----------------------------------------------------------------*/
3528 static iCode *ifxForOp ( operand *op, iCode *ic )
3530 /* if true symbol then needs to be assigned */
3531 if (IS_TRUE_SYMOP(op))
3534 /* if this has register type condition and
3535 the next instruction is ifx with the same operand
3536 and live to of the operand is upto the ifx only then */
3538 ic->next->op == IFX &&
3539 IC_COND(ic->next)->key == op->key &&
3540 OP_SYMBOL(op)->liveTo <= ic->next->seq )
3545 /*-----------------------------------------------------------------*/
3546 /* genAndOp - for && operation */
3547 /*-----------------------------------------------------------------*/
3548 static void genAndOp (iCode *ic)
3550 operand *left,*right, *result;
3553 /* note here that && operations that are in an
3554 if statement are taken away by backPatchLabels
3555 only those used in arthmetic operations remain */
3556 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3557 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3558 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3560 /* if both are bit variables */
3561 if (AOP_TYPE(left) == AOP_CRY &&
3562 AOP_TYPE(right) == AOP_CRY ) {
3563 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3564 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3567 tlbl = newiTempLabel(NULL);
3569 emitcode("jz","%05d$",tlbl->key+100);
3571 emitcode("","%05d$:",tlbl->key+100);
3575 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3576 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3577 freeAsmop(result,NULL,ic,TRUE);
3581 /*-----------------------------------------------------------------*/
3582 /* genOrOp - for || operation */
3583 /*-----------------------------------------------------------------*/
3584 static void genOrOp (iCode *ic)
3586 operand *left,*right, *result;
3589 /* note here that || operations that are in an
3590 if statement are taken away by backPatchLabels
3591 only those used in arthmetic operations remain */
3592 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3593 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3594 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3596 /* if both are bit variables */
3597 if (AOP_TYPE(left) == AOP_CRY &&
3598 AOP_TYPE(right) == AOP_CRY ) {
3599 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3600 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
3603 tlbl = newiTempLabel(NULL);
3605 emitcode("jnz","%05d$",tlbl->key+100);
3607 emitcode("","%05d$:",tlbl->key+100);
3611 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3612 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3613 freeAsmop(result,NULL,ic,TRUE);
3616 /*-----------------------------------------------------------------*/
3617 /* isLiteralBit - test if lit == 2^n */
3618 /*-----------------------------------------------------------------*/
3619 static int isLiteralBit(unsigned long lit)
3621 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
3622 0x100L,0x200L,0x400L,0x800L,
3623 0x1000L,0x2000L,0x4000L,0x8000L,
3624 0x10000L,0x20000L,0x40000L,0x80000L,
3625 0x100000L,0x200000L,0x400000L,0x800000L,
3626 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
3627 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
3630 for(idx = 0; idx < 32; idx++)
3636 /*-----------------------------------------------------------------*/
3637 /* continueIfTrue - */
3638 /*-----------------------------------------------------------------*/
3639 static void continueIfTrue (iCode *ic)
3642 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3646 /*-----------------------------------------------------------------*/
3648 /*-----------------------------------------------------------------*/
3649 static void jumpIfTrue (iCode *ic)
3652 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3656 /*-----------------------------------------------------------------*/
3657 /* jmpTrueOrFalse - */
3658 /*-----------------------------------------------------------------*/
3659 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
3661 // ugly but optimized by peephole
3663 symbol *nlbl = newiTempLabel(NULL);
3664 emitcode("sjmp","%05d$",nlbl->key+100);
3665 emitcode("","%05d$:",tlbl->key+100);
3666 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3667 emitcode("","%05d$:",nlbl->key+100);
3670 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3671 emitcode("","%05d$:",tlbl->key+100);
3676 /*-----------------------------------------------------------------*/
3677 /* genAnd - code for and */
3678 /*-----------------------------------------------------------------*/
3679 static void genAnd (iCode *ic, iCode *ifx)
3681 operand *left, *right, *result;
3683 unsigned long lit = 0L;
3687 aopOp((left = IC_LEFT(ic)),ic,FALSE);
3688 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3689 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3692 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3694 AOP_TYPE(left), AOP_TYPE(right));
3695 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3697 AOP_SIZE(left), AOP_SIZE(right));
3700 /* if left is a literal & right is not then exchange them */
3701 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3702 AOP_NEEDSACC(left)) {
3703 operand *tmp = right ;
3708 /* if result = right then exchange them */
3709 if(sameRegs(AOP(result),AOP(right))){
3710 operand *tmp = right ;
3715 /* if right is bit then exchange them */
3716 if (AOP_TYPE(right) == AOP_CRY &&
3717 AOP_TYPE(left) != AOP_CRY){
3718 operand *tmp = right ;
3722 if(AOP_TYPE(right) == AOP_LIT)
3723 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3725 size = AOP_SIZE(result);
3728 // result = bit & yy;
3729 if (AOP_TYPE(left) == AOP_CRY){
3730 // c = bit & literal;
3731 if(AOP_TYPE(right) == AOP_LIT){
3733 if(size && sameRegs(AOP(result),AOP(left)))
3736 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3739 if(size && (AOP_TYPE(result) == AOP_CRY)){
3740 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
3743 if((AOP_TYPE(result) == AOP_CRY) && ifx){
3747 emitcode("clr","c");
3750 if (AOP_TYPE(right) == AOP_CRY){
3752 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3753 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3756 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
3758 emitcode("rrc","a");
3759 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3767 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
3768 genIfxJump(ifx, "c");
3772 // if(val & 0xZZ) - size = 0, ifx != FALSE -
3773 // bit = val & 0xZZ - size = 1, ifx = FALSE -
3774 if((AOP_TYPE(right) == AOP_LIT) &&
3775 (AOP_TYPE(result) == AOP_CRY) &&
3776 (AOP_TYPE(left) != AOP_CRY)){
3777 int posbit = isLiteralBit(lit);
3781 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
3784 emitcode("mov","c,acc.%d",posbit&0x07);
3788 sprintf(buffer,"acc.%d",posbit&0x07);
3789 genIfxJump(ifx, buffer);
3794 symbol *tlbl = newiTempLabel(NULL);
3795 int sizel = AOP_SIZE(left);
3797 emitcode("setb","c");
3799 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
3800 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
3802 if((posbit = isLiteralBit(bytelit)) != 0)
3803 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
3805 if(bytelit != 0x0FFL)
3806 emitcode("anl","a,%s",
3807 aopGet(AOP(right),offset,FALSE,TRUE));
3808 emitcode("jnz","%05d$",tlbl->key+100);
3813 // bit = left & literal
3815 emitcode("clr","c");
3816 emitcode("","%05d$:",tlbl->key+100);
3818 // if(left & literal)
3821 jmpTrueOrFalse(ifx, tlbl);
3829 /* if left is same as result */
3830 if(sameRegs(AOP(result),AOP(left))){
3831 for(;size--; offset++) {
3832 if(AOP_TYPE(right) == AOP_LIT){
3833 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
3837 aopPut(AOP(result),zero,offset);
3839 if (IS_AOP_PREG(result)) {
3840 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3841 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
3842 aopPut(AOP(result),"a",offset);
3844 emitcode("anl","%s,%s",
3845 aopGet(AOP(left),offset,FALSE,TRUE),
3846 aopGet(AOP(right),offset,FALSE,FALSE));
3848 if (AOP_TYPE(left) == AOP_ACC)
3849 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
3851 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3852 if (IS_AOP_PREG(result)) {
3853 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
3854 aopPut(AOP(result),"a",offset);
3857 emitcode("anl","%s,a",
3858 aopGet(AOP(left),offset,FALSE,TRUE));
3863 // left & result in different registers
3864 if(AOP_TYPE(result) == AOP_CRY){
3866 // if(size), result in bit
3867 // if(!size && ifx), conditional oper: if(left & right)
3868 symbol *tlbl = newiTempLabel(NULL);
3869 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
3871 emitcode("setb","c");
3873 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3874 emitcode("anl","a,%s",
3875 aopGet(AOP(left),offset,FALSE,FALSE));
3876 emitcode("jnz","%05d$",tlbl->key+100);
3881 emitcode("","%05d$:",tlbl->key+100);
3884 jmpTrueOrFalse(ifx, tlbl);
3886 for(;(size--);offset++) {
3888 // result = left & right
3889 if(AOP_TYPE(right) == AOP_LIT){
3890 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
3892 aopGet(AOP(left),offset,FALSE,FALSE),
3895 } else if(bytelit == 0){
3896 aopPut(AOP(result),zero,offset);
3900 // faster than result <- left, anl result,right
3901 // and better if result is SFR
3902 if (AOP_TYPE(left) == AOP_ACC)
3903 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
3905 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3906 emitcode("anl","a,%s",
3907 aopGet(AOP(left),offset,FALSE,FALSE));
3909 aopPut(AOP(result),"a",offset);
3915 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3916 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3917 freeAsmop(result,NULL,ic,TRUE);
3920 /*-----------------------------------------------------------------*/
3921 /* genOr - code for or */
3922 /*-----------------------------------------------------------------*/
3923 static void genOr (iCode *ic, iCode *ifx)
3925 operand *left, *right, *result;
3927 unsigned long lit = 0L;
3929 aopOp((left = IC_LEFT(ic)),ic,FALSE);
3930 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3931 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3934 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3936 AOP_TYPE(left), AOP_TYPE(right));
3937 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3939 AOP_SIZE(left), AOP_SIZE(right));
3942 /* if left is a literal & right is not then exchange them */
3943 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3944 AOP_NEEDSACC(left)) {
3945 operand *tmp = right ;
3950 /* if result = right then exchange them */
3951 if(sameRegs(AOP(result),AOP(right))){
3952 operand *tmp = right ;
3957 /* if right is bit then exchange them */
3958 if (AOP_TYPE(right) == AOP_CRY &&
3959 AOP_TYPE(left) != AOP_CRY){
3960 operand *tmp = right ;
3964 if(AOP_TYPE(right) == AOP_LIT)
3965 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3967 size = AOP_SIZE(result);
3971 if (AOP_TYPE(left) == AOP_CRY){
3972 if(AOP_TYPE(right) == AOP_LIT){
3973 // c = bit & literal;
3975 // lit != 0 => result = 1
3976 if(AOP_TYPE(result) == AOP_CRY){
3978 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
3980 continueIfTrue(ifx);
3983 emitcode("setb","c");
3985 // lit == 0 => result = left
3986 if(size && sameRegs(AOP(result),AOP(left)))
3988 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3991 if (AOP_TYPE(right) == AOP_CRY){
3993 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3994 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
3998 symbol *tlbl = newiTempLabel(NULL);
3999 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4000 emitcode("setb","c");
4001 emitcode("jb","%s,%05d$",
4002 AOP(left)->aopu.aop_dir,tlbl->key+100);
4004 emitcode("jnz","%05d$",tlbl->key+100);
4005 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4006 jmpTrueOrFalse(ifx, tlbl);
4010 emitcode("","%05d$:",tlbl->key+100);
4019 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4020 genIfxJump(ifx, "c");
4024 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4025 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4026 if((AOP_TYPE(right) == AOP_LIT) &&
4027 (AOP_TYPE(result) == AOP_CRY) &&
4028 (AOP_TYPE(left) != AOP_CRY)){
4032 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4034 continueIfTrue(ifx);
4037 // lit = 0, result = boolean(left)
4039 emitcode("setb","c");
4042 symbol *tlbl = newiTempLabel(NULL);
4043 emitcode("jnz","%05d$",tlbl->key+100);
4045 emitcode("","%05d$:",tlbl->key+100);
4047 genIfxJump (ifx,"a");
4055 /* if left is same as result */
4056 if(sameRegs(AOP(result),AOP(left))){
4057 for(;size--; offset++) {
4058 if(AOP_TYPE(right) == AOP_LIT){
4059 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4062 if (IS_AOP_PREG(left)) {
4063 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4064 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4065 aopPut(AOP(result),"a",offset);
4067 emitcode("orl","%s,%s",
4068 aopGet(AOP(left),offset,FALSE,TRUE),
4069 aopGet(AOP(right),offset,FALSE,FALSE));
4071 if (AOP_TYPE(left) == AOP_ACC)
4072 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4074 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4075 if (IS_AOP_PREG(left)) {
4076 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4077 aopPut(AOP(result),"a",offset);
4079 emitcode("orl","%s,a",
4080 aopGet(AOP(left),offset,FALSE,TRUE));
4085 // left & result in different registers
4086 if(AOP_TYPE(result) == AOP_CRY){
4088 // if(size), result in bit
4089 // if(!size && ifx), conditional oper: if(left | right)
4090 symbol *tlbl = newiTempLabel(NULL);
4091 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4093 emitcode("setb","c");
4095 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4096 emitcode("orl","a,%s",
4097 aopGet(AOP(left),offset,FALSE,FALSE));
4098 emitcode("jnz","%05d$",tlbl->key+100);
4103 emitcode("","%05d$:",tlbl->key+100);
4106 jmpTrueOrFalse(ifx, tlbl);
4107 } else for(;(size--);offset++){
4109 // result = left & right
4110 if(AOP_TYPE(right) == AOP_LIT){
4111 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4113 aopGet(AOP(left),offset,FALSE,FALSE),
4118 // faster than result <- left, anl result,right
4119 // and better if result is SFR
4120 if (AOP_TYPE(left) == AOP_ACC)
4121 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4123 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4124 emitcode("orl","a,%s",
4125 aopGet(AOP(left),offset,FALSE,FALSE));
4127 aopPut(AOP(result),"a",offset);
4132 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4133 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4134 freeAsmop(result,NULL,ic,TRUE);
4137 /*-----------------------------------------------------------------*/
4138 /* genXor - code for xclusive or */
4139 /*-----------------------------------------------------------------*/
4140 static void genXor (iCode *ic, iCode *ifx)
4142 operand *left, *right, *result;
4144 unsigned long lit = 0L;
4146 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4147 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4148 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4151 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4153 AOP_TYPE(left), AOP_TYPE(right));
4154 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4156 AOP_SIZE(left), AOP_SIZE(right));
4159 /* if left is a literal & right is not ||
4160 if left needs acc & right does not */
4161 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4162 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4163 operand *tmp = right ;
4168 /* if result = right then exchange them */
4169 if(sameRegs(AOP(result),AOP(right))){
4170 operand *tmp = right ;
4175 /* if right is bit then exchange them */
4176 if (AOP_TYPE(right) == AOP_CRY &&
4177 AOP_TYPE(left) != AOP_CRY){
4178 operand *tmp = right ;
4182 if(AOP_TYPE(right) == AOP_LIT)
4183 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4185 size = AOP_SIZE(result);
4189 if (AOP_TYPE(left) == AOP_CRY){
4190 if(AOP_TYPE(right) == AOP_LIT){
4191 // c = bit & literal;
4193 // lit>>1 != 0 => result = 1
4194 if(AOP_TYPE(result) == AOP_CRY){
4196 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4198 continueIfTrue(ifx);
4201 emitcode("setb","c");
4205 // lit == 0, result = left
4206 if(size && sameRegs(AOP(result),AOP(left)))
4208 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4210 // lit == 1, result = not(left)
4211 if(size && sameRegs(AOP(result),AOP(left))){
4212 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4215 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4216 emitcode("cpl","c");
4223 symbol *tlbl = newiTempLabel(NULL);
4224 if (AOP_TYPE(right) == AOP_CRY){
4226 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4229 int sizer = AOP_SIZE(right);
4231 // if val>>1 != 0, result = 1
4232 emitcode("setb","c");
4234 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
4236 // test the msb of the lsb
4237 emitcode("anl","a,#0xfe");
4238 emitcode("jnz","%05d$",tlbl->key+100);
4242 emitcode("rrc","a");
4244 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4245 emitcode("cpl","c");
4246 emitcode("","%05d$:",(tlbl->key+100));
4253 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4254 genIfxJump(ifx, "c");
4258 if(sameRegs(AOP(result),AOP(left))){
4259 /* if left is same as result */
4260 for(;size--; offset++) {
4261 if(AOP_TYPE(right) == AOP_LIT){
4262 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4265 if (IS_AOP_PREG(left)) {
4266 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4267 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4268 aopPut(AOP(result),"a",offset);
4270 emitcode("xrl","%s,%s",
4271 aopGet(AOP(left),offset,FALSE,TRUE),
4272 aopGet(AOP(right),offset,FALSE,FALSE));
4274 if (AOP_TYPE(left) == AOP_ACC)
4275 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4277 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4278 if (IS_AOP_PREG(left)) {
4279 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4280 aopPut(AOP(result),"a",offset);
4282 emitcode("xrl","%s,a",
4283 aopGet(AOP(left),offset,FALSE,TRUE));
4288 // left & result in different registers
4289 if(AOP_TYPE(result) == AOP_CRY){
4291 // if(size), result in bit
4292 // if(!size && ifx), conditional oper: if(left ^ right)
4293 symbol *tlbl = newiTempLabel(NULL);
4294 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4296 emitcode("setb","c");
4298 if((AOP_TYPE(right) == AOP_LIT) &&
4299 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4300 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4302 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4303 emitcode("xrl","a,%s",
4304 aopGet(AOP(left),offset,FALSE,FALSE));
4306 emitcode("jnz","%05d$",tlbl->key+100);
4311 emitcode("","%05d$:",tlbl->key+100);
4314 jmpTrueOrFalse(ifx, tlbl);
4315 } else for(;(size--);offset++){
4317 // result = left & right
4318 if(AOP_TYPE(right) == AOP_LIT){
4319 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4321 aopGet(AOP(left),offset,FALSE,FALSE),
4326 // faster than result <- left, anl result,right
4327 // and better if result is SFR
4328 if (AOP_TYPE(left) == AOP_ACC)
4329 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4331 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4332 emitcode("xrl","a,%s",
4333 aopGet(AOP(left),offset,FALSE,TRUE));
4335 aopPut(AOP(result),"a",offset);
4340 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4341 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4342 freeAsmop(result,NULL,ic,TRUE);
4345 /*-----------------------------------------------------------------*/
4346 /* genInline - write the inline code out */
4347 /*-----------------------------------------------------------------*/
4348 static void genInline (iCode *ic)
4350 char buffer[MAX_INLINEASM];
4354 _G.inLine += (!options.asmpeep);
4355 strcpy(buffer,IC_INLINE(ic));
4357 /* emit each line as a code */
4376 /* emitcode("",buffer); */
4377 _G.inLine -= (!options.asmpeep);
4380 /*-----------------------------------------------------------------*/
4381 /* genRRC - rotate right with carry */
4382 /*-----------------------------------------------------------------*/
4383 static void genRRC (iCode *ic)
4385 operand *left , *result ;
4386 int size, offset = 0;
4389 /* rotate right with carry */
4391 result=IC_RESULT(ic);
4392 aopOp (left,ic,FALSE);
4393 aopOp (result,ic,FALSE);
4395 /* move it to the result */
4396 size = AOP_SIZE(result);
4400 l = aopGet(AOP(left),offset,FALSE,FALSE);
4402 emitcode("rrc","a");
4403 if (AOP_SIZE(result) > 1)
4404 aopPut(AOP(result),"a",offset--);
4406 /* now we need to put the carry into the
4407 highest order byte of the result */
4408 if (AOP_SIZE(result) > 1) {
4409 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
4412 emitcode("mov","acc.7,c");
4413 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
4414 freeAsmop(left,NULL,ic,TRUE);
4415 freeAsmop(result,NULL,ic,TRUE);
4418 /*-----------------------------------------------------------------*/
4419 /* genRLC - generate code for rotate left with carry */
4420 /*-----------------------------------------------------------------*/
4421 static void genRLC (iCode *ic)
4423 operand *left , *result ;
4424 int size, offset = 0;
4427 /* rotate right with carry */
4429 result=IC_RESULT(ic);
4430 aopOp (left,ic,FALSE);
4431 aopOp (result,ic,FALSE);
4433 /* move it to the result */
4434 size = AOP_SIZE(result);
4437 l = aopGet(AOP(left),offset,FALSE,FALSE);
4439 emitcode("add","a,acc");
4440 if (AOP_SIZE(result) > 1)
4441 aopPut(AOP(result),"a",offset++);
4443 l = aopGet(AOP(left),offset,FALSE,FALSE);
4445 emitcode("rlc","a");
4446 if (AOP_SIZE(result) > 1)
4447 aopPut(AOP(result),"a",offset++);
4450 /* now we need to put the carry into the
4451 highest order byte of the result */
4452 if (AOP_SIZE(result) > 1) {
4453 l = aopGet(AOP(result),0,FALSE,FALSE);
4456 emitcode("mov","acc.0,c");
4457 aopPut(AOP(result),"a",0);
4458 freeAsmop(left,NULL,ic,TRUE);
4459 freeAsmop(result,NULL,ic,TRUE);
4462 /*-----------------------------------------------------------------*/
4463 /* genGetHbit - generates code get highest order bit */
4464 /*-----------------------------------------------------------------*/
4465 static void genGetHbit (iCode *ic)
4467 operand *left, *result;
4469 result=IC_RESULT(ic);
4470 aopOp (left,ic,FALSE);
4471 aopOp (result,ic,FALSE);
4473 /* get the highest order byte into a */
4474 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
4475 if(AOP_TYPE(result) == AOP_CRY){
4476 emitcode("rlc","a");
4481 emitcode("anl","a,#0x01");
4486 freeAsmop(left,NULL,ic,TRUE);
4487 freeAsmop(result,NULL,ic,TRUE);
4490 /*-----------------------------------------------------------------*/
4491 /* AccRol - rotate left accumulator by known count */
4492 /*-----------------------------------------------------------------*/
4493 static void AccRol (int shCount)
4495 shCount &= 0x0007; // shCount : 0..7
4507 emitcode("swap","a");
4511 emitcode("swap","a");
4514 emitcode("swap","a");
4527 /*-----------------------------------------------------------------*/
4528 /* AccLsh - left shift accumulator by known count */
4529 /*-----------------------------------------------------------------*/
4530 static void AccLsh (int shCount)
4534 emitcode("add","a,acc");
4537 emitcode("add","a,acc");
4538 emitcode("add","a,acc");
4540 /* rotate left accumulator */
4542 /* and kill the lower order bits */
4543 emitcode("anl","a,#0x%02x", SLMask[shCount]);
4548 /*-----------------------------------------------------------------*/
4549 /* AccRsh - right shift accumulator by known count */
4550 /*-----------------------------------------------------------------*/
4551 static void AccRsh (int shCount)
4556 emitcode("rrc","a");
4558 /* rotate right accumulator */
4559 AccRol(8 - shCount);
4560 /* and kill the higher order bits */
4561 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4566 /*-----------------------------------------------------------------*/
4567 /* AccSRsh - signed right shift accumulator by known count */
4568 /*-----------------------------------------------------------------*/
4569 static void AccSRsh (int shCount)
4574 emitcode("mov","c,acc.7");
4575 emitcode("rrc","a");
4576 } else if(shCount == 2){
4577 emitcode("mov","c,acc.7");
4578 emitcode("rrc","a");
4579 emitcode("mov","c,acc.7");
4580 emitcode("rrc","a");
4582 tlbl = newiTempLabel(NULL);
4583 /* rotate right accumulator */
4584 AccRol(8 - shCount);
4585 /* and kill the higher order bits */
4586 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4587 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4588 emitcode("orl","a,#0x%02x",
4589 (unsigned char)~SRMask[shCount]);
4590 emitcode("","%05d$:",tlbl->key+100);
4595 /*-----------------------------------------------------------------*/
4596 /* shiftR1Left2Result - shift right one byte from left to result */
4597 /*-----------------------------------------------------------------*/
4598 static void shiftR1Left2Result (operand *left, int offl,
4599 operand *result, int offr,
4600 int shCount, int sign)
4602 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4603 /* shift right accumulator */
4608 aopPut(AOP(result),"a",offr);
4611 /*-----------------------------------------------------------------*/
4612 /* shiftL1Left2Result - shift left one byte from left to result */
4613 /*-----------------------------------------------------------------*/
4614 static void shiftL1Left2Result (operand *left, int offl,
4615 operand *result, int offr, int shCount)
4618 l = aopGet(AOP(left),offl,FALSE,FALSE);
4620 /* shift left accumulator */
4622 aopPut(AOP(result),"a",offr);
4625 /*-----------------------------------------------------------------*/
4626 /* movLeft2Result - move byte from left to result */
4627 /*-----------------------------------------------------------------*/
4628 static void movLeft2Result (operand *left, int offl,
4629 operand *result, int offr, int sign)
4632 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
4633 l = aopGet(AOP(left),offl,FALSE,FALSE);
4635 if (*l == '@' && (IS_AOP_PREG(result))) {
4636 emitcode("mov","a,%s",l);
4637 aopPut(AOP(result),"a",offr);
4640 aopPut(AOP(result),l,offr);
4642 /* MSB sign in acc.7 ! */
4643 if(getDataSize(left) == offl+1){
4644 emitcode("mov","a,%s",l);
4645 aopPut(AOP(result),"a",offr);
4652 /*-----------------------------------------------------------------*/
4653 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
4654 /*-----------------------------------------------------------------*/
4655 static void AccAXRrl1 (char *x)
4657 emitcode("rrc","a");
4658 emitcode("xch","a,%s", x);
4659 emitcode("rrc","a");
4660 emitcode("xch","a,%s", x);
4663 /*-----------------------------------------------------------------*/
4664 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
4665 /*-----------------------------------------------------------------*/
4666 static void AccAXLrl1 (char *x)
4668 emitcode("xch","a,%s",x);
4669 emitcode("rlc","a");
4670 emitcode("xch","a,%s",x);
4671 emitcode("rlc","a");
4674 /*-----------------------------------------------------------------*/
4675 /* AccAXLsh1 - left shift a:x<-0 by 1 */
4676 /*-----------------------------------------------------------------*/
4677 static void AccAXLsh1 (char *x)
4679 emitcode("xch","a,%s",x);
4680 emitcode("add","a,acc");
4681 emitcode("xch","a,%s",x);
4682 emitcode("rlc","a");
4685 /*-----------------------------------------------------------------*/
4686 /* AccAXLsh - left shift a:x by known count (0..7) */
4687 /*-----------------------------------------------------------------*/
4688 static void AccAXLsh (char *x, int shCount)
4702 case 5 : // AAAAABBB:CCCCCDDD
4703 AccRol(shCount); // BBBAAAAA:CCCCCDDD
4704 emitcode("anl","a,#0x%02x",
4705 SLMask[shCount]); // BBB00000:CCCCCDDD
4706 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
4707 AccRol(shCount); // DDDCCCCC:BBB00000
4708 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
4709 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
4710 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
4711 emitcode("anl","a,#0x%02x",
4712 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
4713 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
4714 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
4716 case 6 : // AAAAAABB:CCCCCCDD
4717 emitcode("anl","a,#0x%02x",
4718 SRMask[shCount]); // 000000BB:CCCCCCDD
4719 emitcode("mov","c,acc.0"); // c = B
4720 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
4721 AccAXRrl1(x); // BCCCCCCD:D000000B
4722 AccAXRrl1(x); // BBCCCCCC:DD000000
4724 case 7 : // a:x <<= 7
4725 emitcode("anl","a,#0x%02x",
4726 SRMask[shCount]); // 0000000B:CCCCCCCD
4727 emitcode("mov","c,acc.0"); // c = B
4728 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
4729 AccAXRrl1(x); // BCCCCCCC:D0000000
4736 /*-----------------------------------------------------------------*/
4737 /* AccAXRsh - right shift a:x known count (0..7) */
4738 /*-----------------------------------------------------------------*/
4739 static void AccAXRsh (char *x, int shCount)
4746 AccAXRrl1(x); // 0->a:x
4750 AccAXRrl1(x); // 0->a:x
4752 AccAXRrl1(x); // 0->a:x
4756 case 5 : // AAAAABBB:CCCCCDDD = a:x
4757 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
4758 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
4759 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
4760 emitcode("anl","a,#0x%02x",
4761 SRMask[shCount]); // 000CCCCC:BBBAAAAA
4762 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
4763 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
4764 emitcode("anl","a,#0x%02x",
4765 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
4766 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
4767 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
4768 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
4770 case 6 : // AABBBBBB:CCDDDDDD
4771 emitcode("mov","c,acc.7");
4772 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
4773 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
4774 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
4775 emitcode("anl","a,#0x%02x",
4776 SRMask[shCount]); // 000000AA:BBBBBBCC
4778 case 7 : // ABBBBBBB:CDDDDDDD
4779 emitcode("mov","c,acc.7"); // c = A
4780 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
4781 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
4782 emitcode("anl","a,#0x%02x",
4783 SRMask[shCount]); // 0000000A:BBBBBBBC
4790 /*-----------------------------------------------------------------*/
4791 /* AccAXRshS - right shift signed a:x known count (0..7) */
4792 /*-----------------------------------------------------------------*/
4793 static void AccAXRshS (char *x, int shCount)
4800 emitcode("mov","c,acc.7");
4801 AccAXRrl1(x); // s->a:x
4804 emitcode("mov","c,acc.7");
4805 AccAXRrl1(x); // s->a:x
4806 emitcode("mov","c,acc.7");
4807 AccAXRrl1(x); // s->a:x
4811 case 5 : // AAAAABBB:CCCCCDDD = a:x
4812 tlbl = newiTempLabel(NULL);
4813 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
4814 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
4815 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
4816 emitcode("anl","a,#0x%02x",
4817 SRMask[shCount]); // 000CCCCC:BBBAAAAA
4818 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
4819 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
4820 emitcode("anl","a,#0x%02x",
4821 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
4822 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
4823 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
4824 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
4825 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4826 emitcode("orl","a,#0x%02x",
4827 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
4828 emitcode("","%05d$:",tlbl->key+100);
4829 break; // SSSSAAAA:BBBCCCCC
4830 case 6 : // AABBBBBB:CCDDDDDD
4831 tlbl = newiTempLabel(NULL);
4832 emitcode("mov","c,acc.7");
4833 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
4834 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
4835 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
4836 emitcode("anl","a,#0x%02x",
4837 SRMask[shCount]); // 000000AA:BBBBBBCC
4838 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4839 emitcode("orl","a,#0x%02x",
4840 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
4841 emitcode("","%05d$:",tlbl->key+100);
4843 case 7 : // ABBBBBBB:CDDDDDDD
4844 tlbl = newiTempLabel(NULL);
4845 emitcode("mov","c,acc.7"); // c = A
4846 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
4847 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
4848 emitcode("anl","a,#0x%02x",
4849 SRMask[shCount]); // 0000000A:BBBBBBBC
4850 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4851 emitcode("orl","a,#0x%02x",
4852 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
4853 emitcode("","%05d$:",tlbl->key+100);
4860 /*-----------------------------------------------------------------*/
4861 /* shiftL2Left2Result - shift left two bytes from left to result */
4862 /*-----------------------------------------------------------------*/
4863 static void shiftL2Left2Result (operand *left, int offl,
4864 operand *result, int offr, int shCount)
4866 if(sameRegs(AOP(result), AOP(left)) &&
4867 ((offl + MSB16) == offr)){
4868 /* don't crash result[offr] */
4869 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4870 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4872 movLeft2Result(left,offl, result, offr, 0);
4873 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4875 /* ax << shCount (x = lsb(result))*/
4876 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
4877 aopPut(AOP(result),"a",offr+MSB16);
4881 /*-----------------------------------------------------------------*/
4882 /* shiftR2Left2Result - shift right two bytes from left to result */
4883 /*-----------------------------------------------------------------*/
4884 static void shiftR2Left2Result (operand *left, int offl,
4885 operand *result, int offr,
4886 int shCount, int sign)
4888 if(sameRegs(AOP(result), AOP(left)) &&
4889 ((offl + MSB16) == offr)){
4890 /* don't crash result[offr] */
4891 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4892 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4894 movLeft2Result(left,offl, result, offr, 0);
4895 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4897 /* a:x >> shCount (x = lsb(result))*/
4899 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
4901 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
4902 if(getDataSize(result) > 1)
4903 aopPut(AOP(result),"a",offr+MSB16);
4906 /*-----------------------------------------------------------------*/
4907 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
4908 /*-----------------------------------------------------------------*/
4909 static void shiftLLeftOrResult (operand *left, int offl,
4910 operand *result, int offr, int shCount)
4912 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4913 /* shift left accumulator */
4915 /* or with result */
4916 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
4917 /* back to result */
4918 aopPut(AOP(result),"a",offr);
4921 /*-----------------------------------------------------------------*/
4922 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
4923 /*-----------------------------------------------------------------*/
4924 static void shiftRLeftOrResult (operand *left, int offl,
4925 operand *result, int offr, int shCount)
4927 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4928 /* shift right accumulator */
4930 /* or with result */
4931 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
4932 /* back to result */
4933 aopPut(AOP(result),"a",offr);
4936 /*-----------------------------------------------------------------*/
4937 /* genlshOne - left shift a one byte quantity by known count */
4938 /*-----------------------------------------------------------------*/
4939 static void genlshOne (operand *result, operand *left, int shCount)
4941 shiftL1Left2Result(left, LSB, result, LSB, shCount);
4944 /*-----------------------------------------------------------------*/
4945 /* genlshTwo - left shift two bytes by known amount != 0 */
4946 /*-----------------------------------------------------------------*/
4947 static void genlshTwo (operand *result,operand *left, int shCount)
4951 size = getDataSize(result);
4953 /* if shCount >= 8 */
4959 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
4961 movLeft2Result(left, LSB, result, MSB16, 0);
4963 aopPut(AOP(result),zero,LSB);
4966 /* 1 <= shCount <= 7 */
4969 shiftL1Left2Result(left, LSB, result, LSB, shCount);
4971 shiftL2Left2Result(left, LSB, result, LSB, shCount);
4975 /*-----------------------------------------------------------------*/
4976 /* shiftLLong - shift left one long from left to result */
4977 /* offl = LSB or MSB16 */
4978 /*-----------------------------------------------------------------*/
4979 static void shiftLLong (operand *left, operand *result, int offr )
4982 int size = AOP_SIZE(result);
4984 if(size >= LSB+offr){
4985 l = aopGet(AOP(left),LSB,FALSE,FALSE);
4987 emitcode("add","a,acc");
4988 if (sameRegs(AOP(left),AOP(result)) &&
4989 size >= MSB16+offr && offr != LSB )
4990 emitcode("xch","a,%s",
4991 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
4993 aopPut(AOP(result),"a",LSB+offr);
4996 if(size >= MSB16+offr){
4997 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
4998 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
5001 emitcode("rlc","a");
5002 if (sameRegs(AOP(left),AOP(result)) &&
5003 size >= MSB24+offr && offr != LSB)
5004 emitcode("xch","a,%s",
5005 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
5007 aopPut(AOP(result),"a",MSB16+offr);
5010 if(size >= MSB24+offr){
5011 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5012 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
5015 emitcode("rlc","a");
5016 if (sameRegs(AOP(left),AOP(result)) &&
5017 size >= MSB32+offr && offr != LSB )
5018 emitcode("xch","a,%s",
5019 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
5021 aopPut(AOP(result),"a",MSB24+offr);
5024 if(size > MSB32+offr){
5025 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5026 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
5029 emitcode("rlc","a");
5030 aopPut(AOP(result),"a",MSB32+offr);
5033 aopPut(AOP(result),zero,LSB);
5036 /*-----------------------------------------------------------------*/
5037 /* genlshFour - shift four byte by a known amount != 0 */
5038 /*-----------------------------------------------------------------*/
5039 static void genlshFour (operand *result, operand *left, int shCount)
5043 size = AOP_SIZE(result);
5045 /* if shifting more that 3 bytes */
5046 if (shCount >= 24 ) {
5049 /* lowest order of left goes to the highest
5050 order of the destination */
5051 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5053 movLeft2Result(left, LSB, result, MSB32, 0);
5054 aopPut(AOP(result),zero,LSB);
5055 aopPut(AOP(result),zero,MSB16);
5056 aopPut(AOP(result),zero,MSB32);
5060 /* more than two bytes */
5061 else if ( shCount >= 16 ) {
5062 /* lower order two bytes goes to higher order two bytes */
5064 /* if some more remaining */
5066 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5068 movLeft2Result(left, MSB16, result, MSB32, 0);
5069 movLeft2Result(left, LSB, result, MSB24, 0);
5071 aopPut(AOP(result),zero,MSB16);
5072 aopPut(AOP(result),zero,LSB);
5076 /* if more than 1 byte */
5077 else if ( shCount >= 8 ) {
5078 /* lower order three bytes goes to higher order three bytes */
5082 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5084 movLeft2Result(left, LSB, result, MSB16, 0);
5086 else{ /* size = 4 */
5088 movLeft2Result(left, MSB24, result, MSB32, 0);
5089 movLeft2Result(left, MSB16, result, MSB24, 0);
5090 movLeft2Result(left, LSB, result, MSB16, 0);
5091 aopPut(AOP(result),zero,LSB);
5093 else if(shCount == 1)
5094 shiftLLong(left, result, MSB16);
5096 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5097 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5098 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5099 aopPut(AOP(result),zero,LSB);
5104 /* 1 <= shCount <= 7 */
5105 else if(shCount <= 2){
5106 shiftLLong(left, result, LSB);
5108 shiftLLong(result, result, LSB);
5110 /* 3 <= shCount <= 7, optimize */
5112 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5113 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5114 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5118 /*-----------------------------------------------------------------*/
5119 /* genLeftShiftLiteral - left shifting by known count */
5120 /*-----------------------------------------------------------------*/
5121 static void genLeftShiftLiteral (operand *left,
5126 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5129 freeAsmop(right,NULL,ic,TRUE);
5131 aopOp(left,ic,FALSE);
5132 aopOp(result,ic,FALSE);
5134 size = getSize(operandType(result));
5137 emitcode("; shift left ","result %d, left %d",size,
5141 /* I suppose that the left size >= result size */
5144 movLeft2Result(left, size, result, size, 0);
5148 else if(shCount >= (size * 8))
5150 aopPut(AOP(result),zero,size);
5154 genlshOne (result,left,shCount);
5159 genlshTwo (result,left,shCount);
5163 genlshFour (result,left,shCount);
5167 freeAsmop(left,NULL,ic,TRUE);
5168 freeAsmop(result,NULL,ic,TRUE);
5171 /*-----------------------------------------------------------------*/
5172 /* genLeftShift - generates code for left shifting */
5173 /*-----------------------------------------------------------------*/
5174 static void genLeftShift (iCode *ic)
5176 operand *left,*right, *result;
5179 symbol *tlbl , *tlbl1;
5181 right = IC_RIGHT(ic);
5183 result = IC_RESULT(ic);
5185 aopOp(right,ic,FALSE);
5187 /* if the shift count is known then do it
5188 as efficiently as possible */
5189 if (AOP_TYPE(right) == AOP_LIT) {
5190 genLeftShiftLiteral (left,right,result,ic);
5194 /* shift count is unknown then we have to form
5195 a loop get the loop count in B : Note: we take
5196 only the lower order byte since shifting
5197 more that 32 bits make no sense anyway, ( the
5198 largest size of an object can be only 32 bits ) */
5200 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5201 emitcode("inc","b");
5202 freeAsmop (right,NULL,ic,TRUE);
5203 aopOp(left,ic,FALSE);
5204 aopOp(result,ic,FALSE);
5206 /* now move the left to the result if they are not the
5208 if (!sameRegs(AOP(left),AOP(result)) &&
5209 AOP_SIZE(result) > 1) {
5211 size = AOP_SIZE(result);
5214 l = aopGet(AOP(left),offset,FALSE,TRUE);
5215 if (*l == '@' && (IS_AOP_PREG(result))) {
5217 emitcode("mov","a,%s",l);
5218 aopPut(AOP(result),"a",offset);
5220 aopPut(AOP(result),l,offset);
5225 tlbl = newiTempLabel(NULL);
5226 size = AOP_SIZE(result);
5228 tlbl1 = newiTempLabel(NULL);
5230 /* if it is only one byte then */
5232 symbol *tlbl1 = newiTempLabel(NULL);
5234 l = aopGet(AOP(left),0,FALSE,FALSE);
5236 emitcode("sjmp","%05d$",tlbl1->key+100);
5237 emitcode("","%05d$:",tlbl->key+100);
5238 emitcode("add","a,acc");
5239 emitcode("","%05d$:",tlbl1->key+100);
5240 emitcode("djnz","b,%05d$",tlbl->key+100);
5241 aopPut(AOP(result),"a",0);
5245 reAdjustPreg(AOP(result));
5247 emitcode("sjmp","%05d$",tlbl1->key+100);
5248 emitcode("","%05d$:",tlbl->key+100);
5249 l = aopGet(AOP(result),offset,FALSE,FALSE);
5251 emitcode("add","a,acc");
5252 aopPut(AOP(result),"a",offset++);
5254 l = aopGet(AOP(result),offset,FALSE,FALSE);
5256 emitcode("rlc","a");
5257 aopPut(AOP(result),"a",offset++);
5259 reAdjustPreg(AOP(result));
5261 emitcode("","%05d$:",tlbl1->key+100);
5262 emitcode("djnz","b,%05d$",tlbl->key+100);
5264 freeAsmop(left,NULL,ic,TRUE);
5265 freeAsmop(result,NULL,ic,TRUE);
5268 /*-----------------------------------------------------------------*/
5269 /* genrshOne - right shift a one byte quantity by known count */
5270 /*-----------------------------------------------------------------*/
5271 static void genrshOne (operand *result, operand *left,
5272 int shCount, int sign)
5274 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
5277 /*-----------------------------------------------------------------*/
5278 /* genrshTwo - right shift two bytes by known amount != 0 */
5279 /*-----------------------------------------------------------------*/
5280 static void genrshTwo (operand *result,operand *left,
5281 int shCount, int sign)
5283 /* if shCount >= 8 */
5287 shiftR1Left2Result(left, MSB16, result, LSB,
5290 movLeft2Result(left, MSB16, result, LSB, sign);
5291 addSign(result, MSB16, sign);
5294 /* 1 <= shCount <= 7 */
5296 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
5299 /*-----------------------------------------------------------------*/
5300 /* shiftRLong - shift right one long from left to result */
5301 /* offl = LSB or MSB16 */
5302 /*-----------------------------------------------------------------*/
5303 static void shiftRLong (operand *left, int offl,
5304 operand *result, int sign)
5307 emitcode("clr","c");
5308 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
5310 emitcode("mov","c,acc.7");
5311 emitcode("rrc","a");
5312 aopPut(AOP(result),"a",MSB32-offl);
5314 /* add sign of "a" */
5315 addSign(result, MSB32, sign);
5317 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
5318 emitcode("rrc","a");
5319 aopPut(AOP(result),"a",MSB24-offl);
5321 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
5322 emitcode("rrc","a");
5323 aopPut(AOP(result),"a",MSB16-offl);
5326 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
5327 emitcode("rrc","a");
5328 aopPut(AOP(result),"a",LSB);
5332 /*-----------------------------------------------------------------*/
5333 /* genrshFour - shift four byte by a known amount != 0 */
5334 /*-----------------------------------------------------------------*/
5335 static void genrshFour (operand *result, operand *left,
5336 int shCount, int sign)
5338 /* if shifting more that 3 bytes */
5339 if(shCount >= 24 ) {
5342 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
5344 movLeft2Result(left, MSB32, result, LSB, sign);
5345 addSign(result, MSB16, sign);
5347 else if(shCount >= 16){
5350 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
5352 movLeft2Result(left, MSB24, result, LSB, 0);
5353 movLeft2Result(left, MSB32, result, MSB16, sign);
5355 addSign(result, MSB24, sign);
5357 else if(shCount >= 8){
5360 shiftRLong(left, MSB16, result, sign);
5361 else if(shCount == 0){
5362 movLeft2Result(left, MSB16, result, LSB, 0);
5363 movLeft2Result(left, MSB24, result, MSB16, 0);
5364 movLeft2Result(left, MSB32, result, MSB24, sign);
5365 addSign(result, MSB32, sign);
5368 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
5369 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
5370 /* the last shift is signed */
5371 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
5372 addSign(result, MSB32, sign);
5375 else{ /* 1 <= shCount <= 7 */
5377 shiftRLong(left, LSB, result, sign);
5379 shiftRLong(result, LSB, result, sign);
5382 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
5383 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
5384 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
5389 /*-----------------------------------------------------------------*/
5390 /* genRightShiftLiteral - right shifting by known count */
5391 /*-----------------------------------------------------------------*/
5392 static void genRightShiftLiteral (operand *left,
5398 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5401 freeAsmop(right,NULL,ic,TRUE);
5403 aopOp(left,ic,FALSE);
5404 aopOp(result,ic,FALSE);
5407 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
5411 size = getDataSize(left);
5412 /* test the LEFT size !!! */
5414 /* I suppose that the left size >= result size */
5416 size = getDataSize(result);
5418 movLeft2Result(left, size, result, size, 0);
5421 else if(shCount >= (size * 8)){
5423 /* get sign in acc.7 */
5424 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
5425 addSign(result, LSB, sign);
5429 genrshOne (result,left,shCount,sign);
5433 genrshTwo (result,left,shCount,sign);
5437 genrshFour (result,left,shCount,sign);
5443 freeAsmop(left,NULL,ic,TRUE);
5444 freeAsmop(result,NULL,ic,TRUE);
5448 /*-----------------------------------------------------------------*/
5449 /* genSignedRightShift - right shift of signed number */
5450 /*-----------------------------------------------------------------*/
5451 static void genSignedRightShift (iCode *ic)
5453 operand *right, *left, *result;
5456 symbol *tlbl, *tlbl1 ;
5458 /* we do it the hard way put the shift count in b
5459 and loop thru preserving the sign */
5461 right = IC_RIGHT(ic);
5463 result = IC_RESULT(ic);
5465 aopOp(right,ic,FALSE);
5468 if ( AOP_TYPE(right) == AOP_LIT) {
5469 genRightShiftLiteral (left,right,result,ic,1);
5472 /* shift count is unknown then we have to form
5473 a loop get the loop count in B : Note: we take
5474 only the lower order byte since shifting
5475 more that 32 bits make no sense anyway, ( the
5476 largest size of an object can be only 32 bits ) */
5478 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5479 emitcode("inc","b");
5480 freeAsmop (right,NULL,ic,TRUE);
5481 aopOp(left,ic,FALSE);
5482 aopOp(result,ic,FALSE);
5484 /* now move the left to the result if they are not the
5486 if (!sameRegs(AOP(left),AOP(result)) &&
5487 AOP_SIZE(result) > 1) {
5489 size = AOP_SIZE(result);
5492 l = aopGet(AOP(left),offset,FALSE,TRUE);
5493 if (*l == '@' && IS_AOP_PREG(result)) {
5495 emitcode("mov","a,%s",l);
5496 aopPut(AOP(result),"a",offset);
5498 aopPut(AOP(result),l,offset);
5503 /* mov the highest order bit to OVR */
5504 tlbl = newiTempLabel(NULL);
5505 tlbl1= newiTempLabel(NULL);
5507 size = AOP_SIZE(result);
5509 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
5510 emitcode("rlc","a");
5511 emitcode("mov","ov,c");
5512 /* if it is only one byte then */
5514 l = aopGet(AOP(left),0,FALSE,FALSE);
5516 emitcode("sjmp","%05d$",tlbl1->key+100);
5517 emitcode("","%05d$:",tlbl->key+100);
5518 emitcode("mov","c,ov");
5519 emitcode("rrc","a");
5520 emitcode("","%05d$:",tlbl1->key+100);
5521 emitcode("djnz","b,%05d$",tlbl->key+100);
5522 aopPut(AOP(result),"a",0);
5526 reAdjustPreg(AOP(result));
5527 emitcode("sjmp","%05d$",tlbl1->key+100);
5528 emitcode("","%05d$:",tlbl->key+100);
5529 emitcode("mov","c,ov");
5531 l = aopGet(AOP(result),offset,FALSE,FALSE);
5533 emitcode("rrc","a");
5534 aopPut(AOP(result),"a",offset--);
5536 reAdjustPreg(AOP(result));
5537 emitcode("","%05d$:",tlbl1->key+100);
5538 emitcode("djnz","b,%05d$",tlbl->key+100);
5541 freeAsmop(left,NULL,ic,TRUE);
5542 freeAsmop(result,NULL,ic,TRUE);
5545 /*-----------------------------------------------------------------*/
5546 /* genRightShift - generate code for right shifting */
5547 /*-----------------------------------------------------------------*/
5548 static void genRightShift (iCode *ic)
5550 operand *right, *left, *result;
5554 symbol *tlbl, *tlbl1 ;
5556 /* if signed then we do it the hard way preserve the
5557 sign bit moving it inwards */
5558 retype = getSpec(operandType(IC_RESULT(ic)));
5560 if (!SPEC_USIGN(retype)) {
5561 genSignedRightShift (ic);
5565 /* signed & unsigned types are treated the same : i.e. the
5566 signed is NOT propagated inwards : quoting from the
5567 ANSI - standard : "for E1 >> E2, is equivalent to division
5568 by 2**E2 if unsigned or if it has a non-negative value,
5569 otherwise the result is implementation defined ", MY definition
5570 is that the sign does not get propagated */
5572 right = IC_RIGHT(ic);
5574 result = IC_RESULT(ic);
5576 aopOp(right,ic,FALSE);
5578 /* if the shift count is known then do it
5579 as efficiently as possible */
5580 if (AOP_TYPE(right) == AOP_LIT) {
5581 genRightShiftLiteral (left,right,result,ic, 0);
5585 /* shift count is unknown then we have to form
5586 a loop get the loop count in B : Note: we take
5587 only the lower order byte since shifting
5588 more that 32 bits make no sense anyway, ( the
5589 largest size of an object can be only 32 bits ) */
5591 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5592 emitcode("inc","b");
5593 freeAsmop (right,NULL,ic,TRUE);
5594 aopOp(left,ic,FALSE);
5595 aopOp(result,ic,FALSE);
5597 /* now move the left to the result if they are not the
5599 if (!sameRegs(AOP(left),AOP(result)) &&
5600 AOP_SIZE(result) > 1) {
5602 size = AOP_SIZE(result);
5605 l = aopGet(AOP(left),offset,FALSE,TRUE);
5606 if (*l == '@' && IS_AOP_PREG(result)) {
5608 emitcode("mov","a,%s",l);
5609 aopPut(AOP(result),"a",offset);
5611 aopPut(AOP(result),l,offset);
5616 tlbl = newiTempLabel(NULL);
5617 tlbl1= newiTempLabel(NULL);
5618 size = AOP_SIZE(result);
5621 /* if it is only one byte then */
5623 l = aopGet(AOP(left),0,FALSE,FALSE);
5625 emitcode("sjmp","%05d$",tlbl1->key+100);
5626 emitcode("","%05d$:",tlbl->key+100);
5628 emitcode("rrc","a");
5629 emitcode("","%05d$:",tlbl1->key+100);
5630 emitcode("djnz","b,%05d$",tlbl->key+100);
5631 aopPut(AOP(result),"a",0);
5635 reAdjustPreg(AOP(result));
5636 emitcode("sjmp","%05d$",tlbl1->key+100);
5637 emitcode("","%05d$:",tlbl->key+100);
5640 l = aopGet(AOP(result),offset,FALSE,FALSE);
5642 emitcode("rrc","a");
5643 aopPut(AOP(result),"a",offset--);
5645 reAdjustPreg(AOP(result));
5647 emitcode("","%05d$:",tlbl1->key+100);
5648 emitcode("djnz","b,%05d$",tlbl->key+100);
5651 freeAsmop(left,NULL,ic,TRUE);
5652 freeAsmop(result,NULL,ic,TRUE);
5655 /*-----------------------------------------------------------------*/
5656 /* genUnpackBits - generates code for unpacking bits */
5657 /*-----------------------------------------------------------------*/
5658 static void genUnpackBits (operand *result, char *rname, int ptype)
5665 etype = getSpec(operandType(result));
5667 /* read the first byte */
5672 emitcode("mov","a,@%s",rname);
5676 emitcode("movx","a,@%s",rname);
5680 emitcode("movx","a,@dptr");
5684 emitcode("clr","a");
5685 emitcode("movc","a","@a+dptr");
5689 emitcode("lcall","__gptrget");
5693 /* if we have bitdisplacement then it fits */
5694 /* into this byte completely or if length is */
5695 /* less than a byte */
5696 if ((shCnt = SPEC_BSTR(etype)) ||
5697 (SPEC_BLEN(etype) <= 8)) {
5699 /* shift right acc */
5702 emitcode("anl","a,#0x%02x",
5703 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
5704 aopPut(AOP(result),"a",offset);
5708 /* bit field did not fit in a byte */
5709 rlen = SPEC_BLEN(etype) - 8;
5710 aopPut(AOP(result),"a",offset++);
5717 emitcode("inc","%s",rname);
5718 emitcode("mov","a,@%s",rname);
5722 emitcode("inc","%s",rname);
5723 emitcode("movx","a,@%s",rname);
5727 emitcode("inc","dptr");
5728 emitcode("movx","a,@dptr");
5732 emitcode("clr","a");
5733 emitcode("inc","dptr");
5734 emitcode("movc","a","@a+dptr");
5738 emitcode("inc","dptr");
5739 emitcode("lcall","__gptrget");
5744 /* if we are done */
5748 aopPut(AOP(result),"a",offset++);
5753 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
5754 aopPut(AOP(result),"a",offset);
5761 /*-----------------------------------------------------------------*/
5762 /* genDataPointerGet - generates code when ptr offset is known */
5763 /*-----------------------------------------------------------------*/
5764 static void genDataPointerGet (operand *left,
5770 int size , offset = 0;
5771 aopOp(result,ic,TRUE);
5773 /* get the string representation of the name */
5774 l = aopGet(AOP(left),0,FALSE,TRUE);
5775 size = AOP_SIZE(result);
5778 sprintf(buffer,"(%s + %d)",l+1,offset);
5780 sprintf(buffer,"%s",l+1);
5781 aopPut(AOP(result),buffer,offset++);
5784 freeAsmop(left,NULL,ic,TRUE);
5785 freeAsmop(result,NULL,ic,TRUE);
5788 /*-----------------------------------------------------------------*/
5789 /* genNearPointerGet - emitcode for near pointer fetch */
5790 /*-----------------------------------------------------------------*/
5791 static void genNearPointerGet (operand *left,
5798 link *rtype, *retype;
5799 link *ltype = operandType(left);
5802 rtype = operandType(result);
5803 retype= getSpec(rtype);
5805 aopOp(left,ic,FALSE);
5807 /* if left is rematerialisable and
5808 result is not bit variable type and
5809 the left is pointer to data space i.e
5810 lower 128 bytes of space */
5811 if (AOP_TYPE(left) == AOP_IMMD &&
5812 !IS_BITVAR(retype) &&
5813 DCL_TYPE(ltype) == POINTER) {
5814 genDataPointerGet (left,result,ic);
5818 /* if the value is already in a pointer register
5819 then don't need anything more */
5820 if (!AOP_INPREG(AOP(left))) {
5821 /* otherwise get a free pointer register */
5823 preg = getFreePtr(ic,&aop,FALSE);
5824 emitcode("mov","%s,%s",
5826 aopGet(AOP(left),0,FALSE,TRUE));
5827 rname = preg->name ;
5829 rname = aopGet(AOP(left),0,FALSE,FALSE);
5831 freeAsmop(left,NULL,ic,TRUE);
5832 aopOp (result,ic,FALSE);
5834 /* if bitfield then unpack the bits */
5835 if (IS_BITVAR(retype))
5836 genUnpackBits (result,rname,POINTER);
5838 /* we have can just get the values */
5839 int size = AOP_SIZE(result);
5843 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
5845 emitcode("mov","a,@%s",rname);
5846 aopPut(AOP(result),"a",offset);
5848 sprintf(buffer,"@%s",rname);
5849 aopPut(AOP(result),buffer,offset);
5853 emitcode("inc","%s",rname);
5857 /* now some housekeeping stuff */
5859 /* we had to allocate for this iCode */
5860 freeAsmop(NULL,aop,ic,TRUE);
5862 /* we did not allocate which means left
5863 already in a pointer register, then
5864 if size > 0 && this could be used again
5865 we have to point it back to where it
5867 if (AOP_SIZE(result) > 1 &&
5868 !OP_SYMBOL(left)->remat &&
5869 ( OP_SYMBOL(left)->liveTo > ic->seq ||
5871 int size = AOP_SIZE(result) - 1;
5873 emitcode("dec","%s",rname);
5878 freeAsmop(result,NULL,ic,TRUE);
5882 /*-----------------------------------------------------------------*/
5883 /* genPagedPointerGet - emitcode for paged pointer fetch */
5884 /*-----------------------------------------------------------------*/
5885 static void genPagedPointerGet (operand *left,
5892 link *rtype, *retype;
5894 rtype = operandType(result);
5895 retype= getSpec(rtype);
5897 aopOp(left,ic,FALSE);
5899 /* if the value is already in a pointer register
5900 then don't need anything more */
5901 if (!AOP_INPREG(AOP(left))) {
5902 /* otherwise get a free pointer register */
5904 preg = getFreePtr(ic,&aop,FALSE);
5905 emitcode("mov","%s,%s",
5907 aopGet(AOP(left),0,FALSE,TRUE));
5908 rname = preg->name ;
5910 rname = aopGet(AOP(left),0,FALSE,FALSE);
5912 freeAsmop(left,NULL,ic,TRUE);
5913 aopOp (result,ic,FALSE);
5915 /* if bitfield then unpack the bits */
5916 if (IS_BITVAR(retype))
5917 genUnpackBits (result,rname,PPOINTER);
5919 /* we have can just get the values */
5920 int size = AOP_SIZE(result);
5925 emitcode("movx","a,@%s",rname);
5926 aopPut(AOP(result),"a",offset);
5931 emitcode("inc","%s",rname);
5935 /* now some housekeeping stuff */
5937 /* we had to allocate for this iCode */
5938 freeAsmop(NULL,aop,ic,TRUE);
5940 /* we did not allocate which means left
5941 already in a pointer register, then
5942 if size > 0 && this could be used again
5943 we have to point it back to where it
5945 if (AOP_SIZE(result) > 1 &&
5946 !OP_SYMBOL(left)->remat &&
5947 ( OP_SYMBOL(left)->liveTo > ic->seq ||
5949 int size = AOP_SIZE(result) - 1;
5951 emitcode("dec","%s",rname);
5956 freeAsmop(result,NULL,ic,TRUE);
5961 /*-----------------------------------------------------------------*/
5962 /* genFarPointerGet - gget value from far space */
5963 /*-----------------------------------------------------------------*/
5964 static void genFarPointerGet (operand *left,
5965 operand *result, iCode *ic)
5968 link *retype = getSpec(operandType(result));
5970 aopOp(left,ic,FALSE);
5972 /* if the operand is already in dptr
5973 then we do nothing else we move the value to dptr */
5974 if (AOP_TYPE(left) != AOP_STR) {
5975 /* if this is remateriazable */
5976 if (AOP_TYPE(left) == AOP_IMMD)
5977 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
5978 else { /* we need to get it byte by byte */
5979 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
5980 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
5981 if (options.model == MODEL_FLAT24)
5983 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
5987 /* so dptr know contains the address */
5988 freeAsmop(left,NULL,ic,TRUE);
5989 aopOp(result,ic,FALSE);
5991 /* if bit then unpack */
5992 if (IS_BITVAR(retype))
5993 genUnpackBits(result,"dptr",FPOINTER);
5995 size = AOP_SIZE(result);
5999 emitcode("movx","a,@dptr");
6000 aopPut(AOP(result),"a",offset++);
6002 emitcode("inc","dptr");
6006 freeAsmop(result,NULL,ic,TRUE);
6009 /*-----------------------------------------------------------------*/
6010 /* emitcodePointerGet - gget value from code space */
6011 /*-----------------------------------------------------------------*/
6012 static void emitcodePointerGet (operand *left,
6013 operand *result, iCode *ic)
6016 link *retype = getSpec(operandType(result));
6018 aopOp(left,ic,FALSE);
6020 /* if the operand is already in dptr
6021 then we do nothing else we move the value to dptr */
6022 if (AOP_TYPE(left) != AOP_STR) {
6023 /* if this is remateriazable */
6024 if (AOP_TYPE(left) == AOP_IMMD)
6025 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6026 else { /* we need to get it byte by byte */
6027 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6028 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6029 if (options.model == MODEL_FLAT24)
6031 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6035 /* so dptr know contains the address */
6036 freeAsmop(left,NULL,ic,TRUE);
6037 aopOp(result,ic,FALSE);
6039 /* if bit then unpack */
6040 if (IS_BITVAR(retype))
6041 genUnpackBits(result,"dptr",CPOINTER);
6043 size = AOP_SIZE(result);
6047 emitcode("clr","a");
6048 emitcode("movc","a,@a+dptr");
6049 aopPut(AOP(result),"a",offset++);
6051 emitcode("inc","dptr");
6055 freeAsmop(result,NULL,ic,TRUE);
6058 /*-----------------------------------------------------------------*/
6059 /* genGenPointerGet - gget value from generic pointer space */
6060 /*-----------------------------------------------------------------*/
6061 static void genGenPointerGet (operand *left,
6062 operand *result, iCode *ic)
6065 link *retype = getSpec(operandType(result));
6067 aopOp(left,ic,FALSE);
6069 /* if the operand is already in dptr
6070 then we do nothing else we move the value to dptr */
6071 if (AOP_TYPE(left) != AOP_STR) {
6072 /* if this is remateriazable */
6073 if (AOP_TYPE(left) == AOP_IMMD) {
6074 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6075 emitcode("mov","b,#%d",pointerCode(retype));
6077 else { /* we need to get it byte by byte */
6078 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6079 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6080 if (options.model == MODEL_FLAT24)
6082 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6083 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
6087 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
6091 /* so dptr know contains the address */
6092 freeAsmop(left,NULL,ic,TRUE);
6093 aopOp(result,ic,FALSE);
6095 /* if bit then unpack */
6096 if (IS_BITVAR(retype))
6097 genUnpackBits(result,"dptr",GPOINTER);
6099 size = AOP_SIZE(result);
6103 emitcode("lcall","__gptrget");
6104 aopPut(AOP(result),"a",offset++);
6106 emitcode("inc","dptr");
6110 freeAsmop(result,NULL,ic,TRUE);
6113 /*-----------------------------------------------------------------*/
6114 /* genPointerGet - generate code for pointer get */
6115 /*-----------------------------------------------------------------*/
6116 static void genPointerGet (iCode *ic)
6118 operand *left, *result ;
6123 result = IC_RESULT(ic) ;
6125 /* depending on the type of pointer we need to
6126 move it to the correct pointer register */
6127 type = operandType(left);
6128 etype = getSpec(type);
6129 /* if left is of type of pointer then it is simple */
6130 if (IS_PTR(type) && !IS_FUNC(type->next))
6131 p_type = DCL_TYPE(type);
6134 /* we have to go by the storage class */
6135 if (SPEC_OCLS(etype)->codesp ) {
6139 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
6142 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
6145 if (SPEC_OCLS(etype) == idata )
6151 /* now that we have the pointer type we assign
6152 the pointer values */
6157 genNearPointerGet (left,result,ic);
6161 genPagedPointerGet(left,result,ic);
6165 genFarPointerGet (left,result,ic);
6169 emitcodePointerGet (left,result,ic);
6173 genGenPointerGet (left,result,ic);
6179 /*-----------------------------------------------------------------*/
6180 /* genPackBits - generates code for packed bit storage */
6181 /*-----------------------------------------------------------------*/
6182 static void genPackBits (link *etype ,
6184 char *rname, int p_type)
6192 blen = SPEC_BLEN(etype);
6193 bstr = SPEC_BSTR(etype);
6195 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6198 /* if the bit lenth is less than or */
6199 /* it exactly fits a byte then */
6200 if (SPEC_BLEN(etype) <= 8 ) {
6201 shCount = SPEC_BSTR(etype) ;
6203 /* shift left acc */
6206 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6211 emitcode ("mov","b,a");
6212 emitcode("mov","a,@%s",rname);
6216 emitcode ("mov","b,a");
6217 emitcode("movx","a,@dptr");
6221 emitcode ("push","b");
6222 emitcode ("push","acc");
6223 emitcode ("lcall","__gptrget");
6224 emitcode ("pop","b");
6228 emitcode ("anl","a,#0x%02x",(unsigned char)
6229 ((unsigned char)(0xFF << (blen+bstr)) |
6230 (unsigned char)(0xFF >> (8-bstr)) ) );
6231 emitcode ("orl","a,b");
6232 if (p_type == GPOINTER)
6233 emitcode("pop","b");
6239 emitcode("mov","@%s,a",rname);
6243 emitcode("movx","@dptr,a");
6247 emitcode("lcall","__gptrput");
6252 if ( SPEC_BLEN(etype) <= 8 )
6255 emitcode("inc","%s",rname);
6256 rLen = SPEC_BLEN(etype) ;
6258 /* now generate for lengths greater than one byte */
6261 l = aopGet(AOP(right),offset++,FALSE,TRUE);
6271 emitcode("mov","@%s,a",rname);
6273 emitcode("mov","@%s,%s",rname,l);
6278 emitcode("movx","@dptr,a");
6283 emitcode("lcall","__gptrput");
6286 emitcode ("inc","%s",rname);
6291 /* last last was not complete */
6293 /* save the byte & read byte */
6296 emitcode ("mov","b,a");
6297 emitcode("mov","a,@%s",rname);
6301 emitcode ("mov","b,a");
6302 emitcode("movx","a,@dptr");
6306 emitcode ("push","b");
6307 emitcode ("push","acc");
6308 emitcode ("lcall","__gptrget");
6309 emitcode ("pop","b");
6313 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
6314 emitcode ("orl","a,b");
6317 if (p_type == GPOINTER)
6318 emitcode("pop","b");
6323 emitcode("mov","@%s,a",rname);
6327 emitcode("movx","@dptr,a");
6331 emitcode("lcall","__gptrput");
6335 /*-----------------------------------------------------------------*/
6336 /* genDataPointerSet - remat pointer to data space */
6337 /*-----------------------------------------------------------------*/
6338 static void genDataPointerSet(operand *right,
6342 int size, offset = 0 ;
6343 char *l, buffer[256];
6345 aopOp(right,ic,FALSE);
6347 l = aopGet(AOP(result),0,FALSE,TRUE);
6348 size = AOP_SIZE(right);
6351 sprintf(buffer,"(%s + %d)",l+1,offset);
6353 sprintf(buffer,"%s",l+1);
6354 emitcode("mov","%s,%s",buffer,
6355 aopGet(AOP(right),offset++,FALSE,FALSE));
6358 freeAsmop(right,NULL,ic,TRUE);
6359 freeAsmop(result,NULL,ic,TRUE);
6362 /*-----------------------------------------------------------------*/
6363 /* genNearPointerSet - emitcode for near pointer put */
6364 /*-----------------------------------------------------------------*/
6365 static void genNearPointerSet (operand *right,
6373 link *ptype = operandType(result);
6375 retype= getSpec(operandType(right));
6377 aopOp(result,ic,FALSE);
6379 /* if the result is rematerializable &
6380 in data space & not a bit variable */
6381 if (AOP_TYPE(result) == AOP_IMMD &&
6382 DCL_TYPE(ptype) == POINTER &&
6383 !IS_BITVAR(retype)) {
6384 genDataPointerSet (right,result,ic);
6388 /* if the value is already in a pointer register
6389 then don't need anything more */
6390 if (!AOP_INPREG(AOP(result))) {
6391 /* otherwise get a free pointer register */
6393 preg = getFreePtr(ic,&aop,FALSE);
6394 emitcode("mov","%s,%s",
6396 aopGet(AOP(result),0,FALSE,TRUE));
6397 rname = preg->name ;
6399 rname = aopGet(AOP(result),0,FALSE,FALSE);
6401 freeAsmop(result,NULL,ic,TRUE);
6402 aopOp (right,ic,FALSE);
6404 /* if bitfield then unpack the bits */
6405 if (IS_BITVAR(retype))
6406 genPackBits (retype,right,rname,POINTER);
6408 /* we have can just get the values */
6409 int size = AOP_SIZE(right);
6413 l = aopGet(AOP(right),offset,FALSE,TRUE);
6416 emitcode("mov","@%s,a",rname);
6418 emitcode("mov","@%s,%s",rname,l);
6420 emitcode("inc","%s",rname);
6425 /* now some housekeeping stuff */
6427 /* we had to allocate for this iCode */
6428 freeAsmop(NULL,aop,ic,TRUE);
6430 /* we did not allocate which means left
6431 already in a pointer register, then
6432 if size > 0 && this could be used again
6433 we have to point it back to where it
6435 if (AOP_SIZE(right) > 1 &&
6436 !OP_SYMBOL(result)->remat &&
6437 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6439 int size = AOP_SIZE(right) - 1;
6441 emitcode("dec","%s",rname);
6446 freeAsmop(right,NULL,ic,TRUE);
6451 /*-----------------------------------------------------------------*/
6452 /* genPagedPointerSet - emitcode for Paged pointer put */
6453 /*-----------------------------------------------------------------*/
6454 static void genPagedPointerSet (operand *right,
6463 retype= getSpec(operandType(right));
6465 aopOp(result,ic,FALSE);
6467 /* if the value is already in a pointer register
6468 then don't need anything more */
6469 if (!AOP_INPREG(AOP(result))) {
6470 /* otherwise get a free pointer register */
6472 preg = getFreePtr(ic,&aop,FALSE);
6473 emitcode("mov","%s,%s",
6475 aopGet(AOP(result),0,FALSE,TRUE));
6476 rname = preg->name ;
6478 rname = aopGet(AOP(result),0,FALSE,FALSE);
6480 freeAsmop(result,NULL,ic,TRUE);
6481 aopOp (right,ic,FALSE);
6483 /* if bitfield then unpack the bits */
6484 if (IS_BITVAR(retype))
6485 genPackBits (retype,right,rname,PPOINTER);
6487 /* we have can just get the values */
6488 int size = AOP_SIZE(right);
6492 l = aopGet(AOP(right),offset,FALSE,TRUE);
6495 emitcode("movx","@%s,a",rname);
6498 emitcode("inc","%s",rname);
6504 /* now some housekeeping stuff */
6506 /* we had to allocate for this iCode */
6507 freeAsmop(NULL,aop,ic,TRUE);
6509 /* we did not allocate which means left
6510 already in a pointer register, then
6511 if size > 0 && this could be used again
6512 we have to point it back to where it
6514 if (AOP_SIZE(right) > 1 &&
6515 !OP_SYMBOL(result)->remat &&
6516 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6518 int size = AOP_SIZE(right) - 1;
6520 emitcode("dec","%s",rname);
6525 freeAsmop(right,NULL,ic,TRUE);
6530 /*-----------------------------------------------------------------*/
6531 /* genFarPointerSet - set value from far space */
6532 /*-----------------------------------------------------------------*/
6533 static void genFarPointerSet (operand *right,
6534 operand *result, iCode *ic)
6537 link *retype = getSpec(operandType(right));
6539 aopOp(result,ic,FALSE);
6541 /* if the operand is already in dptr
6542 then we do nothing else we move the value to dptr */
6543 if (AOP_TYPE(result) != AOP_STR) {
6544 /* if this is remateriazable */
6545 if (AOP_TYPE(result) == AOP_IMMD)
6546 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6547 else { /* we need to get it byte by byte */
6548 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6549 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6550 if (options.model == MODEL_FLAT24)
6552 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6556 /* so dptr know contains the address */
6557 freeAsmop(result,NULL,ic,TRUE);
6558 aopOp(right,ic,FALSE);
6560 /* if bit then unpack */
6561 if (IS_BITVAR(retype))
6562 genPackBits(retype,right,"dptr",FPOINTER);
6564 size = AOP_SIZE(right);
6568 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6570 emitcode("movx","@dptr,a");
6572 emitcode("inc","dptr");
6576 freeAsmop(right,NULL,ic,TRUE);
6579 /*-----------------------------------------------------------------*/
6580 /* genGenPointerSet - set value from generic pointer space */
6581 /*-----------------------------------------------------------------*/
6582 static void genGenPointerSet (operand *right,
6583 operand *result, iCode *ic)
6586 link *retype = getSpec(operandType(right));
6588 aopOp(result,ic,FALSE);
6590 /* if the operand is already in dptr
6591 then we do nothing else we move the value to dptr */
6592 if (AOP_TYPE(result) != AOP_STR) {
6593 /* if this is remateriazable */
6594 if (AOP_TYPE(result) == AOP_IMMD) {
6595 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6596 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
6598 else { /* we need to get it byte by byte */
6599 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6600 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6601 if (options.model == MODEL_FLAT24)
6603 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6604 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
6608 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
6612 /* so dptr know contains the address */
6613 freeAsmop(result,NULL,ic,TRUE);
6614 aopOp(right,ic,FALSE);
6616 /* if bit then unpack */
6617 if (IS_BITVAR(retype))
6618 genPackBits(retype,right,"dptr",GPOINTER);
6620 size = AOP_SIZE(right);
6624 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6626 emitcode("lcall","__gptrput");
6628 emitcode("inc","dptr");
6632 freeAsmop(right,NULL,ic,TRUE);
6635 /*-----------------------------------------------------------------*/
6636 /* genPointerSet - stores the value into a pointer location */
6637 /*-----------------------------------------------------------------*/
6638 static void genPointerSet (iCode *ic)
6640 operand *right, *result ;
6644 right = IC_RIGHT(ic);
6645 result = IC_RESULT(ic) ;
6647 /* depending on the type of pointer we need to
6648 move it to the correct pointer register */
6649 type = operandType(result);
6650 etype = getSpec(type);
6651 /* if left is of type of pointer then it is simple */
6652 if (IS_PTR(type) && !IS_FUNC(type->next)) {
6653 p_type = DCL_TYPE(type);
6657 /* we have to go by the storage class */
6658 if (SPEC_OCLS(etype)->codesp ) {
6662 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
6665 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
6668 if (SPEC_OCLS(etype) == idata )
6674 /* now that we have the pointer type we assign
6675 the pointer values */
6680 genNearPointerSet (right,result,ic);
6684 genPagedPointerSet (right,result,ic);
6688 genFarPointerSet (right,result,ic);
6692 genGenPointerSet (right,result,ic);
6698 /*-----------------------------------------------------------------*/
6699 /* genIfx - generate code for Ifx statement */
6700 /*-----------------------------------------------------------------*/
6701 static void genIfx (iCode *ic, iCode *popIc)
6703 operand *cond = IC_COND(ic);
6706 aopOp(cond,ic,FALSE);
6708 /* get the value into acc */
6709 if (AOP_TYPE(cond) != AOP_CRY)
6713 /* the result is now in the accumulator */
6714 freeAsmop(cond,NULL,ic,TRUE);
6716 /* if there was something to be popped then do it */
6720 /* if the condition is a bit variable */
6721 if (isbit && IS_ITEMP(cond) &&
6723 genIfxJump(ic,SPIL_LOC(cond)->rname);
6725 if (isbit && !IS_ITEMP(cond))
6726 genIfxJump(ic,OP_SYMBOL(cond)->rname);
6733 /*-----------------------------------------------------------------*/
6734 /* genAddrOf - generates code for address of */
6735 /*-----------------------------------------------------------------*/
6736 static void genAddrOf (iCode *ic)
6738 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
6741 aopOp(IC_RESULT(ic),ic,FALSE);
6743 /* if the operand is on the stack then we
6744 need to get the stack offset of this
6747 /* if it has an offset then we need to compute
6750 emitcode("mov","a,_bp");
6751 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
6752 aopPut(AOP(IC_RESULT(ic)),"a",0);
6754 /* we can just move _bp */
6755 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
6756 /* fill the result with zero */
6757 size = AOP_SIZE(IC_RESULT(ic)) - 1;
6760 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
6765 /* object not on stack then we need the name */
6766 size = AOP_SIZE(IC_RESULT(ic));
6770 char s[SDCC_NAME_MAX];
6772 sprintf(s,"#(%s >> %d)",
6776 sprintf(s,"#%s",sym->rname);
6777 aopPut(AOP(IC_RESULT(ic)),s,offset++);
6781 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
6785 /*-----------------------------------------------------------------*/
6786 /* genFarFarAssign - assignment when both are in far space */
6787 /*-----------------------------------------------------------------*/
6788 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
6790 int size = AOP_SIZE(right);
6793 /* first push the right side on to the stack */
6795 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6797 emitcode ("push","acc");
6800 freeAsmop(right,NULL,ic,FALSE);
6801 /* now assign DPTR to result */
6802 aopOp(result,ic,FALSE);
6803 size = AOP_SIZE(result);
6805 emitcode ("pop","acc");
6806 aopPut(AOP(result),"a",--offset);
6808 freeAsmop(result,NULL,ic,FALSE);
6812 /*-----------------------------------------------------------------*/
6813 /* genAssign - generate code for assignment */
6814 /*-----------------------------------------------------------------*/
6815 static void genAssign (iCode *ic)
6817 operand *result, *right;
6819 unsigned long lit = 0L;
6821 result = IC_RESULT(ic);
6822 right = IC_RIGHT(ic) ;
6824 /* if they are the same */
6825 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
6828 aopOp(right,ic,FALSE);
6830 /* special case both in far space */
6831 if (AOP_TYPE(right) == AOP_DPTR &&
6832 IS_TRUE_SYMOP(result) &&
6833 isOperandInFarSpace(result)) {
6835 genFarFarAssign (result,right,ic);
6839 aopOp(result,ic,TRUE);
6841 /* if they are the same registers */
6842 if (sameRegs(AOP(right),AOP(result)))
6845 /* if the result is a bit */
6846 if (AOP_TYPE(result) == AOP_CRY) {
6848 /* if the right size is a literal then
6849 we know what the value is */
6850 if (AOP_TYPE(right) == AOP_LIT) {
6851 if (((int) operandLitValue(right)))
6852 aopPut(AOP(result),one,0);
6854 aopPut(AOP(result),zero,0);
6858 /* the right is also a bit variable */
6859 if (AOP_TYPE(right) == AOP_CRY) {
6860 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6861 aopPut(AOP(result),"c",0);
6867 aopPut(AOP(result),"a",0);
6871 /* bit variables done */
6873 size = AOP_SIZE(result);
6875 if(AOP_TYPE(right) == AOP_LIT)
6876 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6878 (AOP_TYPE(result) != AOP_REG) &&
6879 (AOP_TYPE(right) == AOP_LIT) &&
6880 !IS_FLOAT(operandType(right)) &&
6882 emitcode("clr","a");
6884 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
6885 aopPut(AOP(result),"a",size);
6888 aopGet(AOP(right),size,FALSE,FALSE),
6894 aopGet(AOP(right),offset,FALSE,FALSE),
6901 freeAsmop (right,NULL,ic,FALSE);
6902 freeAsmop (result,NULL,ic,TRUE);
6905 /*-----------------------------------------------------------------*/
6906 /* genJumpTab - genrates code for jump table */
6907 /*-----------------------------------------------------------------*/
6908 static void genJumpTab (iCode *ic)
6913 aopOp(IC_JTCOND(ic),ic,FALSE);
6914 /* get the condition into accumulator */
6915 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
6917 /* multiply by three */
6918 emitcode("add","a,acc");
6919 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
6920 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
6922 jtab = newiTempLabel(NULL);
6923 emitcode("mov","dptr,#%05d$",jtab->key+100);
6924 emitcode("jmp","@a+dptr");
6925 emitcode("","%05d$:",jtab->key+100);
6926 /* now generate the jump labels */
6927 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
6928 jtab = setNextItem(IC_JTLABELS(ic)))
6929 emitcode("ljmp","%05d$",jtab->key+100);
6933 /*-----------------------------------------------------------------*/
6934 /* genCast - gen code for casting */
6935 /*-----------------------------------------------------------------*/
6936 static void genCast (iCode *ic)
6938 operand *result = IC_RESULT(ic);
6939 link *ctype = operandType(IC_LEFT(ic));
6940 operand *right = IC_RIGHT(ic);
6943 /* if they are equivalent then do nothing */
6944 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
6947 aopOp(right,ic,FALSE) ;
6948 aopOp(result,ic,FALSE);
6950 /* if the result is a bit */
6951 if (AOP_TYPE(result) == AOP_CRY) {
6952 /* if the right size is a literal then
6953 we know what the value is */
6954 if (AOP_TYPE(right) == AOP_LIT) {
6955 if (((int) operandLitValue(right)))
6956 aopPut(AOP(result),one,0);
6958 aopPut(AOP(result),zero,0);
6963 /* the right is also a bit variable */
6964 if (AOP_TYPE(right) == AOP_CRY) {
6965 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6966 aopPut(AOP(result),"c",0);
6972 aopPut(AOP(result),"a",0);
6976 /* if they are the same size : or less */
6977 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
6979 /* if they are in the same place */
6980 if (sameRegs(AOP(right),AOP(result)))
6983 /* if they in different places then copy */
6984 size = AOP_SIZE(result);
6988 aopGet(AOP(right),offset,FALSE,FALSE),
6996 /* if the result is of type pointer */
6997 if (IS_PTR(ctype)) {
7000 link *type = operandType(right);
7001 link *etype = getSpec(type);
7003 /* pointer to generic pointer */
7004 if (IS_GENPTR(ctype)) {
7008 p_type = DCL_TYPE(type);
7010 /* we have to go by the storage class */
7011 if (SPEC_OCLS(etype)->codesp )
7014 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
7017 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
7020 if (SPEC_OCLS(etype) == idata )
7026 /* the first two bytes are known */
7027 size = GPTRSIZE - 1;
7031 aopGet(AOP(right),offset,FALSE,FALSE),
7035 /* the last byte depending on type */
7052 /* this should never happen */
7053 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7054 "got unknown pointer type");
7057 aopPut(AOP(result),l, GPTRSIZE - 1);
7061 /* just copy the pointers */
7062 size = AOP_SIZE(result);
7066 aopGet(AOP(right),offset,FALSE,FALSE),
7073 /* so we now know that the size of destination is greater
7074 than the size of the source */
7075 /* we move to result for the size of source */
7076 size = AOP_SIZE(right);
7080 aopGet(AOP(right),offset,FALSE,FALSE),
7085 /* now depending on the sign of the destination */
7086 size = AOP_SIZE(result) - AOP_SIZE(right);
7087 /* if unsigned or not an integral type */
7088 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
7090 aopPut(AOP(result),zero,offset++);
7092 /* we need to extend the sign :{ */
7093 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
7096 emitcode("rlc","a");
7097 emitcode("subb","a,acc");
7099 aopPut(AOP(result),"a",offset++);
7102 /* we are done hurray !!!! */
7105 freeAsmop(right,NULL,ic,TRUE);
7106 freeAsmop(result,NULL,ic,TRUE);
7110 /*-----------------------------------------------------------------*/
7111 /* genDjnz - generate decrement & jump if not zero instrucion */
7112 /*-----------------------------------------------------------------*/
7113 static int genDjnz (iCode *ic, iCode *ifx)
7119 /* if the if condition has a false label
7120 then we cannot save */
7124 /* if the minus is not of the form
7126 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
7127 !IS_OP_LITERAL(IC_RIGHT(ic)))
7130 if (operandLitValue(IC_RIGHT(ic)) != 1)
7133 /* if the size of this greater than one then no
7135 if (getSize(operandType(IC_RESULT(ic))) > 1)
7138 /* otherwise we can save BIG */
7139 lbl = newiTempLabel(NULL);
7140 lbl1= newiTempLabel(NULL);
7142 aopOp(IC_RESULT(ic),ic,FALSE);
7144 if (IS_AOP_PREG(IC_RESULT(ic))) {
7145 emitcode("dec","%s",
7146 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7147 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7148 emitcode("jnz","%05d$",lbl->key+100);
7150 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
7153 emitcode ("sjmp","%05d$",lbl1->key+100);
7154 emitcode ("","%05d$:",lbl->key+100);
7155 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
7156 emitcode ("","%05d$:",lbl1->key+100);
7158 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7163 /*-----------------------------------------------------------------*/
7164 /* genReceive - generate code for a receive iCode */
7165 /*-----------------------------------------------------------------*/
7166 static void genReceive (iCode *ic)
7168 if (isOperandInFarSpace(IC_RESULT(ic)) &&
7169 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
7170 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
7172 int size = getSize(operandType(IC_RESULT(ic)));
7173 int offset = 4 - size;
7175 emitcode ("push","%s", (strcmp(fReturn[3 - offset],"a") ?
7176 fReturn[3 - offset] : "acc"));
7179 aopOp(IC_RESULT(ic),ic,FALSE);
7180 size = AOP_SIZE(IC_RESULT(ic));
7183 emitcode ("pop","acc");
7184 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
7189 aopOp(IC_RESULT(ic),ic,FALSE);
7191 assignResultValue(IC_RESULT(ic));
7194 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7197 /*-----------------------------------------------------------------*/
7198 /* gen51Code - generate code for 8051 based controllers */
7199 /*-----------------------------------------------------------------*/
7200 void gen51Code (iCode *lic)
7205 lineHead = lineCurr = NULL;
7207 /* if debug information required */
7208 /* if (options.debug && currFunc) { */
7210 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
7212 if (IS_STATIC(currFunc->etype))
7213 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
7215 emitcode("","G$%s$0$0 ==.",currFunc->name);
7218 /* stack pointer name */
7219 if (options.useXstack)
7225 for (ic = lic ; ic ; ic = ic->next ) {
7227 if ( cln != ic->lineno ) {
7228 if ( options.debug ) {
7230 emitcode("","C$%s$%d$%d$%d ==.",
7231 ic->filename,ic->lineno,
7232 ic->level,ic->block);
7235 emitcode(";","%s %d",ic->filename,ic->lineno);
7238 /* if the result is marked as
7239 spilt and rematerializable or code for
7240 this has already been generated then
7242 if (resultRemat(ic) || ic->generated )
7245 /* depending on the operation */
7264 /* IPOP happens only when trying to restore a
7265 spilt live range, if there is an ifx statement
7266 following this pop then the if statement might
7267 be using some of the registers being popped which
7268 would destory the contents of the register so
7269 we need to check for this condition and handle it */
7271 ic->next->op == IFX &&
7272 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
7273 genIfx (ic->next,ic);
7291 genEndFunction (ic);
7311 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
7328 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
7332 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
7339 /* note these two are xlated by algebraic equivalence
7340 during parsing SDCC.y */
7341 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7342 "got '>=' or '<=' shouldn't have come here");
7346 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
7358 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
7362 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
7366 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
7393 case GET_VALUE_AT_ADDRESS:
7398 if (POINTER_SET(ic))
7425 addSet(&_G.sendSet,ic);
7430 /* piCode(ic,stdout); */
7436 /* now we are ready to call the
7437 peep hole optimizer */
7438 if (!options.nopeep)
7439 peepHole (&lineHead);
7441 /* now do the actual printing */
7442 printLine (lineHead,codeOutFile);