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>
44 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
45 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
51 #include "SDCCpeeph.h"
55 char *aopLiteral (value *val, int offset);
57 /* this is the down and dirty file with all kinds of
58 kludgy & hacky stuff. This is what it is all about
59 CODE GENERATION for a specific MCU . some of the
60 routines may be reusable, will have to see */
62 static char *zero = "#0x00";
63 static char *one = "#0x01";
66 char *fReturn8051[] = {"dpl","dph","b","a" };
67 char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
68 unsigned fReturnSize = 4; /* shared with ralloc.c */
69 char **fReturn = fReturn8051;
70 static char *accUse[] = {"a","b"};
72 static short rbank = -1;
84 extern int mcs51_ptrRegReq ;
85 extern int mcs51_nRegs;
86 extern FILE *codeOutFile;
87 static void saverbank (int, iCode *,bool);
88 #define RESULTONSTACK(x) \
89 (IC_RESULT(x) && IC_RESULT(x)->aop && \
90 IC_RESULT(x)->aop->type == AOP_STK )
92 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x);
93 #define CLRC emitcode("clr","c");
95 static lineNode *lineHead = NULL;
96 static lineNode *lineCurr = NULL;
98 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
99 0xE0, 0xC0, 0x80, 0x00};
100 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
101 0x07, 0x03, 0x01, 0x00};
108 /*-----------------------------------------------------------------*/
109 /* emitcode - writes the code into a file : for now it is simple */
110 /*-----------------------------------------------------------------*/
111 static void emitcode (char *inst,char *fmt, ...)
114 char lb[MAX_INLINEASM];
121 sprintf(lb,"%s\t",inst);
123 sprintf(lb,"%s",inst);
124 vsprintf(lb+(strlen(lb)),fmt,ap);
128 while (isspace(*lbp)) lbp++;
131 lineCurr = (lineCurr ?
132 connectLine(lineCurr,newLineNode(lb)) :
133 (lineHead = newLineNode(lb)));
134 lineCurr->isInline = _G.inLine;
135 lineCurr->isDebug = _G.debugLine;
139 /*-----------------------------------------------------------------*/
140 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
141 /*-----------------------------------------------------------------*/
142 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
144 bool r0iu = FALSE , r1iu = FALSE;
145 bool r0ou = FALSE , r1ou = FALSE;
147 /* the logic: if r0 & r1 used in the instruction
148 then we are in trouble otherwise */
150 /* first check if r0 & r1 are used by this
151 instruction, in which case we are in trouble */
152 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
153 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
158 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
159 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
161 /* if no usage of r0 then return it */
162 if (!r0iu && !r0ou) {
163 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
164 (*aopp)->type = AOP_R0;
166 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R0_IDX);
169 /* if no usage of r1 then return it */
170 if (!r1iu && !r1ou) {
171 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
172 (*aopp)->type = AOP_R1;
174 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R1_IDX);
177 /* now we know they both have usage */
178 /* if r0 not used in this instruction */
180 /* push it if not already pushed */
182 emitcode ("push","%s",
183 mcs51_regWithIdx(R0_IDX)->dname);
187 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
188 (*aopp)->type = AOP_R0;
190 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R0_IDX);
193 /* if r1 not used then */
196 /* push it if not already pushed */
198 emitcode ("push","%s",
199 mcs51_regWithIdx(R1_IDX)->dname);
203 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
204 (*aopp)->type = AOP_R1;
205 return mcs51_regWithIdx(R1_IDX);
209 /* I said end of world but not quite end of world yet */
210 /* if this is a result then we can push it on the stack*/
212 (*aopp)->type = AOP_STK;
217 /* other wise this is true end of the world */
218 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
219 "getFreePtr should never reach here");
223 /*-----------------------------------------------------------------*/
224 /* newAsmop - creates a new asmOp */
225 /*-----------------------------------------------------------------*/
226 static asmop *newAsmop (short type)
230 ALLOC(aop,sizeof(asmop));
235 static void genSetDPTR(int n)
239 emitcode(";", "Select standard DPTR");
240 emitcode("mov", "dps, #0x00");
244 emitcode(";", "Select alternate DPTR");
245 emitcode("mov", "dps, #0x01");
249 /*-----------------------------------------------------------------*/
250 /* pointerCode - returns the code for a pointer type */
251 /*-----------------------------------------------------------------*/
252 static int pointerCode (link *etype)
255 return PTR_TYPE(SPEC_OCLS(etype));
259 /*-----------------------------------------------------------------*/
260 /* aopForSym - for a true symbol */
261 /*-----------------------------------------------------------------*/
262 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
265 memmap *space= SPEC_OCLS(sym->etype);
267 /* if already has one */
271 /* assign depending on the storage class */
272 /* if it is on the stack or indirectly addressable */
273 /* space we need to assign either r0 or r1 to it */
274 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
275 sym->aop = aop = newAsmop(0);
276 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
277 aop->size = getSize(sym->type);
279 /* now assign the address of the variable to
280 the pointer register */
281 if (aop->type != AOP_STK) {
285 emitcode("push","acc");
287 emitcode("mov","a,_bp");
288 emitcode("add","a,#0x%02x",
290 ((char)(sym->stack - _G.nRegsSaved )) :
291 ((char)sym->stack)) & 0xff);
292 emitcode("mov","%s,a",
293 aop->aopu.aop_ptr->name);
296 emitcode("pop","acc");
298 emitcode("mov","%s,#%s",
299 aop->aopu.aop_ptr->name,
301 aop->paged = space->paged;
303 aop->aopu.aop_stk = sym->stack;
307 if (sym->onStack && options.stack10bit)
309 /* It's on the 10 bit stack, which is located in
314 emitcode("push","acc");
316 emitcode("mov","a,_bp");
317 emitcode("add","a,#0x%02x",
319 ((char)(sym->stack - _G.nRegsSaved )) :
320 ((char)sym->stack)) & 0xff);
323 emitcode ("mov","dpx1,#0x40");
324 emitcode ("mov","dph1,#0x00");
325 emitcode ("mov","dpl1, a");
329 emitcode("pop","acc");
331 sym->aop = aop = newAsmop(AOP_DPTR2);
332 aop->size = getSize(sym->type);
336 /* if in bit space */
337 if (IN_BITSPACE(space)) {
338 sym->aop = aop = newAsmop (AOP_CRY);
339 aop->aopu.aop_dir = sym->rname ;
340 aop->size = getSize(sym->type);
343 /* if it is in direct space */
344 if (IN_DIRSPACE(space)) {
345 sym->aop = aop = newAsmop (AOP_DIR);
346 aop->aopu.aop_dir = sym->rname ;
347 aop->size = getSize(sym->type);
351 /* special case for a function */
352 if (IS_FUNC(sym->type)) {
353 sym->aop = aop = newAsmop(AOP_IMMD);
354 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
355 strcpy(aop->aopu.aop_immd,sym->rname);
356 aop->size = FPTRSIZE;
360 /* only remaining is far space */
361 /* in which case DPTR gets the address */
362 sym->aop = aop = newAsmop(AOP_DPTR);
363 emitcode ("mov","dptr,#%s", sym->rname);
364 aop->size = getSize(sym->type);
366 /* if it is in code space */
367 if (IN_CODESPACE(space))
373 /*-----------------------------------------------------------------*/
374 /* aopForRemat - rematerialzes an object */
375 /*-----------------------------------------------------------------*/
376 static asmop *aopForRemat (symbol *sym)
379 iCode *ic = sym->rematiCode;
380 asmop *aop = newAsmop(AOP_IMMD);
384 /* if plus or minus print the right hand side */
385 if (ic->op == '+' || ic->op == '-') {
386 sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
389 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
393 /* we reached the end */
394 sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
398 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
399 strcpy(aop->aopu.aop_immd,buffer);
403 /*-----------------------------------------------------------------*/
404 /* regsInCommon - two operands have some registers in common */
405 /*-----------------------------------------------------------------*/
406 static bool regsInCommon (operand *op1, operand *op2)
411 /* if they have registers in common */
412 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
415 sym1 = OP_SYMBOL(op1);
416 sym2 = OP_SYMBOL(op2);
418 if (sym1->nRegs == 0 || sym2->nRegs == 0)
421 for (i = 0 ; i < sym1->nRegs ; i++) {
426 for (j = 0 ; j < sym2->nRegs ;j++ ) {
430 if (sym2->regs[j] == sym1->regs[i])
438 /*-----------------------------------------------------------------*/
439 /* operandsEqu - equivalent */
440 /*-----------------------------------------------------------------*/
441 static bool operandsEqu ( operand *op1, operand *op2)
445 /* if they not symbols */
446 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
449 sym1 = OP_SYMBOL(op1);
450 sym2 = OP_SYMBOL(op2);
452 /* if both are itemps & one is spilt
453 and the other is not then false */
454 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
455 sym1->isspilt != sym2->isspilt )
458 /* if they are the same */
462 if (strcmp(sym1->rname,sym2->rname) == 0)
466 /* if left is a tmp & right is not */
470 (sym1->usl.spillLoc == sym2))
477 (sym2->usl.spillLoc == sym1))
483 /*-----------------------------------------------------------------*/
484 /* sameRegs - two asmops have the same registers */
485 /*-----------------------------------------------------------------*/
486 static bool sameRegs (asmop *aop1, asmop *aop2 )
493 if (aop1->type != AOP_REG ||
494 aop2->type != AOP_REG )
497 if (aop1->size != aop2->size )
500 for (i = 0 ; i < aop1->size ; i++ )
501 if (aop1->aopu.aop_reg[i] !=
502 aop2->aopu.aop_reg[i] )
508 /*-----------------------------------------------------------------*/
509 /* aopOp - allocates an asmop for an operand : */
510 /*-----------------------------------------------------------------*/
511 static void aopOp (operand *op, iCode *ic, bool result)
520 /* if this a literal */
521 if (IS_OP_LITERAL(op)) {
522 op->aop = aop = newAsmop(AOP_LIT);
523 aop->aopu.aop_lit = op->operand.valOperand;
524 aop->size = getSize(operandType(op));
528 /* if already has a asmop then continue */
532 /* if the underlying symbol has a aop */
533 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
534 op->aop = OP_SYMBOL(op)->aop;
538 /* if this is a true symbol */
539 if (IS_TRUE_SYMOP(op)) {
540 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
544 /* this is a temporary : this has
550 e) can be a return use only */
555 /* if the type is a conditional */
556 if (sym->regType == REG_CND) {
557 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
562 /* if it is spilt then two situations
564 b) has a spill location */
565 if (sym->isspilt || sym->nRegs == 0) {
567 /* rematerialize it NOW */
569 sym->aop = op->aop = aop =
571 aop->size = getSize(sym->type);
577 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
578 aop->size = getSize(sym->type);
579 for ( i = 0 ; i < 2 ; i++ )
580 aop->aopu.aop_str[i] = accUse[i];
586 aop = op->aop = sym->aop = newAsmop(AOP_STR);
587 aop->size = getSize(sym->type);
588 for ( i = 0 ; i < fReturnSize ; i++ )
589 aop->aopu.aop_str[i] = fReturn[i];
593 /* else spill location */
594 sym->aop = op->aop = aop =
595 aopForSym(ic,sym->usl.spillLoc,result);
596 aop->size = getSize(sym->type);
600 /* must be in a register */
601 sym->aop = op->aop = aop = newAsmop(AOP_REG);
602 aop->size = sym->nRegs;
603 for ( i = 0 ; i < sym->nRegs ;i++)
604 aop->aopu.aop_reg[i] = sym->regs[i];
607 /*-----------------------------------------------------------------*/
608 /* freeAsmop - free up the asmop given to an operand */
609 /*----------------------------------------------------------------*/
610 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
627 /* depending on the asmop type only three cases need work AOP_RO
628 , AOP_R1 && AOP_STK */
633 emitcode ("pop","ar0");
637 bitVectUnSetBit(ic->rUsed,R0_IDX);
643 emitcode ("pop","ar1");
647 bitVectUnSetBit(ic->rUsed,R1_IDX);
653 int stk = aop->aopu.aop_stk + aop->size;
654 bitVectUnSetBit(ic->rUsed,R0_IDX);
655 bitVectUnSetBit(ic->rUsed,R1_IDX);
657 getFreePtr(ic,&aop,FALSE);
659 if (options.stack10bit)
661 /* I'm not sure what to do here yet... */
664 "*** Warning: probably generating bad code for "
665 "10 bit stack mode.\n");
669 emitcode ("mov","a,_bp");
670 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
671 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
673 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
677 emitcode("pop","acc");
678 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
680 emitcode("dec","%s",aop->aopu.aop_ptr->name);
683 freeAsmop(op,NULL,ic,TRUE);
685 emitcode("pop","ar0");
690 emitcode("pop","ar1");
697 /* all other cases just dealloc */
701 OP_SYMBOL(op)->aop = NULL;
702 /* if the symbol has a spill */
704 SPIL_LOC(op)->aop = NULL;
709 /*-----------------------------------------------------------------*/
710 /* aopGet - for fetching value of the aop */
711 /*-----------------------------------------------------------------*/
712 static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
717 /* offset is greater than
719 if (offset > (aop->size - 1) &&
720 aop->type != AOP_LIT)
723 /* depending on type */
728 /* if we need to increment it */
729 while (offset > aop->coff) {
730 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
734 while (offset < aop->coff) {
735 emitcode("dec","%s",aop->aopu.aop_ptr->name);
741 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
742 return (dname ? "acc" : "a");
744 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
745 ALLOC_ATOMIC(rs,strlen(s)+1);
752 if (aop->type == AOP_DPTR2)
757 while (offset > aop->coff) {
758 emitcode ("inc","dptr");
762 while (offset < aop->coff) {
763 emitcode("lcall","__decdptr");
770 emitcode("movc","a,@a+dptr");
773 emitcode("movx","a,@dptr");
776 if (aop->type == AOP_DPTR2)
781 return (dname ? "acc" : "a");
786 sprintf (s,"#(%s)",aop->aopu.aop_immd);
789 sprintf(s,"#(%s >> %d)",
795 ALLOC_ATOMIC(rs,strlen(s)+1);
801 sprintf(s,"(%s + %d)",
805 sprintf(s,"%s",aop->aopu.aop_dir);
806 ALLOC_ATOMIC(rs,strlen(s)+1);
812 return aop->aopu.aop_reg[offset]->dname;
814 return aop->aopu.aop_reg[offset]->name;
818 emitcode("mov","c,%s",aop->aopu.aop_dir);
819 emitcode("rlc","a") ;
820 return (dname ? "acc" : "a");
823 if (!offset && dname)
825 return aop->aopu.aop_str[offset];
828 return aopLiteral (aop->aopu.aop_lit,offset);
832 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
836 return aop->aopu.aop_str[offset];
840 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
841 "aopget got unsupported aop->type");
844 /*-----------------------------------------------------------------*/
845 /* aopPut - puts a string for a aop */
846 /*-----------------------------------------------------------------*/
847 static void aopPut (asmop *aop, char *s, int offset)
852 if (aop->size && offset > ( aop->size - 1)) {
853 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
854 "aopPut got offset > aop->size");
858 /* will assign value to value */
859 /* depending on where it is ofcourse */
863 sprintf(d,"(%s + %d)",
864 aop->aopu.aop_dir,offset);
866 sprintf(d,"%s",aop->aopu.aop_dir);
869 emitcode("mov","%s,%s",d,s);
874 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
875 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
877 strcmp(s,"r0") == 0 ||
878 strcmp(s,"r1") == 0 ||
879 strcmp(s,"r2") == 0 ||
880 strcmp(s,"r3") == 0 ||
881 strcmp(s,"r4") == 0 ||
882 strcmp(s,"r5") == 0 ||
883 strcmp(s,"r6") == 0 ||
884 strcmp(s,"r7") == 0 )
885 emitcode("mov","%s,%s",
886 aop->aopu.aop_reg[offset]->dname,s);
888 emitcode("mov","%s,%s",
889 aop->aopu.aop_reg[offset]->name,s);
896 if (aop->type == AOP_DPTR2)
902 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
903 "aopPut writting to code space");
907 while (offset > aop->coff) {
909 emitcode ("inc","dptr");
912 while (offset < aop->coff) {
914 emitcode("lcall","__decdptr");
919 /* if not in accumulater */
922 emitcode ("movx","@dptr,a");
924 if (aop->type == AOP_DPTR2)
932 while (offset > aop->coff) {
934 emitcode("inc","%s",aop->aopu.aop_ptr->name);
936 while (offset < aop->coff) {
938 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
944 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
949 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
951 if (strcmp(s,"r0") == 0 ||
952 strcmp(s,"r1") == 0 ||
953 strcmp(s,"r2") == 0 ||
954 strcmp(s,"r3") == 0 ||
955 strcmp(s,"r4") == 0 ||
956 strcmp(s,"r5") == 0 ||
957 strcmp(s,"r6") == 0 ||
958 strcmp(s,"r7") == 0 ) {
960 sprintf(buffer,"a%s",s);
961 emitcode("mov","@%s,%s",
962 aop->aopu.aop_ptr->name,buffer);
964 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
969 if (strcmp(s,"a") == 0)
970 emitcode("push","acc");
972 emitcode("push","%s",s);
977 /* if bit variable */
978 if (!aop->aopu.aop_dir) {
983 emitcode("clr","%s",aop->aopu.aop_dir);
986 emitcode("setb","%s",aop->aopu.aop_dir);
989 emitcode("mov","%s,c",aop->aopu.aop_dir);
991 lbl = newiTempLabel(NULL);
997 emitcode("jz","%05d$",lbl->key+100);
999 emitcode("","%05d$:",lbl->key+100);
1000 emitcode("mov","%s,c",aop->aopu.aop_dir);
1007 if (strcmp(aop->aopu.aop_str[offset],s))
1008 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1013 if (!offset && (strcmp(s,"acc") == 0))
1016 if (strcmp(aop->aopu.aop_str[offset],s))
1017 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1021 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1022 "aopPut got unsupported aop->type");
1030 /*-----------------------------------------------------------------*/
1031 /* pointToEnd :- points to the last byte of the operand */
1032 /*-----------------------------------------------------------------*/
1033 static void pointToEnd (asmop *aop)
1039 aop->coff = count = (aop->size - 1);
1040 switch (aop->type) {
1044 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1048 emitcode("inc","dptr");
1055 /*-----------------------------------------------------------------*/
1056 /* reAdjustPreg - points a register back to where it should */
1057 /*-----------------------------------------------------------------*/
1058 static void reAdjustPreg (asmop *aop)
1063 if ((size = aop->size) <= 1)
1066 switch (aop->type) {
1070 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1074 if (aop->type == AOP_DPTR2)
1080 emitcode("lcall","__decdptr");
1083 if (aop->type == AOP_DPTR2)
1093 #define AOP(op) op->aop
1094 #define AOP_TYPE(op) AOP(op)->type
1095 #define AOP_SIZE(op) AOP(op)->size
1096 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1097 AOP_TYPE(x) == AOP_R0))
1099 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1100 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1103 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1104 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1105 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1107 /*-----------------------------------------------------------------*/
1108 /* genNotFloat - generates not for float operations */
1109 /*-----------------------------------------------------------------*/
1110 static void genNotFloat (operand *op, operand *res)
1116 /* we will put 127 in the first byte of
1118 aopPut(AOP(res),"#127",0);
1119 size = AOP_SIZE(op) - 1;
1122 l = aopGet(op->aop,offset++,FALSE,FALSE);
1126 emitcode("orl","a,%s",
1128 offset++,FALSE,FALSE));
1130 tlbl = newiTempLabel(NULL);
1132 tlbl = newiTempLabel(NULL);
1133 aopPut(res->aop,one,1);
1134 emitcode("jz","%05d$",(tlbl->key+100));
1135 aopPut(res->aop,zero,1);
1136 emitcode("","%05d$:",(tlbl->key+100));
1138 size = res->aop->size - 2;
1140 /* put zeros in the rest */
1142 aopPut(res->aop,zero,offset++);
1145 /*-----------------------------------------------------------------*/
1146 /* opIsGptr: returns non-zero if the passed operand is */
1147 /* a generic pointer type. */
1148 /*-----------------------------------------------------------------*/
1149 static int opIsGptr(operand *op)
1151 link *type = operandType(op);
1153 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1160 /*-----------------------------------------------------------------*/
1161 /* getDataSize - get the operand data size */
1162 /*-----------------------------------------------------------------*/
1163 static int getDataSize(operand *op)
1166 size = AOP_SIZE(op);
1167 if (size == GPTRSIZE)
1169 link *type = operandType(op);
1170 if (IS_GENPTR(type))
1172 /* generic pointer; arithmetic operations
1173 * should ignore the high byte (pointer type).
1181 /*-----------------------------------------------------------------*/
1182 /* outAcc - output Acc */
1183 /*-----------------------------------------------------------------*/
1184 static void outAcc(operand *result)
1187 size = getDataSize(result);
1189 aopPut(AOP(result),"a",0);
1192 /* unsigned or positive */
1194 aopPut(AOP(result),zero,offset++);
1199 /*-----------------------------------------------------------------*/
1200 /* outBitC - output a bit C */
1201 /*-----------------------------------------------------------------*/
1202 static void outBitC(operand *result)
1204 /* if the result is bit */
1205 if (AOP_TYPE(result) == AOP_CRY)
1206 aopPut(AOP(result),"c",0);
1208 emitcode("clr","a");
1209 emitcode("rlc","a");
1214 /*-----------------------------------------------------------------*/
1215 /* toBoolean - emit code for orl a,operator(sizeop) */
1216 /*-----------------------------------------------------------------*/
1217 static void toBoolean(operand *oper)
1219 int size = AOP_SIZE(oper) - 1;
1221 MOVA(aopGet(AOP(oper),0,FALSE,FALSE));
1223 emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE));
1227 /*-----------------------------------------------------------------*/
1228 /* genNot - generate code for ! operation */
1229 /*-----------------------------------------------------------------*/
1230 static void genNot (iCode *ic)
1233 link *optype = operandType(IC_LEFT(ic));
1235 /* assign asmOps to operand & result */
1236 aopOp (IC_LEFT(ic),ic,FALSE);
1237 aopOp (IC_RESULT(ic),ic,TRUE);
1239 /* if in bit space then a special case */
1240 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1241 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1242 emitcode("cpl","c");
1243 outBitC(IC_RESULT(ic));
1247 /* if type float then do float */
1248 if (IS_FLOAT(optype)) {
1249 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1253 toBoolean(IC_LEFT(ic));
1255 tlbl = newiTempLabel(NULL);
1256 emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1257 emitcode("","%05d$:",tlbl->key+100);
1258 outBitC(IC_RESULT(ic));
1261 /* release the aops */
1262 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1263 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1267 /*-----------------------------------------------------------------*/
1268 /* genCpl - generate code for complement */
1269 /*-----------------------------------------------------------------*/
1270 static void genCpl (iCode *ic)
1276 /* assign asmOps to operand & result */
1277 aopOp (IC_LEFT(ic),ic,FALSE);
1278 aopOp (IC_RESULT(ic),ic,TRUE);
1280 /* if both are in bit space then
1282 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1283 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1285 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1286 emitcode("cpl","c");
1287 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1291 size = AOP_SIZE(IC_RESULT(ic));
1293 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1295 emitcode("cpl","a");
1296 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1301 /* release the aops */
1302 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1303 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1306 /*-----------------------------------------------------------------*/
1307 /* genUminusFloat - unary minus for floating points */
1308 /*-----------------------------------------------------------------*/
1309 static void genUminusFloat(operand *op,operand *result)
1311 int size ,offset =0 ;
1313 /* for this we just need to flip the
1314 first it then copy the rest in place */
1315 size = AOP_SIZE(op) - 1;
1316 l = aopGet(AOP(op),3,FALSE,FALSE);
1320 emitcode("cpl","acc.7");
1321 aopPut(AOP(result),"a",3);
1325 aopGet(AOP(op),offset,FALSE,FALSE),
1331 /*-----------------------------------------------------------------*/
1332 /* genUminus - unary minus code generation */
1333 /*-----------------------------------------------------------------*/
1334 static void genUminus (iCode *ic)
1337 link *optype, *rtype;
1341 aopOp(IC_LEFT(ic),ic,FALSE);
1342 aopOp(IC_RESULT(ic),ic,TRUE);
1344 /* if both in bit space then special
1346 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1347 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1349 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1350 emitcode("cpl","c");
1351 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1355 optype = operandType(IC_LEFT(ic));
1356 rtype = operandType(IC_RESULT(ic));
1358 /* if float then do float stuff */
1359 if (IS_FLOAT(optype)) {
1360 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1364 /* otherwise subtract from zero */
1365 size = AOP_SIZE(IC_LEFT(ic));
1369 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1370 if (!strcmp(l,"a")) {
1371 emitcode("cpl","a");
1372 emitcode("inc","a");
1374 emitcode("clr","a");
1375 emitcode("subb","a,%s",l);
1377 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1380 /* if any remaining bytes in the result */
1381 /* we just need to propagate the sign */
1382 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1383 emitcode("rlc","a");
1384 emitcode("subb","a,acc");
1386 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1390 /* release the aops */
1391 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1392 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1395 /*-----------------------------------------------------------------*/
1396 /* saveRegisters - will look for a call and save the registers */
1397 /*-----------------------------------------------------------------*/
1398 static void saveRegisters(iCode *lic)
1406 for (ic = lic ; ic ; ic = ic->next)
1407 if (ic->op == CALL || ic->op == PCALL)
1411 fprintf(stderr,"found parameter push with no function call\n");
1415 /* if the registers have been saved already then
1417 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1420 /* find the registers in use at this time
1421 and push them away to safety */
1422 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1426 if (options.useXstack) {
1427 if (bitVectBitValue(rsave,R0_IDX))
1428 emitcode("mov","b,r0");
1429 emitcode("mov","r0,%s",spname);
1430 for (i = 0 ; i < mcs51_nRegs ; i++) {
1431 if (bitVectBitValue(rsave,i)) {
1433 emitcode("mov","a,b");
1435 emitcode("mov","a,%s",mcs51_regWithIdx(i)->name);
1436 emitcode("movx","@r0,a");
1437 emitcode("inc","r0");
1440 emitcode("mov","%s,r0",spname);
1441 if (bitVectBitValue(rsave,R0_IDX))
1442 emitcode("mov","r0,b");
1444 for (i = 0 ; i < mcs51_nRegs ; i++) {
1445 if (bitVectBitValue(rsave,i))
1446 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
1449 detype = getSpec(operandType(IC_LEFT(ic)));
1451 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1452 IS_ISR(currFunc->etype) &&
1455 saverbank(SPEC_BANK(detype),ic,TRUE);
1458 /*-----------------------------------------------------------------*/
1459 /* unsaveRegisters - pop the pushed registers */
1460 /*-----------------------------------------------------------------*/
1461 static void unsaveRegisters (iCode *ic)
1465 /* find the registers in use at this time
1466 and push them away to safety */
1467 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1470 if (options.useXstack) {
1471 emitcode("mov","r0,%s",spname);
1472 for (i = mcs51_nRegs ; i >= 0 ; i--) {
1473 if (bitVectBitValue(rsave,i)) {
1474 emitcode("dec","r0");
1475 emitcode("movx","a,@r0");
1477 emitcode("mov","b,a");
1479 emitcode("mov","%s,a",mcs51_regWithIdx(i)->name);
1483 emitcode("mov","%s,r0",spname);
1484 if (bitVectBitValue(rsave,R0_IDX))
1485 emitcode("mov","r0,b");
1487 for (i = mcs51_nRegs ; i >= 0 ; i--) {
1488 if (bitVectBitValue(rsave,i))
1489 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
1495 /*-----------------------------------------------------------------*/
1497 /*-----------------------------------------------------------------*/
1498 static void pushSide(operand * oper, int size)
1502 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1503 if (AOP_TYPE(oper) != AOP_REG &&
1504 AOP_TYPE(oper) != AOP_DIR &&
1506 emitcode("mov","a,%s",l);
1507 emitcode("push","acc");
1509 emitcode("push","%s",l);
1513 /*-----------------------------------------------------------------*/
1514 /* assignResultValue - */
1515 /*-----------------------------------------------------------------*/
1516 static void assignResultValue(operand * oper)
1519 int size = AOP_SIZE(oper);
1521 aopPut(AOP(oper),fReturn[offset],offset);
1527 /*-----------------------------------------------------------------*/
1528 /* genXpush - pushes onto the external stack */
1529 /*-----------------------------------------------------------------*/
1530 static void genXpush (iCode *ic)
1532 asmop *aop = newAsmop(0);
1534 int size,offset = 0;
1536 aopOp(IC_LEFT(ic),ic,FALSE);
1537 r = getFreePtr(ic,&aop,FALSE);
1540 emitcode("mov","%s,_spx",r->name);
1542 size = AOP_SIZE(IC_LEFT(ic));
1545 char *l = aopGet(AOP(IC_LEFT(ic)),
1546 offset++,FALSE,FALSE);
1548 emitcode("movx","@%s,a",r->name);
1549 emitcode("inc","%s",r->name);
1554 emitcode("mov","_spx,%s",r->name);
1556 freeAsmop(NULL,aop,ic,TRUE);
1557 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1560 /*-----------------------------------------------------------------*/
1561 /* genIpush - genrate code for pushing this gets a little complex */
1562 /*-----------------------------------------------------------------*/
1563 static void genIpush (iCode *ic)
1565 int size, offset = 0 ;
1569 /* if this is not a parm push : ie. it is spill push
1570 and spill push is always done on the local stack */
1571 if (!ic->parmPush) {
1573 /* and the item is spilt then do nothing */
1574 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1577 aopOp(IC_LEFT(ic),ic,FALSE);
1578 size = AOP_SIZE(IC_LEFT(ic));
1579 /* push it on the stack */
1581 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1586 emitcode("push","%s",l);
1591 /* this is a paramter push: in this case we call
1592 the routine to find the call and save those
1593 registers that need to be saved */
1596 /* if use external stack then call the external
1597 stack pushing routine */
1598 if (options.useXstack) {
1603 /* then do the push */
1604 aopOp(IC_LEFT(ic),ic,FALSE);
1607 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1608 size = AOP_SIZE(IC_LEFT(ic));
1611 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1612 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1613 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1615 emitcode("mov","a,%s",l);
1616 emitcode("push","acc");
1618 emitcode("push","%s",l);
1621 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1624 /*-----------------------------------------------------------------*/
1625 /* genIpop - recover the registers: can happen only for spilling */
1626 /*-----------------------------------------------------------------*/
1627 static void genIpop (iCode *ic)
1632 /* if the temp was not pushed then */
1633 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1636 aopOp(IC_LEFT(ic),ic,FALSE);
1637 size = AOP_SIZE(IC_LEFT(ic));
1640 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1643 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1646 /*-----------------------------------------------------------------*/
1647 /* unsaverbank - restores the resgister bank from stack */
1648 /*-----------------------------------------------------------------*/
1649 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1656 if (options.useXstack) {
1658 r = getFreePtr(ic,&aop,FALSE);
1661 emitcode("mov","%s,_spx",r->name);
1662 emitcode("movx","a,@%s",r->name);
1663 emitcode("mov","psw,a");
1664 emitcode("dec","%s",r->name);
1667 emitcode ("pop","psw");
1670 for (i = (mcs51_nRegs - 1) ; i >= 0 ;i--) {
1671 if (options.useXstack) {
1672 emitcode("movx","a,@%s",r->name);
1673 emitcode("mov","(%s+%d),a",
1674 regs8051[i].base,8*bank+regs8051[i].offset);
1675 emitcode("dec","%s",r->name);
1678 emitcode("pop","(%s+%d)",
1679 regs8051[i].base,8*bank+regs8051[i].offset);
1682 if (options.useXstack) {
1684 emitcode("mov","_spx,%s",r->name);
1685 freeAsmop(NULL,aop,ic,TRUE);
1690 /*-----------------------------------------------------------------*/
1691 /* saverbank - saves an entire register bank on the stack */
1692 /*-----------------------------------------------------------------*/
1693 static void saverbank (int bank, iCode *ic, bool pushPsw)
1699 if (options.useXstack) {
1702 r = getFreePtr(ic,&aop,FALSE);
1703 emitcode("mov","%s,_spx",r->name);
1707 for (i = 0 ; i < mcs51_nRegs ;i++) {
1708 if (options.useXstack) {
1709 emitcode("inc","%s",r->name);
1710 emitcode("mov","a,(%s+%d)",
1711 regs8051[i].base,8*bank+regs8051[i].offset);
1712 emitcode("movx","@%s,a",r->name);
1714 emitcode("push","(%s+%d)",
1715 regs8051[i].base,8*bank+regs8051[i].offset);
1719 if (options.useXstack) {
1720 emitcode("mov","a,psw");
1721 emitcode("movx","@%s,a",r->name);
1722 emitcode("inc","%s",r->name);
1723 emitcode("mov","_spx,%s",r->name);
1724 freeAsmop (NULL,aop,ic,TRUE);
1727 emitcode("push","psw");
1729 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1735 /*-----------------------------------------------------------------*/
1736 /* genCall - generates a call statement */
1737 /*-----------------------------------------------------------------*/
1738 static void genCall (iCode *ic)
1742 /* if caller saves & we have not saved then */
1746 /* if we are calling a function that is not using
1747 the same register bank then we need to save the
1748 destination registers on the stack */
1749 detype = getSpec(operandType(IC_LEFT(ic)));
1751 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1752 IS_ISR(currFunc->etype) &&
1755 saverbank(SPEC_BANK(detype),ic,TRUE);
1757 /* if send set is not empty the assign */
1761 for (sic = setFirstItem(_G.sendSet) ; sic ;
1762 sic = setNextItem(_G.sendSet)) {
1763 int size, offset = 0;
1764 aopOp(IC_LEFT(sic),sic,FALSE);
1765 size = AOP_SIZE(IC_LEFT(sic));
1767 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1769 if (strcmp(l,fReturn[offset]))
1770 emitcode("mov","%s,%s",
1775 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1780 emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1781 OP_SYMBOL(IC_LEFT(ic))->rname :
1782 OP_SYMBOL(IC_LEFT(ic))->name));
1784 /* if we need assign a result value */
1785 if ((IS_ITEMP(IC_RESULT(ic)) &&
1786 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1787 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1788 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1791 aopOp(IC_RESULT(ic),ic,FALSE);
1794 assignResultValue(IC_RESULT(ic));
1796 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1799 /* adjust the stack for parameters if
1801 if (IC_LEFT(ic)->parmBytes) {
1803 if (IC_LEFT(ic)->parmBytes > 3) {
1804 emitcode("mov","a,%s",spname);
1805 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1806 emitcode("mov","%s,a",spname);
1808 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1809 emitcode("dec","%s",spname);
1813 /* if register bank was saved then pop them */
1815 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1817 /* if we hade saved some registers then unsave them */
1818 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1819 unsaveRegisters (ic);
1824 /*-----------------------------------------------------------------*/
1825 /* genPcall - generates a call by pointer statement */
1826 /*-----------------------------------------------------------------*/
1827 static void genPcall (iCode *ic)
1830 symbol *rlbl = newiTempLabel(NULL);
1833 /* if caller saves & we have not saved then */
1837 /* if we are calling a function that is not using
1838 the same register bank then we need to save the
1839 destination registers on the stack */
1840 detype = getSpec(operandType(IC_LEFT(ic)));
1842 IS_ISR(currFunc->etype) &&
1843 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
1844 saverbank(SPEC_BANK(detype),ic,TRUE);
1847 /* push the return address on to the stack */
1848 emitcode("mov","a,#%05d$",(rlbl->key+100));
1849 emitcode("push","acc");
1850 emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
1851 emitcode("push","acc");
1853 if (options.model == MODEL_FLAT24)
1855 emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
1856 emitcode("push","acc");
1859 /* now push the calling address */
1860 aopOp(IC_LEFT(ic),ic,FALSE);
1862 pushSide(IC_LEFT(ic), FPTRSIZE);
1864 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1866 /* if send set is not empty the assign */
1870 for (sic = setFirstItem(_G.sendSet) ; sic ;
1871 sic = setNextItem(_G.sendSet)) {
1872 int size, offset = 0;
1873 aopOp(IC_LEFT(sic),sic,FALSE);
1874 size = AOP_SIZE(IC_LEFT(sic));
1876 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1878 if (strcmp(l,fReturn[offset]))
1879 emitcode("mov","%s,%s",
1884 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1890 emitcode("","%05d$:",(rlbl->key+100));
1893 /* if we need assign a result value */
1894 if ((IS_ITEMP(IC_RESULT(ic)) &&
1895 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1896 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
1897 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1900 aopOp(IC_RESULT(ic),ic,FALSE);
1903 assignResultValue(IC_RESULT(ic));
1905 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1908 /* adjust the stack for parameters if
1910 if (IC_LEFT(ic)->parmBytes) {
1912 if (IC_LEFT(ic)->parmBytes > 3) {
1913 emitcode("mov","a,%s",spname);
1914 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1915 emitcode("mov","%s,a",spname);
1917 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1918 emitcode("dec","%s",spname);
1922 /* if register bank was saved then unsave them */
1924 (SPEC_BANK(currFunc->etype) !=
1926 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1928 /* if we hade saved some registers then
1931 unsaveRegisters (ic);
1935 /*-----------------------------------------------------------------*/
1936 /* resultRemat - result is rematerializable */
1937 /*-----------------------------------------------------------------*/
1938 static int resultRemat (iCode *ic)
1940 if (SKIP_IC(ic) || ic->op == IFX)
1943 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1944 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1945 if (sym->remat && !POINTER_SET(ic))
1953 #define STRCASECMP stricmp
1955 #define STRCASECMP strcasecmp
1958 /*-----------------------------------------------------------------*/
1959 /* inExcludeList - return 1 if the string is in exclude Reg list */
1960 /*-----------------------------------------------------------------*/
1961 static bool inExcludeList(char *s)
1965 if (options.excludeRegs[i] &&
1966 STRCASECMP(options.excludeRegs[i],"none") == 0)
1969 for ( i = 0 ; options.excludeRegs[i]; i++) {
1970 if (options.excludeRegs[i] &&
1971 STRCASECMP(s,options.excludeRegs[i]) == 0)
1977 /*-----------------------------------------------------------------*/
1978 /* genFunction - generated code for function entry */
1979 /*-----------------------------------------------------------------*/
1980 static void genFunction (iCode *ic)
1986 /* create the function header */
1987 emitcode(";","-----------------------------------------");
1988 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1989 emitcode(";","-----------------------------------------");
1991 emitcode("","%s:",sym->rname);
1992 fetype = getSpec(operandType(IC_LEFT(ic)));
1994 /* if critical function then turn interrupts off */
1995 if (SPEC_CRTCL(fetype))
1996 emitcode("clr","ea");
1998 /* here we need to generate the equates for the
1999 register bank if required */
2000 if (SPEC_BANK(fetype) != rbank) {
2003 rbank = SPEC_BANK(fetype);
2004 for ( i = 0 ; i < mcs51_nRegs ; i++ ) {
2005 if (strcmp(regs8051[i].base,"0") == 0)
2006 emitcode("","%s = 0x%02x",
2008 8*rbank+regs8051[i].offset);
2010 emitcode ("","%s = %s + 0x%02x",
2013 8*rbank+regs8051[i].offset);
2017 /* if this is an interrupt service routine then
2018 save acc, b, dpl, dph */
2019 if (IS_ISR(sym->etype)) {
2021 if (!inExcludeList("acc"))
2022 emitcode ("push","acc");
2023 if (!inExcludeList("b"))
2024 emitcode ("push","b");
2025 if (!inExcludeList("dpl"))
2026 emitcode ("push","dpl");
2027 if (!inExcludeList("dph"))
2028 emitcode ("push","dph");
2029 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2031 emitcode ("push", "dpx");
2032 /* Make sure we're using standard DPTR */
2033 emitcode ("push", "dps");
2034 emitcode ("mov", "dps, #0x00");
2035 if (options.stack10bit)
2037 /* This ISR could conceivably use DPTR2. Better save it. */
2038 emitcode ("push", "dpl1");
2039 emitcode ("push", "dph1");
2040 emitcode ("push", "dpx1");
2043 /* if this isr has no bank i.e. is going to
2044 run with bank 0 , then we need to save more
2046 if (!SPEC_BANK(sym->etype)) {
2048 /* if this function does not call any other
2049 function then we can be economical and
2050 save only those registers that are used */
2051 if (! sym->hasFcall) {
2054 /* if any registers used */
2055 if (sym->regsUsed) {
2056 /* save the registers used */
2057 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2058 if (bitVectBitValue(sym->regsUsed,i) ||
2059 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2060 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
2065 /* this function has a function call cannot
2066 determines register usage so we will have the
2068 saverbank(0,ic,FALSE);
2072 /* if callee-save to be used for this function
2073 then save the registers being used in this function */
2074 if (sym->calleeSave) {
2077 /* if any registers used */
2078 if (sym->regsUsed) {
2079 /* save the registers used */
2080 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2081 if (bitVectBitValue(sym->regsUsed,i) ||
2082 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2083 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
2091 /* set the register bank to the desired value */
2092 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2093 emitcode("push","psw");
2094 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2097 if (IS_RENT(sym->etype) || options.stackAuto) {
2099 if (options.useXstack) {
2100 emitcode("mov","r0,%s",spname);
2101 emitcode("mov","a,_bp");
2102 emitcode("movx","@r0,a");
2103 emitcode("inc","%s",spname);
2107 /* set up the stack */
2108 emitcode ("push","_bp"); /* save the callers stack */
2110 emitcode ("mov","_bp,%s",spname);
2113 /* adjust the stack for the function */
2118 werror(W_STACK_OVERFLOW,sym->name);
2120 if (i > 3 && sym->recvSize < 4) {
2122 emitcode ("mov","a,sp");
2123 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2124 emitcode ("mov","sp,a");
2129 emitcode("inc","sp");
2134 emitcode ("mov","a,_spx");
2135 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2136 emitcode ("mov","_spx,a");
2141 /*-----------------------------------------------------------------*/
2142 /* genEndFunction - generates epilogue for functions */
2143 /*-----------------------------------------------------------------*/
2144 static void genEndFunction (iCode *ic)
2146 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2148 if (IS_RENT(sym->etype) || options.stackAuto)
2150 emitcode ("mov","%s,_bp",spname);
2153 /* if use external stack but some variables were
2154 added to the local stack then decrement the
2156 if (options.useXstack && sym->stack) {
2157 emitcode("mov","a,sp");
2158 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2159 emitcode("mov","sp,a");
2163 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2164 if (options.useXstack) {
2165 emitcode("mov","r0,%s",spname);
2166 emitcode("movx","a,@r0");
2167 emitcode("mov","_bp,a");
2168 emitcode("dec","%s",spname);
2172 emitcode ("pop","_bp");
2176 /* restore the register bank */
2177 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2178 emitcode ("pop","psw");
2180 if (IS_ISR(sym->etype)) {
2182 /* now we need to restore the registers */
2183 /* if this isr has no bank i.e. is going to
2184 run with bank 0 , then we need to save more
2186 if (!SPEC_BANK(sym->etype)) {
2188 /* if this function does not call any other
2189 function then we can be economical and
2190 save only those registers that are used */
2191 if (! sym->hasFcall) {
2194 /* if any registers used */
2195 if (sym->regsUsed) {
2196 /* save the registers used */
2197 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2198 if (bitVectBitValue(sym->regsUsed,i) ||
2199 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2200 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
2205 /* this function has a function call cannot
2206 determines register usage so we will have the
2208 unsaverbank(0,ic,FALSE);
2212 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2214 if (options.stack10bit)
2216 emitcode ("pop", "dpx1");
2217 emitcode ("pop", "dph1");
2218 emitcode ("pop", "dpl1");
2220 emitcode ("pop", "dps");
2221 emitcode ("pop", "dpx");
2223 if (!inExcludeList("dph"))
2224 emitcode ("pop","dph");
2225 if (!inExcludeList("dpl"))
2226 emitcode ("pop","dpl");
2227 if (!inExcludeList("b"))
2228 emitcode ("pop","b");
2229 if (!inExcludeList("acc"))
2230 emitcode ("pop","acc");
2232 if (SPEC_CRTCL(sym->etype))
2233 emitcode("setb","ea");
2235 /* if debug then send end of function */
2236 /* if (options.debug && currFunc) { */
2239 emitcode("","C$%s$%d$%d$%d ==.",
2240 ic->filename,currFunc->lastLine,
2241 ic->level,ic->block);
2242 if (IS_STATIC(currFunc->etype))
2243 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2245 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2249 emitcode ("reti","");
2252 if (SPEC_CRTCL(sym->etype))
2253 emitcode("setb","ea");
2255 if (sym->calleeSave) {
2258 /* if any registers used */
2259 if (sym->regsUsed) {
2260 /* save the registers used */
2261 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2262 if (bitVectBitValue(sym->regsUsed,i) ||
2263 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2264 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
2270 /* if debug then send end of function */
2273 emitcode("","C$%s$%d$%d$%d ==.",
2274 ic->filename,currFunc->lastLine,
2275 ic->level,ic->block);
2276 if (IS_STATIC(currFunc->etype))
2277 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2279 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2283 emitcode ("ret","");
2288 /*-----------------------------------------------------------------*/
2289 /* genRet - generate code for return statement */
2290 /*-----------------------------------------------------------------*/
2291 static void genRet (iCode *ic)
2293 int size,offset = 0 , pushed = 0;
2295 /* if we have no return value then
2296 just generate the "ret" */
2300 /* we have something to return then
2301 move the return value into place */
2302 aopOp(IC_LEFT(ic),ic,FALSE);
2303 size = AOP_SIZE(IC_LEFT(ic));
2307 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2309 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2311 emitcode("push","%s",l);
2314 l = aopGet(AOP(IC_LEFT(ic)),offset,
2316 if (strcmp(fReturn[offset],l))
2317 emitcode("mov","%s,%s",fReturn[offset++],l);
2324 if (strcmp(fReturn[pushed],"a"))
2325 emitcode("pop",fReturn[pushed]);
2327 emitcode("pop","acc");
2330 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2333 /* generate a jump to the return label
2334 if the next is not the return statement */
2335 if (!(ic->next && ic->next->op == LABEL &&
2336 IC_LABEL(ic->next) == returnLabel))
2338 emitcode("ljmp","%05d$",(returnLabel->key+100));
2342 /*-----------------------------------------------------------------*/
2343 /* genLabel - generates a label */
2344 /*-----------------------------------------------------------------*/
2345 static void genLabel (iCode *ic)
2347 /* special case never generate */
2348 if (IC_LABEL(ic) == entryLabel)
2351 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2354 /*-----------------------------------------------------------------*/
2355 /* genGoto - generates a ljmp */
2356 /*-----------------------------------------------------------------*/
2357 static void genGoto (iCode *ic)
2359 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2362 /*-----------------------------------------------------------------*/
2363 /* findLabelBackwards: walks back through the iCode chain looking */
2364 /* for the given label. Returns number of iCode instructions */
2365 /* between that label and given ic. */
2366 /* Returns zero if label not found. */
2367 /*-----------------------------------------------------------------*/
2368 static int findLabelBackwards(iCode *ic, int key)
2377 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2379 /* printf("findLabelBackwards = %d\n", count); */
2387 /*-----------------------------------------------------------------*/
2388 /* genPlusIncr :- does addition with increment if possible */
2389 /*-----------------------------------------------------------------*/
2390 static bool genPlusIncr (iCode *ic)
2392 unsigned int icount ;
2393 unsigned int size = getDataSize(IC_RESULT(ic));
2395 /* will try to generate an increment */
2396 /* if the right side is not a literal
2398 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2401 /* if the literal value of the right hand side
2402 is greater than 4 then it is not worth it */
2403 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2406 /* if increment 16 bits in register */
2407 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2414 /* If the next instruction is a goto and the goto target
2415 * is < 10 instructions previous to this, we can generate
2416 * jumps straight to that target.
2418 if (ic->next && ic->next->op == GOTO
2419 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2420 && labelRange <= 10 )
2422 emitcode(";", "tail increment optimized");
2423 tlbl = IC_LABEL(ic->next);
2428 tlbl = newiTempLabel(NULL);
2431 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2432 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2433 IS_AOP_PREG(IC_RESULT(ic)))
2434 emitcode("cjne","%s,#0x00,%05d$"
2435 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2438 emitcode("clr","a");
2439 emitcode("cjne","a,%s,%05d$"
2440 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2444 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2447 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2448 IS_AOP_PREG(IC_RESULT(ic)))
2449 emitcode("cjne","%s,#0x00,%05d$"
2450 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2453 emitcode("cjne","a,%s,%05d$"
2454 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2457 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2461 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2462 IS_AOP_PREG(IC_RESULT(ic)))
2463 emitcode("cjne","%s,#0x00,%05d$"
2464 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2467 emitcode("cjne","a,%s,%05d$"
2468 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2471 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2476 emitcode("","%05d$:",tlbl->key+100);
2481 /* if the sizes are greater than 1 then we cannot */
2482 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2483 AOP_SIZE(IC_LEFT(ic)) > 1 )
2486 /* we can if the aops of the left & result match or
2487 if they are in registers and the registers are the
2489 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2492 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2493 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2494 aopPut(AOP(IC_RESULT(ic)),"a",0);
2498 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2507 /*-----------------------------------------------------------------*/
2508 /* outBitAcc - output a bit in acc */
2509 /*-----------------------------------------------------------------*/
2510 static void outBitAcc(operand *result)
2512 symbol *tlbl = newiTempLabel(NULL);
2513 /* if the result is a bit */
2514 if (AOP_TYPE(result) == AOP_CRY){
2515 aopPut(AOP(result),"a",0);
2518 emitcode("jz","%05d$",tlbl->key+100);
2519 emitcode("mov","a,%s",one);
2520 emitcode("","%05d$:",tlbl->key+100);
2525 /*-----------------------------------------------------------------*/
2526 /* genPlusBits - generates code for addition of two bits */
2527 /*-----------------------------------------------------------------*/
2528 static void genPlusBits (iCode *ic)
2530 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2531 symbol *lbl = newiTempLabel(NULL);
2532 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2533 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2534 emitcode("cpl","c");
2535 emitcode("","%05d$:",(lbl->key+100));
2536 outBitC(IC_RESULT(ic));
2539 emitcode("clr","a");
2540 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2541 emitcode("rlc","a");
2542 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2543 emitcode("addc","a,#0x00");
2544 outAcc(IC_RESULT(ic));
2549 /* This is the original version of this code.
2551 * This is being kept around for reference,
2552 * because I am not entirely sure I got it right...
2554 static void adjustArithmeticResult(iCode *ic)
2556 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2557 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2558 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2559 aopPut(AOP(IC_RESULT(ic)),
2560 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2563 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2564 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
2565 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2566 aopPut(AOP(IC_RESULT(ic)),
2567 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2570 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2571 AOP_SIZE(IC_LEFT(ic)) < 3 &&
2572 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
2573 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2574 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2576 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2577 aopPut(AOP(IC_RESULT(ic)),buffer,2);
2581 /* This is the pure and virtuous version of this code.
2582 * I'm pretty certain it's right, but not enough to toss the old
2585 static void adjustArithmeticResult(iCode *ic)
2587 if (opIsGptr(IC_RESULT(ic)) &&
2588 opIsGptr(IC_LEFT(ic)) &&
2589 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2591 aopPut(AOP(IC_RESULT(ic)),
2592 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
2596 if (opIsGptr(IC_RESULT(ic)) &&
2597 opIsGptr(IC_RIGHT(ic)) &&
2598 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2600 aopPut(AOP(IC_RESULT(ic)),
2601 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
2605 if (opIsGptr(IC_RESULT(ic)) &&
2606 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2607 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2608 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2609 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2611 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2612 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2617 /*-----------------------------------------------------------------*/
2618 /* genPlus - generates code for addition */
2619 /*-----------------------------------------------------------------*/
2620 static void genPlus (iCode *ic)
2622 int size, offset = 0;
2624 /* special cases :- */
2626 aopOp (IC_LEFT(ic),ic,FALSE);
2627 aopOp (IC_RIGHT(ic),ic,FALSE);
2628 aopOp (IC_RESULT(ic),ic,TRUE);
2630 /* if literal, literal on the right or
2631 if left requires ACC or right is already
2633 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2634 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2635 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2636 operand *t = IC_RIGHT(ic);
2637 IC_RIGHT(ic) = IC_LEFT(ic);
2641 /* if both left & right are in bit
2643 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2644 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2649 /* if left in bit space & right literal */
2650 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2651 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2652 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2653 /* if result in bit space */
2654 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2655 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
2656 emitcode("cpl","c");
2657 outBitC(IC_RESULT(ic));
2659 size = getDataSize(IC_RESULT(ic));
2661 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2662 emitcode("addc","a,#00");
2663 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2669 /* if I can do an increment instead
2670 of add then GOOD for ME */
2671 if (genPlusIncr (ic) == TRUE)
2674 size = getDataSize(IC_RESULT(ic));
2677 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2678 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2680 emitcode("add","a,%s",
2681 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2683 emitcode("addc","a,%s",
2684 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2686 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2688 emitcode("add","a,%s",
2689 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2691 emitcode("addc","a,%s",
2692 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2694 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2697 adjustArithmeticResult(ic);
2700 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2701 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2702 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2705 /*-----------------------------------------------------------------*/
2706 /* genMinusDec :- does subtraction with deccrement if possible */
2707 /*-----------------------------------------------------------------*/
2708 static bool genMinusDec (iCode *ic)
2710 unsigned int icount ;
2711 unsigned int size = getDataSize(IC_RESULT(ic));
2713 /* will try to generate an increment */
2714 /* if the right side is not a literal
2716 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2719 /* if the literal value of the right hand side
2720 is greater than 4 then it is not worth it */
2721 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2724 /* if decrement 16 bits in register */
2725 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2732 /* If the next instruction is a goto and the goto target
2733 * is <= 10 instructions previous to this, we can generate
2734 * jumps straight to that target.
2736 if (ic->next && ic->next->op == GOTO
2737 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2738 && labelRange <= 10 )
2740 emitcode(";", "tail decrement optimized");
2741 tlbl = IC_LABEL(ic->next);
2746 tlbl = newiTempLabel(NULL);
2750 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2751 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2752 IS_AOP_PREG(IC_RESULT(ic)))
2753 emitcode("cjne","%s,#0xff,%05d$"
2754 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2757 emitcode("mov","a,#0xff");
2758 emitcode("cjne","a,%s,%05d$"
2759 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2762 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2765 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2766 IS_AOP_PREG(IC_RESULT(ic)))
2767 emitcode("cjne","%s,#0xff,%05d$"
2768 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2771 emitcode("cjne","a,%s,%05d$"
2772 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2775 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2779 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2780 IS_AOP_PREG(IC_RESULT(ic)))
2781 emitcode("cjne","%s,#0xff,%05d$"
2782 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2785 emitcode("cjne","a,%s,%05d$"
2786 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2789 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2793 emitcode("","%05d$:",tlbl->key+100);
2798 /* if the sizes are greater than 1 then we cannot */
2799 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2800 AOP_SIZE(IC_LEFT(ic)) > 1 )
2803 /* we can if the aops of the left & result match or
2804 if they are in registers and the registers are the
2806 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2809 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2817 /*-----------------------------------------------------------------*/
2818 /* addSign - complete with sign */
2819 /*-----------------------------------------------------------------*/
2820 static void addSign(operand *result, int offset, int sign)
2822 int size = (getDataSize(result) - offset);
2825 emitcode("rlc","a");
2826 emitcode("subb","a,acc");
2828 aopPut(AOP(result),"a",offset++);
2831 aopPut(AOP(result),zero,offset++);
2835 /*-----------------------------------------------------------------*/
2836 /* genMinusBits - generates code for subtraction of two bits */
2837 /*-----------------------------------------------------------------*/
2838 static void genMinusBits (iCode *ic)
2840 symbol *lbl = newiTempLabel(NULL);
2841 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2842 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2843 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2844 emitcode("cpl","c");
2845 emitcode("","%05d$:",(lbl->key+100));
2846 outBitC(IC_RESULT(ic));
2849 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2850 emitcode("subb","a,acc");
2851 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
2852 emitcode("inc","a");
2853 emitcode("","%05d$:",(lbl->key+100));
2854 aopPut(AOP(IC_RESULT(ic)),"a",0);
2855 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
2859 /*-----------------------------------------------------------------*/
2860 /* genMinus - generates code for subtraction */
2861 /*-----------------------------------------------------------------*/
2862 static void genMinus (iCode *ic)
2864 int size, offset = 0;
2865 unsigned long lit = 0L;
2867 aopOp (IC_LEFT(ic),ic,FALSE);
2868 aopOp (IC_RIGHT(ic),ic,FALSE);
2869 aopOp (IC_RESULT(ic),ic,TRUE);
2871 /* special cases :- */
2872 /* if both left & right are in bit space */
2873 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2874 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2879 /* if I can do an decrement instead
2880 of subtract then GOOD for ME */
2881 if (genMinusDec (ic) == TRUE)
2884 size = getDataSize(IC_RESULT(ic));
2886 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
2890 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2894 /* if literal, add a,#-lit, else normal subb */
2896 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2897 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2898 emitcode("subb","a,%s",
2899 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2901 /* first add without previous c */
2903 emitcode("add","a,#0x%02x",
2904 (unsigned int)(lit & 0x0FFL));
2906 emitcode("addc","a,#0x%02x",
2907 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
2909 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2912 adjustArithmeticResult(ic);
2915 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2916 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2917 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2921 /*-----------------------------------------------------------------*/
2922 /* genMultbits :- multiplication of bits */
2923 /*-----------------------------------------------------------------*/
2924 static void genMultbits (operand *left,
2928 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2929 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
2934 /*-----------------------------------------------------------------*/
2935 /* genMultOneByte : 8 bit multiplication & division */
2936 /*-----------------------------------------------------------------*/
2937 static void genMultOneByte (operand *left,
2941 link *opetype = operandType(result);
2946 /* (if two literals, the value is computed before) */
2947 /* if one literal, literal on the right */
2948 if (AOP_TYPE(left) == AOP_LIT){
2954 size = AOP_SIZE(result);
2955 /* signed or unsigned */
2956 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2957 l = aopGet(AOP(left),0,FALSE,FALSE);
2959 emitcode("mul","ab");
2960 /* if result size = 1, mul signed = mul unsigned */
2961 aopPut(AOP(result),"a",0);
2963 if (SPEC_USIGN(opetype)){
2964 aopPut(AOP(result),"b",1);
2966 /* for filling the MSBs */
2967 emitcode("clr","a");
2970 emitcode("mov","a,b");
2972 /* adjust the MSB if left or right neg */
2974 /* if one literal */
2975 if (AOP_TYPE(right) == AOP_LIT){
2976 /* AND literal negative */
2977 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
2978 /* adjust MSB (c==0 after mul) */
2979 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2983 lbl = newiTempLabel(NULL);
2984 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2985 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
2986 emitcode("","%05d$:",(lbl->key+100));
2987 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2988 lbl = newiTempLabel(NULL);
2989 emitcode("jc","%05d$",(lbl->key+100));
2990 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2991 emitcode("","%05d$:",(lbl->key+100));
2994 lbl = newiTempLabel(NULL);
2995 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
2996 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
2997 emitcode("","%05d$:",(lbl->key+100));
2998 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
2999 lbl = newiTempLabel(NULL);
3000 emitcode("jc","%05d$",(lbl->key+100));
3001 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
3002 emitcode("","%05d$:",(lbl->key+100));
3004 aopPut(AOP(result),"a",1);
3007 emitcode("rlc","a");
3008 emitcode("subb","a,acc");
3015 aopPut(AOP(result),"a",offset++);
3019 /*-----------------------------------------------------------------*/
3020 /* genMult - generates code for multiplication */
3021 /*-----------------------------------------------------------------*/
3022 static void genMult (iCode *ic)
3024 operand *left = IC_LEFT(ic);
3025 operand *right = IC_RIGHT(ic);
3026 operand *result= IC_RESULT(ic);
3028 /* assign the amsops */
3029 aopOp (left,ic,FALSE);
3030 aopOp (right,ic,FALSE);
3031 aopOp (result,ic,TRUE);
3033 /* special cases first */
3035 if (AOP_TYPE(left) == AOP_CRY &&
3036 AOP_TYPE(right)== AOP_CRY) {
3037 genMultbits(left,right,result);
3041 /* if both are of size == 1 */
3042 if (AOP_SIZE(left) == 1 &&
3043 AOP_SIZE(right) == 1 ) {
3044 genMultOneByte(left,right,result);
3048 /* should have been converted to function call */
3052 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3053 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3054 freeAsmop(result,NULL,ic,TRUE);
3057 /*-----------------------------------------------------------------*/
3058 /* genDivbits :- division of bits */
3059 /*-----------------------------------------------------------------*/
3060 static void genDivbits (operand *left,
3067 /* the result must be bit */
3068 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3069 l = aopGet(AOP(left),0,FALSE,FALSE);
3073 emitcode("div","ab");
3074 emitcode("rrc","a");
3075 aopPut(AOP(result),"c",0);
3078 /*-----------------------------------------------------------------*/
3079 /* genDivOneByte : 8 bit division */
3080 /*-----------------------------------------------------------------*/
3081 static void genDivOneByte (operand *left,
3085 link *opetype = operandType(result);
3090 size = AOP_SIZE(result) - 1;
3092 /* signed or unsigned */
3093 if (SPEC_USIGN(opetype)) {
3094 /* unsigned is easy */
3095 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3096 l = aopGet(AOP(left),0,FALSE,FALSE);
3098 emitcode("div","ab");
3099 aopPut(AOP(result),"a",0);
3101 aopPut(AOP(result),zero,offset++);
3105 /* signed is a little bit more difficult */
3107 /* save the signs of the operands */
3108 l = aopGet(AOP(left),0,FALSE,FALSE);
3110 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3111 emitcode("push","acc"); /* save it on the stack */
3113 /* now sign adjust for both left & right */
3114 l = aopGet(AOP(right),0,FALSE,FALSE);
3116 lbl = newiTempLabel(NULL);
3117 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3118 emitcode("cpl","a");
3119 emitcode("inc","a");
3120 emitcode("","%05d$:",(lbl->key+100));
3121 emitcode("mov","b,a");
3123 /* sign adjust left side */
3124 l = aopGet(AOP(left),0,FALSE,FALSE);
3127 lbl = newiTempLabel(NULL);
3128 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3129 emitcode("cpl","a");
3130 emitcode("inc","a");
3131 emitcode("","%05d$:",(lbl->key+100));
3133 /* now the division */
3134 emitcode("div","ab");
3135 /* we are interested in the lower order
3137 emitcode("mov","b,a");
3138 lbl = newiTempLabel(NULL);
3139 emitcode("pop","acc");
3140 /* if there was an over flow we don't
3141 adjust the sign of the result */
3142 emitcode("jb","ov,%05d$",(lbl->key+100));
3143 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3145 emitcode("clr","a");
3146 emitcode("subb","a,b");
3147 emitcode("mov","b,a");
3148 emitcode("","%05d$:",(lbl->key+100));
3150 /* now we are done */
3151 aopPut(AOP(result),"b",0);
3153 emitcode("mov","c,b.7");
3154 emitcode("subb","a,acc");
3157 aopPut(AOP(result),"a",offset++);
3161 /*-----------------------------------------------------------------*/
3162 /* genDiv - generates code for division */
3163 /*-----------------------------------------------------------------*/
3164 static void genDiv (iCode *ic)
3166 operand *left = IC_LEFT(ic);
3167 operand *right = IC_RIGHT(ic);
3168 operand *result= IC_RESULT(ic);
3170 /* assign the amsops */
3171 aopOp (left,ic,FALSE);
3172 aopOp (right,ic,FALSE);
3173 aopOp (result,ic,TRUE);
3175 /* special cases first */
3177 if (AOP_TYPE(left) == AOP_CRY &&
3178 AOP_TYPE(right)== AOP_CRY) {
3179 genDivbits(left,right,result);
3183 /* if both are of size == 1 */
3184 if (AOP_SIZE(left) == 1 &&
3185 AOP_SIZE(right) == 1 ) {
3186 genDivOneByte(left,right,result);
3190 /* should have been converted to function call */
3193 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3194 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3195 freeAsmop(result,NULL,ic,TRUE);
3198 /*-----------------------------------------------------------------*/
3199 /* genModbits :- modulus of bits */
3200 /*-----------------------------------------------------------------*/
3201 static void genModbits (operand *left,
3208 /* the result must be bit */
3209 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3210 l = aopGet(AOP(left),0,FALSE,FALSE);
3214 emitcode("div","ab");
3215 emitcode("mov","a,b");
3216 emitcode("rrc","a");
3217 aopPut(AOP(result),"c",0);
3220 /*-----------------------------------------------------------------*/
3221 /* genModOneByte : 8 bit modulus */
3222 /*-----------------------------------------------------------------*/
3223 static void genModOneByte (operand *left,
3227 link *opetype = operandType(result);
3231 /* signed or unsigned */
3232 if (SPEC_USIGN(opetype)) {
3233 /* unsigned is easy */
3234 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3235 l = aopGet(AOP(left),0,FALSE,FALSE);
3237 emitcode("div","ab");
3238 aopPut(AOP(result),"b",0);
3242 /* signed is a little bit more difficult */
3244 /* save the signs of the operands */
3245 l = aopGet(AOP(left),0,FALSE,FALSE);
3248 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3249 emitcode("push","acc"); /* save it on the stack */
3251 /* now sign adjust for both left & right */
3252 l = aopGet(AOP(right),0,FALSE,FALSE);
3255 lbl = newiTempLabel(NULL);
3256 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3257 emitcode("cpl","a");
3258 emitcode("inc","a");
3259 emitcode("","%05d$:",(lbl->key+100));
3260 emitcode("mov","b,a");
3262 /* sign adjust left side */
3263 l = aopGet(AOP(left),0,FALSE,FALSE);
3266 lbl = newiTempLabel(NULL);
3267 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3268 emitcode("cpl","a");
3269 emitcode("inc","a");
3270 emitcode("","%05d$:",(lbl->key+100));
3272 /* now the multiplication */
3273 emitcode("div","ab");
3274 /* we are interested in the lower order
3276 lbl = newiTempLabel(NULL);
3277 emitcode("pop","acc");
3278 /* if there was an over flow we don't
3279 adjust the sign of the result */
3280 emitcode("jb","ov,%05d$",(lbl->key+100));
3281 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3283 emitcode("clr","a");
3284 emitcode("subb","a,b");
3285 emitcode("mov","b,a");
3286 emitcode("","%05d$:",(lbl->key+100));
3288 /* now we are done */
3289 aopPut(AOP(result),"b",0);
3293 /*-----------------------------------------------------------------*/
3294 /* genMod - generates code for division */
3295 /*-----------------------------------------------------------------*/
3296 static void genMod (iCode *ic)
3298 operand *left = IC_LEFT(ic);
3299 operand *right = IC_RIGHT(ic);
3300 operand *result= IC_RESULT(ic);
3302 /* assign the amsops */
3303 aopOp (left,ic,FALSE);
3304 aopOp (right,ic,FALSE);
3305 aopOp (result,ic,TRUE);
3307 /* special cases first */
3309 if (AOP_TYPE(left) == AOP_CRY &&
3310 AOP_TYPE(right)== AOP_CRY) {
3311 genModbits(left,right,result);
3315 /* if both are of size == 1 */
3316 if (AOP_SIZE(left) == 1 &&
3317 AOP_SIZE(right) == 1 ) {
3318 genModOneByte(left,right,result);
3322 /* should have been converted to function call */
3326 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3327 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3328 freeAsmop(result,NULL,ic,TRUE);
3331 /*-----------------------------------------------------------------*/
3332 /* genIfxJump :- will create a jump depending on the ifx */
3333 /*-----------------------------------------------------------------*/
3334 static void genIfxJump (iCode *ic, char *jval)
3337 symbol *tlbl = newiTempLabel(NULL);
3340 /* if true label then we jump if condition
3342 if ( IC_TRUE(ic) ) {
3344 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3345 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3348 /* false label is present */
3349 jlbl = IC_FALSE(ic) ;
3350 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3351 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3353 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3354 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3356 emitcode(inst,"%05d$",tlbl->key+100);
3357 emitcode("ljmp","%05d$",jlbl->key+100);
3358 emitcode("","%05d$:",tlbl->key+100);
3360 /* mark the icode as generated */
3364 /*-----------------------------------------------------------------*/
3365 /* genCmp :- greater or less than comparison */
3366 /*-----------------------------------------------------------------*/
3367 static void genCmp (operand *left,operand *right,
3368 operand *result, iCode *ifx, int sign)
3370 int size, offset = 0 ;
3371 unsigned long lit = 0L;
3373 /* if left & right are bit variables */
3374 if (AOP_TYPE(left) == AOP_CRY &&
3375 AOP_TYPE(right) == AOP_CRY ) {
3376 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3377 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3379 /* subtract right from left if at the
3380 end the carry flag is set then we know that
3381 left is greater than right */
3382 size = max(AOP_SIZE(left),AOP_SIZE(right));
3384 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3385 if((size == 1) && !sign &&
3386 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3387 symbol *lbl = newiTempLabel(NULL);
3388 emitcode("cjne","%s,%s,%05d$",
3389 aopGet(AOP(left),offset,FALSE,FALSE),
3390 aopGet(AOP(right),offset,FALSE,FALSE),
3392 emitcode("","%05d$:",lbl->key+100);
3394 if(AOP_TYPE(right) == AOP_LIT){
3395 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3396 /* optimize if(x < 0) or if(x >= 0) */
3402 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE));
3403 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3404 genIfxJump (ifx,"acc.7");
3408 emitcode("rlc","a");
3415 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3416 if (sign && size == 0) {
3417 emitcode("xrl","a,#0x80");
3418 if (AOP_TYPE(right) == AOP_LIT){
3419 unsigned long lit = (unsigned long)
3420 floatFromVal(AOP(right)->aopu.aop_lit);
3421 emitcode("subb","a,#0x%02x",
3422 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3424 emitcode("mov","b,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3425 emitcode("xrl","b,#0x80");
3426 emitcode("subb","a,b");
3429 emitcode("subb","a,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3435 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3438 /* if the result is used in the next
3439 ifx conditional branch then generate
3440 code a little differently */
3442 genIfxJump (ifx,"c");
3445 /* leave the result in acc */
3449 /*-----------------------------------------------------------------*/
3450 /* genCmpGt :- greater than comparison */
3451 /*-----------------------------------------------------------------*/
3452 static void genCmpGt (iCode *ic, iCode *ifx)
3454 operand *left, *right, *result;
3455 link *letype , *retype;
3459 right= IC_RIGHT(ic);
3460 result = IC_RESULT(ic);
3462 letype = getSpec(operandType(left));
3463 retype =getSpec(operandType(right));
3464 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3465 /* assign the amsops */
3466 aopOp (left,ic,FALSE);
3467 aopOp (right,ic,FALSE);
3468 aopOp (result,ic,TRUE);
3470 genCmp(right, left, result, ifx, sign);
3472 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3473 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3474 freeAsmop(result,NULL,ic,TRUE);
3477 /*-----------------------------------------------------------------*/
3478 /* genCmpLt - less than comparisons */
3479 /*-----------------------------------------------------------------*/
3480 static void genCmpLt (iCode *ic, iCode *ifx)
3482 operand *left, *right, *result;
3483 link *letype , *retype;
3487 right= IC_RIGHT(ic);
3488 result = IC_RESULT(ic);
3490 letype = getSpec(operandType(left));
3491 retype =getSpec(operandType(right));
3492 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3494 /* assign the amsops */
3495 aopOp (left,ic,FALSE);
3496 aopOp (right,ic,FALSE);
3497 aopOp (result,ic,TRUE);
3499 genCmp(left, right, result, ifx, sign);
3501 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3502 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3503 freeAsmop(result,NULL,ic,TRUE);
3506 /*-----------------------------------------------------------------*/
3507 /* gencjneshort - compare and jump if not equal */
3508 /*-----------------------------------------------------------------*/
3509 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3511 int size = max(AOP_SIZE(left),AOP_SIZE(right));
3513 unsigned long lit = 0L;
3515 /* if the left side is a literal or
3516 if the right is in a pointer register and left
3518 if ((AOP_TYPE(left) == AOP_LIT) ||
3519 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3524 if(AOP_TYPE(right) == AOP_LIT)
3525 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3527 /* if the right side is a literal then anything goes */
3528 if (AOP_TYPE(right) == AOP_LIT &&
3529 AOP_TYPE(left) != AOP_DIR ) {
3531 emitcode("cjne","%s,%s,%05d$",
3532 aopGet(AOP(left),offset,FALSE,FALSE),
3533 aopGet(AOP(right),offset,FALSE,FALSE),
3539 /* if the right side is in a register or in direct space or
3540 if the left is a pointer register & right is not */
3541 else if (AOP_TYPE(right) == AOP_REG ||
3542 AOP_TYPE(right) == AOP_DIR ||
3543 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3544 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3546 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3547 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3548 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
3549 emitcode("jnz","%05d$",lbl->key+100);
3551 emitcode("cjne","a,%s,%05d$",
3552 aopGet(AOP(right),offset,FALSE,TRUE),
3557 /* right is a pointer reg need both a & b */
3559 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
3561 emitcode("mov","b,%s",l);
3562 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3563 emitcode("cjne","a,b,%05d$",lbl->key+100);
3569 /*-----------------------------------------------------------------*/
3570 /* gencjne - compare and jump if not equal */
3571 /*-----------------------------------------------------------------*/
3572 static void gencjne(operand *left, operand *right, symbol *lbl)
3574 symbol *tlbl = newiTempLabel(NULL);
3576 gencjneshort(left, right, lbl);
3578 emitcode("mov","a,%s",one);
3579 emitcode("sjmp","%05d$",tlbl->key+100);
3580 emitcode("","%05d$:",lbl->key+100);
3581 emitcode("clr","a");
3582 emitcode("","%05d$:",tlbl->key+100);
3585 /*-----------------------------------------------------------------*/
3586 /* genCmpEq - generates code for equal to */
3587 /*-----------------------------------------------------------------*/
3588 static void genCmpEq (iCode *ic, iCode *ifx)
3590 operand *left, *right, *result;
3592 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3593 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3594 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3596 /* if literal, literal on the right or
3597 if the right is in a pointer register and left
3599 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
3600 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3601 operand *t = IC_RIGHT(ic);
3602 IC_RIGHT(ic) = IC_LEFT(ic);
3606 if(ifx && !AOP_SIZE(result)){
3608 /* if they are both bit variables */
3609 if (AOP_TYPE(left) == AOP_CRY &&
3610 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3611 if(AOP_TYPE(right) == AOP_LIT){
3612 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3614 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3615 emitcode("cpl","c");
3616 } else if(lit == 1L) {
3617 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3619 emitcode("clr","c");
3621 /* AOP_TYPE(right) == AOP_CRY */
3623 symbol *lbl = newiTempLabel(NULL);
3624 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3625 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3626 emitcode("cpl","c");
3627 emitcode("","%05d$:",(lbl->key+100));
3629 /* if true label then we jump if condition
3631 tlbl = newiTempLabel(NULL);
3632 if ( IC_TRUE(ifx) ) {
3633 emitcode("jnc","%05d$",tlbl->key+100);
3634 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3636 emitcode("jc","%05d$",tlbl->key+100);
3637 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3639 emitcode("","%05d$:",tlbl->key+100);
3641 tlbl = newiTempLabel(NULL);
3642 gencjneshort(left, right, tlbl);
3643 if ( IC_TRUE(ifx) ) {
3644 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3645 emitcode("","%05d$:",tlbl->key+100);
3647 symbol *lbl = newiTempLabel(NULL);
3648 emitcode("sjmp","%05d$",lbl->key+100);
3649 emitcode("","%05d$:",tlbl->key+100);
3650 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3651 emitcode("","%05d$:",lbl->key+100);
3654 /* mark the icode as generated */
3659 /* if they are both bit variables */
3660 if (AOP_TYPE(left) == AOP_CRY &&
3661 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3662 if(AOP_TYPE(right) == AOP_LIT){
3663 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3665 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3666 emitcode("cpl","c");
3667 } else if(lit == 1L) {
3668 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3670 emitcode("clr","c");
3672 /* AOP_TYPE(right) == AOP_CRY */
3674 symbol *lbl = newiTempLabel(NULL);
3675 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3676 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3677 emitcode("cpl","c");
3678 emitcode("","%05d$:",(lbl->key+100));
3681 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
3686 genIfxJump (ifx,"c");
3689 /* if the result is used in an arithmetic operation
3690 then put the result in place */
3693 gencjne(left,right,newiTempLabel(NULL));
3694 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3695 aopPut(AOP(result),"a",0);
3699 genIfxJump (ifx,"a");
3702 /* if the result is used in an arithmetic operation
3703 then put the result in place */
3704 if (AOP_TYPE(result) != AOP_CRY)
3706 /* leave the result in acc */
3710 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3711 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3712 freeAsmop(result,NULL,ic,TRUE);
3715 /*-----------------------------------------------------------------*/
3716 /* ifxForOp - returns the icode containing the ifx for operand */
3717 /*-----------------------------------------------------------------*/
3718 static iCode *ifxForOp ( operand *op, iCode *ic )
3720 /* if true symbol then needs to be assigned */
3721 if (IS_TRUE_SYMOP(op))
3724 /* if this has register type condition and
3725 the next instruction is ifx with the same operand
3726 and live to of the operand is upto the ifx only then */
3728 ic->next->op == IFX &&
3729 IC_COND(ic->next)->key == op->key &&
3730 OP_SYMBOL(op)->liveTo <= ic->next->seq )
3735 /*-----------------------------------------------------------------*/
3736 /* genAndOp - for && operation */
3737 /*-----------------------------------------------------------------*/
3738 static void genAndOp (iCode *ic)
3740 operand *left,*right, *result;
3743 /* note here that && operations that are in an
3744 if statement are taken away by backPatchLabels
3745 only those used in arthmetic operations remain */
3746 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3747 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3748 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3750 /* if both are bit variables */
3751 if (AOP_TYPE(left) == AOP_CRY &&
3752 AOP_TYPE(right) == AOP_CRY ) {
3753 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3754 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3757 tlbl = newiTempLabel(NULL);
3759 emitcode("jz","%05d$",tlbl->key+100);
3761 emitcode("","%05d$:",tlbl->key+100);
3765 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3766 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3767 freeAsmop(result,NULL,ic,TRUE);
3771 /*-----------------------------------------------------------------*/
3772 /* genOrOp - for || operation */
3773 /*-----------------------------------------------------------------*/
3774 static void genOrOp (iCode *ic)
3776 operand *left,*right, *result;
3779 /* note here that || operations that are in an
3780 if statement are taken away by backPatchLabels
3781 only those used in arthmetic operations remain */
3782 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3783 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3784 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3786 /* if both are bit variables */
3787 if (AOP_TYPE(left) == AOP_CRY &&
3788 AOP_TYPE(right) == AOP_CRY ) {
3789 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3790 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
3793 tlbl = newiTempLabel(NULL);
3795 emitcode("jnz","%05d$",tlbl->key+100);
3797 emitcode("","%05d$:",tlbl->key+100);
3801 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3802 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3803 freeAsmop(result,NULL,ic,TRUE);
3806 /*-----------------------------------------------------------------*/
3807 /* isLiteralBit - test if lit == 2^n */
3808 /*-----------------------------------------------------------------*/
3809 static int isLiteralBit(unsigned long lit)
3811 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
3812 0x100L,0x200L,0x400L,0x800L,
3813 0x1000L,0x2000L,0x4000L,0x8000L,
3814 0x10000L,0x20000L,0x40000L,0x80000L,
3815 0x100000L,0x200000L,0x400000L,0x800000L,
3816 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
3817 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
3820 for(idx = 0; idx < 32; idx++)
3826 /*-----------------------------------------------------------------*/
3827 /* continueIfTrue - */
3828 /*-----------------------------------------------------------------*/
3829 static void continueIfTrue (iCode *ic)
3832 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3836 /*-----------------------------------------------------------------*/
3838 /*-----------------------------------------------------------------*/
3839 static void jumpIfTrue (iCode *ic)
3842 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3846 /*-----------------------------------------------------------------*/
3847 /* jmpTrueOrFalse - */
3848 /*-----------------------------------------------------------------*/
3849 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
3851 // ugly but optimized by peephole
3853 symbol *nlbl = newiTempLabel(NULL);
3854 emitcode("sjmp","%05d$",nlbl->key+100);
3855 emitcode("","%05d$:",tlbl->key+100);
3856 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3857 emitcode("","%05d$:",nlbl->key+100);
3860 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3861 emitcode("","%05d$:",tlbl->key+100);
3866 /*-----------------------------------------------------------------*/
3867 /* genAnd - code for and */
3868 /*-----------------------------------------------------------------*/
3869 static void genAnd (iCode *ic, iCode *ifx)
3871 operand *left, *right, *result;
3873 unsigned long lit = 0L;
3877 aopOp((left = IC_LEFT(ic)),ic,FALSE);
3878 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3879 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3882 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3884 AOP_TYPE(left), AOP_TYPE(right));
3885 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3887 AOP_SIZE(left), AOP_SIZE(right));
3890 /* if left is a literal & right is not then exchange them */
3891 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3892 AOP_NEEDSACC(left)) {
3893 operand *tmp = right ;
3898 /* if result = right then exchange them */
3899 if(sameRegs(AOP(result),AOP(right))){
3900 operand *tmp = right ;
3905 /* if right is bit then exchange them */
3906 if (AOP_TYPE(right) == AOP_CRY &&
3907 AOP_TYPE(left) != AOP_CRY){
3908 operand *tmp = right ;
3912 if(AOP_TYPE(right) == AOP_LIT)
3913 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3915 size = AOP_SIZE(result);
3918 // result = bit & yy;
3919 if (AOP_TYPE(left) == AOP_CRY){
3920 // c = bit & literal;
3921 if(AOP_TYPE(right) == AOP_LIT){
3923 if(size && sameRegs(AOP(result),AOP(left)))
3926 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3929 if(size && (AOP_TYPE(result) == AOP_CRY)){
3930 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
3933 if((AOP_TYPE(result) == AOP_CRY) && ifx){
3937 emitcode("clr","c");
3940 if (AOP_TYPE(right) == AOP_CRY){
3942 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3943 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3946 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
3948 emitcode("rrc","a");
3949 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3957 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
3958 genIfxJump(ifx, "c");
3962 // if(val & 0xZZ) - size = 0, ifx != FALSE -
3963 // bit = val & 0xZZ - size = 1, ifx = FALSE -
3964 if((AOP_TYPE(right) == AOP_LIT) &&
3965 (AOP_TYPE(result) == AOP_CRY) &&
3966 (AOP_TYPE(left) != AOP_CRY)){
3967 int posbit = isLiteralBit(lit);
3971 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
3974 emitcode("mov","c,acc.%d",posbit&0x07);
3978 sprintf(buffer,"acc.%d",posbit&0x07);
3979 genIfxJump(ifx, buffer);
3984 symbol *tlbl = newiTempLabel(NULL);
3985 int sizel = AOP_SIZE(left);
3987 emitcode("setb","c");
3989 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
3990 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
3992 if((posbit = isLiteralBit(bytelit)) != 0)
3993 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
3995 if(bytelit != 0x0FFL)
3996 emitcode("anl","a,%s",
3997 aopGet(AOP(right),offset,FALSE,TRUE));
3998 emitcode("jnz","%05d$",tlbl->key+100);
4003 // bit = left & literal
4005 emitcode("clr","c");
4006 emitcode("","%05d$:",tlbl->key+100);
4008 // if(left & literal)
4011 jmpTrueOrFalse(ifx, tlbl);
4019 /* if left is same as result */
4020 if(sameRegs(AOP(result),AOP(left))){
4021 for(;size--; offset++) {
4022 if(AOP_TYPE(right) == AOP_LIT){
4023 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4027 aopPut(AOP(result),zero,offset);
4029 if (IS_AOP_PREG(result)) {
4030 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4031 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4032 aopPut(AOP(result),"a",offset);
4034 emitcode("anl","%s,%s",
4035 aopGet(AOP(left),offset,FALSE,TRUE),
4036 aopGet(AOP(right),offset,FALSE,FALSE));
4038 if (AOP_TYPE(left) == AOP_ACC)
4039 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4041 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4042 if (IS_AOP_PREG(result)) {
4043 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4044 aopPut(AOP(result),"a",offset);
4047 emitcode("anl","%s,a",
4048 aopGet(AOP(left),offset,FALSE,TRUE));
4053 // left & result in different registers
4054 if(AOP_TYPE(result) == AOP_CRY){
4056 // if(size), result in bit
4057 // if(!size && ifx), conditional oper: if(left & right)
4058 symbol *tlbl = newiTempLabel(NULL);
4059 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4061 emitcode("setb","c");
4063 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4064 emitcode("anl","a,%s",
4065 aopGet(AOP(left),offset,FALSE,FALSE));
4066 emitcode("jnz","%05d$",tlbl->key+100);
4071 emitcode("","%05d$:",tlbl->key+100);
4074 jmpTrueOrFalse(ifx, tlbl);
4076 for(;(size--);offset++) {
4078 // result = left & right
4079 if(AOP_TYPE(right) == AOP_LIT){
4080 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
4082 aopGet(AOP(left),offset,FALSE,FALSE),
4085 } else if(bytelit == 0){
4086 aopPut(AOP(result),zero,offset);
4090 // faster than result <- left, anl result,right
4091 // and better if result is SFR
4092 if (AOP_TYPE(left) == AOP_ACC)
4093 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4095 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4096 emitcode("anl","a,%s",
4097 aopGet(AOP(left),offset,FALSE,FALSE));
4099 aopPut(AOP(result),"a",offset);
4105 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4106 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4107 freeAsmop(result,NULL,ic,TRUE);
4110 /*-----------------------------------------------------------------*/
4111 /* genOr - code for or */
4112 /*-----------------------------------------------------------------*/
4113 static void genOr (iCode *ic, iCode *ifx)
4115 operand *left, *right, *result;
4117 unsigned long lit = 0L;
4119 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4120 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4121 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4124 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4126 AOP_TYPE(left), AOP_TYPE(right));
4127 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4129 AOP_SIZE(left), AOP_SIZE(right));
4132 /* if left is a literal & right is not then exchange them */
4133 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4134 AOP_NEEDSACC(left)) {
4135 operand *tmp = right ;
4140 /* if result = right then exchange them */
4141 if(sameRegs(AOP(result),AOP(right))){
4142 operand *tmp = right ;
4147 /* if right is bit then exchange them */
4148 if (AOP_TYPE(right) == AOP_CRY &&
4149 AOP_TYPE(left) != AOP_CRY){
4150 operand *tmp = right ;
4154 if(AOP_TYPE(right) == AOP_LIT)
4155 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4157 size = AOP_SIZE(result);
4161 if (AOP_TYPE(left) == AOP_CRY){
4162 if(AOP_TYPE(right) == AOP_LIT){
4163 // c = bit & literal;
4165 // lit != 0 => result = 1
4166 if(AOP_TYPE(result) == AOP_CRY){
4168 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4170 continueIfTrue(ifx);
4173 emitcode("setb","c");
4175 // lit == 0 => result = left
4176 if(size && sameRegs(AOP(result),AOP(left)))
4178 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4181 if (AOP_TYPE(right) == AOP_CRY){
4183 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4184 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4188 symbol *tlbl = newiTempLabel(NULL);
4189 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4190 emitcode("setb","c");
4191 emitcode("jb","%s,%05d$",
4192 AOP(left)->aopu.aop_dir,tlbl->key+100);
4194 emitcode("jnz","%05d$",tlbl->key+100);
4195 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4196 jmpTrueOrFalse(ifx, tlbl);
4200 emitcode("","%05d$:",tlbl->key+100);
4209 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4210 genIfxJump(ifx, "c");
4214 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4215 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4216 if((AOP_TYPE(right) == AOP_LIT) &&
4217 (AOP_TYPE(result) == AOP_CRY) &&
4218 (AOP_TYPE(left) != AOP_CRY)){
4222 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4224 continueIfTrue(ifx);
4227 // lit = 0, result = boolean(left)
4229 emitcode("setb","c");
4232 symbol *tlbl = newiTempLabel(NULL);
4233 emitcode("jnz","%05d$",tlbl->key+100);
4235 emitcode("","%05d$:",tlbl->key+100);
4237 genIfxJump (ifx,"a");
4245 /* if left is same as result */
4246 if(sameRegs(AOP(result),AOP(left))){
4247 for(;size--; offset++) {
4248 if(AOP_TYPE(right) == AOP_LIT){
4249 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4252 if (IS_AOP_PREG(left)) {
4253 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4254 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4255 aopPut(AOP(result),"a",offset);
4257 emitcode("orl","%s,%s",
4258 aopGet(AOP(left),offset,FALSE,TRUE),
4259 aopGet(AOP(right),offset,FALSE,FALSE));
4261 if (AOP_TYPE(left) == AOP_ACC)
4262 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4264 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4265 if (IS_AOP_PREG(left)) {
4266 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4267 aopPut(AOP(result),"a",offset);
4269 emitcode("orl","%s,a",
4270 aopGet(AOP(left),offset,FALSE,TRUE));
4275 // left & result in different registers
4276 if(AOP_TYPE(result) == AOP_CRY){
4278 // if(size), result in bit
4279 // if(!size && ifx), conditional oper: if(left | right)
4280 symbol *tlbl = newiTempLabel(NULL);
4281 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4283 emitcode("setb","c");
4285 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4286 emitcode("orl","a,%s",
4287 aopGet(AOP(left),offset,FALSE,FALSE));
4288 emitcode("jnz","%05d$",tlbl->key+100);
4293 emitcode("","%05d$:",tlbl->key+100);
4296 jmpTrueOrFalse(ifx, tlbl);
4297 } else for(;(size--);offset++){
4299 // result = left & right
4300 if(AOP_TYPE(right) == AOP_LIT){
4301 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4303 aopGet(AOP(left),offset,FALSE,FALSE),
4308 // faster than result <- left, anl result,right
4309 // and better if result is SFR
4310 if (AOP_TYPE(left) == AOP_ACC)
4311 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4313 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4314 emitcode("orl","a,%s",
4315 aopGet(AOP(left),offset,FALSE,FALSE));
4317 aopPut(AOP(result),"a",offset);
4322 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4323 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4324 freeAsmop(result,NULL,ic,TRUE);
4327 /*-----------------------------------------------------------------*/
4328 /* genXor - code for xclusive or */
4329 /*-----------------------------------------------------------------*/
4330 static void genXor (iCode *ic, iCode *ifx)
4332 operand *left, *right, *result;
4334 unsigned long lit = 0L;
4336 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4337 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4338 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4341 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4343 AOP_TYPE(left), AOP_TYPE(right));
4344 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4346 AOP_SIZE(left), AOP_SIZE(right));
4349 /* if left is a literal & right is not ||
4350 if left needs acc & right does not */
4351 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4352 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4353 operand *tmp = right ;
4358 /* if result = right then exchange them */
4359 if(sameRegs(AOP(result),AOP(right))){
4360 operand *tmp = right ;
4365 /* if right is bit then exchange them */
4366 if (AOP_TYPE(right) == AOP_CRY &&
4367 AOP_TYPE(left) != AOP_CRY){
4368 operand *tmp = right ;
4372 if(AOP_TYPE(right) == AOP_LIT)
4373 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4375 size = AOP_SIZE(result);
4379 if (AOP_TYPE(left) == AOP_CRY){
4380 if(AOP_TYPE(right) == AOP_LIT){
4381 // c = bit & literal;
4383 // lit>>1 != 0 => result = 1
4384 if(AOP_TYPE(result) == AOP_CRY){
4386 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4388 continueIfTrue(ifx);
4391 emitcode("setb","c");
4395 // lit == 0, result = left
4396 if(size && sameRegs(AOP(result),AOP(left)))
4398 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4400 // lit == 1, result = not(left)
4401 if(size && sameRegs(AOP(result),AOP(left))){
4402 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4405 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4406 emitcode("cpl","c");
4413 symbol *tlbl = newiTempLabel(NULL);
4414 if (AOP_TYPE(right) == AOP_CRY){
4416 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4419 int sizer = AOP_SIZE(right);
4421 // if val>>1 != 0, result = 1
4422 emitcode("setb","c");
4424 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
4426 // test the msb of the lsb
4427 emitcode("anl","a,#0xfe");
4428 emitcode("jnz","%05d$",tlbl->key+100);
4432 emitcode("rrc","a");
4434 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4435 emitcode("cpl","c");
4436 emitcode("","%05d$:",(tlbl->key+100));
4443 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4444 genIfxJump(ifx, "c");
4448 if(sameRegs(AOP(result),AOP(left))){
4449 /* if left is same as result */
4450 for(;size--; offset++) {
4451 if(AOP_TYPE(right) == AOP_LIT){
4452 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4455 if (IS_AOP_PREG(left)) {
4456 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4457 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4458 aopPut(AOP(result),"a",offset);
4460 emitcode("xrl","%s,%s",
4461 aopGet(AOP(left),offset,FALSE,TRUE),
4462 aopGet(AOP(right),offset,FALSE,FALSE));
4464 if (AOP_TYPE(left) == AOP_ACC)
4465 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4467 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4468 if (IS_AOP_PREG(left)) {
4469 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4470 aopPut(AOP(result),"a",offset);
4472 emitcode("xrl","%s,a",
4473 aopGet(AOP(left),offset,FALSE,TRUE));
4478 // left & result in different registers
4479 if(AOP_TYPE(result) == AOP_CRY){
4481 // if(size), result in bit
4482 // if(!size && ifx), conditional oper: if(left ^ right)
4483 symbol *tlbl = newiTempLabel(NULL);
4484 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4486 emitcode("setb","c");
4488 if((AOP_TYPE(right) == AOP_LIT) &&
4489 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4490 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4492 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4493 emitcode("xrl","a,%s",
4494 aopGet(AOP(left),offset,FALSE,FALSE));
4496 emitcode("jnz","%05d$",tlbl->key+100);
4501 emitcode("","%05d$:",tlbl->key+100);
4504 jmpTrueOrFalse(ifx, tlbl);
4505 } else for(;(size--);offset++){
4507 // result = left & right
4508 if(AOP_TYPE(right) == AOP_LIT){
4509 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4511 aopGet(AOP(left),offset,FALSE,FALSE),
4516 // faster than result <- left, anl result,right
4517 // and better if result is SFR
4518 if (AOP_TYPE(left) == AOP_ACC)
4519 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4521 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4522 emitcode("xrl","a,%s",
4523 aopGet(AOP(left),offset,FALSE,TRUE));
4525 aopPut(AOP(result),"a",offset);
4530 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4531 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4532 freeAsmop(result,NULL,ic,TRUE);
4535 /*-----------------------------------------------------------------*/
4536 /* genInline - write the inline code out */
4537 /*-----------------------------------------------------------------*/
4538 static void genInline (iCode *ic)
4540 char buffer[MAX_INLINEASM];
4544 _G.inLine += (!options.asmpeep);
4545 strcpy(buffer,IC_INLINE(ic));
4547 /* emit each line as a code */
4566 /* emitcode("",buffer); */
4567 _G.inLine -= (!options.asmpeep);
4570 /*-----------------------------------------------------------------*/
4571 /* genRRC - rotate right with carry */
4572 /*-----------------------------------------------------------------*/
4573 static void genRRC (iCode *ic)
4575 operand *left , *result ;
4576 int size, offset = 0;
4579 /* rotate right with carry */
4581 result=IC_RESULT(ic);
4582 aopOp (left,ic,FALSE);
4583 aopOp (result,ic,FALSE);
4585 /* move it to the result */
4586 size = AOP_SIZE(result);
4590 l = aopGet(AOP(left),offset,FALSE,FALSE);
4592 emitcode("rrc","a");
4593 if (AOP_SIZE(result) > 1)
4594 aopPut(AOP(result),"a",offset--);
4596 /* now we need to put the carry into the
4597 highest order byte of the result */
4598 if (AOP_SIZE(result) > 1) {
4599 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
4602 emitcode("mov","acc.7,c");
4603 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
4604 freeAsmop(left,NULL,ic,TRUE);
4605 freeAsmop(result,NULL,ic,TRUE);
4608 /*-----------------------------------------------------------------*/
4609 /* genRLC - generate code for rotate left with carry */
4610 /*-----------------------------------------------------------------*/
4611 static void genRLC (iCode *ic)
4613 operand *left , *result ;
4614 int size, offset = 0;
4617 /* rotate right with carry */
4619 result=IC_RESULT(ic);
4620 aopOp (left,ic,FALSE);
4621 aopOp (result,ic,FALSE);
4623 /* move it to the result */
4624 size = AOP_SIZE(result);
4627 l = aopGet(AOP(left),offset,FALSE,FALSE);
4629 emitcode("add","a,acc");
4630 if (AOP_SIZE(result) > 1)
4631 aopPut(AOP(result),"a",offset++);
4633 l = aopGet(AOP(left),offset,FALSE,FALSE);
4635 emitcode("rlc","a");
4636 if (AOP_SIZE(result) > 1)
4637 aopPut(AOP(result),"a",offset++);
4640 /* now we need to put the carry into the
4641 highest order byte of the result */
4642 if (AOP_SIZE(result) > 1) {
4643 l = aopGet(AOP(result),0,FALSE,FALSE);
4646 emitcode("mov","acc.0,c");
4647 aopPut(AOP(result),"a",0);
4648 freeAsmop(left,NULL,ic,TRUE);
4649 freeAsmop(result,NULL,ic,TRUE);
4652 /*-----------------------------------------------------------------*/
4653 /* genGetHbit - generates code get highest order bit */
4654 /*-----------------------------------------------------------------*/
4655 static void genGetHbit (iCode *ic)
4657 operand *left, *result;
4659 result=IC_RESULT(ic);
4660 aopOp (left,ic,FALSE);
4661 aopOp (result,ic,FALSE);
4663 /* get the highest order byte into a */
4664 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
4665 if(AOP_TYPE(result) == AOP_CRY){
4666 emitcode("rlc","a");
4671 emitcode("anl","a,#0x01");
4676 freeAsmop(left,NULL,ic,TRUE);
4677 freeAsmop(result,NULL,ic,TRUE);
4680 /*-----------------------------------------------------------------*/
4681 /* AccRol - rotate left accumulator by known count */
4682 /*-----------------------------------------------------------------*/
4683 static void AccRol (int shCount)
4685 shCount &= 0x0007; // shCount : 0..7
4697 emitcode("swap","a");
4701 emitcode("swap","a");
4704 emitcode("swap","a");
4717 /*-----------------------------------------------------------------*/
4718 /* AccLsh - left shift accumulator by known count */
4719 /*-----------------------------------------------------------------*/
4720 static void AccLsh (int shCount)
4724 emitcode("add","a,acc");
4727 emitcode("add","a,acc");
4728 emitcode("add","a,acc");
4730 /* rotate left accumulator */
4732 /* and kill the lower order bits */
4733 emitcode("anl","a,#0x%02x", SLMask[shCount]);
4738 /*-----------------------------------------------------------------*/
4739 /* AccRsh - right shift accumulator by known count */
4740 /*-----------------------------------------------------------------*/
4741 static void AccRsh (int shCount)
4746 emitcode("rrc","a");
4748 /* rotate right accumulator */
4749 AccRol(8 - shCount);
4750 /* and kill the higher order bits */
4751 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4756 /*-----------------------------------------------------------------*/
4757 /* AccSRsh - signed right shift accumulator by known count */
4758 /*-----------------------------------------------------------------*/
4759 static void AccSRsh (int shCount)
4764 emitcode("mov","c,acc.7");
4765 emitcode("rrc","a");
4766 } else if(shCount == 2){
4767 emitcode("mov","c,acc.7");
4768 emitcode("rrc","a");
4769 emitcode("mov","c,acc.7");
4770 emitcode("rrc","a");
4772 tlbl = newiTempLabel(NULL);
4773 /* rotate right accumulator */
4774 AccRol(8 - shCount);
4775 /* and kill the higher order bits */
4776 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4777 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4778 emitcode("orl","a,#0x%02x",
4779 (unsigned char)~SRMask[shCount]);
4780 emitcode("","%05d$:",tlbl->key+100);
4785 /*-----------------------------------------------------------------*/
4786 /* shiftR1Left2Result - shift right one byte from left to result */
4787 /*-----------------------------------------------------------------*/
4788 static void shiftR1Left2Result (operand *left, int offl,
4789 operand *result, int offr,
4790 int shCount, int sign)
4792 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4793 /* shift right accumulator */
4798 aopPut(AOP(result),"a",offr);
4801 /*-----------------------------------------------------------------*/
4802 /* shiftL1Left2Result - shift left one byte from left to result */
4803 /*-----------------------------------------------------------------*/
4804 static void shiftL1Left2Result (operand *left, int offl,
4805 operand *result, int offr, int shCount)
4808 l = aopGet(AOP(left),offl,FALSE,FALSE);
4810 /* shift left accumulator */
4812 aopPut(AOP(result),"a",offr);
4815 /*-----------------------------------------------------------------*/
4816 /* movLeft2Result - move byte from left to result */
4817 /*-----------------------------------------------------------------*/
4818 static void movLeft2Result (operand *left, int offl,
4819 operand *result, int offr, int sign)
4822 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
4823 l = aopGet(AOP(left),offl,FALSE,FALSE);
4825 if (*l == '@' && (IS_AOP_PREG(result))) {
4826 emitcode("mov","a,%s",l);
4827 aopPut(AOP(result),"a",offr);
4830 aopPut(AOP(result),l,offr);
4832 /* MSB sign in acc.7 ! */
4833 if(getDataSize(left) == offl+1){
4834 emitcode("mov","a,%s",l);
4835 aopPut(AOP(result),"a",offr);
4842 /*-----------------------------------------------------------------*/
4843 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
4844 /*-----------------------------------------------------------------*/
4845 static void AccAXRrl1 (char *x)
4847 emitcode("rrc","a");
4848 emitcode("xch","a,%s", x);
4849 emitcode("rrc","a");
4850 emitcode("xch","a,%s", x);
4853 /*-----------------------------------------------------------------*/
4854 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
4855 /*-----------------------------------------------------------------*/
4856 static void AccAXLrl1 (char *x)
4858 emitcode("xch","a,%s",x);
4859 emitcode("rlc","a");
4860 emitcode("xch","a,%s",x);
4861 emitcode("rlc","a");
4864 /*-----------------------------------------------------------------*/
4865 /* AccAXLsh1 - left shift a:x<-0 by 1 */
4866 /*-----------------------------------------------------------------*/
4867 static void AccAXLsh1 (char *x)
4869 emitcode("xch","a,%s",x);
4870 emitcode("add","a,acc");
4871 emitcode("xch","a,%s",x);
4872 emitcode("rlc","a");
4875 /*-----------------------------------------------------------------*/
4876 /* AccAXLsh - left shift a:x by known count (0..7) */
4877 /*-----------------------------------------------------------------*/
4878 static void AccAXLsh (char *x, int shCount)
4892 case 5 : // AAAAABBB:CCCCCDDD
4893 AccRol(shCount); // BBBAAAAA:CCCCCDDD
4894 emitcode("anl","a,#0x%02x",
4895 SLMask[shCount]); // BBB00000:CCCCCDDD
4896 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
4897 AccRol(shCount); // DDDCCCCC:BBB00000
4898 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
4899 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
4900 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
4901 emitcode("anl","a,#0x%02x",
4902 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
4903 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
4904 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
4906 case 6 : // AAAAAABB:CCCCCCDD
4907 emitcode("anl","a,#0x%02x",
4908 SRMask[shCount]); // 000000BB:CCCCCCDD
4909 emitcode("mov","c,acc.0"); // c = B
4910 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
4911 AccAXRrl1(x); // BCCCCCCD:D000000B
4912 AccAXRrl1(x); // BBCCCCCC:DD000000
4914 case 7 : // a:x <<= 7
4915 emitcode("anl","a,#0x%02x",
4916 SRMask[shCount]); // 0000000B:CCCCCCCD
4917 emitcode("mov","c,acc.0"); // c = B
4918 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
4919 AccAXRrl1(x); // BCCCCCCC:D0000000
4926 /*-----------------------------------------------------------------*/
4927 /* AccAXRsh - right shift a:x known count (0..7) */
4928 /*-----------------------------------------------------------------*/
4929 static void AccAXRsh (char *x, int shCount)
4936 AccAXRrl1(x); // 0->a:x
4940 AccAXRrl1(x); // 0->a:x
4942 AccAXRrl1(x); // 0->a:x
4946 case 5 : // AAAAABBB:CCCCCDDD = a:x
4947 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
4948 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
4949 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
4950 emitcode("anl","a,#0x%02x",
4951 SRMask[shCount]); // 000CCCCC:BBBAAAAA
4952 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
4953 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
4954 emitcode("anl","a,#0x%02x",
4955 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
4956 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
4957 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
4958 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
4960 case 6 : // AABBBBBB:CCDDDDDD
4961 emitcode("mov","c,acc.7");
4962 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
4963 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
4964 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
4965 emitcode("anl","a,#0x%02x",
4966 SRMask[shCount]); // 000000AA:BBBBBBCC
4968 case 7 : // ABBBBBBB:CDDDDDDD
4969 emitcode("mov","c,acc.7"); // c = A
4970 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
4971 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
4972 emitcode("anl","a,#0x%02x",
4973 SRMask[shCount]); // 0000000A:BBBBBBBC
4980 /*-----------------------------------------------------------------*/
4981 /* AccAXRshS - right shift signed a:x known count (0..7) */
4982 /*-----------------------------------------------------------------*/
4983 static void AccAXRshS (char *x, int shCount)
4990 emitcode("mov","c,acc.7");
4991 AccAXRrl1(x); // s->a:x
4994 emitcode("mov","c,acc.7");
4995 AccAXRrl1(x); // s->a:x
4996 emitcode("mov","c,acc.7");
4997 AccAXRrl1(x); // s->a:x
5001 case 5 : // AAAAABBB:CCCCCDDD = a:x
5002 tlbl = newiTempLabel(NULL);
5003 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5004 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5005 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5006 emitcode("anl","a,#0x%02x",
5007 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5008 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5009 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5010 emitcode("anl","a,#0x%02x",
5011 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5012 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5013 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5014 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5015 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5016 emitcode("orl","a,#0x%02x",
5017 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5018 emitcode("","%05d$:",tlbl->key+100);
5019 break; // SSSSAAAA:BBBCCCCC
5020 case 6 : // AABBBBBB:CCDDDDDD
5021 tlbl = newiTempLabel(NULL);
5022 emitcode("mov","c,acc.7");
5023 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5024 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5025 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5026 emitcode("anl","a,#0x%02x",
5027 SRMask[shCount]); // 000000AA:BBBBBBCC
5028 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5029 emitcode("orl","a,#0x%02x",
5030 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5031 emitcode("","%05d$:",tlbl->key+100);
5033 case 7 : // ABBBBBBB:CDDDDDDD
5034 tlbl = newiTempLabel(NULL);
5035 emitcode("mov","c,acc.7"); // c = A
5036 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5037 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5038 emitcode("anl","a,#0x%02x",
5039 SRMask[shCount]); // 0000000A:BBBBBBBC
5040 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5041 emitcode("orl","a,#0x%02x",
5042 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5043 emitcode("","%05d$:",tlbl->key+100);
5050 /*-----------------------------------------------------------------*/
5051 /* shiftL2Left2Result - shift left two bytes from left to result */
5052 /*-----------------------------------------------------------------*/
5053 static void shiftL2Left2Result (operand *left, int offl,
5054 operand *result, int offr, int shCount)
5056 if(sameRegs(AOP(result), AOP(left)) &&
5057 ((offl + MSB16) == offr)){
5058 /* don't crash result[offr] */
5059 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5060 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5062 movLeft2Result(left,offl, result, offr, 0);
5063 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5065 /* ax << shCount (x = lsb(result))*/
5066 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5067 aopPut(AOP(result),"a",offr+MSB16);
5071 /*-----------------------------------------------------------------*/
5072 /* shiftR2Left2Result - shift right two bytes from left to result */
5073 /*-----------------------------------------------------------------*/
5074 static void shiftR2Left2Result (operand *left, int offl,
5075 operand *result, int offr,
5076 int shCount, int sign)
5078 if(sameRegs(AOP(result), AOP(left)) &&
5079 ((offl + MSB16) == offr)){
5080 /* don't crash result[offr] */
5081 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5082 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5084 movLeft2Result(left,offl, result, offr, 0);
5085 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5087 /* a:x >> shCount (x = lsb(result))*/
5089 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5091 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5092 if(getDataSize(result) > 1)
5093 aopPut(AOP(result),"a",offr+MSB16);
5096 /*-----------------------------------------------------------------*/
5097 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5098 /*-----------------------------------------------------------------*/
5099 static void shiftLLeftOrResult (operand *left, int offl,
5100 operand *result, int offr, int shCount)
5102 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5103 /* shift left accumulator */
5105 /* or with result */
5106 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5107 /* back to result */
5108 aopPut(AOP(result),"a",offr);
5111 /*-----------------------------------------------------------------*/
5112 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5113 /*-----------------------------------------------------------------*/
5114 static void shiftRLeftOrResult (operand *left, int offl,
5115 operand *result, int offr, int shCount)
5117 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5118 /* shift right accumulator */
5120 /* or with result */
5121 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5122 /* back to result */
5123 aopPut(AOP(result),"a",offr);
5126 /*-----------------------------------------------------------------*/
5127 /* genlshOne - left shift a one byte quantity by known count */
5128 /*-----------------------------------------------------------------*/
5129 static void genlshOne (operand *result, operand *left, int shCount)
5131 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5134 /*-----------------------------------------------------------------*/
5135 /* genlshTwo - left shift two bytes by known amount != 0 */
5136 /*-----------------------------------------------------------------*/
5137 static void genlshTwo (operand *result,operand *left, int shCount)
5141 size = getDataSize(result);
5143 /* if shCount >= 8 */
5149 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5151 movLeft2Result(left, LSB, result, MSB16, 0);
5153 aopPut(AOP(result),zero,LSB);
5156 /* 1 <= shCount <= 7 */
5159 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5161 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5165 /*-----------------------------------------------------------------*/
5166 /* shiftLLong - shift left one long from left to result */
5167 /* offl = LSB or MSB16 */
5168 /*-----------------------------------------------------------------*/
5169 static void shiftLLong (operand *left, operand *result, int offr )
5172 int size = AOP_SIZE(result);
5174 if(size >= LSB+offr){
5175 l = aopGet(AOP(left),LSB,FALSE,FALSE);
5177 emitcode("add","a,acc");
5178 if (sameRegs(AOP(left),AOP(result)) &&
5179 size >= MSB16+offr && offr != LSB )
5180 emitcode("xch","a,%s",
5181 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
5183 aopPut(AOP(result),"a",LSB+offr);
5186 if(size >= MSB16+offr){
5187 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5188 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
5191 emitcode("rlc","a");
5192 if (sameRegs(AOP(left),AOP(result)) &&
5193 size >= MSB24+offr && offr != LSB)
5194 emitcode("xch","a,%s",
5195 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
5197 aopPut(AOP(result),"a",MSB16+offr);
5200 if(size >= MSB24+offr){
5201 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5202 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
5205 emitcode("rlc","a");
5206 if (sameRegs(AOP(left),AOP(result)) &&
5207 size >= MSB32+offr && offr != LSB )
5208 emitcode("xch","a,%s",
5209 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
5211 aopPut(AOP(result),"a",MSB24+offr);
5214 if(size > MSB32+offr){
5215 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5216 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
5219 emitcode("rlc","a");
5220 aopPut(AOP(result),"a",MSB32+offr);
5223 aopPut(AOP(result),zero,LSB);
5226 /*-----------------------------------------------------------------*/
5227 /* genlshFour - shift four byte by a known amount != 0 */
5228 /*-----------------------------------------------------------------*/
5229 static void genlshFour (operand *result, operand *left, int shCount)
5233 size = AOP_SIZE(result);
5235 /* if shifting more that 3 bytes */
5236 if (shCount >= 24 ) {
5239 /* lowest order of left goes to the highest
5240 order of the destination */
5241 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5243 movLeft2Result(left, LSB, result, MSB32, 0);
5244 aopPut(AOP(result),zero,LSB);
5245 aopPut(AOP(result),zero,MSB16);
5246 aopPut(AOP(result),zero,MSB32);
5250 /* more than two bytes */
5251 else if ( shCount >= 16 ) {
5252 /* lower order two bytes goes to higher order two bytes */
5254 /* if some more remaining */
5256 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5258 movLeft2Result(left, MSB16, result, MSB32, 0);
5259 movLeft2Result(left, LSB, result, MSB24, 0);
5261 aopPut(AOP(result),zero,MSB16);
5262 aopPut(AOP(result),zero,LSB);
5266 /* if more than 1 byte */
5267 else if ( shCount >= 8 ) {
5268 /* lower order three bytes goes to higher order three bytes */
5272 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5274 movLeft2Result(left, LSB, result, MSB16, 0);
5276 else{ /* size = 4 */
5278 movLeft2Result(left, MSB24, result, MSB32, 0);
5279 movLeft2Result(left, MSB16, result, MSB24, 0);
5280 movLeft2Result(left, LSB, result, MSB16, 0);
5281 aopPut(AOP(result),zero,LSB);
5283 else if(shCount == 1)
5284 shiftLLong(left, result, MSB16);
5286 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5287 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5288 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5289 aopPut(AOP(result),zero,LSB);
5294 /* 1 <= shCount <= 7 */
5295 else if(shCount <= 2){
5296 shiftLLong(left, result, LSB);
5298 shiftLLong(result, result, LSB);
5300 /* 3 <= shCount <= 7, optimize */
5302 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5303 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5304 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5308 /*-----------------------------------------------------------------*/
5309 /* genLeftShiftLiteral - left shifting by known count */
5310 /*-----------------------------------------------------------------*/
5311 static void genLeftShiftLiteral (operand *left,
5316 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5319 freeAsmop(right,NULL,ic,TRUE);
5321 aopOp(left,ic,FALSE);
5322 aopOp(result,ic,FALSE);
5324 size = getSize(operandType(result));
5327 emitcode("; shift left ","result %d, left %d",size,
5331 /* I suppose that the left size >= result size */
5334 movLeft2Result(left, size, result, size, 0);
5338 else if(shCount >= (size * 8))
5340 aopPut(AOP(result),zero,size);
5344 genlshOne (result,left,shCount);
5349 genlshTwo (result,left,shCount);
5353 genlshFour (result,left,shCount);
5357 freeAsmop(left,NULL,ic,TRUE);
5358 freeAsmop(result,NULL,ic,TRUE);
5361 /*-----------------------------------------------------------------*/
5362 /* genLeftShift - generates code for left shifting */
5363 /*-----------------------------------------------------------------*/
5364 static void genLeftShift (iCode *ic)
5366 operand *left,*right, *result;
5369 symbol *tlbl , *tlbl1;
5371 right = IC_RIGHT(ic);
5373 result = IC_RESULT(ic);
5375 aopOp(right,ic,FALSE);
5377 /* if the shift count is known then do it
5378 as efficiently as possible */
5379 if (AOP_TYPE(right) == AOP_LIT) {
5380 genLeftShiftLiteral (left,right,result,ic);
5384 /* shift count is unknown then we have to form
5385 a loop get the loop count in B : Note: we take
5386 only the lower order byte since shifting
5387 more that 32 bits make no sense anyway, ( the
5388 largest size of an object can be only 32 bits ) */
5390 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5391 emitcode("inc","b");
5392 freeAsmop (right,NULL,ic,TRUE);
5393 aopOp(left,ic,FALSE);
5394 aopOp(result,ic,FALSE);
5396 /* now move the left to the result if they are not the
5398 if (!sameRegs(AOP(left),AOP(result)) &&
5399 AOP_SIZE(result) > 1) {
5401 size = AOP_SIZE(result);
5404 l = aopGet(AOP(left),offset,FALSE,TRUE);
5405 if (*l == '@' && (IS_AOP_PREG(result))) {
5407 emitcode("mov","a,%s",l);
5408 aopPut(AOP(result),"a",offset);
5410 aopPut(AOP(result),l,offset);
5415 tlbl = newiTempLabel(NULL);
5416 size = AOP_SIZE(result);
5418 tlbl1 = newiTempLabel(NULL);
5420 /* if it is only one byte then */
5422 symbol *tlbl1 = newiTempLabel(NULL);
5424 l = aopGet(AOP(left),0,FALSE,FALSE);
5426 emitcode("sjmp","%05d$",tlbl1->key+100);
5427 emitcode("","%05d$:",tlbl->key+100);
5428 emitcode("add","a,acc");
5429 emitcode("","%05d$:",tlbl1->key+100);
5430 emitcode("djnz","b,%05d$",tlbl->key+100);
5431 aopPut(AOP(result),"a",0);
5435 reAdjustPreg(AOP(result));
5437 emitcode("sjmp","%05d$",tlbl1->key+100);
5438 emitcode("","%05d$:",tlbl->key+100);
5439 l = aopGet(AOP(result),offset,FALSE,FALSE);
5441 emitcode("add","a,acc");
5442 aopPut(AOP(result),"a",offset++);
5444 l = aopGet(AOP(result),offset,FALSE,FALSE);
5446 emitcode("rlc","a");
5447 aopPut(AOP(result),"a",offset++);
5449 reAdjustPreg(AOP(result));
5451 emitcode("","%05d$:",tlbl1->key+100);
5452 emitcode("djnz","b,%05d$",tlbl->key+100);
5454 freeAsmop(left,NULL,ic,TRUE);
5455 freeAsmop(result,NULL,ic,TRUE);
5458 /*-----------------------------------------------------------------*/
5459 /* genrshOne - right shift a one byte quantity by known count */
5460 /*-----------------------------------------------------------------*/
5461 static void genrshOne (operand *result, operand *left,
5462 int shCount, int sign)
5464 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
5467 /*-----------------------------------------------------------------*/
5468 /* genrshTwo - right shift two bytes by known amount != 0 */
5469 /*-----------------------------------------------------------------*/
5470 static void genrshTwo (operand *result,operand *left,
5471 int shCount, int sign)
5473 /* if shCount >= 8 */
5477 shiftR1Left2Result(left, MSB16, result, LSB,
5480 movLeft2Result(left, MSB16, result, LSB, sign);
5481 addSign(result, MSB16, sign);
5484 /* 1 <= shCount <= 7 */
5486 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
5489 /*-----------------------------------------------------------------*/
5490 /* shiftRLong - shift right one long from left to result */
5491 /* offl = LSB or MSB16 */
5492 /*-----------------------------------------------------------------*/
5493 static void shiftRLong (operand *left, int offl,
5494 operand *result, int sign)
5497 emitcode("clr","c");
5498 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
5500 emitcode("mov","c,acc.7");
5501 emitcode("rrc","a");
5502 aopPut(AOP(result),"a",MSB32-offl);
5504 /* add sign of "a" */
5505 addSign(result, MSB32, sign);
5507 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
5508 emitcode("rrc","a");
5509 aopPut(AOP(result),"a",MSB24-offl);
5511 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
5512 emitcode("rrc","a");
5513 aopPut(AOP(result),"a",MSB16-offl);
5516 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
5517 emitcode("rrc","a");
5518 aopPut(AOP(result),"a",LSB);
5522 /*-----------------------------------------------------------------*/
5523 /* genrshFour - shift four byte by a known amount != 0 */
5524 /*-----------------------------------------------------------------*/
5525 static void genrshFour (operand *result, operand *left,
5526 int shCount, int sign)
5528 /* if shifting more that 3 bytes */
5529 if(shCount >= 24 ) {
5532 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
5534 movLeft2Result(left, MSB32, result, LSB, sign);
5535 addSign(result, MSB16, sign);
5537 else if(shCount >= 16){
5540 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
5542 movLeft2Result(left, MSB24, result, LSB, 0);
5543 movLeft2Result(left, MSB32, result, MSB16, sign);
5545 addSign(result, MSB24, sign);
5547 else if(shCount >= 8){
5550 shiftRLong(left, MSB16, result, sign);
5551 else if(shCount == 0){
5552 movLeft2Result(left, MSB16, result, LSB, 0);
5553 movLeft2Result(left, MSB24, result, MSB16, 0);
5554 movLeft2Result(left, MSB32, result, MSB24, sign);
5555 addSign(result, MSB32, sign);
5558 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
5559 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
5560 /* the last shift is signed */
5561 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
5562 addSign(result, MSB32, sign);
5565 else{ /* 1 <= shCount <= 7 */
5567 shiftRLong(left, LSB, result, sign);
5569 shiftRLong(result, LSB, result, sign);
5572 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
5573 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
5574 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
5579 /*-----------------------------------------------------------------*/
5580 /* genRightShiftLiteral - right shifting by known count */
5581 /*-----------------------------------------------------------------*/
5582 static void genRightShiftLiteral (operand *left,
5588 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5591 freeAsmop(right,NULL,ic,TRUE);
5593 aopOp(left,ic,FALSE);
5594 aopOp(result,ic,FALSE);
5597 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
5601 size = getDataSize(left);
5602 /* test the LEFT size !!! */
5604 /* I suppose that the left size >= result size */
5606 size = getDataSize(result);
5608 movLeft2Result(left, size, result, size, 0);
5611 else if(shCount >= (size * 8)){
5613 /* get sign in acc.7 */
5614 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
5615 addSign(result, LSB, sign);
5619 genrshOne (result,left,shCount,sign);
5623 genrshTwo (result,left,shCount,sign);
5627 genrshFour (result,left,shCount,sign);
5633 freeAsmop(left,NULL,ic,TRUE);
5634 freeAsmop(result,NULL,ic,TRUE);
5638 /*-----------------------------------------------------------------*/
5639 /* genSignedRightShift - right shift of signed number */
5640 /*-----------------------------------------------------------------*/
5641 static void genSignedRightShift (iCode *ic)
5643 operand *right, *left, *result;
5646 symbol *tlbl, *tlbl1 ;
5648 /* we do it the hard way put the shift count in b
5649 and loop thru preserving the sign */
5651 right = IC_RIGHT(ic);
5653 result = IC_RESULT(ic);
5655 aopOp(right,ic,FALSE);
5658 if ( AOP_TYPE(right) == AOP_LIT) {
5659 genRightShiftLiteral (left,right,result,ic,1);
5662 /* shift count is unknown then we have to form
5663 a loop get the loop count in B : Note: we take
5664 only the lower order byte since shifting
5665 more that 32 bits make no sense anyway, ( the
5666 largest size of an object can be only 32 bits ) */
5668 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5669 emitcode("inc","b");
5670 freeAsmop (right,NULL,ic,TRUE);
5671 aopOp(left,ic,FALSE);
5672 aopOp(result,ic,FALSE);
5674 /* now move the left to the result if they are not the
5676 if (!sameRegs(AOP(left),AOP(result)) &&
5677 AOP_SIZE(result) > 1) {
5679 size = AOP_SIZE(result);
5682 l = aopGet(AOP(left),offset,FALSE,TRUE);
5683 if (*l == '@' && IS_AOP_PREG(result)) {
5685 emitcode("mov","a,%s",l);
5686 aopPut(AOP(result),"a",offset);
5688 aopPut(AOP(result),l,offset);
5693 /* mov the highest order bit to OVR */
5694 tlbl = newiTempLabel(NULL);
5695 tlbl1= newiTempLabel(NULL);
5697 size = AOP_SIZE(result);
5699 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
5700 emitcode("rlc","a");
5701 emitcode("mov","ov,c");
5702 /* if it is only one byte then */
5704 l = aopGet(AOP(left),0,FALSE,FALSE);
5706 emitcode("sjmp","%05d$",tlbl1->key+100);
5707 emitcode("","%05d$:",tlbl->key+100);
5708 emitcode("mov","c,ov");
5709 emitcode("rrc","a");
5710 emitcode("","%05d$:",tlbl1->key+100);
5711 emitcode("djnz","b,%05d$",tlbl->key+100);
5712 aopPut(AOP(result),"a",0);
5716 reAdjustPreg(AOP(result));
5717 emitcode("sjmp","%05d$",tlbl1->key+100);
5718 emitcode("","%05d$:",tlbl->key+100);
5719 emitcode("mov","c,ov");
5721 l = aopGet(AOP(result),offset,FALSE,FALSE);
5723 emitcode("rrc","a");
5724 aopPut(AOP(result),"a",offset--);
5726 reAdjustPreg(AOP(result));
5727 emitcode("","%05d$:",tlbl1->key+100);
5728 emitcode("djnz","b,%05d$",tlbl->key+100);
5731 freeAsmop(left,NULL,ic,TRUE);
5732 freeAsmop(result,NULL,ic,TRUE);
5735 /*-----------------------------------------------------------------*/
5736 /* genRightShift - generate code for right shifting */
5737 /*-----------------------------------------------------------------*/
5738 static void genRightShift (iCode *ic)
5740 operand *right, *left, *result;
5744 symbol *tlbl, *tlbl1 ;
5746 /* if signed then we do it the hard way preserve the
5747 sign bit moving it inwards */
5748 retype = getSpec(operandType(IC_RESULT(ic)));
5750 if (!SPEC_USIGN(retype)) {
5751 genSignedRightShift (ic);
5755 /* signed & unsigned types are treated the same : i.e. the
5756 signed is NOT propagated inwards : quoting from the
5757 ANSI - standard : "for E1 >> E2, is equivalent to division
5758 by 2**E2 if unsigned or if it has a non-negative value,
5759 otherwise the result is implementation defined ", MY definition
5760 is that the sign does not get propagated */
5762 right = IC_RIGHT(ic);
5764 result = IC_RESULT(ic);
5766 aopOp(right,ic,FALSE);
5768 /* if the shift count is known then do it
5769 as efficiently as possible */
5770 if (AOP_TYPE(right) == AOP_LIT) {
5771 genRightShiftLiteral (left,right,result,ic, 0);
5775 /* shift count is unknown then we have to form
5776 a loop get the loop count in B : Note: we take
5777 only the lower order byte since shifting
5778 more that 32 bits make no sense anyway, ( the
5779 largest size of an object can be only 32 bits ) */
5781 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5782 emitcode("inc","b");
5783 freeAsmop (right,NULL,ic,TRUE);
5784 aopOp(left,ic,FALSE);
5785 aopOp(result,ic,FALSE);
5787 /* now move the left to the result if they are not the
5789 if (!sameRegs(AOP(left),AOP(result)) &&
5790 AOP_SIZE(result) > 1) {
5792 size = AOP_SIZE(result);
5795 l = aopGet(AOP(left),offset,FALSE,TRUE);
5796 if (*l == '@' && IS_AOP_PREG(result)) {
5798 emitcode("mov","a,%s",l);
5799 aopPut(AOP(result),"a",offset);
5801 aopPut(AOP(result),l,offset);
5806 tlbl = newiTempLabel(NULL);
5807 tlbl1= newiTempLabel(NULL);
5808 size = AOP_SIZE(result);
5811 /* if it is only one byte then */
5813 l = aopGet(AOP(left),0,FALSE,FALSE);
5815 emitcode("sjmp","%05d$",tlbl1->key+100);
5816 emitcode("","%05d$:",tlbl->key+100);
5818 emitcode("rrc","a");
5819 emitcode("","%05d$:",tlbl1->key+100);
5820 emitcode("djnz","b,%05d$",tlbl->key+100);
5821 aopPut(AOP(result),"a",0);
5825 reAdjustPreg(AOP(result));
5826 emitcode("sjmp","%05d$",tlbl1->key+100);
5827 emitcode("","%05d$:",tlbl->key+100);
5830 l = aopGet(AOP(result),offset,FALSE,FALSE);
5832 emitcode("rrc","a");
5833 aopPut(AOP(result),"a",offset--);
5835 reAdjustPreg(AOP(result));
5837 emitcode("","%05d$:",tlbl1->key+100);
5838 emitcode("djnz","b,%05d$",tlbl->key+100);
5841 freeAsmop(left,NULL,ic,TRUE);
5842 freeAsmop(result,NULL,ic,TRUE);
5845 /*-----------------------------------------------------------------*/
5846 /* genUnpackBits - generates code for unpacking bits */
5847 /*-----------------------------------------------------------------*/
5848 static void genUnpackBits (operand *result, char *rname, int ptype)
5855 etype = getSpec(operandType(result));
5857 /* read the first byte */
5862 emitcode("mov","a,@%s",rname);
5866 emitcode("movx","a,@%s",rname);
5870 emitcode("movx","a,@dptr");
5874 emitcode("clr","a");
5875 emitcode("movc","a","@a+dptr");
5879 emitcode("lcall","__gptrget");
5883 /* if we have bitdisplacement then it fits */
5884 /* into this byte completely or if length is */
5885 /* less than a byte */
5886 if ((shCnt = SPEC_BSTR(etype)) ||
5887 (SPEC_BLEN(etype) <= 8)) {
5889 /* shift right acc */
5892 emitcode("anl","a,#0x%02x",
5893 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
5894 aopPut(AOP(result),"a",offset);
5898 /* bit field did not fit in a byte */
5899 rlen = SPEC_BLEN(etype) - 8;
5900 aopPut(AOP(result),"a",offset++);
5907 emitcode("inc","%s",rname);
5908 emitcode("mov","a,@%s",rname);
5912 emitcode("inc","%s",rname);
5913 emitcode("movx","a,@%s",rname);
5917 emitcode("inc","dptr");
5918 emitcode("movx","a,@dptr");
5922 emitcode("clr","a");
5923 emitcode("inc","dptr");
5924 emitcode("movc","a","@a+dptr");
5928 emitcode("inc","dptr");
5929 emitcode("lcall","__gptrget");
5934 /* if we are done */
5938 aopPut(AOP(result),"a",offset++);
5943 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
5944 aopPut(AOP(result),"a",offset);
5951 /*-----------------------------------------------------------------*/
5952 /* genDataPointerGet - generates code when ptr offset is known */
5953 /*-----------------------------------------------------------------*/
5954 static void genDataPointerGet (operand *left,
5960 int size , offset = 0;
5961 aopOp(result,ic,TRUE);
5963 /* get the string representation of the name */
5964 l = aopGet(AOP(left),0,FALSE,TRUE);
5965 size = AOP_SIZE(result);
5968 sprintf(buffer,"(%s + %d)",l+1,offset);
5970 sprintf(buffer,"%s",l+1);
5971 aopPut(AOP(result),buffer,offset++);
5974 freeAsmop(left,NULL,ic,TRUE);
5975 freeAsmop(result,NULL,ic,TRUE);
5978 /*-----------------------------------------------------------------*/
5979 /* genNearPointerGet - emitcode for near pointer fetch */
5980 /*-----------------------------------------------------------------*/
5981 static void genNearPointerGet (operand *left,
5988 link *rtype, *retype;
5989 link *ltype = operandType(left);
5992 rtype = operandType(result);
5993 retype= getSpec(rtype);
5995 aopOp(left,ic,FALSE);
5997 /* if left is rematerialisable and
5998 result is not bit variable type and
5999 the left is pointer to data space i.e
6000 lower 128 bytes of space */
6001 if (AOP_TYPE(left) == AOP_IMMD &&
6002 !IS_BITVAR(retype) &&
6003 DCL_TYPE(ltype) == POINTER) {
6004 genDataPointerGet (left,result,ic);
6008 /* if the value is already in a pointer register
6009 then don't need anything more */
6010 if (!AOP_INPREG(AOP(left))) {
6011 /* otherwise get a free pointer register */
6013 preg = getFreePtr(ic,&aop,FALSE);
6014 emitcode("mov","%s,%s",
6016 aopGet(AOP(left),0,FALSE,TRUE));
6017 rname = preg->name ;
6019 rname = aopGet(AOP(left),0,FALSE,FALSE);
6021 freeAsmop(left,NULL,ic,TRUE);
6022 aopOp (result,ic,FALSE);
6024 /* if bitfield then unpack the bits */
6025 if (IS_BITVAR(retype))
6026 genUnpackBits (result,rname,POINTER);
6028 /* we have can just get the values */
6029 int size = AOP_SIZE(result);
6033 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6035 emitcode("mov","a,@%s",rname);
6036 aopPut(AOP(result),"a",offset);
6038 sprintf(buffer,"@%s",rname);
6039 aopPut(AOP(result),buffer,offset);
6043 emitcode("inc","%s",rname);
6047 /* now some housekeeping stuff */
6049 /* we had to allocate for this iCode */
6050 freeAsmop(NULL,aop,ic,TRUE);
6052 /* we did not allocate which means left
6053 already in a pointer register, then
6054 if size > 0 && this could be used again
6055 we have to point it back to where it
6057 if (AOP_SIZE(result) > 1 &&
6058 !OP_SYMBOL(left)->remat &&
6059 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6061 int size = AOP_SIZE(result) - 1;
6063 emitcode("dec","%s",rname);
6068 freeAsmop(result,NULL,ic,TRUE);
6072 /*-----------------------------------------------------------------*/
6073 /* genPagedPointerGet - emitcode for paged pointer fetch */
6074 /*-----------------------------------------------------------------*/
6075 static void genPagedPointerGet (operand *left,
6082 link *rtype, *retype;
6084 rtype = operandType(result);
6085 retype= getSpec(rtype);
6087 aopOp(left,ic,FALSE);
6089 /* if the value is already in a pointer register
6090 then don't need anything more */
6091 if (!AOP_INPREG(AOP(left))) {
6092 /* otherwise get a free pointer register */
6094 preg = getFreePtr(ic,&aop,FALSE);
6095 emitcode("mov","%s,%s",
6097 aopGet(AOP(left),0,FALSE,TRUE));
6098 rname = preg->name ;
6100 rname = aopGet(AOP(left),0,FALSE,FALSE);
6102 freeAsmop(left,NULL,ic,TRUE);
6103 aopOp (result,ic,FALSE);
6105 /* if bitfield then unpack the bits */
6106 if (IS_BITVAR(retype))
6107 genUnpackBits (result,rname,PPOINTER);
6109 /* we have can just get the values */
6110 int size = AOP_SIZE(result);
6115 emitcode("movx","a,@%s",rname);
6116 aopPut(AOP(result),"a",offset);
6121 emitcode("inc","%s",rname);
6125 /* now some housekeeping stuff */
6127 /* we had to allocate for this iCode */
6128 freeAsmop(NULL,aop,ic,TRUE);
6130 /* we did not allocate which means left
6131 already in a pointer register, then
6132 if size > 0 && this could be used again
6133 we have to point it back to where it
6135 if (AOP_SIZE(result) > 1 &&
6136 !OP_SYMBOL(left)->remat &&
6137 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6139 int size = AOP_SIZE(result) - 1;
6141 emitcode("dec","%s",rname);
6146 freeAsmop(result,NULL,ic,TRUE);
6151 /*-----------------------------------------------------------------*/
6152 /* genFarPointerGet - gget value from far space */
6153 /*-----------------------------------------------------------------*/
6154 static void genFarPointerGet (operand *left,
6155 operand *result, iCode *ic)
6158 link *retype = getSpec(operandType(result));
6160 aopOp(left,ic,FALSE);
6162 /* if the operand is already in dptr
6163 then we do nothing else we move the value to dptr */
6164 if (AOP_TYPE(left) != AOP_STR) {
6165 /* if this is remateriazable */
6166 if (AOP_TYPE(left) == AOP_IMMD)
6167 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6168 else { /* we need to get it byte by byte */
6169 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6170 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6171 if (options.model == MODEL_FLAT24)
6173 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6177 /* so dptr know contains the address */
6178 freeAsmop(left,NULL,ic,TRUE);
6179 aopOp(result,ic,FALSE);
6181 /* if bit then unpack */
6182 if (IS_BITVAR(retype))
6183 genUnpackBits(result,"dptr",FPOINTER);
6185 size = AOP_SIZE(result);
6189 emitcode("movx","a,@dptr");
6190 aopPut(AOP(result),"a",offset++);
6192 emitcode("inc","dptr");
6196 freeAsmop(result,NULL,ic,TRUE);
6199 /*-----------------------------------------------------------------*/
6200 /* emitcodePointerGet - gget value from code space */
6201 /*-----------------------------------------------------------------*/
6202 static void emitcodePointerGet (operand *left,
6203 operand *result, iCode *ic)
6206 link *retype = getSpec(operandType(result));
6208 aopOp(left,ic,FALSE);
6210 /* if the operand is already in dptr
6211 then we do nothing else we move the value to dptr */
6212 if (AOP_TYPE(left) != AOP_STR) {
6213 /* if this is remateriazable */
6214 if (AOP_TYPE(left) == AOP_IMMD)
6215 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6216 else { /* we need to get it byte by byte */
6217 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6218 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6219 if (options.model == MODEL_FLAT24)
6221 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6225 /* so dptr know contains the address */
6226 freeAsmop(left,NULL,ic,TRUE);
6227 aopOp(result,ic,FALSE);
6229 /* if bit then unpack */
6230 if (IS_BITVAR(retype))
6231 genUnpackBits(result,"dptr",CPOINTER);
6233 size = AOP_SIZE(result);
6237 emitcode("clr","a");
6238 emitcode("movc","a,@a+dptr");
6239 aopPut(AOP(result),"a",offset++);
6241 emitcode("inc","dptr");
6245 freeAsmop(result,NULL,ic,TRUE);
6248 /*-----------------------------------------------------------------*/
6249 /* genGenPointerGet - gget value from generic pointer space */
6250 /*-----------------------------------------------------------------*/
6251 static void genGenPointerGet (operand *left,
6252 operand *result, iCode *ic)
6255 link *retype = getSpec(operandType(result));
6257 aopOp(left,ic,FALSE);
6259 /* if the operand is already in dptr
6260 then we do nothing else we move the value to dptr */
6261 if (AOP_TYPE(left) != AOP_STR) {
6262 /* if this is remateriazable */
6263 if (AOP_TYPE(left) == AOP_IMMD) {
6264 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6265 emitcode("mov","b,#%d",pointerCode(retype));
6267 else { /* we need to get it byte by byte */
6268 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6269 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6270 if (options.model == MODEL_FLAT24)
6272 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6273 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
6277 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
6281 /* so dptr know contains the address */
6282 freeAsmop(left,NULL,ic,TRUE);
6283 aopOp(result,ic,FALSE);
6285 /* if bit then unpack */
6286 if (IS_BITVAR(retype))
6287 genUnpackBits(result,"dptr",GPOINTER);
6289 size = AOP_SIZE(result);
6293 emitcode("lcall","__gptrget");
6294 aopPut(AOP(result),"a",offset++);
6296 emitcode("inc","dptr");
6300 freeAsmop(result,NULL,ic,TRUE);
6303 /*-----------------------------------------------------------------*/
6304 /* genPointerGet - generate code for pointer get */
6305 /*-----------------------------------------------------------------*/
6306 static void genPointerGet (iCode *ic)
6308 operand *left, *result ;
6313 result = IC_RESULT(ic) ;
6315 /* depending on the type of pointer we need to
6316 move it to the correct pointer register */
6317 type = operandType(left);
6318 etype = getSpec(type);
6319 /* if left is of type of pointer then it is simple */
6320 if (IS_PTR(type) && !IS_FUNC(type->next))
6321 p_type = DCL_TYPE(type);
6323 /* we have to go by the storage class */
6324 p_type = PTR_TYPE(SPEC_OCLS(etype));
6326 /* if (SPEC_OCLS(etype)->codesp ) { */
6327 /* p_type = CPOINTER ; */
6330 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6331 /* p_type = FPOINTER ; */
6333 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6334 /* p_type = PPOINTER; */
6336 /* if (SPEC_OCLS(etype) == idata ) */
6337 /* p_type = IPOINTER; */
6339 /* p_type = POINTER ; */
6342 /* now that we have the pointer type we assign
6343 the pointer values */
6348 genNearPointerGet (left,result,ic);
6352 genPagedPointerGet(left,result,ic);
6356 genFarPointerGet (left,result,ic);
6360 emitcodePointerGet (left,result,ic);
6364 genGenPointerGet (left,result,ic);
6370 /*-----------------------------------------------------------------*/
6371 /* genPackBits - generates code for packed bit storage */
6372 /*-----------------------------------------------------------------*/
6373 static void genPackBits (link *etype ,
6375 char *rname, int p_type)
6383 blen = SPEC_BLEN(etype);
6384 bstr = SPEC_BSTR(etype);
6386 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6389 /* if the bit lenth is less than or */
6390 /* it exactly fits a byte then */
6391 if (SPEC_BLEN(etype) <= 8 ) {
6392 shCount = SPEC_BSTR(etype) ;
6394 /* shift left acc */
6397 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6402 emitcode ("mov","b,a");
6403 emitcode("mov","a,@%s",rname);
6407 emitcode ("mov","b,a");
6408 emitcode("movx","a,@dptr");
6412 emitcode ("push","b");
6413 emitcode ("push","acc");
6414 emitcode ("lcall","__gptrget");
6415 emitcode ("pop","b");
6419 emitcode ("anl","a,#0x%02x",(unsigned char)
6420 ((unsigned char)(0xFF << (blen+bstr)) |
6421 (unsigned char)(0xFF >> (8-bstr)) ) );
6422 emitcode ("orl","a,b");
6423 if (p_type == GPOINTER)
6424 emitcode("pop","b");
6430 emitcode("mov","@%s,a",rname);
6434 emitcode("movx","@dptr,a");
6438 emitcode("lcall","__gptrput");
6443 if ( SPEC_BLEN(etype) <= 8 )
6446 emitcode("inc","%s",rname);
6447 rLen = SPEC_BLEN(etype) ;
6449 /* now generate for lengths greater than one byte */
6452 l = aopGet(AOP(right),offset++,FALSE,TRUE);
6462 emitcode("mov","@%s,a",rname);
6464 emitcode("mov","@%s,%s",rname,l);
6469 emitcode("movx","@dptr,a");
6474 emitcode("lcall","__gptrput");
6477 emitcode ("inc","%s",rname);
6482 /* last last was not complete */
6484 /* save the byte & read byte */
6487 emitcode ("mov","b,a");
6488 emitcode("mov","a,@%s",rname);
6492 emitcode ("mov","b,a");
6493 emitcode("movx","a,@dptr");
6497 emitcode ("push","b");
6498 emitcode ("push","acc");
6499 emitcode ("lcall","__gptrget");
6500 emitcode ("pop","b");
6504 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
6505 emitcode ("orl","a,b");
6508 if (p_type == GPOINTER)
6509 emitcode("pop","b");
6514 emitcode("mov","@%s,a",rname);
6518 emitcode("movx","@dptr,a");
6522 emitcode("lcall","__gptrput");
6526 /*-----------------------------------------------------------------*/
6527 /* genDataPointerSet - remat pointer to data space */
6528 /*-----------------------------------------------------------------*/
6529 static void genDataPointerSet(operand *right,
6533 int size, offset = 0 ;
6534 char *l, buffer[256];
6536 aopOp(right,ic,FALSE);
6538 l = aopGet(AOP(result),0,FALSE,TRUE);
6539 size = AOP_SIZE(right);
6542 sprintf(buffer,"(%s + %d)",l+1,offset);
6544 sprintf(buffer,"%s",l+1);
6545 emitcode("mov","%s,%s",buffer,
6546 aopGet(AOP(right),offset++,FALSE,FALSE));
6549 freeAsmop(right,NULL,ic,TRUE);
6550 freeAsmop(result,NULL,ic,TRUE);
6553 /*-----------------------------------------------------------------*/
6554 /* genNearPointerSet - emitcode for near pointer put */
6555 /*-----------------------------------------------------------------*/
6556 static void genNearPointerSet (operand *right,
6564 link *ptype = operandType(result);
6566 retype= getSpec(operandType(right));
6568 aopOp(result,ic,FALSE);
6570 /* if the result is rematerializable &
6571 in data space & not a bit variable */
6572 if (AOP_TYPE(result) == AOP_IMMD &&
6573 DCL_TYPE(ptype) == POINTER &&
6574 !IS_BITVAR(retype)) {
6575 genDataPointerSet (right,result,ic);
6579 /* if the value is already in a pointer register
6580 then don't need anything more */
6581 if (!AOP_INPREG(AOP(result))) {
6582 /* otherwise get a free pointer register */
6584 preg = getFreePtr(ic,&aop,FALSE);
6585 emitcode("mov","%s,%s",
6587 aopGet(AOP(result),0,FALSE,TRUE));
6588 rname = preg->name ;
6590 rname = aopGet(AOP(result),0,FALSE,FALSE);
6592 freeAsmop(result,NULL,ic,TRUE);
6593 aopOp (right,ic,FALSE);
6595 /* if bitfield then unpack the bits */
6596 if (IS_BITVAR(retype))
6597 genPackBits (retype,right,rname,POINTER);
6599 /* we have can just get the values */
6600 int size = AOP_SIZE(right);
6604 l = aopGet(AOP(right),offset,FALSE,TRUE);
6607 emitcode("mov","@%s,a",rname);
6609 emitcode("mov","@%s,%s",rname,l);
6611 emitcode("inc","%s",rname);
6616 /* now some housekeeping stuff */
6618 /* we had to allocate for this iCode */
6619 freeAsmop(NULL,aop,ic,TRUE);
6621 /* we did not allocate which means left
6622 already in a pointer register, then
6623 if size > 0 && this could be used again
6624 we have to point it back to where it
6626 if (AOP_SIZE(right) > 1 &&
6627 !OP_SYMBOL(result)->remat &&
6628 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6630 int size = AOP_SIZE(right) - 1;
6632 emitcode("dec","%s",rname);
6637 freeAsmop(right,NULL,ic,TRUE);
6642 /*-----------------------------------------------------------------*/
6643 /* genPagedPointerSet - emitcode for Paged pointer put */
6644 /*-----------------------------------------------------------------*/
6645 static void genPagedPointerSet (operand *right,
6654 retype= getSpec(operandType(right));
6656 aopOp(result,ic,FALSE);
6658 /* if the value is already in a pointer register
6659 then don't need anything more */
6660 if (!AOP_INPREG(AOP(result))) {
6661 /* otherwise get a free pointer register */
6663 preg = getFreePtr(ic,&aop,FALSE);
6664 emitcode("mov","%s,%s",
6666 aopGet(AOP(result),0,FALSE,TRUE));
6667 rname = preg->name ;
6669 rname = aopGet(AOP(result),0,FALSE,FALSE);
6671 freeAsmop(result,NULL,ic,TRUE);
6672 aopOp (right,ic,FALSE);
6674 /* if bitfield then unpack the bits */
6675 if (IS_BITVAR(retype))
6676 genPackBits (retype,right,rname,PPOINTER);
6678 /* we have can just get the values */
6679 int size = AOP_SIZE(right);
6683 l = aopGet(AOP(right),offset,FALSE,TRUE);
6686 emitcode("movx","@%s,a",rname);
6689 emitcode("inc","%s",rname);
6695 /* now some housekeeping stuff */
6697 /* we had to allocate for this iCode */
6698 freeAsmop(NULL,aop,ic,TRUE);
6700 /* we did not allocate which means left
6701 already in a pointer register, then
6702 if size > 0 && this could be used again
6703 we have to point it back to where it
6705 if (AOP_SIZE(right) > 1 &&
6706 !OP_SYMBOL(result)->remat &&
6707 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6709 int size = AOP_SIZE(right) - 1;
6711 emitcode("dec","%s",rname);
6716 freeAsmop(right,NULL,ic,TRUE);
6721 /*-----------------------------------------------------------------*/
6722 /* genFarPointerSet - set value from far space */
6723 /*-----------------------------------------------------------------*/
6724 static void genFarPointerSet (operand *right,
6725 operand *result, iCode *ic)
6728 link *retype = getSpec(operandType(right));
6730 aopOp(result,ic,FALSE);
6732 /* if the operand is already in dptr
6733 then we do nothing else we move the value to dptr */
6734 if (AOP_TYPE(result) != AOP_STR) {
6735 /* if this is remateriazable */
6736 if (AOP_TYPE(result) == AOP_IMMD)
6737 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6738 else { /* we need to get it byte by byte */
6739 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6740 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6741 if (options.model == MODEL_FLAT24)
6743 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6747 /* so dptr know contains the address */
6748 freeAsmop(result,NULL,ic,TRUE);
6749 aopOp(right,ic,FALSE);
6751 /* if bit then unpack */
6752 if (IS_BITVAR(retype))
6753 genPackBits(retype,right,"dptr",FPOINTER);
6755 size = AOP_SIZE(right);
6759 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6761 emitcode("movx","@dptr,a");
6763 emitcode("inc","dptr");
6767 freeAsmop(right,NULL,ic,TRUE);
6770 /*-----------------------------------------------------------------*/
6771 /* genGenPointerSet - set value from generic pointer space */
6772 /*-----------------------------------------------------------------*/
6773 static void genGenPointerSet (operand *right,
6774 operand *result, iCode *ic)
6777 link *retype = getSpec(operandType(right));
6779 aopOp(result,ic,FALSE);
6781 /* if the operand is already in dptr
6782 then we do nothing else we move the value to dptr */
6783 if (AOP_TYPE(result) != AOP_STR) {
6784 /* if this is remateriazable */
6785 if (AOP_TYPE(result) == AOP_IMMD) {
6786 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6787 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
6789 else { /* we need to get it byte by byte */
6790 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6791 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6792 if (options.model == MODEL_FLAT24)
6794 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6795 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
6799 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
6803 /* so dptr know contains the address */
6804 freeAsmop(result,NULL,ic,TRUE);
6805 aopOp(right,ic,FALSE);
6807 /* if bit then unpack */
6808 if (IS_BITVAR(retype))
6809 genPackBits(retype,right,"dptr",GPOINTER);
6811 size = AOP_SIZE(right);
6815 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6817 emitcode("lcall","__gptrput");
6819 emitcode("inc","dptr");
6823 freeAsmop(right,NULL,ic,TRUE);
6826 /*-----------------------------------------------------------------*/
6827 /* genPointerSet - stores the value into a pointer location */
6828 /*-----------------------------------------------------------------*/
6829 static void genPointerSet (iCode *ic)
6831 operand *right, *result ;
6835 right = IC_RIGHT(ic);
6836 result = IC_RESULT(ic) ;
6838 /* depending on the type of pointer we need to
6839 move it to the correct pointer register */
6840 type = operandType(result);
6841 etype = getSpec(type);
6842 /* if left is of type of pointer then it is simple */
6843 if (IS_PTR(type) && !IS_FUNC(type->next)) {
6844 p_type = DCL_TYPE(type);
6847 /* we have to go by the storage class */
6848 p_type = PTR_TYPE(SPEC_OCLS(etype));
6850 /* if (SPEC_OCLS(etype)->codesp ) { */
6851 /* p_type = CPOINTER ; */
6854 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6855 /* p_type = FPOINTER ; */
6857 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6858 /* p_type = PPOINTER ; */
6860 /* if (SPEC_OCLS(etype) == idata ) */
6861 /* p_type = IPOINTER ; */
6863 /* p_type = POINTER ; */
6866 /* now that we have the pointer type we assign
6867 the pointer values */
6872 genNearPointerSet (right,result,ic);
6876 genPagedPointerSet (right,result,ic);
6880 genFarPointerSet (right,result,ic);
6884 genGenPointerSet (right,result,ic);
6890 /*-----------------------------------------------------------------*/
6891 /* genIfx - generate code for Ifx statement */
6892 /*-----------------------------------------------------------------*/
6893 static void genIfx (iCode *ic, iCode *popIc)
6895 operand *cond = IC_COND(ic);
6898 aopOp(cond,ic,FALSE);
6900 /* get the value into acc */
6901 if (AOP_TYPE(cond) != AOP_CRY)
6905 /* the result is now in the accumulator */
6906 freeAsmop(cond,NULL,ic,TRUE);
6908 /* if there was something to be popped then do it */
6912 /* if the condition is a bit variable */
6913 if (isbit && IS_ITEMP(cond) &&
6915 genIfxJump(ic,SPIL_LOC(cond)->rname);
6917 if (isbit && !IS_ITEMP(cond))
6918 genIfxJump(ic,OP_SYMBOL(cond)->rname);
6925 /*-----------------------------------------------------------------*/
6926 /* genAddrOf - generates code for address of */
6927 /*-----------------------------------------------------------------*/
6928 static void genAddrOf (iCode *ic)
6930 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
6933 aopOp(IC_RESULT(ic),ic,FALSE);
6935 /* if the operand is on the stack then we
6936 need to get the stack offset of this
6939 /* if it has an offset then we need to compute
6942 emitcode("mov","a,_bp");
6943 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
6944 aopPut(AOP(IC_RESULT(ic)),"a",0);
6946 /* we can just move _bp */
6947 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
6949 /* fill the result with zero */
6950 size = AOP_SIZE(IC_RESULT(ic)) - 1;
6953 if (options.stack10bit && size < (FPTRSIZE - 1))
6956 "*** warning: pointer to stack var truncated.\n");
6963 if (options.stack10bit && offset == 2)
6965 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
6969 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
6976 /* object not on stack then we need the name */
6977 size = AOP_SIZE(IC_RESULT(ic));
6981 char s[SDCC_NAME_MAX];
6983 sprintf(s,"#(%s >> %d)",
6987 sprintf(s,"#%s",sym->rname);
6988 aopPut(AOP(IC_RESULT(ic)),s,offset++);
6992 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
6996 /*-----------------------------------------------------------------*/
6997 /* genFarFarAssign - assignment when both are in far space */
6998 /*-----------------------------------------------------------------*/
6999 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7001 int size = AOP_SIZE(right);
7004 /* first push the right side on to the stack */
7006 l = aopGet(AOP(right),offset++,FALSE,FALSE);
7008 emitcode ("push","acc");
7011 freeAsmop(right,NULL,ic,FALSE);
7012 /* now assign DPTR to result */
7013 aopOp(result,ic,FALSE);
7014 size = AOP_SIZE(result);
7016 emitcode ("pop","acc");
7017 aopPut(AOP(result),"a",--offset);
7019 freeAsmop(result,NULL,ic,FALSE);
7023 /*-----------------------------------------------------------------*/
7024 /* genAssign - generate code for assignment */
7025 /*-----------------------------------------------------------------*/
7026 static void genAssign (iCode *ic)
7028 operand *result, *right;
7030 unsigned long lit = 0L;
7032 result = IC_RESULT(ic);
7033 right = IC_RIGHT(ic) ;
7035 /* if they are the same */
7036 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7039 aopOp(right,ic,FALSE);
7041 /* special case both in far space */
7042 if ((AOP_TYPE(right) == AOP_DPTR ||
7043 AOP_TYPE(right) == AOP_DPTR2) &&
7044 IS_TRUE_SYMOP(result) &&
7045 isOperandInFarSpace(result)) {
7047 genFarFarAssign (result,right,ic);
7051 aopOp(result,ic,TRUE);
7053 /* if they are the same registers */
7054 if (sameRegs(AOP(right),AOP(result)))
7057 /* if the result is a bit */
7058 if (AOP_TYPE(result) == AOP_CRY) {
7060 /* if the right size is a literal then
7061 we know what the value is */
7062 if (AOP_TYPE(right) == AOP_LIT) {
7063 if (((int) operandLitValue(right)))
7064 aopPut(AOP(result),one,0);
7066 aopPut(AOP(result),zero,0);
7070 /* the right is also a bit variable */
7071 if (AOP_TYPE(right) == AOP_CRY) {
7072 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7073 aopPut(AOP(result),"c",0);
7079 aopPut(AOP(result),"a",0);
7083 /* bit variables done */
7085 size = AOP_SIZE(result);
7087 if(AOP_TYPE(right) == AOP_LIT)
7088 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7090 (AOP_TYPE(result) != AOP_REG) &&
7091 (AOP_TYPE(right) == AOP_LIT) &&
7092 !IS_FLOAT(operandType(right)) &&
7094 emitcode("clr","a");
7096 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7097 aopPut(AOP(result),"a",size);
7100 aopGet(AOP(right),size,FALSE,FALSE),
7106 aopGet(AOP(right),offset,FALSE,FALSE),
7113 freeAsmop (right,NULL,ic,FALSE);
7114 freeAsmop (result,NULL,ic,TRUE);
7117 /*-----------------------------------------------------------------*/
7118 /* genJumpTab - genrates code for jump table */
7119 /*-----------------------------------------------------------------*/
7120 static void genJumpTab (iCode *ic)
7125 aopOp(IC_JTCOND(ic),ic,FALSE);
7126 /* get the condition into accumulator */
7127 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
7129 /* multiply by three */
7130 emitcode("add","a,acc");
7131 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
7132 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7134 jtab = newiTempLabel(NULL);
7135 emitcode("mov","dptr,#%05d$",jtab->key+100);
7136 emitcode("jmp","@a+dptr");
7137 emitcode("","%05d$:",jtab->key+100);
7138 /* now generate the jump labels */
7139 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
7140 jtab = setNextItem(IC_JTLABELS(ic)))
7141 emitcode("ljmp","%05d$",jtab->key+100);
7145 /*-----------------------------------------------------------------*/
7146 /* genCast - gen code for casting */
7147 /*-----------------------------------------------------------------*/
7148 static void genCast (iCode *ic)
7150 operand *result = IC_RESULT(ic);
7151 link *ctype = operandType(IC_LEFT(ic));
7152 operand *right = IC_RIGHT(ic);
7155 /* if they are equivalent then do nothing */
7156 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
7159 aopOp(right,ic,FALSE) ;
7160 aopOp(result,ic,FALSE);
7162 /* if the result is a bit */
7163 if (AOP_TYPE(result) == AOP_CRY) {
7164 /* if the right size is a literal then
7165 we know what the value is */
7166 if (AOP_TYPE(right) == AOP_LIT) {
7167 if (((int) operandLitValue(right)))
7168 aopPut(AOP(result),one,0);
7170 aopPut(AOP(result),zero,0);
7175 /* the right is also a bit variable */
7176 if (AOP_TYPE(right) == AOP_CRY) {
7177 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7178 aopPut(AOP(result),"c",0);
7184 aopPut(AOP(result),"a",0);
7188 /* if they are the same size : or less */
7189 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
7191 /* if they are in the same place */
7192 if (sameRegs(AOP(right),AOP(result)))
7195 /* if they in different places then copy */
7196 size = AOP_SIZE(result);
7200 aopGet(AOP(right),offset,FALSE,FALSE),
7208 /* if the result is of type pointer */
7209 if (IS_PTR(ctype)) {
7212 link *type = operandType(right);
7213 link *etype = getSpec(type);
7215 /* pointer to generic pointer */
7216 if (IS_GENPTR(ctype)) {
7220 p_type = DCL_TYPE(type);
7222 /* we have to go by the storage class */
7223 p_type = PTR_TYPE(SPEC_OCLS(etype));
7225 /* if (SPEC_OCLS(etype)->codesp ) */
7226 /* p_type = CPOINTER ; */
7228 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7229 /* p_type = FPOINTER ; */
7231 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7232 /* p_type = PPOINTER; */
7234 /* if (SPEC_OCLS(etype) == idata ) */
7235 /* p_type = IPOINTER ; */
7237 /* p_type = POINTER ; */
7240 /* the first two bytes are known */
7241 size = GPTRSIZE - 1;
7245 aopGet(AOP(right),offset,FALSE,FALSE),
7249 /* the last byte depending on type */
7266 /* this should never happen */
7267 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7268 "got unknown pointer type");
7271 aopPut(AOP(result),l, GPTRSIZE - 1);
7275 /* just copy the pointers */
7276 size = AOP_SIZE(result);
7280 aopGet(AOP(right),offset,FALSE,FALSE),
7287 /* so we now know that the size of destination is greater
7288 than the size of the source */
7289 /* we move to result for the size of source */
7290 size = AOP_SIZE(right);
7294 aopGet(AOP(right),offset,FALSE,FALSE),
7299 /* now depending on the sign of the destination */
7300 size = AOP_SIZE(result) - AOP_SIZE(right);
7301 /* if unsigned or not an integral type */
7302 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
7304 aopPut(AOP(result),zero,offset++);
7306 /* we need to extend the sign :{ */
7307 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
7310 emitcode("rlc","a");
7311 emitcode("subb","a,acc");
7313 aopPut(AOP(result),"a",offset++);
7316 /* we are done hurray !!!! */
7319 freeAsmop(right,NULL,ic,TRUE);
7320 freeAsmop(result,NULL,ic,TRUE);
7324 /*-----------------------------------------------------------------*/
7325 /* genDjnz - generate decrement & jump if not zero instrucion */
7326 /*-----------------------------------------------------------------*/
7327 static int genDjnz (iCode *ic, iCode *ifx)
7333 /* if the if condition has a false label
7334 then we cannot save */
7338 /* if the minus is not of the form
7340 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
7341 !IS_OP_LITERAL(IC_RIGHT(ic)))
7344 if (operandLitValue(IC_RIGHT(ic)) != 1)
7347 /* if the size of this greater than one then no
7349 if (getSize(operandType(IC_RESULT(ic))) > 1)
7352 /* otherwise we can save BIG */
7353 lbl = newiTempLabel(NULL);
7354 lbl1= newiTempLabel(NULL);
7356 aopOp(IC_RESULT(ic),ic,FALSE);
7358 if (IS_AOP_PREG(IC_RESULT(ic))) {
7359 emitcode("dec","%s",
7360 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7361 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7362 emitcode("jnz","%05d$",lbl->key+100);
7364 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
7367 emitcode ("sjmp","%05d$",lbl1->key+100);
7368 emitcode ("","%05d$:",lbl->key+100);
7369 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
7370 emitcode ("","%05d$:",lbl1->key+100);
7372 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7377 /*-----------------------------------------------------------------*/
7378 /* genReceive - generate code for a receive iCode */
7379 /*-----------------------------------------------------------------*/
7380 static void genReceive (iCode *ic)
7382 if (isOperandInFarSpace(IC_RESULT(ic)) &&
7383 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
7384 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
7386 int size = getSize(operandType(IC_RESULT(ic)));
7387 int offset = fReturnSize - size;
7389 emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
7390 fReturn[fReturnSize - offset - 1] : "acc"));
7393 aopOp(IC_RESULT(ic),ic,FALSE);
7394 size = AOP_SIZE(IC_RESULT(ic));
7397 emitcode ("pop","acc");
7398 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
7403 aopOp(IC_RESULT(ic),ic,FALSE);
7405 assignResultValue(IC_RESULT(ic));
7408 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7411 /*-----------------------------------------------------------------*/
7412 /* gen51Code - generate code for 8051 based controllers */
7413 /*-----------------------------------------------------------------*/
7414 void gen51Code (iCode *lic)
7419 lineHead = lineCurr = NULL;
7421 /* if debug information required */
7422 /* if (options.debug && currFunc) { */
7424 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
7426 if (IS_STATIC(currFunc->etype))
7427 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
7429 emitcode("","G$%s$0$0 ==.",currFunc->name);
7432 /* stack pointer name */
7433 if (options.useXstack)
7439 for (ic = lic ; ic ; ic = ic->next ) {
7441 if ( cln != ic->lineno ) {
7442 if ( options.debug ) {
7444 emitcode("","C$%s$%d$%d$%d ==.",
7445 ic->filename,ic->lineno,
7446 ic->level,ic->block);
7449 emitcode(";","%s %d",ic->filename,ic->lineno);
7452 /* if the result is marked as
7453 spilt and rematerializable or code for
7454 this has already been generated then
7456 if (resultRemat(ic) || ic->generated )
7459 /* depending on the operation */
7478 /* IPOP happens only when trying to restore a
7479 spilt live range, if there is an ifx statement
7480 following this pop then the if statement might
7481 be using some of the registers being popped which
7482 would destory the contents of the register so
7483 we need to check for this condition and handle it */
7485 ic->next->op == IFX &&
7486 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
7487 genIfx (ic->next,ic);
7505 genEndFunction (ic);
7525 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
7542 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
7546 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
7553 /* note these two are xlated by algebraic equivalence
7554 during parsing SDCC.y */
7555 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7556 "got '>=' or '<=' shouldn't have come here");
7560 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
7572 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
7576 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
7580 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
7607 case GET_VALUE_AT_ADDRESS:
7612 if (POINTER_SET(ic))
7639 addSet(&_G.sendSet,ic);
7644 /* piCode(ic,stdout); */
7650 /* now we are ready to call the
7651 peep hole optimizer */
7652 if (!options.nopeep)
7653 peepHole (&lineHead);
7655 /* now do the actual printing */
7656 printLine (lineHead,codeOutFile);