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)
378 iCode *ic = sym->rematiCode;
379 asmop *aop = newAsmop(AOP_IMMD);
384 val += operandLitValue(IC_RIGHT(ic));
385 else if (ic->op == '-')
386 val -= operandLitValue(IC_RIGHT(ic));
390 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
394 sprintf(buffer,"(%s %c 0x%04x)",
395 OP_SYMBOL(IC_LEFT(ic))->rname,
396 val >= 0 ? '+' : '-',
399 strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
401 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
402 strcpy(aop->aopu.aop_immd,buffer);
406 /*-----------------------------------------------------------------*/
407 /* regsInCommon - two operands have some registers in common */
408 /*-----------------------------------------------------------------*/
409 static bool regsInCommon (operand *op1, operand *op2)
414 /* if they have registers in common */
415 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
418 sym1 = OP_SYMBOL(op1);
419 sym2 = OP_SYMBOL(op2);
421 if (sym1->nRegs == 0 || sym2->nRegs == 0)
424 for (i = 0 ; i < sym1->nRegs ; i++) {
429 for (j = 0 ; j < sym2->nRegs ;j++ ) {
433 if (sym2->regs[j] == sym1->regs[i])
441 /*-----------------------------------------------------------------*/
442 /* operandsEqu - equivalent */
443 /*-----------------------------------------------------------------*/
444 static bool operandsEqu ( operand *op1, operand *op2)
448 /* if they not symbols */
449 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
452 sym1 = OP_SYMBOL(op1);
453 sym2 = OP_SYMBOL(op2);
455 /* if both are itemps & one is spilt
456 and the other is not then false */
457 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
458 sym1->isspilt != sym2->isspilt )
461 /* if they are the same */
465 if (strcmp(sym1->rname,sym2->rname) == 0)
469 /* if left is a tmp & right is not */
473 (sym1->usl.spillLoc == sym2))
480 (sym2->usl.spillLoc == sym1))
486 /*-----------------------------------------------------------------*/
487 /* sameRegs - two asmops have the same registers */
488 /*-----------------------------------------------------------------*/
489 static bool sameRegs (asmop *aop1, asmop *aop2 )
496 if (aop1->type != AOP_REG ||
497 aop2->type != AOP_REG )
500 if (aop1->size != aop2->size )
503 for (i = 0 ; i < aop1->size ; i++ )
504 if (aop1->aopu.aop_reg[i] !=
505 aop2->aopu.aop_reg[i] )
511 /*-----------------------------------------------------------------*/
512 /* aopOp - allocates an asmop for an operand : */
513 /*-----------------------------------------------------------------*/
514 static void aopOp (operand *op, iCode *ic, bool result)
523 /* if this a literal */
524 if (IS_OP_LITERAL(op)) {
525 op->aop = aop = newAsmop(AOP_LIT);
526 aop->aopu.aop_lit = op->operand.valOperand;
527 aop->size = getSize(operandType(op));
531 /* if already has a asmop then continue */
535 /* if the underlying symbol has a aop */
536 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
537 op->aop = OP_SYMBOL(op)->aop;
541 /* if this is a true symbol */
542 if (IS_TRUE_SYMOP(op)) {
543 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
547 /* this is a temporary : this has
553 e) can be a return use only */
558 /* if the type is a conditional */
559 if (sym->regType == REG_CND) {
560 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
565 /* if it is spilt then two situations
567 b) has a spill location */
568 if (sym->isspilt || sym->nRegs == 0) {
570 /* rematerialize it NOW */
572 sym->aop = op->aop = aop =
574 aop->size = getSize(sym->type);
580 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
581 aop->size = getSize(sym->type);
582 for ( i = 0 ; i < 2 ; i++ )
583 aop->aopu.aop_str[i] = accUse[i];
589 aop = op->aop = sym->aop = newAsmop(AOP_STR);
590 aop->size = getSize(sym->type);
591 for ( i = 0 ; i < fReturnSize ; i++ )
592 aop->aopu.aop_str[i] = fReturn[i];
596 /* else spill location */
597 sym->aop = op->aop = aop =
598 aopForSym(ic,sym->usl.spillLoc,result);
599 aop->size = getSize(sym->type);
603 /* must be in a register */
604 sym->aop = op->aop = aop = newAsmop(AOP_REG);
605 aop->size = sym->nRegs;
606 for ( i = 0 ; i < sym->nRegs ;i++)
607 aop->aopu.aop_reg[i] = sym->regs[i];
610 /*-----------------------------------------------------------------*/
611 /* freeAsmop - free up the asmop given to an operand */
612 /*----------------------------------------------------------------*/
613 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
630 /* depending on the asmop type only three cases need work AOP_RO
631 , AOP_R1 && AOP_STK */
636 emitcode ("pop","ar0");
640 bitVectUnSetBit(ic->rUsed,R0_IDX);
646 emitcode ("pop","ar1");
650 bitVectUnSetBit(ic->rUsed,R1_IDX);
656 int stk = aop->aopu.aop_stk + aop->size;
657 bitVectUnSetBit(ic->rUsed,R0_IDX);
658 bitVectUnSetBit(ic->rUsed,R1_IDX);
660 getFreePtr(ic,&aop,FALSE);
662 if (options.stack10bit)
664 /* I'm not sure what to do here yet... */
667 "*** Warning: probably generating bad code for "
668 "10 bit stack mode.\n");
672 emitcode ("mov","a,_bp");
673 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
674 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
676 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
680 emitcode("pop","acc");
681 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
683 emitcode("dec","%s",aop->aopu.aop_ptr->name);
686 freeAsmop(op,NULL,ic,TRUE);
688 emitcode("pop","ar0");
693 emitcode("pop","ar1");
700 /* all other cases just dealloc */
704 OP_SYMBOL(op)->aop = NULL;
705 /* if the symbol has a spill */
707 SPIL_LOC(op)->aop = NULL;
712 /*-----------------------------------------------------------------*/
713 /* aopGet - for fetching value of the aop */
714 /*-----------------------------------------------------------------*/
715 static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
720 /* offset is greater than
722 if (offset > (aop->size - 1) &&
723 aop->type != AOP_LIT)
726 /* depending on type */
731 /* if we need to increment it */
732 while (offset > aop->coff) {
733 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
737 while (offset < aop->coff) {
738 emitcode("dec","%s",aop->aopu.aop_ptr->name);
744 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
745 return (dname ? "acc" : "a");
747 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
748 ALLOC_ATOMIC(rs,strlen(s)+1);
755 if (aop->type == AOP_DPTR2)
760 while (offset > aop->coff) {
761 emitcode ("inc","dptr");
765 while (offset < aop->coff) {
766 emitcode("lcall","__decdptr");
773 emitcode("movc","a,@a+dptr");
776 emitcode("movx","a,@dptr");
779 if (aop->type == AOP_DPTR2)
784 return (dname ? "acc" : "a");
789 sprintf (s,"#%s",aop->aopu.aop_immd);
792 sprintf(s,"#(%s >> %d)",
798 ALLOC_ATOMIC(rs,strlen(s)+1);
804 sprintf(s,"(%s + %d)",
808 sprintf(s,"%s",aop->aopu.aop_dir);
809 ALLOC_ATOMIC(rs,strlen(s)+1);
815 return aop->aopu.aop_reg[offset]->dname;
817 return aop->aopu.aop_reg[offset]->name;
821 emitcode("mov","c,%s",aop->aopu.aop_dir);
822 emitcode("rlc","a") ;
823 return (dname ? "acc" : "a");
826 if (!offset && dname)
828 return aop->aopu.aop_str[offset];
831 return aopLiteral (aop->aopu.aop_lit,offset);
835 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
839 return aop->aopu.aop_str[offset];
843 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
844 "aopget got unsupported aop->type");
847 /*-----------------------------------------------------------------*/
848 /* aopPut - puts a string for a aop */
849 /*-----------------------------------------------------------------*/
850 static void aopPut (asmop *aop, char *s, int offset)
855 if (aop->size && offset > ( aop->size - 1)) {
856 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
857 "aopPut got offset > aop->size");
861 /* will assign value to value */
862 /* depending on where it is ofcourse */
866 sprintf(d,"(%s + %d)",
867 aop->aopu.aop_dir,offset);
869 sprintf(d,"%s",aop->aopu.aop_dir);
872 emitcode("mov","%s,%s",d,s);
877 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
878 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
880 strcmp(s,"r0") == 0 ||
881 strcmp(s,"r1") == 0 ||
882 strcmp(s,"r2") == 0 ||
883 strcmp(s,"r3") == 0 ||
884 strcmp(s,"r4") == 0 ||
885 strcmp(s,"r5") == 0 ||
886 strcmp(s,"r6") == 0 ||
887 strcmp(s,"r7") == 0 )
888 emitcode("mov","%s,%s",
889 aop->aopu.aop_reg[offset]->dname,s);
891 emitcode("mov","%s,%s",
892 aop->aopu.aop_reg[offset]->name,s);
899 if (aop->type == AOP_DPTR2)
905 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
906 "aopPut writting to code space");
910 while (offset > aop->coff) {
912 emitcode ("inc","dptr");
915 while (offset < aop->coff) {
917 emitcode("lcall","__decdptr");
922 /* if not in accumulater */
925 emitcode ("movx","@dptr,a");
927 if (aop->type == AOP_DPTR2)
935 while (offset > aop->coff) {
937 emitcode("inc","%s",aop->aopu.aop_ptr->name);
939 while (offset < aop->coff) {
941 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
947 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
952 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
954 if (strcmp(s,"r0") == 0 ||
955 strcmp(s,"r1") == 0 ||
956 strcmp(s,"r2") == 0 ||
957 strcmp(s,"r3") == 0 ||
958 strcmp(s,"r4") == 0 ||
959 strcmp(s,"r5") == 0 ||
960 strcmp(s,"r6") == 0 ||
961 strcmp(s,"r7") == 0 ) {
963 sprintf(buffer,"a%s",s);
964 emitcode("mov","@%s,%s",
965 aop->aopu.aop_ptr->name,buffer);
967 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
972 if (strcmp(s,"a") == 0)
973 emitcode("push","acc");
975 emitcode("push","%s",s);
980 /* if bit variable */
981 if (!aop->aopu.aop_dir) {
986 emitcode("clr","%s",aop->aopu.aop_dir);
989 emitcode("setb","%s",aop->aopu.aop_dir);
992 emitcode("mov","%s,c",aop->aopu.aop_dir);
994 lbl = newiTempLabel(NULL);
1000 emitcode("jz","%05d$",lbl->key+100);
1001 emitcode("cpl","c");
1002 emitcode("","%05d$:",lbl->key+100);
1003 emitcode("mov","%s,c",aop->aopu.aop_dir);
1010 if (strcmp(aop->aopu.aop_str[offset],s))
1011 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1016 if (!offset && (strcmp(s,"acc") == 0))
1019 if (strcmp(aop->aopu.aop_str[offset],s))
1020 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1024 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1025 "aopPut got unsupported aop->type");
1033 /*-----------------------------------------------------------------*/
1034 /* pointToEnd :- points to the last byte of the operand */
1035 /*-----------------------------------------------------------------*/
1036 static void pointToEnd (asmop *aop)
1042 aop->coff = count = (aop->size - 1);
1043 switch (aop->type) {
1047 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1051 emitcode("inc","dptr");
1058 /*-----------------------------------------------------------------*/
1059 /* reAdjustPreg - points a register back to where it should */
1060 /*-----------------------------------------------------------------*/
1061 static void reAdjustPreg (asmop *aop)
1066 if ((size = aop->size) <= 1)
1069 switch (aop->type) {
1073 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1077 if (aop->type == AOP_DPTR2)
1083 emitcode("lcall","__decdptr");
1086 if (aop->type == AOP_DPTR2)
1096 #define AOP(op) op->aop
1097 #define AOP_TYPE(op) AOP(op)->type
1098 #define AOP_SIZE(op) AOP(op)->size
1099 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1100 AOP_TYPE(x) == AOP_R0))
1102 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1103 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1106 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1107 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1108 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1110 /*-----------------------------------------------------------------*/
1111 /* genNotFloat - generates not for float operations */
1112 /*-----------------------------------------------------------------*/
1113 static void genNotFloat (operand *op, operand *res)
1119 /* we will put 127 in the first byte of
1121 aopPut(AOP(res),"#127",0);
1122 size = AOP_SIZE(op) - 1;
1125 l = aopGet(op->aop,offset++,FALSE,FALSE);
1129 emitcode("orl","a,%s",
1131 offset++,FALSE,FALSE));
1133 tlbl = newiTempLabel(NULL);
1135 tlbl = newiTempLabel(NULL);
1136 aopPut(res->aop,one,1);
1137 emitcode("jz","%05d$",(tlbl->key+100));
1138 aopPut(res->aop,zero,1);
1139 emitcode("","%05d$:",(tlbl->key+100));
1141 size = res->aop->size - 2;
1143 /* put zeros in the rest */
1145 aopPut(res->aop,zero,offset++);
1148 /*-----------------------------------------------------------------*/
1149 /* opIsGptr: returns non-zero if the passed operand is */
1150 /* a generic pointer type. */
1151 /*-----------------------------------------------------------------*/
1152 static int opIsGptr(operand *op)
1154 link *type = operandType(op);
1156 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1163 /*-----------------------------------------------------------------*/
1164 /* getDataSize - get the operand data size */
1165 /*-----------------------------------------------------------------*/
1166 static int getDataSize(operand *op)
1169 size = AOP_SIZE(op);
1170 if (size == GPTRSIZE)
1172 link *type = operandType(op);
1173 if (IS_GENPTR(type))
1175 /* generic pointer; arithmetic operations
1176 * should ignore the high byte (pointer type).
1184 /*-----------------------------------------------------------------*/
1185 /* outAcc - output Acc */
1186 /*-----------------------------------------------------------------*/
1187 static void outAcc(operand *result)
1190 size = getDataSize(result);
1192 aopPut(AOP(result),"a",0);
1195 /* unsigned or positive */
1197 aopPut(AOP(result),zero,offset++);
1202 /*-----------------------------------------------------------------*/
1203 /* outBitC - output a bit C */
1204 /*-----------------------------------------------------------------*/
1205 static void outBitC(operand *result)
1207 /* if the result is bit */
1208 if (AOP_TYPE(result) == AOP_CRY)
1209 aopPut(AOP(result),"c",0);
1211 emitcode("clr","a");
1212 emitcode("rlc","a");
1217 /*-----------------------------------------------------------------*/
1218 /* toBoolean - emit code for orl a,operator(sizeop) */
1219 /*-----------------------------------------------------------------*/
1220 static void toBoolean(operand *oper)
1222 int size = AOP_SIZE(oper) - 1;
1224 MOVA(aopGet(AOP(oper),0,FALSE,FALSE));
1226 emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE));
1230 /*-----------------------------------------------------------------*/
1231 /* genNot - generate code for ! operation */
1232 /*-----------------------------------------------------------------*/
1233 static void genNot (iCode *ic)
1236 link *optype = operandType(IC_LEFT(ic));
1238 /* assign asmOps to operand & result */
1239 aopOp (IC_LEFT(ic),ic,FALSE);
1240 aopOp (IC_RESULT(ic),ic,TRUE);
1242 /* if in bit space then a special case */
1243 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1244 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1245 emitcode("cpl","c");
1246 outBitC(IC_RESULT(ic));
1250 /* if type float then do float */
1251 if (IS_FLOAT(optype)) {
1252 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1256 toBoolean(IC_LEFT(ic));
1258 tlbl = newiTempLabel(NULL);
1259 emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1260 emitcode("","%05d$:",tlbl->key+100);
1261 outBitC(IC_RESULT(ic));
1264 /* release the aops */
1265 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1266 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1270 /*-----------------------------------------------------------------*/
1271 /* genCpl - generate code for complement */
1272 /*-----------------------------------------------------------------*/
1273 static void genCpl (iCode *ic)
1279 /* assign asmOps to operand & result */
1280 aopOp (IC_LEFT(ic),ic,FALSE);
1281 aopOp (IC_RESULT(ic),ic,TRUE);
1283 /* if both are in bit space then
1285 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1286 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1288 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1289 emitcode("cpl","c");
1290 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1294 size = AOP_SIZE(IC_RESULT(ic));
1296 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1298 emitcode("cpl","a");
1299 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1304 /* release the aops */
1305 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1306 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1309 /*-----------------------------------------------------------------*/
1310 /* genUminusFloat - unary minus for floating points */
1311 /*-----------------------------------------------------------------*/
1312 static void genUminusFloat(operand *op,operand *result)
1314 int size ,offset =0 ;
1316 /* for this we just need to flip the
1317 first it then copy the rest in place */
1318 size = AOP_SIZE(op) - 1;
1319 l = aopGet(AOP(op),3,FALSE,FALSE);
1323 emitcode("cpl","acc.7");
1324 aopPut(AOP(result),"a",3);
1328 aopGet(AOP(op),offset,FALSE,FALSE),
1334 /*-----------------------------------------------------------------*/
1335 /* genUminus - unary minus code generation */
1336 /*-----------------------------------------------------------------*/
1337 static void genUminus (iCode *ic)
1340 link *optype, *rtype;
1344 aopOp(IC_LEFT(ic),ic,FALSE);
1345 aopOp(IC_RESULT(ic),ic,TRUE);
1347 /* if both in bit space then special
1349 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1350 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1352 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1353 emitcode("cpl","c");
1354 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1358 optype = operandType(IC_LEFT(ic));
1359 rtype = operandType(IC_RESULT(ic));
1361 /* if float then do float stuff */
1362 if (IS_FLOAT(optype)) {
1363 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1367 /* otherwise subtract from zero */
1368 size = AOP_SIZE(IC_LEFT(ic));
1372 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1373 if (!strcmp(l,"a")) {
1374 emitcode("cpl","a");
1375 emitcode("inc","a");
1377 emitcode("clr","a");
1378 emitcode("subb","a,%s",l);
1380 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1383 /* if any remaining bytes in the result */
1384 /* we just need to propagate the sign */
1385 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1386 emitcode("rlc","a");
1387 emitcode("subb","a,acc");
1389 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1393 /* release the aops */
1394 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1395 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1398 /*-----------------------------------------------------------------*/
1399 /* saveRegisters - will look for a call and save the registers */
1400 /*-----------------------------------------------------------------*/
1401 static void saveRegisters(iCode *lic)
1409 for (ic = lic ; ic ; ic = ic->next)
1410 if (ic->op == CALL || ic->op == PCALL)
1414 fprintf(stderr,"found parameter push with no function call\n");
1418 /* if the registers have been saved already then
1420 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1423 /* find the registers in use at this time
1424 and push them away to safety */
1425 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1429 if (options.useXstack) {
1430 if (bitVectBitValue(rsave,R0_IDX))
1431 emitcode("mov","b,r0");
1432 emitcode("mov","r0,%s",spname);
1433 for (i = 0 ; i < mcs51_nRegs ; i++) {
1434 if (bitVectBitValue(rsave,i)) {
1436 emitcode("mov","a,b");
1438 emitcode("mov","a,%s",mcs51_regWithIdx(i)->name);
1439 emitcode("movx","@r0,a");
1440 emitcode("inc","r0");
1443 emitcode("mov","%s,r0",spname);
1444 if (bitVectBitValue(rsave,R0_IDX))
1445 emitcode("mov","r0,b");
1447 for (i = 0 ; i < mcs51_nRegs ; i++) {
1448 if (bitVectBitValue(rsave,i))
1449 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
1452 detype = getSpec(operandType(IC_LEFT(ic)));
1454 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1455 IS_ISR(currFunc->etype) &&
1458 saverbank(SPEC_BANK(detype),ic,TRUE);
1461 /*-----------------------------------------------------------------*/
1462 /* unsaveRegisters - pop the pushed registers */
1463 /*-----------------------------------------------------------------*/
1464 static void unsaveRegisters (iCode *ic)
1468 /* find the registers in use at this time
1469 and push them away to safety */
1470 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1473 if (options.useXstack) {
1474 emitcode("mov","r0,%s",spname);
1475 for (i = mcs51_nRegs ; i >= 0 ; i--) {
1476 if (bitVectBitValue(rsave,i)) {
1477 emitcode("dec","r0");
1478 emitcode("movx","a,@r0");
1480 emitcode("mov","b,a");
1482 emitcode("mov","%s,a",mcs51_regWithIdx(i)->name);
1486 emitcode("mov","%s,r0",spname);
1487 if (bitVectBitValue(rsave,R0_IDX))
1488 emitcode("mov","r0,b");
1490 for (i = mcs51_nRegs ; i >= 0 ; i--) {
1491 if (bitVectBitValue(rsave,i))
1492 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
1498 /*-----------------------------------------------------------------*/
1500 /*-----------------------------------------------------------------*/
1501 static void pushSide(operand * oper, int size)
1505 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1506 if (AOP_TYPE(oper) != AOP_REG &&
1507 AOP_TYPE(oper) != AOP_DIR &&
1509 emitcode("mov","a,%s",l);
1510 emitcode("push","acc");
1512 emitcode("push","%s",l);
1516 /*-----------------------------------------------------------------*/
1517 /* assignResultValue - */
1518 /*-----------------------------------------------------------------*/
1519 static void assignResultValue(operand * oper)
1522 int size = AOP_SIZE(oper);
1524 aopPut(AOP(oper),fReturn[offset],offset);
1530 /*-----------------------------------------------------------------*/
1531 /* genXpush - pushes onto the external stack */
1532 /*-----------------------------------------------------------------*/
1533 static void genXpush (iCode *ic)
1535 asmop *aop = newAsmop(0);
1537 int size,offset = 0;
1539 aopOp(IC_LEFT(ic),ic,FALSE);
1540 r = getFreePtr(ic,&aop,FALSE);
1543 emitcode("mov","%s,_spx",r->name);
1545 size = AOP_SIZE(IC_LEFT(ic));
1548 char *l = aopGet(AOP(IC_LEFT(ic)),
1549 offset++,FALSE,FALSE);
1551 emitcode("movx","@%s,a",r->name);
1552 emitcode("inc","%s",r->name);
1557 emitcode("mov","_spx,%s",r->name);
1559 freeAsmop(NULL,aop,ic,TRUE);
1560 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1563 /*-----------------------------------------------------------------*/
1564 /* genIpush - genrate code for pushing this gets a little complex */
1565 /*-----------------------------------------------------------------*/
1566 static void genIpush (iCode *ic)
1568 int size, offset = 0 ;
1572 /* if this is not a parm push : ie. it is spill push
1573 and spill push is always done on the local stack */
1574 if (!ic->parmPush) {
1576 /* and the item is spilt then do nothing */
1577 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1580 aopOp(IC_LEFT(ic),ic,FALSE);
1581 size = AOP_SIZE(IC_LEFT(ic));
1582 /* push it on the stack */
1584 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1589 emitcode("push","%s",l);
1594 /* this is a paramter push: in this case we call
1595 the routine to find the call and save those
1596 registers that need to be saved */
1599 /* if use external stack then call the external
1600 stack pushing routine */
1601 if (options.useXstack) {
1606 /* then do the push */
1607 aopOp(IC_LEFT(ic),ic,FALSE);
1610 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1611 size = AOP_SIZE(IC_LEFT(ic));
1614 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1615 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1616 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1618 emitcode("mov","a,%s",l);
1619 emitcode("push","acc");
1621 emitcode("push","%s",l);
1624 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1627 /*-----------------------------------------------------------------*/
1628 /* genIpop - recover the registers: can happen only for spilling */
1629 /*-----------------------------------------------------------------*/
1630 static void genIpop (iCode *ic)
1635 /* if the temp was not pushed then */
1636 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1639 aopOp(IC_LEFT(ic),ic,FALSE);
1640 size = AOP_SIZE(IC_LEFT(ic));
1643 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1646 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1649 /*-----------------------------------------------------------------*/
1650 /* unsaverbank - restores the resgister bank from stack */
1651 /*-----------------------------------------------------------------*/
1652 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1659 if (options.useXstack) {
1661 r = getFreePtr(ic,&aop,FALSE);
1664 emitcode("mov","%s,_spx",r->name);
1665 emitcode("movx","a,@%s",r->name);
1666 emitcode("mov","psw,a");
1667 emitcode("dec","%s",r->name);
1670 emitcode ("pop","psw");
1673 for (i = (mcs51_nRegs - 1) ; i >= 0 ;i--) {
1674 if (options.useXstack) {
1675 emitcode("movx","a,@%s",r->name);
1676 emitcode("mov","(%s+%d),a",
1677 regs8051[i].base,8*bank+regs8051[i].offset);
1678 emitcode("dec","%s",r->name);
1681 emitcode("pop","(%s+%d)",
1682 regs8051[i].base,8*bank+regs8051[i].offset);
1685 if (options.useXstack) {
1687 emitcode("mov","_spx,%s",r->name);
1688 freeAsmop(NULL,aop,ic,TRUE);
1693 /*-----------------------------------------------------------------*/
1694 /* saverbank - saves an entire register bank on the stack */
1695 /*-----------------------------------------------------------------*/
1696 static void saverbank (int bank, iCode *ic, bool pushPsw)
1702 if (options.useXstack) {
1705 r = getFreePtr(ic,&aop,FALSE);
1706 emitcode("mov","%s,_spx",r->name);
1710 for (i = 0 ; i < mcs51_nRegs ;i++) {
1711 if (options.useXstack) {
1712 emitcode("inc","%s",r->name);
1713 emitcode("mov","a,(%s+%d)",
1714 regs8051[i].base,8*bank+regs8051[i].offset);
1715 emitcode("movx","@%s,a",r->name);
1717 emitcode("push","(%s+%d)",
1718 regs8051[i].base,8*bank+regs8051[i].offset);
1722 if (options.useXstack) {
1723 emitcode("mov","a,psw");
1724 emitcode("movx","@%s,a",r->name);
1725 emitcode("inc","%s",r->name);
1726 emitcode("mov","_spx,%s",r->name);
1727 freeAsmop (NULL,aop,ic,TRUE);
1730 emitcode("push","psw");
1732 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1738 /*-----------------------------------------------------------------*/
1739 /* genCall - generates a call statement */
1740 /*-----------------------------------------------------------------*/
1741 static void genCall (iCode *ic)
1745 /* if caller saves & we have not saved then */
1749 /* if we are calling a function that is not using
1750 the same register bank then we need to save the
1751 destination registers on the stack */
1752 detype = getSpec(operandType(IC_LEFT(ic)));
1754 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1755 IS_ISR(currFunc->etype) &&
1758 saverbank(SPEC_BANK(detype),ic,TRUE);
1760 /* if send set is not empty the assign */
1764 for (sic = setFirstItem(_G.sendSet) ; sic ;
1765 sic = setNextItem(_G.sendSet)) {
1766 int size, offset = 0;
1767 aopOp(IC_LEFT(sic),sic,FALSE);
1768 size = AOP_SIZE(IC_LEFT(sic));
1770 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1772 if (strcmp(l,fReturn[offset]))
1773 emitcode("mov","%s,%s",
1778 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1783 emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1784 OP_SYMBOL(IC_LEFT(ic))->rname :
1785 OP_SYMBOL(IC_LEFT(ic))->name));
1787 /* if we need assign a result value */
1788 if ((IS_ITEMP(IC_RESULT(ic)) &&
1789 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1790 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1791 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1794 aopOp(IC_RESULT(ic),ic,FALSE);
1797 assignResultValue(IC_RESULT(ic));
1799 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1802 /* adjust the stack for parameters if
1804 if (IC_LEFT(ic)->parmBytes) {
1806 if (IC_LEFT(ic)->parmBytes > 3) {
1807 emitcode("mov","a,%s",spname);
1808 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1809 emitcode("mov","%s,a",spname);
1811 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1812 emitcode("dec","%s",spname);
1816 /* if register bank was saved then pop them */
1818 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1820 /* if we hade saved some registers then unsave them */
1821 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1822 unsaveRegisters (ic);
1827 /*-----------------------------------------------------------------*/
1828 /* genPcall - generates a call by pointer statement */
1829 /*-----------------------------------------------------------------*/
1830 static void genPcall (iCode *ic)
1833 symbol *rlbl = newiTempLabel(NULL);
1836 /* if caller saves & we have not saved then */
1840 /* if we are calling a function that is not using
1841 the same register bank then we need to save the
1842 destination registers on the stack */
1843 detype = getSpec(operandType(IC_LEFT(ic)));
1845 IS_ISR(currFunc->etype) &&
1846 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
1847 saverbank(SPEC_BANK(detype),ic,TRUE);
1850 /* push the return address on to the stack */
1851 emitcode("mov","a,#%05d$",(rlbl->key+100));
1852 emitcode("push","acc");
1853 emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
1854 emitcode("push","acc");
1856 if (options.model == MODEL_FLAT24)
1858 emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
1859 emitcode("push","acc");
1862 /* now push the calling address */
1863 aopOp(IC_LEFT(ic),ic,FALSE);
1865 pushSide(IC_LEFT(ic), FPTRSIZE);
1867 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1869 /* if send set is not empty the assign */
1873 for (sic = setFirstItem(_G.sendSet) ; sic ;
1874 sic = setNextItem(_G.sendSet)) {
1875 int size, offset = 0;
1876 aopOp(IC_LEFT(sic),sic,FALSE);
1877 size = AOP_SIZE(IC_LEFT(sic));
1879 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1881 if (strcmp(l,fReturn[offset]))
1882 emitcode("mov","%s,%s",
1887 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1893 emitcode("","%05d$:",(rlbl->key+100));
1896 /* if we need assign a result value */
1897 if ((IS_ITEMP(IC_RESULT(ic)) &&
1898 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1899 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
1900 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1903 aopOp(IC_RESULT(ic),ic,FALSE);
1906 assignResultValue(IC_RESULT(ic));
1908 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1911 /* adjust the stack for parameters if
1913 if (IC_LEFT(ic)->parmBytes) {
1915 if (IC_LEFT(ic)->parmBytes > 3) {
1916 emitcode("mov","a,%s",spname);
1917 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1918 emitcode("mov","%s,a",spname);
1920 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1921 emitcode("dec","%s",spname);
1925 /* if register bank was saved then unsave them */
1927 (SPEC_BANK(currFunc->etype) !=
1929 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1931 /* if we hade saved some registers then
1934 unsaveRegisters (ic);
1938 /*-----------------------------------------------------------------*/
1939 /* resultRemat - result is rematerializable */
1940 /*-----------------------------------------------------------------*/
1941 static int resultRemat (iCode *ic)
1943 if (SKIP_IC(ic) || ic->op == IFX)
1946 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1947 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1948 if (sym->remat && !POINTER_SET(ic))
1956 #define STRCASECMP stricmp
1958 #define STRCASECMP strcasecmp
1961 /*-----------------------------------------------------------------*/
1962 /* inExcludeList - return 1 if the string is in exclude Reg list */
1963 /*-----------------------------------------------------------------*/
1964 static bool inExcludeList(char *s)
1968 if (options.excludeRegs[i] &&
1969 STRCASECMP(options.excludeRegs[i],"none") == 0)
1972 for ( i = 0 ; options.excludeRegs[i]; i++) {
1973 if (options.excludeRegs[i] &&
1974 STRCASECMP(s,options.excludeRegs[i]) == 0)
1980 /*-----------------------------------------------------------------*/
1981 /* genFunction - generated code for function entry */
1982 /*-----------------------------------------------------------------*/
1983 static void genFunction (iCode *ic)
1989 /* create the function header */
1990 emitcode(";","-----------------------------------------");
1991 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1992 emitcode(";","-----------------------------------------");
1994 emitcode("","%s:",sym->rname);
1995 fetype = getSpec(operandType(IC_LEFT(ic)));
1997 /* if critical function then turn interrupts off */
1998 if (SPEC_CRTCL(fetype))
1999 emitcode("clr","ea");
2001 /* here we need to generate the equates for the
2002 register bank if required */
2003 if (SPEC_BANK(fetype) != rbank) {
2006 rbank = SPEC_BANK(fetype);
2007 for ( i = 0 ; i < mcs51_nRegs ; i++ ) {
2008 if (strcmp(regs8051[i].base,"0") == 0)
2009 emitcode("","%s = 0x%02x",
2011 8*rbank+regs8051[i].offset);
2013 emitcode ("","%s = %s + 0x%02x",
2016 8*rbank+regs8051[i].offset);
2020 /* if this is an interrupt service routine then
2021 save acc, b, dpl, dph */
2022 if (IS_ISR(sym->etype)) {
2024 if (!inExcludeList("acc"))
2025 emitcode ("push","acc");
2026 if (!inExcludeList("b"))
2027 emitcode ("push","b");
2028 if (!inExcludeList("dpl"))
2029 emitcode ("push","dpl");
2030 if (!inExcludeList("dph"))
2031 emitcode ("push","dph");
2032 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2034 emitcode ("push", "dpx");
2035 /* Make sure we're using standard DPTR */
2036 emitcode ("push", "dps");
2037 emitcode ("mov", "dps, #0x00");
2038 if (options.stack10bit)
2040 /* This ISR could conceivably use DPTR2. Better save it. */
2041 emitcode ("push", "dpl1");
2042 emitcode ("push", "dph1");
2043 emitcode ("push", "dpx1");
2046 /* if this isr has no bank i.e. is going to
2047 run with bank 0 , then we need to save more
2049 if (!SPEC_BANK(sym->etype)) {
2051 /* if this function does not call any other
2052 function then we can be economical and
2053 save only those registers that are used */
2054 if (! sym->hasFcall) {
2057 /* if any registers used */
2058 if (sym->regsUsed) {
2059 /* save the registers used */
2060 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2061 if (bitVectBitValue(sym->regsUsed,i) ||
2062 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2063 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
2068 /* this function has a function call cannot
2069 determines register usage so we will have the
2071 saverbank(0,ic,FALSE);
2075 /* if callee-save to be used for this function
2076 then save the registers being used in this function */
2077 if (sym->calleeSave) {
2080 /* if any registers used */
2081 if (sym->regsUsed) {
2082 /* save the registers used */
2083 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2084 if (bitVectBitValue(sym->regsUsed,i) ||
2085 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2086 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
2094 /* set the register bank to the desired value */
2095 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2096 emitcode("push","psw");
2097 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2100 if (IS_RENT(sym->etype) || options.stackAuto) {
2102 if (options.useXstack) {
2103 emitcode("mov","r0,%s",spname);
2104 emitcode("mov","a,_bp");
2105 emitcode("movx","@r0,a");
2106 emitcode("inc","%s",spname);
2110 /* set up the stack */
2111 emitcode ("push","_bp"); /* save the callers stack */
2113 emitcode ("mov","_bp,%s",spname);
2116 /* adjust the stack for the function */
2121 werror(W_STACK_OVERFLOW,sym->name);
2123 if (i > 3 && sym->recvSize < 4) {
2125 emitcode ("mov","a,sp");
2126 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2127 emitcode ("mov","sp,a");
2132 emitcode("inc","sp");
2137 emitcode ("mov","a,_spx");
2138 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2139 emitcode ("mov","_spx,a");
2144 /*-----------------------------------------------------------------*/
2145 /* genEndFunction - generates epilogue for functions */
2146 /*-----------------------------------------------------------------*/
2147 static void genEndFunction (iCode *ic)
2149 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2151 if (IS_RENT(sym->etype) || options.stackAuto)
2153 emitcode ("mov","%s,_bp",spname);
2156 /* if use external stack but some variables were
2157 added to the local stack then decrement the
2159 if (options.useXstack && sym->stack) {
2160 emitcode("mov","a,sp");
2161 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2162 emitcode("mov","sp,a");
2166 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2167 if (options.useXstack) {
2168 emitcode("mov","r0,%s",spname);
2169 emitcode("movx","a,@r0");
2170 emitcode("mov","_bp,a");
2171 emitcode("dec","%s",spname);
2175 emitcode ("pop","_bp");
2179 /* restore the register bank */
2180 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2181 emitcode ("pop","psw");
2183 if (IS_ISR(sym->etype)) {
2185 /* now we need to restore the registers */
2186 /* if this isr has no bank i.e. is going to
2187 run with bank 0 , then we need to save more
2189 if (!SPEC_BANK(sym->etype)) {
2191 /* if this function does not call any other
2192 function then we can be economical and
2193 save only those registers that are used */
2194 if (! sym->hasFcall) {
2197 /* if any registers used */
2198 if (sym->regsUsed) {
2199 /* save the registers used */
2200 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2201 if (bitVectBitValue(sym->regsUsed,i) ||
2202 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2203 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
2208 /* this function has a function call cannot
2209 determines register usage so we will have the
2211 unsaverbank(0,ic,FALSE);
2215 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2217 if (options.stack10bit)
2219 emitcode ("pop", "dpx1");
2220 emitcode ("pop", "dph1");
2221 emitcode ("pop", "dpl1");
2223 emitcode ("pop", "dps");
2224 emitcode ("pop", "dpx");
2226 if (!inExcludeList("dph"))
2227 emitcode ("pop","dph");
2228 if (!inExcludeList("dpl"))
2229 emitcode ("pop","dpl");
2230 if (!inExcludeList("b"))
2231 emitcode ("pop","b");
2232 if (!inExcludeList("acc"))
2233 emitcode ("pop","acc");
2235 if (SPEC_CRTCL(sym->etype))
2236 emitcode("setb","ea");
2238 /* if debug then send end of function */
2239 /* if (options.debug && currFunc) { */
2242 emitcode("","C$%s$%d$%d$%d ==.",
2243 ic->filename,currFunc->lastLine,
2244 ic->level,ic->block);
2245 if (IS_STATIC(currFunc->etype))
2246 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2248 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2252 emitcode ("reti","");
2255 if (SPEC_CRTCL(sym->etype))
2256 emitcode("setb","ea");
2258 if (sym->calleeSave) {
2261 /* if any registers used */
2262 if (sym->regsUsed) {
2263 /* save the registers used */
2264 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2265 if (bitVectBitValue(sym->regsUsed,i) ||
2266 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2267 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
2273 /* if debug then send end of function */
2276 emitcode("","C$%s$%d$%d$%d ==.",
2277 ic->filename,currFunc->lastLine,
2278 ic->level,ic->block);
2279 if (IS_STATIC(currFunc->etype))
2280 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2282 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2286 emitcode ("ret","");
2291 /*-----------------------------------------------------------------*/
2292 /* genRet - generate code for return statement */
2293 /*-----------------------------------------------------------------*/
2294 static void genRet (iCode *ic)
2296 int size,offset = 0 , pushed = 0;
2298 /* if we have no return value then
2299 just generate the "ret" */
2303 /* we have something to return then
2304 move the return value into place */
2305 aopOp(IC_LEFT(ic),ic,FALSE);
2306 size = AOP_SIZE(IC_LEFT(ic));
2310 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2312 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2314 emitcode("push","%s",l);
2317 l = aopGet(AOP(IC_LEFT(ic)),offset,
2319 if (strcmp(fReturn[offset],l))
2320 emitcode("mov","%s,%s",fReturn[offset++],l);
2327 if (strcmp(fReturn[pushed],"a"))
2328 emitcode("pop",fReturn[pushed]);
2330 emitcode("pop","acc");
2333 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2336 /* generate a jump to the return label
2337 if the next is not the return statement */
2338 if (!(ic->next && ic->next->op == LABEL &&
2339 IC_LABEL(ic->next) == returnLabel))
2341 emitcode("ljmp","%05d$",(returnLabel->key+100));
2345 /*-----------------------------------------------------------------*/
2346 /* genLabel - generates a label */
2347 /*-----------------------------------------------------------------*/
2348 static void genLabel (iCode *ic)
2350 /* special case never generate */
2351 if (IC_LABEL(ic) == entryLabel)
2354 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2357 /*-----------------------------------------------------------------*/
2358 /* genGoto - generates a ljmp */
2359 /*-----------------------------------------------------------------*/
2360 static void genGoto (iCode *ic)
2362 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2365 /*-----------------------------------------------------------------*/
2366 /* findLabelBackwards: walks back through the iCode chain looking */
2367 /* for the given label. Returns number of iCode instructions */
2368 /* between that label and given ic. */
2369 /* Returns zero if label not found. */
2370 /*-----------------------------------------------------------------*/
2371 static int findLabelBackwards(iCode *ic, int key)
2380 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2382 /* printf("findLabelBackwards = %d\n", count); */
2390 /*-----------------------------------------------------------------*/
2391 /* genPlusIncr :- does addition with increment if possible */
2392 /*-----------------------------------------------------------------*/
2393 static bool genPlusIncr (iCode *ic)
2395 unsigned int icount ;
2396 unsigned int size = getDataSize(IC_RESULT(ic));
2398 /* will try to generate an increment */
2399 /* if the right side is not a literal
2401 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2404 /* if the literal value of the right hand side
2405 is greater than 4 then it is not worth it */
2406 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2409 /* if increment 16 bits in register */
2410 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2417 /* If the next instruction is a goto and the goto target
2418 * is < 10 instructions previous to this, we can generate
2419 * jumps straight to that target.
2421 if (ic->next && ic->next->op == GOTO
2422 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2423 && labelRange <= 10 )
2425 emitcode(";", "tail increment optimized");
2426 tlbl = IC_LABEL(ic->next);
2431 tlbl = newiTempLabel(NULL);
2434 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2435 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2436 IS_AOP_PREG(IC_RESULT(ic)))
2437 emitcode("cjne","%s,#0x00,%05d$"
2438 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2441 emitcode("clr","a");
2442 emitcode("cjne","a,%s,%05d$"
2443 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2447 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2450 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2451 IS_AOP_PREG(IC_RESULT(ic)))
2452 emitcode("cjne","%s,#0x00,%05d$"
2453 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2456 emitcode("cjne","a,%s,%05d$"
2457 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2460 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2464 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2465 IS_AOP_PREG(IC_RESULT(ic)))
2466 emitcode("cjne","%s,#0x00,%05d$"
2467 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2470 emitcode("cjne","a,%s,%05d$"
2471 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2474 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2479 emitcode("","%05d$:",tlbl->key+100);
2484 /* if the sizes are greater than 1 then we cannot */
2485 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2486 AOP_SIZE(IC_LEFT(ic)) > 1 )
2489 /* we can if the aops of the left & result match or
2490 if they are in registers and the registers are the
2492 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2495 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2496 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2497 aopPut(AOP(IC_RESULT(ic)),"a",0);
2501 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2510 /*-----------------------------------------------------------------*/
2511 /* outBitAcc - output a bit in acc */
2512 /*-----------------------------------------------------------------*/
2513 static void outBitAcc(operand *result)
2515 symbol *tlbl = newiTempLabel(NULL);
2516 /* if the result is a bit */
2517 if (AOP_TYPE(result) == AOP_CRY){
2518 aopPut(AOP(result),"a",0);
2521 emitcode("jz","%05d$",tlbl->key+100);
2522 emitcode("mov","a,%s",one);
2523 emitcode("","%05d$:",tlbl->key+100);
2528 /*-----------------------------------------------------------------*/
2529 /* genPlusBits - generates code for addition of two bits */
2530 /*-----------------------------------------------------------------*/
2531 static void genPlusBits (iCode *ic)
2533 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2534 symbol *lbl = newiTempLabel(NULL);
2535 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2536 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2537 emitcode("cpl","c");
2538 emitcode("","%05d$:",(lbl->key+100));
2539 outBitC(IC_RESULT(ic));
2542 emitcode("clr","a");
2543 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2544 emitcode("rlc","a");
2545 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2546 emitcode("addc","a,#0x00");
2547 outAcc(IC_RESULT(ic));
2552 /* This is the original version of this code.
2554 * This is being kept around for reference,
2555 * because I am not entirely sure I got it right...
2557 static void adjustArithmeticResult(iCode *ic)
2559 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2560 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2561 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2562 aopPut(AOP(IC_RESULT(ic)),
2563 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2566 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2567 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
2568 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2569 aopPut(AOP(IC_RESULT(ic)),
2570 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2573 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2574 AOP_SIZE(IC_LEFT(ic)) < 3 &&
2575 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
2576 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2577 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2579 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2580 aopPut(AOP(IC_RESULT(ic)),buffer,2);
2584 /* This is the pure and virtuous version of this code.
2585 * I'm pretty certain it's right, but not enough to toss the old
2588 static void adjustArithmeticResult(iCode *ic)
2590 if (opIsGptr(IC_RESULT(ic)) &&
2591 opIsGptr(IC_LEFT(ic)) &&
2592 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2594 aopPut(AOP(IC_RESULT(ic)),
2595 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
2599 if (opIsGptr(IC_RESULT(ic)) &&
2600 opIsGptr(IC_RIGHT(ic)) &&
2601 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2603 aopPut(AOP(IC_RESULT(ic)),
2604 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
2608 if (opIsGptr(IC_RESULT(ic)) &&
2609 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2610 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2611 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2612 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2614 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2615 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2620 /*-----------------------------------------------------------------*/
2621 /* genPlus - generates code for addition */
2622 /*-----------------------------------------------------------------*/
2623 static void genPlus (iCode *ic)
2625 int size, offset = 0;
2627 /* special cases :- */
2629 aopOp (IC_LEFT(ic),ic,FALSE);
2630 aopOp (IC_RIGHT(ic),ic,FALSE);
2631 aopOp (IC_RESULT(ic),ic,TRUE);
2633 /* if literal, literal on the right or
2634 if left requires ACC or right is already
2636 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2637 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2638 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2639 operand *t = IC_RIGHT(ic);
2640 IC_RIGHT(ic) = IC_LEFT(ic);
2644 /* if both left & right are in bit
2646 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2647 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2652 /* if left in bit space & right literal */
2653 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2654 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2655 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2656 /* if result in bit space */
2657 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2658 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
2659 emitcode("cpl","c");
2660 outBitC(IC_RESULT(ic));
2662 size = getDataSize(IC_RESULT(ic));
2664 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2665 emitcode("addc","a,#00");
2666 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2672 /* if I can do an increment instead
2673 of add then GOOD for ME */
2674 if (genPlusIncr (ic) == TRUE)
2677 size = getDataSize(IC_RESULT(ic));
2680 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2681 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2683 emitcode("add","a,%s",
2684 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2686 emitcode("addc","a,%s",
2687 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2689 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2691 emitcode("add","a,%s",
2692 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2694 emitcode("addc","a,%s",
2695 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2697 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2700 adjustArithmeticResult(ic);
2703 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2704 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2705 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2708 /*-----------------------------------------------------------------*/
2709 /* genMinusDec :- does subtraction with deccrement if possible */
2710 /*-----------------------------------------------------------------*/
2711 static bool genMinusDec (iCode *ic)
2713 unsigned int icount ;
2714 unsigned int size = getDataSize(IC_RESULT(ic));
2716 /* will try to generate an increment */
2717 /* if the right side is not a literal
2719 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2722 /* if the literal value of the right hand side
2723 is greater than 4 then it is not worth it */
2724 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2727 /* if decrement 16 bits in register */
2728 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2735 /* If the next instruction is a goto and the goto target
2736 * is <= 10 instructions previous to this, we can generate
2737 * jumps straight to that target.
2739 if (ic->next && ic->next->op == GOTO
2740 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2741 && labelRange <= 10 )
2743 emitcode(";", "tail decrement optimized");
2744 tlbl = IC_LABEL(ic->next);
2749 tlbl = newiTempLabel(NULL);
2753 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2754 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2755 IS_AOP_PREG(IC_RESULT(ic)))
2756 emitcode("cjne","%s,#0xff,%05d$"
2757 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2760 emitcode("mov","a,#0xff");
2761 emitcode("cjne","a,%s,%05d$"
2762 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2765 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2768 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2769 IS_AOP_PREG(IC_RESULT(ic)))
2770 emitcode("cjne","%s,#0xff,%05d$"
2771 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2774 emitcode("cjne","a,%s,%05d$"
2775 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2778 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2782 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2783 IS_AOP_PREG(IC_RESULT(ic)))
2784 emitcode("cjne","%s,#0xff,%05d$"
2785 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2788 emitcode("cjne","a,%s,%05d$"
2789 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2792 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2796 emitcode("","%05d$:",tlbl->key+100);
2801 /* if the sizes are greater than 1 then we cannot */
2802 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2803 AOP_SIZE(IC_LEFT(ic)) > 1 )
2806 /* we can if the aops of the left & result match or
2807 if they are in registers and the registers are the
2809 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2812 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2820 /*-----------------------------------------------------------------*/
2821 /* addSign - complete with sign */
2822 /*-----------------------------------------------------------------*/
2823 static void addSign(operand *result, int offset, int sign)
2825 int size = (getDataSize(result) - offset);
2828 emitcode("rlc","a");
2829 emitcode("subb","a,acc");
2831 aopPut(AOP(result),"a",offset++);
2834 aopPut(AOP(result),zero,offset++);
2838 /*-----------------------------------------------------------------*/
2839 /* genMinusBits - generates code for subtraction of two bits */
2840 /*-----------------------------------------------------------------*/
2841 static void genMinusBits (iCode *ic)
2843 symbol *lbl = newiTempLabel(NULL);
2844 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2845 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2846 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2847 emitcode("cpl","c");
2848 emitcode("","%05d$:",(lbl->key+100));
2849 outBitC(IC_RESULT(ic));
2852 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2853 emitcode("subb","a,acc");
2854 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
2855 emitcode("inc","a");
2856 emitcode("","%05d$:",(lbl->key+100));
2857 aopPut(AOP(IC_RESULT(ic)),"a",0);
2858 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
2862 /*-----------------------------------------------------------------*/
2863 /* genMinus - generates code for subtraction */
2864 /*-----------------------------------------------------------------*/
2865 static void genMinus (iCode *ic)
2867 int size, offset = 0;
2868 unsigned long lit = 0L;
2870 aopOp (IC_LEFT(ic),ic,FALSE);
2871 aopOp (IC_RIGHT(ic),ic,FALSE);
2872 aopOp (IC_RESULT(ic),ic,TRUE);
2874 /* special cases :- */
2875 /* if both left & right are in bit space */
2876 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2877 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2882 /* if I can do an decrement instead
2883 of subtract then GOOD for ME */
2884 if (genMinusDec (ic) == TRUE)
2887 size = getDataSize(IC_RESULT(ic));
2889 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
2893 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2897 /* if literal, add a,#-lit, else normal subb */
2899 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2900 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2901 emitcode("subb","a,%s",
2902 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2904 /* first add without previous c */
2906 emitcode("add","a,#0x%02x",
2907 (unsigned int)(lit & 0x0FFL));
2909 emitcode("addc","a,#0x%02x",
2910 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
2912 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2915 adjustArithmeticResult(ic);
2918 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2919 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2920 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2924 /*-----------------------------------------------------------------*/
2925 /* genMultbits :- multiplication of bits */
2926 /*-----------------------------------------------------------------*/
2927 static void genMultbits (operand *left,
2931 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2932 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
2937 /*-----------------------------------------------------------------*/
2938 /* genMultOneByte : 8 bit multiplication & division */
2939 /*-----------------------------------------------------------------*/
2940 static void genMultOneByte (operand *left,
2944 link *opetype = operandType(result);
2949 /* (if two literals, the value is computed before) */
2950 /* if one literal, literal on the right */
2951 if (AOP_TYPE(left) == AOP_LIT){
2957 size = AOP_SIZE(result);
2958 /* signed or unsigned */
2959 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2960 l = aopGet(AOP(left),0,FALSE,FALSE);
2962 emitcode("mul","ab");
2963 /* if result size = 1, mul signed = mul unsigned */
2964 aopPut(AOP(result),"a",0);
2966 if (SPEC_USIGN(opetype)){
2967 aopPut(AOP(result),"b",1);
2969 /* for filling the MSBs */
2970 emitcode("clr","a");
2973 emitcode("mov","a,b");
2975 /* adjust the MSB if left or right neg */
2977 /* if one literal */
2978 if (AOP_TYPE(right) == AOP_LIT){
2979 /* AND literal negative */
2980 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
2981 /* adjust MSB (c==0 after mul) */
2982 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2986 lbl = newiTempLabel(NULL);
2987 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2988 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
2989 emitcode("","%05d$:",(lbl->key+100));
2990 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2991 lbl = newiTempLabel(NULL);
2992 emitcode("jc","%05d$",(lbl->key+100));
2993 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2994 emitcode("","%05d$:",(lbl->key+100));
2997 lbl = newiTempLabel(NULL);
2998 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
2999 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3000 emitcode("","%05d$:",(lbl->key+100));
3001 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3002 lbl = newiTempLabel(NULL);
3003 emitcode("jc","%05d$",(lbl->key+100));
3004 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
3005 emitcode("","%05d$:",(lbl->key+100));
3007 aopPut(AOP(result),"a",1);
3010 emitcode("rlc","a");
3011 emitcode("subb","a,acc");
3018 aopPut(AOP(result),"a",offset++);
3022 /*-----------------------------------------------------------------*/
3023 /* genMult - generates code for multiplication */
3024 /*-----------------------------------------------------------------*/
3025 static void genMult (iCode *ic)
3027 operand *left = IC_LEFT(ic);
3028 operand *right = IC_RIGHT(ic);
3029 operand *result= IC_RESULT(ic);
3031 /* assign the amsops */
3032 aopOp (left,ic,FALSE);
3033 aopOp (right,ic,FALSE);
3034 aopOp (result,ic,TRUE);
3036 /* special cases first */
3038 if (AOP_TYPE(left) == AOP_CRY &&
3039 AOP_TYPE(right)== AOP_CRY) {
3040 genMultbits(left,right,result);
3044 /* if both are of size == 1 */
3045 if (AOP_SIZE(left) == 1 &&
3046 AOP_SIZE(right) == 1 ) {
3047 genMultOneByte(left,right,result);
3051 /* should have been converted to function call */
3055 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3056 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3057 freeAsmop(result,NULL,ic,TRUE);
3060 /*-----------------------------------------------------------------*/
3061 /* genDivbits :- division of bits */
3062 /*-----------------------------------------------------------------*/
3063 static void genDivbits (operand *left,
3070 /* the result must be bit */
3071 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3072 l = aopGet(AOP(left),0,FALSE,FALSE);
3076 emitcode("div","ab");
3077 emitcode("rrc","a");
3078 aopPut(AOP(result),"c",0);
3081 /*-----------------------------------------------------------------*/
3082 /* genDivOneByte : 8 bit division */
3083 /*-----------------------------------------------------------------*/
3084 static void genDivOneByte (operand *left,
3088 link *opetype = operandType(result);
3093 size = AOP_SIZE(result) - 1;
3095 /* signed or unsigned */
3096 if (SPEC_USIGN(opetype)) {
3097 /* unsigned is easy */
3098 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3099 l = aopGet(AOP(left),0,FALSE,FALSE);
3101 emitcode("div","ab");
3102 aopPut(AOP(result),"a",0);
3104 aopPut(AOP(result),zero,offset++);
3108 /* signed is a little bit more difficult */
3110 /* save the signs of the operands */
3111 l = aopGet(AOP(left),0,FALSE,FALSE);
3113 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3114 emitcode("push","acc"); /* save it on the stack */
3116 /* now sign adjust for both left & right */
3117 l = aopGet(AOP(right),0,FALSE,FALSE);
3119 lbl = newiTempLabel(NULL);
3120 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3121 emitcode("cpl","a");
3122 emitcode("inc","a");
3123 emitcode("","%05d$:",(lbl->key+100));
3124 emitcode("mov","b,a");
3126 /* sign adjust left side */
3127 l = aopGet(AOP(left),0,FALSE,FALSE);
3130 lbl = newiTempLabel(NULL);
3131 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3132 emitcode("cpl","a");
3133 emitcode("inc","a");
3134 emitcode("","%05d$:",(lbl->key+100));
3136 /* now the division */
3137 emitcode("div","ab");
3138 /* we are interested in the lower order
3140 emitcode("mov","b,a");
3141 lbl = newiTempLabel(NULL);
3142 emitcode("pop","acc");
3143 /* if there was an over flow we don't
3144 adjust the sign of the result */
3145 emitcode("jb","ov,%05d$",(lbl->key+100));
3146 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3148 emitcode("clr","a");
3149 emitcode("subb","a,b");
3150 emitcode("mov","b,a");
3151 emitcode("","%05d$:",(lbl->key+100));
3153 /* now we are done */
3154 aopPut(AOP(result),"b",0);
3156 emitcode("mov","c,b.7");
3157 emitcode("subb","a,acc");
3160 aopPut(AOP(result),"a",offset++);
3164 /*-----------------------------------------------------------------*/
3165 /* genDiv - generates code for division */
3166 /*-----------------------------------------------------------------*/
3167 static void genDiv (iCode *ic)
3169 operand *left = IC_LEFT(ic);
3170 operand *right = IC_RIGHT(ic);
3171 operand *result= IC_RESULT(ic);
3173 /* assign the amsops */
3174 aopOp (left,ic,FALSE);
3175 aopOp (right,ic,FALSE);
3176 aopOp (result,ic,TRUE);
3178 /* special cases first */
3180 if (AOP_TYPE(left) == AOP_CRY &&
3181 AOP_TYPE(right)== AOP_CRY) {
3182 genDivbits(left,right,result);
3186 /* if both are of size == 1 */
3187 if (AOP_SIZE(left) == 1 &&
3188 AOP_SIZE(right) == 1 ) {
3189 genDivOneByte(left,right,result);
3193 /* should have been converted to function call */
3196 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3197 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3198 freeAsmop(result,NULL,ic,TRUE);
3201 /*-----------------------------------------------------------------*/
3202 /* genModbits :- modulus of bits */
3203 /*-----------------------------------------------------------------*/
3204 static void genModbits (operand *left,
3211 /* the result must be bit */
3212 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3213 l = aopGet(AOP(left),0,FALSE,FALSE);
3217 emitcode("div","ab");
3218 emitcode("mov","a,b");
3219 emitcode("rrc","a");
3220 aopPut(AOP(result),"c",0);
3223 /*-----------------------------------------------------------------*/
3224 /* genModOneByte : 8 bit modulus */
3225 /*-----------------------------------------------------------------*/
3226 static void genModOneByte (operand *left,
3230 link *opetype = operandType(result);
3234 /* signed or unsigned */
3235 if (SPEC_USIGN(opetype)) {
3236 /* unsigned is easy */
3237 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3238 l = aopGet(AOP(left),0,FALSE,FALSE);
3240 emitcode("div","ab");
3241 aopPut(AOP(result),"b",0);
3245 /* signed is a little bit more difficult */
3247 /* save the signs of the operands */
3248 l = aopGet(AOP(left),0,FALSE,FALSE);
3251 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3252 emitcode("push","acc"); /* save it on the stack */
3254 /* now sign adjust for both left & right */
3255 l = aopGet(AOP(right),0,FALSE,FALSE);
3258 lbl = newiTempLabel(NULL);
3259 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3260 emitcode("cpl","a");
3261 emitcode("inc","a");
3262 emitcode("","%05d$:",(lbl->key+100));
3263 emitcode("mov","b,a");
3265 /* sign adjust left side */
3266 l = aopGet(AOP(left),0,FALSE,FALSE);
3269 lbl = newiTempLabel(NULL);
3270 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3271 emitcode("cpl","a");
3272 emitcode("inc","a");
3273 emitcode("","%05d$:",(lbl->key+100));
3275 /* now the multiplication */
3276 emitcode("div","ab");
3277 /* we are interested in the lower order
3279 lbl = newiTempLabel(NULL);
3280 emitcode("pop","acc");
3281 /* if there was an over flow we don't
3282 adjust the sign of the result */
3283 emitcode("jb","ov,%05d$",(lbl->key+100));
3284 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3286 emitcode("clr","a");
3287 emitcode("subb","a,b");
3288 emitcode("mov","b,a");
3289 emitcode("","%05d$:",(lbl->key+100));
3291 /* now we are done */
3292 aopPut(AOP(result),"b",0);
3296 /*-----------------------------------------------------------------*/
3297 /* genMod - generates code for division */
3298 /*-----------------------------------------------------------------*/
3299 static void genMod (iCode *ic)
3301 operand *left = IC_LEFT(ic);
3302 operand *right = IC_RIGHT(ic);
3303 operand *result= IC_RESULT(ic);
3305 /* assign the amsops */
3306 aopOp (left,ic,FALSE);
3307 aopOp (right,ic,FALSE);
3308 aopOp (result,ic,TRUE);
3310 /* special cases first */
3312 if (AOP_TYPE(left) == AOP_CRY &&
3313 AOP_TYPE(right)== AOP_CRY) {
3314 genModbits(left,right,result);
3318 /* if both are of size == 1 */
3319 if (AOP_SIZE(left) == 1 &&
3320 AOP_SIZE(right) == 1 ) {
3321 genModOneByte(left,right,result);
3325 /* should have been converted to function call */
3329 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3330 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3331 freeAsmop(result,NULL,ic,TRUE);
3334 /*-----------------------------------------------------------------*/
3335 /* genIfxJump :- will create a jump depending on the ifx */
3336 /*-----------------------------------------------------------------*/
3337 static void genIfxJump (iCode *ic, char *jval)
3340 symbol *tlbl = newiTempLabel(NULL);
3343 /* if true label then we jump if condition
3345 if ( IC_TRUE(ic) ) {
3347 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3348 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3351 /* false label is present */
3352 jlbl = IC_FALSE(ic) ;
3353 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3354 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3356 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3357 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3359 emitcode(inst,"%05d$",tlbl->key+100);
3360 emitcode("ljmp","%05d$",jlbl->key+100);
3361 emitcode("","%05d$:",tlbl->key+100);
3363 /* mark the icode as generated */
3367 /*-----------------------------------------------------------------*/
3368 /* genCmp :- greater or less than comparison */
3369 /*-----------------------------------------------------------------*/
3370 static void genCmp (operand *left,operand *right,
3371 operand *result, iCode *ifx, int sign)
3373 int size, offset = 0 ;
3374 unsigned long lit = 0L;
3376 /* if left & right are bit variables */
3377 if (AOP_TYPE(left) == AOP_CRY &&
3378 AOP_TYPE(right) == AOP_CRY ) {
3379 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3380 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3382 /* subtract right from left if at the
3383 end the carry flag is set then we know that
3384 left is greater than right */
3385 size = max(AOP_SIZE(left),AOP_SIZE(right));
3387 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3388 if((size == 1) && !sign &&
3389 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3390 symbol *lbl = newiTempLabel(NULL);
3391 emitcode("cjne","%s,%s,%05d$",
3392 aopGet(AOP(left),offset,FALSE,FALSE),
3393 aopGet(AOP(right),offset,FALSE,FALSE),
3395 emitcode("","%05d$:",lbl->key+100);
3397 if(AOP_TYPE(right) == AOP_LIT){
3398 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3399 /* optimize if(x < 0) or if(x >= 0) */
3405 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE));
3406 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3407 genIfxJump (ifx,"acc.7");
3411 emitcode("rlc","a");
3418 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3419 if (sign && size == 0) {
3420 emitcode("xrl","a,#0x80");
3421 if (AOP_TYPE(right) == AOP_LIT){
3422 unsigned long lit = (unsigned long)
3423 floatFromVal(AOP(right)->aopu.aop_lit);
3424 emitcode("subb","a,#0x%02x",
3425 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3427 emitcode("mov","b,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3428 emitcode("xrl","b,#0x80");
3429 emitcode("subb","a,b");
3432 emitcode("subb","a,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3438 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3441 /* if the result is used in the next
3442 ifx conditional branch then generate
3443 code a little differently */
3445 genIfxJump (ifx,"c");
3448 /* leave the result in acc */
3452 /*-----------------------------------------------------------------*/
3453 /* genCmpGt :- greater than comparison */
3454 /*-----------------------------------------------------------------*/
3455 static void genCmpGt (iCode *ic, iCode *ifx)
3457 operand *left, *right, *result;
3458 link *letype , *retype;
3462 right= IC_RIGHT(ic);
3463 result = IC_RESULT(ic);
3465 letype = getSpec(operandType(left));
3466 retype =getSpec(operandType(right));
3467 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3468 /* assign the amsops */
3469 aopOp (left,ic,FALSE);
3470 aopOp (right,ic,FALSE);
3471 aopOp (result,ic,TRUE);
3473 genCmp(right, left, result, ifx, sign);
3475 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3476 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3477 freeAsmop(result,NULL,ic,TRUE);
3480 /*-----------------------------------------------------------------*/
3481 /* genCmpLt - less than comparisons */
3482 /*-----------------------------------------------------------------*/
3483 static void genCmpLt (iCode *ic, iCode *ifx)
3485 operand *left, *right, *result;
3486 link *letype , *retype;
3490 right= IC_RIGHT(ic);
3491 result = IC_RESULT(ic);
3493 letype = getSpec(operandType(left));
3494 retype =getSpec(operandType(right));
3495 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3497 /* assign the amsops */
3498 aopOp (left,ic,FALSE);
3499 aopOp (right,ic,FALSE);
3500 aopOp (result,ic,TRUE);
3502 genCmp(left, right, result, ifx, sign);
3504 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3505 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3506 freeAsmop(result,NULL,ic,TRUE);
3509 /*-----------------------------------------------------------------*/
3510 /* gencjneshort - compare and jump if not equal */
3511 /*-----------------------------------------------------------------*/
3512 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3514 int size = max(AOP_SIZE(left),AOP_SIZE(right));
3516 unsigned long lit = 0L;
3518 /* if the left side is a literal or
3519 if the right is in a pointer register and left
3521 if ((AOP_TYPE(left) == AOP_LIT) ||
3522 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3527 if(AOP_TYPE(right) == AOP_LIT)
3528 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3530 /* if the right side is a literal then anything goes */
3531 if (AOP_TYPE(right) == AOP_LIT &&
3532 AOP_TYPE(left) != AOP_DIR ) {
3534 emitcode("cjne","%s,%s,%05d$",
3535 aopGet(AOP(left),offset,FALSE,FALSE),
3536 aopGet(AOP(right),offset,FALSE,FALSE),
3542 /* if the right side is in a register or in direct space or
3543 if the left is a pointer register & right is not */
3544 else if (AOP_TYPE(right) == AOP_REG ||
3545 AOP_TYPE(right) == AOP_DIR ||
3546 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3547 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3549 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3550 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3551 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
3552 emitcode("jnz","%05d$",lbl->key+100);
3554 emitcode("cjne","a,%s,%05d$",
3555 aopGet(AOP(right),offset,FALSE,TRUE),
3560 /* right is a pointer reg need both a & b */
3562 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
3564 emitcode("mov","b,%s",l);
3565 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3566 emitcode("cjne","a,b,%05d$",lbl->key+100);
3572 /*-----------------------------------------------------------------*/
3573 /* gencjne - compare and jump if not equal */
3574 /*-----------------------------------------------------------------*/
3575 static void gencjne(operand *left, operand *right, symbol *lbl)
3577 symbol *tlbl = newiTempLabel(NULL);
3579 gencjneshort(left, right, lbl);
3581 emitcode("mov","a,%s",one);
3582 emitcode("sjmp","%05d$",tlbl->key+100);
3583 emitcode("","%05d$:",lbl->key+100);
3584 emitcode("clr","a");
3585 emitcode("","%05d$:",tlbl->key+100);
3588 /*-----------------------------------------------------------------*/
3589 /* genCmpEq - generates code for equal to */
3590 /*-----------------------------------------------------------------*/
3591 static void genCmpEq (iCode *ic, iCode *ifx)
3593 operand *left, *right, *result;
3595 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3596 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3597 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3599 /* if literal, literal on the right or
3600 if the right is in a pointer register and left
3602 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
3603 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3604 operand *t = IC_RIGHT(ic);
3605 IC_RIGHT(ic) = IC_LEFT(ic);
3609 if(ifx && !AOP_SIZE(result)){
3611 /* if they are both bit variables */
3612 if (AOP_TYPE(left) == AOP_CRY &&
3613 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3614 if(AOP_TYPE(right) == AOP_LIT){
3615 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3617 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3618 emitcode("cpl","c");
3619 } else if(lit == 1L) {
3620 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3622 emitcode("clr","c");
3624 /* AOP_TYPE(right) == AOP_CRY */
3626 symbol *lbl = newiTempLabel(NULL);
3627 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3628 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3629 emitcode("cpl","c");
3630 emitcode("","%05d$:",(lbl->key+100));
3632 /* if true label then we jump if condition
3634 tlbl = newiTempLabel(NULL);
3635 if ( IC_TRUE(ifx) ) {
3636 emitcode("jnc","%05d$",tlbl->key+100);
3637 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3639 emitcode("jc","%05d$",tlbl->key+100);
3640 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3642 emitcode("","%05d$:",tlbl->key+100);
3644 tlbl = newiTempLabel(NULL);
3645 gencjneshort(left, right, tlbl);
3646 if ( IC_TRUE(ifx) ) {
3647 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3648 emitcode("","%05d$:",tlbl->key+100);
3650 symbol *lbl = newiTempLabel(NULL);
3651 emitcode("sjmp","%05d$",lbl->key+100);
3652 emitcode("","%05d$:",tlbl->key+100);
3653 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3654 emitcode("","%05d$:",lbl->key+100);
3657 /* mark the icode as generated */
3662 /* if they are both bit variables */
3663 if (AOP_TYPE(left) == AOP_CRY &&
3664 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3665 if(AOP_TYPE(right) == AOP_LIT){
3666 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3668 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3669 emitcode("cpl","c");
3670 } else if(lit == 1L) {
3671 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3673 emitcode("clr","c");
3675 /* AOP_TYPE(right) == AOP_CRY */
3677 symbol *lbl = newiTempLabel(NULL);
3678 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3679 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3680 emitcode("cpl","c");
3681 emitcode("","%05d$:",(lbl->key+100));
3684 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
3689 genIfxJump (ifx,"c");
3692 /* if the result is used in an arithmetic operation
3693 then put the result in place */
3696 gencjne(left,right,newiTempLabel(NULL));
3697 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3698 aopPut(AOP(result),"a",0);
3702 genIfxJump (ifx,"a");
3705 /* if the result is used in an arithmetic operation
3706 then put the result in place */
3707 if (AOP_TYPE(result) != AOP_CRY)
3709 /* leave the result in acc */
3713 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3714 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3715 freeAsmop(result,NULL,ic,TRUE);
3718 /*-----------------------------------------------------------------*/
3719 /* ifxForOp - returns the icode containing the ifx for operand */
3720 /*-----------------------------------------------------------------*/
3721 static iCode *ifxForOp ( operand *op, iCode *ic )
3723 /* if true symbol then needs to be assigned */
3724 if (IS_TRUE_SYMOP(op))
3727 /* if this has register type condition and
3728 the next instruction is ifx with the same operand
3729 and live to of the operand is upto the ifx only then */
3731 ic->next->op == IFX &&
3732 IC_COND(ic->next)->key == op->key &&
3733 OP_SYMBOL(op)->liveTo <= ic->next->seq )
3738 /*-----------------------------------------------------------------*/
3739 /* genAndOp - for && operation */
3740 /*-----------------------------------------------------------------*/
3741 static void genAndOp (iCode *ic)
3743 operand *left,*right, *result;
3746 /* note here that && operations that are in an
3747 if statement are taken away by backPatchLabels
3748 only those used in arthmetic operations remain */
3749 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3750 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3751 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3753 /* if both are bit variables */
3754 if (AOP_TYPE(left) == AOP_CRY &&
3755 AOP_TYPE(right) == AOP_CRY ) {
3756 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3757 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3760 tlbl = newiTempLabel(NULL);
3762 emitcode("jz","%05d$",tlbl->key+100);
3764 emitcode("","%05d$:",tlbl->key+100);
3768 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3769 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3770 freeAsmop(result,NULL,ic,TRUE);
3774 /*-----------------------------------------------------------------*/
3775 /* genOrOp - for || operation */
3776 /*-----------------------------------------------------------------*/
3777 static void genOrOp (iCode *ic)
3779 operand *left,*right, *result;
3782 /* note here that || operations that are in an
3783 if statement are taken away by backPatchLabels
3784 only those used in arthmetic operations remain */
3785 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3786 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3787 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3789 /* if both are bit variables */
3790 if (AOP_TYPE(left) == AOP_CRY &&
3791 AOP_TYPE(right) == AOP_CRY ) {
3792 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3793 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
3796 tlbl = newiTempLabel(NULL);
3798 emitcode("jnz","%05d$",tlbl->key+100);
3800 emitcode("","%05d$:",tlbl->key+100);
3804 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3805 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3806 freeAsmop(result,NULL,ic,TRUE);
3809 /*-----------------------------------------------------------------*/
3810 /* isLiteralBit - test if lit == 2^n */
3811 /*-----------------------------------------------------------------*/
3812 static int isLiteralBit(unsigned long lit)
3814 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
3815 0x100L,0x200L,0x400L,0x800L,
3816 0x1000L,0x2000L,0x4000L,0x8000L,
3817 0x10000L,0x20000L,0x40000L,0x80000L,
3818 0x100000L,0x200000L,0x400000L,0x800000L,
3819 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
3820 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
3823 for(idx = 0; idx < 32; idx++)
3829 /*-----------------------------------------------------------------*/
3830 /* continueIfTrue - */
3831 /*-----------------------------------------------------------------*/
3832 static void continueIfTrue (iCode *ic)
3835 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3839 /*-----------------------------------------------------------------*/
3841 /*-----------------------------------------------------------------*/
3842 static void jumpIfTrue (iCode *ic)
3845 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3849 /*-----------------------------------------------------------------*/
3850 /* jmpTrueOrFalse - */
3851 /*-----------------------------------------------------------------*/
3852 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
3854 // ugly but optimized by peephole
3856 symbol *nlbl = newiTempLabel(NULL);
3857 emitcode("sjmp","%05d$",nlbl->key+100);
3858 emitcode("","%05d$:",tlbl->key+100);
3859 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3860 emitcode("","%05d$:",nlbl->key+100);
3863 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3864 emitcode("","%05d$:",tlbl->key+100);
3869 /*-----------------------------------------------------------------*/
3870 /* genAnd - code for and */
3871 /*-----------------------------------------------------------------*/
3872 static void genAnd (iCode *ic, iCode *ifx)
3874 operand *left, *right, *result;
3876 unsigned long lit = 0L;
3880 aopOp((left = IC_LEFT(ic)),ic,FALSE);
3881 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3882 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3885 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3887 AOP_TYPE(left), AOP_TYPE(right));
3888 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3890 AOP_SIZE(left), AOP_SIZE(right));
3893 /* if left is a literal & right is not then exchange them */
3894 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3895 AOP_NEEDSACC(left)) {
3896 operand *tmp = right ;
3901 /* if result = right then exchange them */
3902 if(sameRegs(AOP(result),AOP(right))){
3903 operand *tmp = right ;
3908 /* if right is bit then exchange them */
3909 if (AOP_TYPE(right) == AOP_CRY &&
3910 AOP_TYPE(left) != AOP_CRY){
3911 operand *tmp = right ;
3915 if(AOP_TYPE(right) == AOP_LIT)
3916 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3918 size = AOP_SIZE(result);
3921 // result = bit & yy;
3922 if (AOP_TYPE(left) == AOP_CRY){
3923 // c = bit & literal;
3924 if(AOP_TYPE(right) == AOP_LIT){
3926 if(size && sameRegs(AOP(result),AOP(left)))
3929 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3932 if(size && (AOP_TYPE(result) == AOP_CRY)){
3933 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
3936 if((AOP_TYPE(result) == AOP_CRY) && ifx){
3940 emitcode("clr","c");
3943 if (AOP_TYPE(right) == AOP_CRY){
3945 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3946 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3949 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
3951 emitcode("rrc","a");
3952 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3960 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
3961 genIfxJump(ifx, "c");
3965 // if(val & 0xZZ) - size = 0, ifx != FALSE -
3966 // bit = val & 0xZZ - size = 1, ifx = FALSE -
3967 if((AOP_TYPE(right) == AOP_LIT) &&
3968 (AOP_TYPE(result) == AOP_CRY) &&
3969 (AOP_TYPE(left) != AOP_CRY)){
3970 int posbit = isLiteralBit(lit);
3974 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
3977 emitcode("mov","c,acc.%d",posbit&0x07);
3981 sprintf(buffer,"acc.%d",posbit&0x07);
3982 genIfxJump(ifx, buffer);
3987 symbol *tlbl = newiTempLabel(NULL);
3988 int sizel = AOP_SIZE(left);
3990 emitcode("setb","c");
3992 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
3993 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
3995 if((posbit = isLiteralBit(bytelit)) != 0)
3996 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
3998 if(bytelit != 0x0FFL)
3999 emitcode("anl","a,%s",
4000 aopGet(AOP(right),offset,FALSE,TRUE));
4001 emitcode("jnz","%05d$",tlbl->key+100);
4006 // bit = left & literal
4008 emitcode("clr","c");
4009 emitcode("","%05d$:",tlbl->key+100);
4011 // if(left & literal)
4014 jmpTrueOrFalse(ifx, tlbl);
4022 /* if left is same as result */
4023 if(sameRegs(AOP(result),AOP(left))){
4024 for(;size--; offset++) {
4025 if(AOP_TYPE(right) == AOP_LIT){
4026 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4030 aopPut(AOP(result),zero,offset);
4032 if (IS_AOP_PREG(result)) {
4033 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4034 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4035 aopPut(AOP(result),"a",offset);
4037 emitcode("anl","%s,%s",
4038 aopGet(AOP(left),offset,FALSE,TRUE),
4039 aopGet(AOP(right),offset,FALSE,FALSE));
4041 if (AOP_TYPE(left) == AOP_ACC)
4042 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4044 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4045 if (IS_AOP_PREG(result)) {
4046 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4047 aopPut(AOP(result),"a",offset);
4050 emitcode("anl","%s,a",
4051 aopGet(AOP(left),offset,FALSE,TRUE));
4056 // left & result in different registers
4057 if(AOP_TYPE(result) == AOP_CRY){
4059 // if(size), result in bit
4060 // if(!size && ifx), conditional oper: if(left & right)
4061 symbol *tlbl = newiTempLabel(NULL);
4062 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4064 emitcode("setb","c");
4066 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4067 emitcode("anl","a,%s",
4068 aopGet(AOP(left),offset,FALSE,FALSE));
4069 emitcode("jnz","%05d$",tlbl->key+100);
4074 emitcode("","%05d$:",tlbl->key+100);
4077 jmpTrueOrFalse(ifx, tlbl);
4079 for(;(size--);offset++) {
4081 // result = left & right
4082 if(AOP_TYPE(right) == AOP_LIT){
4083 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
4085 aopGet(AOP(left),offset,FALSE,FALSE),
4088 } else if(bytelit == 0){
4089 aopPut(AOP(result),zero,offset);
4093 // faster than result <- left, anl result,right
4094 // and better if result is SFR
4095 if (AOP_TYPE(left) == AOP_ACC)
4096 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4098 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4099 emitcode("anl","a,%s",
4100 aopGet(AOP(left),offset,FALSE,FALSE));
4102 aopPut(AOP(result),"a",offset);
4108 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4109 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4110 freeAsmop(result,NULL,ic,TRUE);
4113 /*-----------------------------------------------------------------*/
4114 /* genOr - code for or */
4115 /*-----------------------------------------------------------------*/
4116 static void genOr (iCode *ic, iCode *ifx)
4118 operand *left, *right, *result;
4120 unsigned long lit = 0L;
4122 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4123 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4124 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4127 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4129 AOP_TYPE(left), AOP_TYPE(right));
4130 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4132 AOP_SIZE(left), AOP_SIZE(right));
4135 /* if left is a literal & right is not then exchange them */
4136 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4137 AOP_NEEDSACC(left)) {
4138 operand *tmp = right ;
4143 /* if result = right then exchange them */
4144 if(sameRegs(AOP(result),AOP(right))){
4145 operand *tmp = right ;
4150 /* if right is bit then exchange them */
4151 if (AOP_TYPE(right) == AOP_CRY &&
4152 AOP_TYPE(left) != AOP_CRY){
4153 operand *tmp = right ;
4157 if(AOP_TYPE(right) == AOP_LIT)
4158 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4160 size = AOP_SIZE(result);
4164 if (AOP_TYPE(left) == AOP_CRY){
4165 if(AOP_TYPE(right) == AOP_LIT){
4166 // c = bit & literal;
4168 // lit != 0 => result = 1
4169 if(AOP_TYPE(result) == AOP_CRY){
4171 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4173 continueIfTrue(ifx);
4176 emitcode("setb","c");
4178 // lit == 0 => result = left
4179 if(size && sameRegs(AOP(result),AOP(left)))
4181 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4184 if (AOP_TYPE(right) == AOP_CRY){
4186 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4187 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4191 symbol *tlbl = newiTempLabel(NULL);
4192 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4193 emitcode("setb","c");
4194 emitcode("jb","%s,%05d$",
4195 AOP(left)->aopu.aop_dir,tlbl->key+100);
4197 emitcode("jnz","%05d$",tlbl->key+100);
4198 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4199 jmpTrueOrFalse(ifx, tlbl);
4203 emitcode("","%05d$:",tlbl->key+100);
4212 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4213 genIfxJump(ifx, "c");
4217 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4218 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4219 if((AOP_TYPE(right) == AOP_LIT) &&
4220 (AOP_TYPE(result) == AOP_CRY) &&
4221 (AOP_TYPE(left) != AOP_CRY)){
4225 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4227 continueIfTrue(ifx);
4230 // lit = 0, result = boolean(left)
4232 emitcode("setb","c");
4235 symbol *tlbl = newiTempLabel(NULL);
4236 emitcode("jnz","%05d$",tlbl->key+100);
4238 emitcode("","%05d$:",tlbl->key+100);
4240 genIfxJump (ifx,"a");
4248 /* if left is same as result */
4249 if(sameRegs(AOP(result),AOP(left))){
4250 for(;size--; offset++) {
4251 if(AOP_TYPE(right) == AOP_LIT){
4252 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4255 if (IS_AOP_PREG(left)) {
4256 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4257 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4258 aopPut(AOP(result),"a",offset);
4260 emitcode("orl","%s,%s",
4261 aopGet(AOP(left),offset,FALSE,TRUE),
4262 aopGet(AOP(right),offset,FALSE,FALSE));
4264 if (AOP_TYPE(left) == AOP_ACC)
4265 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4267 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4268 if (IS_AOP_PREG(left)) {
4269 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4270 aopPut(AOP(result),"a",offset);
4272 emitcode("orl","%s,a",
4273 aopGet(AOP(left),offset,FALSE,TRUE));
4278 // left & result in different registers
4279 if(AOP_TYPE(result) == AOP_CRY){
4281 // if(size), result in bit
4282 // if(!size && ifx), conditional oper: if(left | right)
4283 symbol *tlbl = newiTempLabel(NULL);
4284 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4286 emitcode("setb","c");
4288 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4289 emitcode("orl","a,%s",
4290 aopGet(AOP(left),offset,FALSE,FALSE));
4291 emitcode("jnz","%05d$",tlbl->key+100);
4296 emitcode("","%05d$:",tlbl->key+100);
4299 jmpTrueOrFalse(ifx, tlbl);
4300 } else for(;(size--);offset++){
4302 // result = left & right
4303 if(AOP_TYPE(right) == AOP_LIT){
4304 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4306 aopGet(AOP(left),offset,FALSE,FALSE),
4311 // faster than result <- left, anl result,right
4312 // and better if result is SFR
4313 if (AOP_TYPE(left) == AOP_ACC)
4314 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4316 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4317 emitcode("orl","a,%s",
4318 aopGet(AOP(left),offset,FALSE,FALSE));
4320 aopPut(AOP(result),"a",offset);
4325 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4326 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4327 freeAsmop(result,NULL,ic,TRUE);
4330 /*-----------------------------------------------------------------*/
4331 /* genXor - code for xclusive or */
4332 /*-----------------------------------------------------------------*/
4333 static void genXor (iCode *ic, iCode *ifx)
4335 operand *left, *right, *result;
4337 unsigned long lit = 0L;
4339 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4340 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4341 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4344 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4346 AOP_TYPE(left), AOP_TYPE(right));
4347 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4349 AOP_SIZE(left), AOP_SIZE(right));
4352 /* if left is a literal & right is not ||
4353 if left needs acc & right does not */
4354 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4355 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4356 operand *tmp = right ;
4361 /* if result = right then exchange them */
4362 if(sameRegs(AOP(result),AOP(right))){
4363 operand *tmp = right ;
4368 /* if right is bit then exchange them */
4369 if (AOP_TYPE(right) == AOP_CRY &&
4370 AOP_TYPE(left) != AOP_CRY){
4371 operand *tmp = right ;
4375 if(AOP_TYPE(right) == AOP_LIT)
4376 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4378 size = AOP_SIZE(result);
4382 if (AOP_TYPE(left) == AOP_CRY){
4383 if(AOP_TYPE(right) == AOP_LIT){
4384 // c = bit & literal;
4386 // lit>>1 != 0 => result = 1
4387 if(AOP_TYPE(result) == AOP_CRY){
4389 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4391 continueIfTrue(ifx);
4394 emitcode("setb","c");
4398 // lit == 0, result = left
4399 if(size && sameRegs(AOP(result),AOP(left)))
4401 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4403 // lit == 1, result = not(left)
4404 if(size && sameRegs(AOP(result),AOP(left))){
4405 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4408 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4409 emitcode("cpl","c");
4416 symbol *tlbl = newiTempLabel(NULL);
4417 if (AOP_TYPE(right) == AOP_CRY){
4419 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4422 int sizer = AOP_SIZE(right);
4424 // if val>>1 != 0, result = 1
4425 emitcode("setb","c");
4427 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
4429 // test the msb of the lsb
4430 emitcode("anl","a,#0xfe");
4431 emitcode("jnz","%05d$",tlbl->key+100);
4435 emitcode("rrc","a");
4437 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4438 emitcode("cpl","c");
4439 emitcode("","%05d$:",(tlbl->key+100));
4446 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4447 genIfxJump(ifx, "c");
4451 if(sameRegs(AOP(result),AOP(left))){
4452 /* if left is same as result */
4453 for(;size--; offset++) {
4454 if(AOP_TYPE(right) == AOP_LIT){
4455 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4458 if (IS_AOP_PREG(left)) {
4459 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4460 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4461 aopPut(AOP(result),"a",offset);
4463 emitcode("xrl","%s,%s",
4464 aopGet(AOP(left),offset,FALSE,TRUE),
4465 aopGet(AOP(right),offset,FALSE,FALSE));
4467 if (AOP_TYPE(left) == AOP_ACC)
4468 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4470 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4471 if (IS_AOP_PREG(left)) {
4472 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4473 aopPut(AOP(result),"a",offset);
4475 emitcode("xrl","%s,a",
4476 aopGet(AOP(left),offset,FALSE,TRUE));
4481 // left & result in different registers
4482 if(AOP_TYPE(result) == AOP_CRY){
4484 // if(size), result in bit
4485 // if(!size && ifx), conditional oper: if(left ^ right)
4486 symbol *tlbl = newiTempLabel(NULL);
4487 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4489 emitcode("setb","c");
4491 if((AOP_TYPE(right) == AOP_LIT) &&
4492 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4493 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4495 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4496 emitcode("xrl","a,%s",
4497 aopGet(AOP(left),offset,FALSE,FALSE));
4499 emitcode("jnz","%05d$",tlbl->key+100);
4504 emitcode("","%05d$:",tlbl->key+100);
4507 jmpTrueOrFalse(ifx, tlbl);
4508 } else for(;(size--);offset++){
4510 // result = left & right
4511 if(AOP_TYPE(right) == AOP_LIT){
4512 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4514 aopGet(AOP(left),offset,FALSE,FALSE),
4519 // faster than result <- left, anl result,right
4520 // and better if result is SFR
4521 if (AOP_TYPE(left) == AOP_ACC)
4522 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4524 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4525 emitcode("xrl","a,%s",
4526 aopGet(AOP(left),offset,FALSE,TRUE));
4528 aopPut(AOP(result),"a",offset);
4533 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4534 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4535 freeAsmop(result,NULL,ic,TRUE);
4538 /*-----------------------------------------------------------------*/
4539 /* genInline - write the inline code out */
4540 /*-----------------------------------------------------------------*/
4541 static void genInline (iCode *ic)
4543 char buffer[MAX_INLINEASM];
4547 _G.inLine += (!options.asmpeep);
4548 strcpy(buffer,IC_INLINE(ic));
4550 /* emit each line as a code */
4569 /* emitcode("",buffer); */
4570 _G.inLine -= (!options.asmpeep);
4573 /*-----------------------------------------------------------------*/
4574 /* genRRC - rotate right with carry */
4575 /*-----------------------------------------------------------------*/
4576 static void genRRC (iCode *ic)
4578 operand *left , *result ;
4579 int size, offset = 0;
4582 /* rotate right with carry */
4584 result=IC_RESULT(ic);
4585 aopOp (left,ic,FALSE);
4586 aopOp (result,ic,FALSE);
4588 /* move it to the result */
4589 size = AOP_SIZE(result);
4593 l = aopGet(AOP(left),offset,FALSE,FALSE);
4595 emitcode("rrc","a");
4596 if (AOP_SIZE(result) > 1)
4597 aopPut(AOP(result),"a",offset--);
4599 /* now we need to put the carry into the
4600 highest order byte of the result */
4601 if (AOP_SIZE(result) > 1) {
4602 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
4605 emitcode("mov","acc.7,c");
4606 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
4607 freeAsmop(left,NULL,ic,TRUE);
4608 freeAsmop(result,NULL,ic,TRUE);
4611 /*-----------------------------------------------------------------*/
4612 /* genRLC - generate code for rotate left with carry */
4613 /*-----------------------------------------------------------------*/
4614 static void genRLC (iCode *ic)
4616 operand *left , *result ;
4617 int size, offset = 0;
4620 /* rotate right with carry */
4622 result=IC_RESULT(ic);
4623 aopOp (left,ic,FALSE);
4624 aopOp (result,ic,FALSE);
4626 /* move it to the result */
4627 size = AOP_SIZE(result);
4630 l = aopGet(AOP(left),offset,FALSE,FALSE);
4632 emitcode("add","a,acc");
4633 if (AOP_SIZE(result) > 1)
4634 aopPut(AOP(result),"a",offset++);
4636 l = aopGet(AOP(left),offset,FALSE,FALSE);
4638 emitcode("rlc","a");
4639 if (AOP_SIZE(result) > 1)
4640 aopPut(AOP(result),"a",offset++);
4643 /* now we need to put the carry into the
4644 highest order byte of the result */
4645 if (AOP_SIZE(result) > 1) {
4646 l = aopGet(AOP(result),0,FALSE,FALSE);
4649 emitcode("mov","acc.0,c");
4650 aopPut(AOP(result),"a",0);
4651 freeAsmop(left,NULL,ic,TRUE);
4652 freeAsmop(result,NULL,ic,TRUE);
4655 /*-----------------------------------------------------------------*/
4656 /* genGetHbit - generates code get highest order bit */
4657 /*-----------------------------------------------------------------*/
4658 static void genGetHbit (iCode *ic)
4660 operand *left, *result;
4662 result=IC_RESULT(ic);
4663 aopOp (left,ic,FALSE);
4664 aopOp (result,ic,FALSE);
4666 /* get the highest order byte into a */
4667 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
4668 if(AOP_TYPE(result) == AOP_CRY){
4669 emitcode("rlc","a");
4674 emitcode("anl","a,#0x01");
4679 freeAsmop(left,NULL,ic,TRUE);
4680 freeAsmop(result,NULL,ic,TRUE);
4683 /*-----------------------------------------------------------------*/
4684 /* AccRol - rotate left accumulator by known count */
4685 /*-----------------------------------------------------------------*/
4686 static void AccRol (int shCount)
4688 shCount &= 0x0007; // shCount : 0..7
4700 emitcode("swap","a");
4704 emitcode("swap","a");
4707 emitcode("swap","a");
4720 /*-----------------------------------------------------------------*/
4721 /* AccLsh - left shift accumulator by known count */
4722 /*-----------------------------------------------------------------*/
4723 static void AccLsh (int shCount)
4727 emitcode("add","a,acc");
4730 emitcode("add","a,acc");
4731 emitcode("add","a,acc");
4733 /* rotate left accumulator */
4735 /* and kill the lower order bits */
4736 emitcode("anl","a,#0x%02x", SLMask[shCount]);
4741 /*-----------------------------------------------------------------*/
4742 /* AccRsh - right shift accumulator by known count */
4743 /*-----------------------------------------------------------------*/
4744 static void AccRsh (int shCount)
4749 emitcode("rrc","a");
4751 /* rotate right accumulator */
4752 AccRol(8 - shCount);
4753 /* and kill the higher order bits */
4754 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4759 /*-----------------------------------------------------------------*/
4760 /* AccSRsh - signed right shift accumulator by known count */
4761 /*-----------------------------------------------------------------*/
4762 static void AccSRsh (int shCount)
4767 emitcode("mov","c,acc.7");
4768 emitcode("rrc","a");
4769 } else if(shCount == 2){
4770 emitcode("mov","c,acc.7");
4771 emitcode("rrc","a");
4772 emitcode("mov","c,acc.7");
4773 emitcode("rrc","a");
4775 tlbl = newiTempLabel(NULL);
4776 /* rotate right accumulator */
4777 AccRol(8 - shCount);
4778 /* and kill the higher order bits */
4779 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4780 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4781 emitcode("orl","a,#0x%02x",
4782 (unsigned char)~SRMask[shCount]);
4783 emitcode("","%05d$:",tlbl->key+100);
4788 /*-----------------------------------------------------------------*/
4789 /* shiftR1Left2Result - shift right one byte from left to result */
4790 /*-----------------------------------------------------------------*/
4791 static void shiftR1Left2Result (operand *left, int offl,
4792 operand *result, int offr,
4793 int shCount, int sign)
4795 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4796 /* shift right accumulator */
4801 aopPut(AOP(result),"a",offr);
4804 /*-----------------------------------------------------------------*/
4805 /* shiftL1Left2Result - shift left one byte from left to result */
4806 /*-----------------------------------------------------------------*/
4807 static void shiftL1Left2Result (operand *left, int offl,
4808 operand *result, int offr, int shCount)
4811 l = aopGet(AOP(left),offl,FALSE,FALSE);
4813 /* shift left accumulator */
4815 aopPut(AOP(result),"a",offr);
4818 /*-----------------------------------------------------------------*/
4819 /* movLeft2Result - move byte from left to result */
4820 /*-----------------------------------------------------------------*/
4821 static void movLeft2Result (operand *left, int offl,
4822 operand *result, int offr, int sign)
4825 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
4826 l = aopGet(AOP(left),offl,FALSE,FALSE);
4828 if (*l == '@' && (IS_AOP_PREG(result))) {
4829 emitcode("mov","a,%s",l);
4830 aopPut(AOP(result),"a",offr);
4833 aopPut(AOP(result),l,offr);
4835 /* MSB sign in acc.7 ! */
4836 if(getDataSize(left) == offl+1){
4837 emitcode("mov","a,%s",l);
4838 aopPut(AOP(result),"a",offr);
4845 /*-----------------------------------------------------------------*/
4846 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
4847 /*-----------------------------------------------------------------*/
4848 static void AccAXRrl1 (char *x)
4850 emitcode("rrc","a");
4851 emitcode("xch","a,%s", x);
4852 emitcode("rrc","a");
4853 emitcode("xch","a,%s", x);
4856 /*-----------------------------------------------------------------*/
4857 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
4858 /*-----------------------------------------------------------------*/
4859 static void AccAXLrl1 (char *x)
4861 emitcode("xch","a,%s",x);
4862 emitcode("rlc","a");
4863 emitcode("xch","a,%s",x);
4864 emitcode("rlc","a");
4867 /*-----------------------------------------------------------------*/
4868 /* AccAXLsh1 - left shift a:x<-0 by 1 */
4869 /*-----------------------------------------------------------------*/
4870 static void AccAXLsh1 (char *x)
4872 emitcode("xch","a,%s",x);
4873 emitcode("add","a,acc");
4874 emitcode("xch","a,%s",x);
4875 emitcode("rlc","a");
4878 /*-----------------------------------------------------------------*/
4879 /* AccAXLsh - left shift a:x by known count (0..7) */
4880 /*-----------------------------------------------------------------*/
4881 static void AccAXLsh (char *x, int shCount)
4895 case 5 : // AAAAABBB:CCCCCDDD
4896 AccRol(shCount); // BBBAAAAA:CCCCCDDD
4897 emitcode("anl","a,#0x%02x",
4898 SLMask[shCount]); // BBB00000:CCCCCDDD
4899 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
4900 AccRol(shCount); // DDDCCCCC:BBB00000
4901 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
4902 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
4903 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
4904 emitcode("anl","a,#0x%02x",
4905 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
4906 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
4907 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
4909 case 6 : // AAAAAABB:CCCCCCDD
4910 emitcode("anl","a,#0x%02x",
4911 SRMask[shCount]); // 000000BB:CCCCCCDD
4912 emitcode("mov","c,acc.0"); // c = B
4913 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
4914 AccAXRrl1(x); // BCCCCCCD:D000000B
4915 AccAXRrl1(x); // BBCCCCCC:DD000000
4917 case 7 : // a:x <<= 7
4918 emitcode("anl","a,#0x%02x",
4919 SRMask[shCount]); // 0000000B:CCCCCCCD
4920 emitcode("mov","c,acc.0"); // c = B
4921 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
4922 AccAXRrl1(x); // BCCCCCCC:D0000000
4929 /*-----------------------------------------------------------------*/
4930 /* AccAXRsh - right shift a:x known count (0..7) */
4931 /*-----------------------------------------------------------------*/
4932 static void AccAXRsh (char *x, int shCount)
4939 AccAXRrl1(x); // 0->a:x
4943 AccAXRrl1(x); // 0->a:x
4945 AccAXRrl1(x); // 0->a:x
4949 case 5 : // AAAAABBB:CCCCCDDD = a:x
4950 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
4951 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
4952 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
4953 emitcode("anl","a,#0x%02x",
4954 SRMask[shCount]); // 000CCCCC:BBBAAAAA
4955 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
4956 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
4957 emitcode("anl","a,#0x%02x",
4958 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
4959 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
4960 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
4961 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
4963 case 6 : // AABBBBBB:CCDDDDDD
4964 emitcode("mov","c,acc.7");
4965 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
4966 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
4967 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
4968 emitcode("anl","a,#0x%02x",
4969 SRMask[shCount]); // 000000AA:BBBBBBCC
4971 case 7 : // ABBBBBBB:CDDDDDDD
4972 emitcode("mov","c,acc.7"); // c = A
4973 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
4974 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
4975 emitcode("anl","a,#0x%02x",
4976 SRMask[shCount]); // 0000000A:BBBBBBBC
4983 /*-----------------------------------------------------------------*/
4984 /* AccAXRshS - right shift signed a:x known count (0..7) */
4985 /*-----------------------------------------------------------------*/
4986 static void AccAXRshS (char *x, int shCount)
4993 emitcode("mov","c,acc.7");
4994 AccAXRrl1(x); // s->a:x
4997 emitcode("mov","c,acc.7");
4998 AccAXRrl1(x); // s->a:x
4999 emitcode("mov","c,acc.7");
5000 AccAXRrl1(x); // s->a:x
5004 case 5 : // AAAAABBB:CCCCCDDD = a:x
5005 tlbl = newiTempLabel(NULL);
5006 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5007 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5008 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5009 emitcode("anl","a,#0x%02x",
5010 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5011 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5012 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5013 emitcode("anl","a,#0x%02x",
5014 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5015 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5016 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5017 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5018 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5019 emitcode("orl","a,#0x%02x",
5020 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5021 emitcode("","%05d$:",tlbl->key+100);
5022 break; // SSSSAAAA:BBBCCCCC
5023 case 6 : // AABBBBBB:CCDDDDDD
5024 tlbl = newiTempLabel(NULL);
5025 emitcode("mov","c,acc.7");
5026 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5027 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5028 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5029 emitcode("anl","a,#0x%02x",
5030 SRMask[shCount]); // 000000AA:BBBBBBCC
5031 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5032 emitcode("orl","a,#0x%02x",
5033 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5034 emitcode("","%05d$:",tlbl->key+100);
5036 case 7 : // ABBBBBBB:CDDDDDDD
5037 tlbl = newiTempLabel(NULL);
5038 emitcode("mov","c,acc.7"); // c = A
5039 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5040 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5041 emitcode("anl","a,#0x%02x",
5042 SRMask[shCount]); // 0000000A:BBBBBBBC
5043 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5044 emitcode("orl","a,#0x%02x",
5045 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5046 emitcode("","%05d$:",tlbl->key+100);
5053 /*-----------------------------------------------------------------*/
5054 /* shiftL2Left2Result - shift left two bytes from left to result */
5055 /*-----------------------------------------------------------------*/
5056 static void shiftL2Left2Result (operand *left, int offl,
5057 operand *result, int offr, int shCount)
5059 if(sameRegs(AOP(result), AOP(left)) &&
5060 ((offl + MSB16) == offr)){
5061 /* don't crash result[offr] */
5062 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5063 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5065 movLeft2Result(left,offl, result, offr, 0);
5066 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5068 /* ax << shCount (x = lsb(result))*/
5069 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5070 aopPut(AOP(result),"a",offr+MSB16);
5074 /*-----------------------------------------------------------------*/
5075 /* shiftR2Left2Result - shift right two bytes from left to result */
5076 /*-----------------------------------------------------------------*/
5077 static void shiftR2Left2Result (operand *left, int offl,
5078 operand *result, int offr,
5079 int shCount, int sign)
5081 if(sameRegs(AOP(result), AOP(left)) &&
5082 ((offl + MSB16) == offr)){
5083 /* don't crash result[offr] */
5084 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5085 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5087 movLeft2Result(left,offl, result, offr, 0);
5088 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5090 /* a:x >> shCount (x = lsb(result))*/
5092 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5094 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5095 if(getDataSize(result) > 1)
5096 aopPut(AOP(result),"a",offr+MSB16);
5099 /*-----------------------------------------------------------------*/
5100 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5101 /*-----------------------------------------------------------------*/
5102 static void shiftLLeftOrResult (operand *left, int offl,
5103 operand *result, int offr, int shCount)
5105 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5106 /* shift left accumulator */
5108 /* or with result */
5109 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5110 /* back to result */
5111 aopPut(AOP(result),"a",offr);
5114 /*-----------------------------------------------------------------*/
5115 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5116 /*-----------------------------------------------------------------*/
5117 static void shiftRLeftOrResult (operand *left, int offl,
5118 operand *result, int offr, int shCount)
5120 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5121 /* shift right accumulator */
5123 /* or with result */
5124 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5125 /* back to result */
5126 aopPut(AOP(result),"a",offr);
5129 /*-----------------------------------------------------------------*/
5130 /* genlshOne - left shift a one byte quantity by known count */
5131 /*-----------------------------------------------------------------*/
5132 static void genlshOne (operand *result, operand *left, int shCount)
5134 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5137 /*-----------------------------------------------------------------*/
5138 /* genlshTwo - left shift two bytes by known amount != 0 */
5139 /*-----------------------------------------------------------------*/
5140 static void genlshTwo (operand *result,operand *left, int shCount)
5144 size = getDataSize(result);
5146 /* if shCount >= 8 */
5152 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5154 movLeft2Result(left, LSB, result, MSB16, 0);
5156 aopPut(AOP(result),zero,LSB);
5159 /* 1 <= shCount <= 7 */
5162 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5164 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5168 /*-----------------------------------------------------------------*/
5169 /* shiftLLong - shift left one long from left to result */
5170 /* offl = LSB or MSB16 */
5171 /*-----------------------------------------------------------------*/
5172 static void shiftLLong (operand *left, operand *result, int offr )
5175 int size = AOP_SIZE(result);
5177 if(size >= LSB+offr){
5178 l = aopGet(AOP(left),LSB,FALSE,FALSE);
5180 emitcode("add","a,acc");
5181 if (sameRegs(AOP(left),AOP(result)) &&
5182 size >= MSB16+offr && offr != LSB )
5183 emitcode("xch","a,%s",
5184 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
5186 aopPut(AOP(result),"a",LSB+offr);
5189 if(size >= MSB16+offr){
5190 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5191 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
5194 emitcode("rlc","a");
5195 if (sameRegs(AOP(left),AOP(result)) &&
5196 size >= MSB24+offr && offr != LSB)
5197 emitcode("xch","a,%s",
5198 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
5200 aopPut(AOP(result),"a",MSB16+offr);
5203 if(size >= MSB24+offr){
5204 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5205 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
5208 emitcode("rlc","a");
5209 if (sameRegs(AOP(left),AOP(result)) &&
5210 size >= MSB32+offr && offr != LSB )
5211 emitcode("xch","a,%s",
5212 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
5214 aopPut(AOP(result),"a",MSB24+offr);
5217 if(size > MSB32+offr){
5218 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5219 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
5222 emitcode("rlc","a");
5223 aopPut(AOP(result),"a",MSB32+offr);
5226 aopPut(AOP(result),zero,LSB);
5229 /*-----------------------------------------------------------------*/
5230 /* genlshFour - shift four byte by a known amount != 0 */
5231 /*-----------------------------------------------------------------*/
5232 static void genlshFour (operand *result, operand *left, int shCount)
5236 size = AOP_SIZE(result);
5238 /* if shifting more that 3 bytes */
5239 if (shCount >= 24 ) {
5242 /* lowest order of left goes to the highest
5243 order of the destination */
5244 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5246 movLeft2Result(left, LSB, result, MSB32, 0);
5247 aopPut(AOP(result),zero,LSB);
5248 aopPut(AOP(result),zero,MSB16);
5249 aopPut(AOP(result),zero,MSB32);
5253 /* more than two bytes */
5254 else if ( shCount >= 16 ) {
5255 /* lower order two bytes goes to higher order two bytes */
5257 /* if some more remaining */
5259 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5261 movLeft2Result(left, MSB16, result, MSB32, 0);
5262 movLeft2Result(left, LSB, result, MSB24, 0);
5264 aopPut(AOP(result),zero,MSB16);
5265 aopPut(AOP(result),zero,LSB);
5269 /* if more than 1 byte */
5270 else if ( shCount >= 8 ) {
5271 /* lower order three bytes goes to higher order three bytes */
5275 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5277 movLeft2Result(left, LSB, result, MSB16, 0);
5279 else{ /* size = 4 */
5281 movLeft2Result(left, MSB24, result, MSB32, 0);
5282 movLeft2Result(left, MSB16, result, MSB24, 0);
5283 movLeft2Result(left, LSB, result, MSB16, 0);
5284 aopPut(AOP(result),zero,LSB);
5286 else if(shCount == 1)
5287 shiftLLong(left, result, MSB16);
5289 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5290 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5291 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5292 aopPut(AOP(result),zero,LSB);
5297 /* 1 <= shCount <= 7 */
5298 else if(shCount <= 2){
5299 shiftLLong(left, result, LSB);
5301 shiftLLong(result, result, LSB);
5303 /* 3 <= shCount <= 7, optimize */
5305 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5306 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5307 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5311 /*-----------------------------------------------------------------*/
5312 /* genLeftShiftLiteral - left shifting by known count */
5313 /*-----------------------------------------------------------------*/
5314 static void genLeftShiftLiteral (operand *left,
5319 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5322 freeAsmop(right,NULL,ic,TRUE);
5324 aopOp(left,ic,FALSE);
5325 aopOp(result,ic,FALSE);
5327 size = getSize(operandType(result));
5330 emitcode("; shift left ","result %d, left %d",size,
5334 /* I suppose that the left size >= result size */
5337 movLeft2Result(left, size, result, size, 0);
5341 else if(shCount >= (size * 8))
5343 aopPut(AOP(result),zero,size);
5347 genlshOne (result,left,shCount);
5352 genlshTwo (result,left,shCount);
5356 genlshFour (result,left,shCount);
5360 freeAsmop(left,NULL,ic,TRUE);
5361 freeAsmop(result,NULL,ic,TRUE);
5364 /*-----------------------------------------------------------------*/
5365 /* genLeftShift - generates code for left shifting */
5366 /*-----------------------------------------------------------------*/
5367 static void genLeftShift (iCode *ic)
5369 operand *left,*right, *result;
5372 symbol *tlbl , *tlbl1;
5374 right = IC_RIGHT(ic);
5376 result = IC_RESULT(ic);
5378 aopOp(right,ic,FALSE);
5380 /* if the shift count is known then do it
5381 as efficiently as possible */
5382 if (AOP_TYPE(right) == AOP_LIT) {
5383 genLeftShiftLiteral (left,right,result,ic);
5387 /* shift count is unknown then we have to form
5388 a loop get the loop count in B : Note: we take
5389 only the lower order byte since shifting
5390 more that 32 bits make no sense anyway, ( the
5391 largest size of an object can be only 32 bits ) */
5393 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5394 emitcode("inc","b");
5395 freeAsmop (right,NULL,ic,TRUE);
5396 aopOp(left,ic,FALSE);
5397 aopOp(result,ic,FALSE);
5399 /* now move the left to the result if they are not the
5401 if (!sameRegs(AOP(left),AOP(result)) &&
5402 AOP_SIZE(result) > 1) {
5404 size = AOP_SIZE(result);
5407 l = aopGet(AOP(left),offset,FALSE,TRUE);
5408 if (*l == '@' && (IS_AOP_PREG(result))) {
5410 emitcode("mov","a,%s",l);
5411 aopPut(AOP(result),"a",offset);
5413 aopPut(AOP(result),l,offset);
5418 tlbl = newiTempLabel(NULL);
5419 size = AOP_SIZE(result);
5421 tlbl1 = newiTempLabel(NULL);
5423 /* if it is only one byte then */
5425 symbol *tlbl1 = newiTempLabel(NULL);
5427 l = aopGet(AOP(left),0,FALSE,FALSE);
5429 emitcode("sjmp","%05d$",tlbl1->key+100);
5430 emitcode("","%05d$:",tlbl->key+100);
5431 emitcode("add","a,acc");
5432 emitcode("","%05d$:",tlbl1->key+100);
5433 emitcode("djnz","b,%05d$",tlbl->key+100);
5434 aopPut(AOP(result),"a",0);
5438 reAdjustPreg(AOP(result));
5440 emitcode("sjmp","%05d$",tlbl1->key+100);
5441 emitcode("","%05d$:",tlbl->key+100);
5442 l = aopGet(AOP(result),offset,FALSE,FALSE);
5444 emitcode("add","a,acc");
5445 aopPut(AOP(result),"a",offset++);
5447 l = aopGet(AOP(result),offset,FALSE,FALSE);
5449 emitcode("rlc","a");
5450 aopPut(AOP(result),"a",offset++);
5452 reAdjustPreg(AOP(result));
5454 emitcode("","%05d$:",tlbl1->key+100);
5455 emitcode("djnz","b,%05d$",tlbl->key+100);
5457 freeAsmop(left,NULL,ic,TRUE);
5458 freeAsmop(result,NULL,ic,TRUE);
5461 /*-----------------------------------------------------------------*/
5462 /* genrshOne - right shift a one byte quantity by known count */
5463 /*-----------------------------------------------------------------*/
5464 static void genrshOne (operand *result, operand *left,
5465 int shCount, int sign)
5467 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
5470 /*-----------------------------------------------------------------*/
5471 /* genrshTwo - right shift two bytes by known amount != 0 */
5472 /*-----------------------------------------------------------------*/
5473 static void genrshTwo (operand *result,operand *left,
5474 int shCount, int sign)
5476 /* if shCount >= 8 */
5480 shiftR1Left2Result(left, MSB16, result, LSB,
5483 movLeft2Result(left, MSB16, result, LSB, sign);
5484 addSign(result, MSB16, sign);
5487 /* 1 <= shCount <= 7 */
5489 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
5492 /*-----------------------------------------------------------------*/
5493 /* shiftRLong - shift right one long from left to result */
5494 /* offl = LSB or MSB16 */
5495 /*-----------------------------------------------------------------*/
5496 static void shiftRLong (operand *left, int offl,
5497 operand *result, int sign)
5500 emitcode("clr","c");
5501 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
5503 emitcode("mov","c,acc.7");
5504 emitcode("rrc","a");
5505 aopPut(AOP(result),"a",MSB32-offl);
5507 /* add sign of "a" */
5508 addSign(result, MSB32, sign);
5510 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
5511 emitcode("rrc","a");
5512 aopPut(AOP(result),"a",MSB24-offl);
5514 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
5515 emitcode("rrc","a");
5516 aopPut(AOP(result),"a",MSB16-offl);
5519 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
5520 emitcode("rrc","a");
5521 aopPut(AOP(result),"a",LSB);
5525 /*-----------------------------------------------------------------*/
5526 /* genrshFour - shift four byte by a known amount != 0 */
5527 /*-----------------------------------------------------------------*/
5528 static void genrshFour (operand *result, operand *left,
5529 int shCount, int sign)
5531 /* if shifting more that 3 bytes */
5532 if(shCount >= 24 ) {
5535 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
5537 movLeft2Result(left, MSB32, result, LSB, sign);
5538 addSign(result, MSB16, sign);
5540 else if(shCount >= 16){
5543 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
5545 movLeft2Result(left, MSB24, result, LSB, 0);
5546 movLeft2Result(left, MSB32, result, MSB16, sign);
5548 addSign(result, MSB24, sign);
5550 else if(shCount >= 8){
5553 shiftRLong(left, MSB16, result, sign);
5554 else if(shCount == 0){
5555 movLeft2Result(left, MSB16, result, LSB, 0);
5556 movLeft2Result(left, MSB24, result, MSB16, 0);
5557 movLeft2Result(left, MSB32, result, MSB24, sign);
5558 addSign(result, MSB32, sign);
5561 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
5562 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
5563 /* the last shift is signed */
5564 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
5565 addSign(result, MSB32, sign);
5568 else{ /* 1 <= shCount <= 7 */
5570 shiftRLong(left, LSB, result, sign);
5572 shiftRLong(result, LSB, result, sign);
5575 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
5576 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
5577 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
5582 /*-----------------------------------------------------------------*/
5583 /* genRightShiftLiteral - right shifting by known count */
5584 /*-----------------------------------------------------------------*/
5585 static void genRightShiftLiteral (operand *left,
5591 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5594 freeAsmop(right,NULL,ic,TRUE);
5596 aopOp(left,ic,FALSE);
5597 aopOp(result,ic,FALSE);
5600 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
5604 size = getDataSize(left);
5605 /* test the LEFT size !!! */
5607 /* I suppose that the left size >= result size */
5609 size = getDataSize(result);
5611 movLeft2Result(left, size, result, size, 0);
5614 else if(shCount >= (size * 8)){
5616 /* get sign in acc.7 */
5617 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
5618 addSign(result, LSB, sign);
5622 genrshOne (result,left,shCount,sign);
5626 genrshTwo (result,left,shCount,sign);
5630 genrshFour (result,left,shCount,sign);
5636 freeAsmop(left,NULL,ic,TRUE);
5637 freeAsmop(result,NULL,ic,TRUE);
5641 /*-----------------------------------------------------------------*/
5642 /* genSignedRightShift - right shift of signed number */
5643 /*-----------------------------------------------------------------*/
5644 static void genSignedRightShift (iCode *ic)
5646 operand *right, *left, *result;
5649 symbol *tlbl, *tlbl1 ;
5651 /* we do it the hard way put the shift count in b
5652 and loop thru preserving the sign */
5654 right = IC_RIGHT(ic);
5656 result = IC_RESULT(ic);
5658 aopOp(right,ic,FALSE);
5661 if ( AOP_TYPE(right) == AOP_LIT) {
5662 genRightShiftLiteral (left,right,result,ic,1);
5665 /* shift count is unknown then we have to form
5666 a loop get the loop count in B : Note: we take
5667 only the lower order byte since shifting
5668 more that 32 bits make no sense anyway, ( the
5669 largest size of an object can be only 32 bits ) */
5671 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5672 emitcode("inc","b");
5673 freeAsmop (right,NULL,ic,TRUE);
5674 aopOp(left,ic,FALSE);
5675 aopOp(result,ic,FALSE);
5677 /* now move the left to the result if they are not the
5679 if (!sameRegs(AOP(left),AOP(result)) &&
5680 AOP_SIZE(result) > 1) {
5682 size = AOP_SIZE(result);
5685 l = aopGet(AOP(left),offset,FALSE,TRUE);
5686 if (*l == '@' && IS_AOP_PREG(result)) {
5688 emitcode("mov","a,%s",l);
5689 aopPut(AOP(result),"a",offset);
5691 aopPut(AOP(result),l,offset);
5696 /* mov the highest order bit to OVR */
5697 tlbl = newiTempLabel(NULL);
5698 tlbl1= newiTempLabel(NULL);
5700 size = AOP_SIZE(result);
5702 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
5703 emitcode("rlc","a");
5704 emitcode("mov","ov,c");
5705 /* if it is only one byte then */
5707 l = aopGet(AOP(left),0,FALSE,FALSE);
5709 emitcode("sjmp","%05d$",tlbl1->key+100);
5710 emitcode("","%05d$:",tlbl->key+100);
5711 emitcode("mov","c,ov");
5712 emitcode("rrc","a");
5713 emitcode("","%05d$:",tlbl1->key+100);
5714 emitcode("djnz","b,%05d$",tlbl->key+100);
5715 aopPut(AOP(result),"a",0);
5719 reAdjustPreg(AOP(result));
5720 emitcode("sjmp","%05d$",tlbl1->key+100);
5721 emitcode("","%05d$:",tlbl->key+100);
5722 emitcode("mov","c,ov");
5724 l = aopGet(AOP(result),offset,FALSE,FALSE);
5726 emitcode("rrc","a");
5727 aopPut(AOP(result),"a",offset--);
5729 reAdjustPreg(AOP(result));
5730 emitcode("","%05d$:",tlbl1->key+100);
5731 emitcode("djnz","b,%05d$",tlbl->key+100);
5734 freeAsmop(left,NULL,ic,TRUE);
5735 freeAsmop(result,NULL,ic,TRUE);
5738 /*-----------------------------------------------------------------*/
5739 /* genRightShift - generate code for right shifting */
5740 /*-----------------------------------------------------------------*/
5741 static void genRightShift (iCode *ic)
5743 operand *right, *left, *result;
5747 symbol *tlbl, *tlbl1 ;
5749 /* if signed then we do it the hard way preserve the
5750 sign bit moving it inwards */
5751 retype = getSpec(operandType(IC_RESULT(ic)));
5753 if (!SPEC_USIGN(retype)) {
5754 genSignedRightShift (ic);
5758 /* signed & unsigned types are treated the same : i.e. the
5759 signed is NOT propagated inwards : quoting from the
5760 ANSI - standard : "for E1 >> E2, is equivalent to division
5761 by 2**E2 if unsigned or if it has a non-negative value,
5762 otherwise the result is implementation defined ", MY definition
5763 is that the sign does not get propagated */
5765 right = IC_RIGHT(ic);
5767 result = IC_RESULT(ic);
5769 aopOp(right,ic,FALSE);
5771 /* if the shift count is known then do it
5772 as efficiently as possible */
5773 if (AOP_TYPE(right) == AOP_LIT) {
5774 genRightShiftLiteral (left,right,result,ic, 0);
5778 /* shift count is unknown then we have to form
5779 a loop get the loop count in B : Note: we take
5780 only the lower order byte since shifting
5781 more that 32 bits make no sense anyway, ( the
5782 largest size of an object can be only 32 bits ) */
5784 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5785 emitcode("inc","b");
5786 freeAsmop (right,NULL,ic,TRUE);
5787 aopOp(left,ic,FALSE);
5788 aopOp(result,ic,FALSE);
5790 /* now move the left to the result if they are not the
5792 if (!sameRegs(AOP(left),AOP(result)) &&
5793 AOP_SIZE(result) > 1) {
5795 size = AOP_SIZE(result);
5798 l = aopGet(AOP(left),offset,FALSE,TRUE);
5799 if (*l == '@' && IS_AOP_PREG(result)) {
5801 emitcode("mov","a,%s",l);
5802 aopPut(AOP(result),"a",offset);
5804 aopPut(AOP(result),l,offset);
5809 tlbl = newiTempLabel(NULL);
5810 tlbl1= newiTempLabel(NULL);
5811 size = AOP_SIZE(result);
5814 /* if it is only one byte then */
5816 l = aopGet(AOP(left),0,FALSE,FALSE);
5818 emitcode("sjmp","%05d$",tlbl1->key+100);
5819 emitcode("","%05d$:",tlbl->key+100);
5821 emitcode("rrc","a");
5822 emitcode("","%05d$:",tlbl1->key+100);
5823 emitcode("djnz","b,%05d$",tlbl->key+100);
5824 aopPut(AOP(result),"a",0);
5828 reAdjustPreg(AOP(result));
5829 emitcode("sjmp","%05d$",tlbl1->key+100);
5830 emitcode("","%05d$:",tlbl->key+100);
5833 l = aopGet(AOP(result),offset,FALSE,FALSE);
5835 emitcode("rrc","a");
5836 aopPut(AOP(result),"a",offset--);
5838 reAdjustPreg(AOP(result));
5840 emitcode("","%05d$:",tlbl1->key+100);
5841 emitcode("djnz","b,%05d$",tlbl->key+100);
5844 freeAsmop(left,NULL,ic,TRUE);
5845 freeAsmop(result,NULL,ic,TRUE);
5848 /*-----------------------------------------------------------------*/
5849 /* genUnpackBits - generates code for unpacking bits */
5850 /*-----------------------------------------------------------------*/
5851 static void genUnpackBits (operand *result, char *rname, int ptype)
5858 etype = getSpec(operandType(result));
5860 /* read the first byte */
5865 emitcode("mov","a,@%s",rname);
5869 emitcode("movx","a,@%s",rname);
5873 emitcode("movx","a,@dptr");
5877 emitcode("clr","a");
5878 emitcode("movc","a","@a+dptr");
5882 emitcode("lcall","__gptrget");
5886 /* if we have bitdisplacement then it fits */
5887 /* into this byte completely or if length is */
5888 /* less than a byte */
5889 if ((shCnt = SPEC_BSTR(etype)) ||
5890 (SPEC_BLEN(etype) <= 8)) {
5892 /* shift right acc */
5895 emitcode("anl","a,#0x%02x",
5896 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
5897 aopPut(AOP(result),"a",offset);
5901 /* bit field did not fit in a byte */
5902 rlen = SPEC_BLEN(etype) - 8;
5903 aopPut(AOP(result),"a",offset++);
5910 emitcode("inc","%s",rname);
5911 emitcode("mov","a,@%s",rname);
5915 emitcode("inc","%s",rname);
5916 emitcode("movx","a,@%s",rname);
5920 emitcode("inc","dptr");
5921 emitcode("movx","a,@dptr");
5925 emitcode("clr","a");
5926 emitcode("inc","dptr");
5927 emitcode("movc","a","@a+dptr");
5931 emitcode("inc","dptr");
5932 emitcode("lcall","__gptrget");
5937 /* if we are done */
5941 aopPut(AOP(result),"a",offset++);
5946 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
5947 aopPut(AOP(result),"a",offset);
5954 /*-----------------------------------------------------------------*/
5955 /* genDataPointerGet - generates code when ptr offset is known */
5956 /*-----------------------------------------------------------------*/
5957 static void genDataPointerGet (operand *left,
5963 int size , offset = 0;
5964 aopOp(result,ic,TRUE);
5966 /* get the string representation of the name */
5967 l = aopGet(AOP(left),0,FALSE,TRUE);
5968 size = AOP_SIZE(result);
5971 sprintf(buffer,"(%s + %d)",l+1,offset);
5973 sprintf(buffer,"%s",l+1);
5974 aopPut(AOP(result),buffer,offset++);
5977 freeAsmop(left,NULL,ic,TRUE);
5978 freeAsmop(result,NULL,ic,TRUE);
5981 /*-----------------------------------------------------------------*/
5982 /* genNearPointerGet - emitcode for near pointer fetch */
5983 /*-----------------------------------------------------------------*/
5984 static void genNearPointerGet (operand *left,
5991 link *rtype, *retype;
5992 link *ltype = operandType(left);
5995 rtype = operandType(result);
5996 retype= getSpec(rtype);
5998 aopOp(left,ic,FALSE);
6000 /* if left is rematerialisable and
6001 result is not bit variable type and
6002 the left is pointer to data space i.e
6003 lower 128 bytes of space */
6004 if (AOP_TYPE(left) == AOP_IMMD &&
6005 !IS_BITVAR(retype) &&
6006 DCL_TYPE(ltype) == POINTER) {
6007 genDataPointerGet (left,result,ic);
6011 /* if the value is already in a pointer register
6012 then don't need anything more */
6013 if (!AOP_INPREG(AOP(left))) {
6014 /* otherwise get a free pointer register */
6016 preg = getFreePtr(ic,&aop,FALSE);
6017 emitcode("mov","%s,%s",
6019 aopGet(AOP(left),0,FALSE,TRUE));
6020 rname = preg->name ;
6022 rname = aopGet(AOP(left),0,FALSE,FALSE);
6024 freeAsmop(left,NULL,ic,TRUE);
6025 aopOp (result,ic,FALSE);
6027 /* if bitfield then unpack the bits */
6028 if (IS_BITVAR(retype))
6029 genUnpackBits (result,rname,POINTER);
6031 /* we have can just get the values */
6032 int size = AOP_SIZE(result);
6036 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6038 emitcode("mov","a,@%s",rname);
6039 aopPut(AOP(result),"a",offset);
6041 sprintf(buffer,"@%s",rname);
6042 aopPut(AOP(result),buffer,offset);
6046 emitcode("inc","%s",rname);
6050 /* now some housekeeping stuff */
6052 /* we had to allocate for this iCode */
6053 freeAsmop(NULL,aop,ic,TRUE);
6055 /* we did not allocate which means left
6056 already in a pointer register, then
6057 if size > 0 && this could be used again
6058 we have to point it back to where it
6060 if (AOP_SIZE(result) > 1 &&
6061 !OP_SYMBOL(left)->remat &&
6062 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6064 int size = AOP_SIZE(result) - 1;
6066 emitcode("dec","%s",rname);
6071 freeAsmop(result,NULL,ic,TRUE);
6075 /*-----------------------------------------------------------------*/
6076 /* genPagedPointerGet - emitcode for paged pointer fetch */
6077 /*-----------------------------------------------------------------*/
6078 static void genPagedPointerGet (operand *left,
6085 link *rtype, *retype;
6087 rtype = operandType(result);
6088 retype= getSpec(rtype);
6090 aopOp(left,ic,FALSE);
6092 /* if the value is already in a pointer register
6093 then don't need anything more */
6094 if (!AOP_INPREG(AOP(left))) {
6095 /* otherwise get a free pointer register */
6097 preg = getFreePtr(ic,&aop,FALSE);
6098 emitcode("mov","%s,%s",
6100 aopGet(AOP(left),0,FALSE,TRUE));
6101 rname = preg->name ;
6103 rname = aopGet(AOP(left),0,FALSE,FALSE);
6105 freeAsmop(left,NULL,ic,TRUE);
6106 aopOp (result,ic,FALSE);
6108 /* if bitfield then unpack the bits */
6109 if (IS_BITVAR(retype))
6110 genUnpackBits (result,rname,PPOINTER);
6112 /* we have can just get the values */
6113 int size = AOP_SIZE(result);
6118 emitcode("movx","a,@%s",rname);
6119 aopPut(AOP(result),"a",offset);
6124 emitcode("inc","%s",rname);
6128 /* now some housekeeping stuff */
6130 /* we had to allocate for this iCode */
6131 freeAsmop(NULL,aop,ic,TRUE);
6133 /* we did not allocate which means left
6134 already in a pointer register, then
6135 if size > 0 && this could be used again
6136 we have to point it back to where it
6138 if (AOP_SIZE(result) > 1 &&
6139 !OP_SYMBOL(left)->remat &&
6140 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6142 int size = AOP_SIZE(result) - 1;
6144 emitcode("dec","%s",rname);
6149 freeAsmop(result,NULL,ic,TRUE);
6154 /*-----------------------------------------------------------------*/
6155 /* genFarPointerGet - gget value from far space */
6156 /*-----------------------------------------------------------------*/
6157 static void genFarPointerGet (operand *left,
6158 operand *result, iCode *ic)
6161 link *retype = getSpec(operandType(result));
6163 aopOp(left,ic,FALSE);
6165 /* if the operand is already in dptr
6166 then we do nothing else we move the value to dptr */
6167 if (AOP_TYPE(left) != AOP_STR) {
6168 /* if this is remateriazable */
6169 if (AOP_TYPE(left) == AOP_IMMD)
6170 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6171 else { /* we need to get it byte by byte */
6172 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6173 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6174 if (options.model == MODEL_FLAT24)
6176 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6180 /* so dptr know contains the address */
6181 freeAsmop(left,NULL,ic,TRUE);
6182 aopOp(result,ic,FALSE);
6184 /* if bit then unpack */
6185 if (IS_BITVAR(retype))
6186 genUnpackBits(result,"dptr",FPOINTER);
6188 size = AOP_SIZE(result);
6192 emitcode("movx","a,@dptr");
6193 aopPut(AOP(result),"a",offset++);
6195 emitcode("inc","dptr");
6199 freeAsmop(result,NULL,ic,TRUE);
6202 /*-----------------------------------------------------------------*/
6203 /* emitcodePointerGet - gget value from code space */
6204 /*-----------------------------------------------------------------*/
6205 static void emitcodePointerGet (operand *left,
6206 operand *result, iCode *ic)
6209 link *retype = getSpec(operandType(result));
6211 aopOp(left,ic,FALSE);
6213 /* if the operand is already in dptr
6214 then we do nothing else we move the value to dptr */
6215 if (AOP_TYPE(left) != AOP_STR) {
6216 /* if this is remateriazable */
6217 if (AOP_TYPE(left) == AOP_IMMD)
6218 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6219 else { /* we need to get it byte by byte */
6220 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6221 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6222 if (options.model == MODEL_FLAT24)
6224 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6228 /* so dptr know contains the address */
6229 freeAsmop(left,NULL,ic,TRUE);
6230 aopOp(result,ic,FALSE);
6232 /* if bit then unpack */
6233 if (IS_BITVAR(retype))
6234 genUnpackBits(result,"dptr",CPOINTER);
6236 size = AOP_SIZE(result);
6240 emitcode("clr","a");
6241 emitcode("movc","a,@a+dptr");
6242 aopPut(AOP(result),"a",offset++);
6244 emitcode("inc","dptr");
6248 freeAsmop(result,NULL,ic,TRUE);
6251 /*-----------------------------------------------------------------*/
6252 /* genGenPointerGet - gget value from generic pointer space */
6253 /*-----------------------------------------------------------------*/
6254 static void genGenPointerGet (operand *left,
6255 operand *result, iCode *ic)
6258 link *retype = getSpec(operandType(result));
6260 aopOp(left,ic,FALSE);
6262 /* if the operand is already in dptr
6263 then we do nothing else we move the value to dptr */
6264 if (AOP_TYPE(left) != AOP_STR) {
6265 /* if this is remateriazable */
6266 if (AOP_TYPE(left) == AOP_IMMD) {
6267 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6268 emitcode("mov","b,#%d",pointerCode(retype));
6270 else { /* we need to get it byte by byte */
6271 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6272 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6273 if (options.model == MODEL_FLAT24)
6275 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6276 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
6280 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
6284 /* so dptr know contains the address */
6285 freeAsmop(left,NULL,ic,TRUE);
6286 aopOp(result,ic,FALSE);
6288 /* if bit then unpack */
6289 if (IS_BITVAR(retype))
6290 genUnpackBits(result,"dptr",GPOINTER);
6292 size = AOP_SIZE(result);
6296 emitcode("lcall","__gptrget");
6297 aopPut(AOP(result),"a",offset++);
6299 emitcode("inc","dptr");
6303 freeAsmop(result,NULL,ic,TRUE);
6306 /*-----------------------------------------------------------------*/
6307 /* genPointerGet - generate code for pointer get */
6308 /*-----------------------------------------------------------------*/
6309 static void genPointerGet (iCode *ic)
6311 operand *left, *result ;
6316 result = IC_RESULT(ic) ;
6318 /* depending on the type of pointer we need to
6319 move it to the correct pointer register */
6320 type = operandType(left);
6321 etype = getSpec(type);
6322 /* if left is of type of pointer then it is simple */
6323 if (IS_PTR(type) && !IS_FUNC(type->next))
6324 p_type = DCL_TYPE(type);
6326 /* we have to go by the storage class */
6327 p_type = PTR_TYPE(SPEC_OCLS(etype));
6329 /* if (SPEC_OCLS(etype)->codesp ) { */
6330 /* p_type = CPOINTER ; */
6333 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6334 /* p_type = FPOINTER ; */
6336 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6337 /* p_type = PPOINTER; */
6339 /* if (SPEC_OCLS(etype) == idata ) */
6340 /* p_type = IPOINTER; */
6342 /* p_type = POINTER ; */
6345 /* now that we have the pointer type we assign
6346 the pointer values */
6351 genNearPointerGet (left,result,ic);
6355 genPagedPointerGet(left,result,ic);
6359 genFarPointerGet (left,result,ic);
6363 emitcodePointerGet (left,result,ic);
6367 genGenPointerGet (left,result,ic);
6373 /*-----------------------------------------------------------------*/
6374 /* genPackBits - generates code for packed bit storage */
6375 /*-----------------------------------------------------------------*/
6376 static void genPackBits (link *etype ,
6378 char *rname, int p_type)
6386 blen = SPEC_BLEN(etype);
6387 bstr = SPEC_BSTR(etype);
6389 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6392 /* if the bit lenth is less than or */
6393 /* it exactly fits a byte then */
6394 if (SPEC_BLEN(etype) <= 8 ) {
6395 shCount = SPEC_BSTR(etype) ;
6397 /* shift left acc */
6400 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6405 emitcode ("mov","b,a");
6406 emitcode("mov","a,@%s",rname);
6410 emitcode ("mov","b,a");
6411 emitcode("movx","a,@dptr");
6415 emitcode ("push","b");
6416 emitcode ("push","acc");
6417 emitcode ("lcall","__gptrget");
6418 emitcode ("pop","b");
6422 emitcode ("anl","a,#0x%02x",(unsigned char)
6423 ((unsigned char)(0xFF << (blen+bstr)) |
6424 (unsigned char)(0xFF >> (8-bstr)) ) );
6425 emitcode ("orl","a,b");
6426 if (p_type == GPOINTER)
6427 emitcode("pop","b");
6433 emitcode("mov","@%s,a",rname);
6437 emitcode("movx","@dptr,a");
6441 emitcode("lcall","__gptrput");
6446 if ( SPEC_BLEN(etype) <= 8 )
6449 emitcode("inc","%s",rname);
6450 rLen = SPEC_BLEN(etype) ;
6452 /* now generate for lengths greater than one byte */
6455 l = aopGet(AOP(right),offset++,FALSE,TRUE);
6465 emitcode("mov","@%s,a",rname);
6467 emitcode("mov","@%s,%s",rname,l);
6472 emitcode("movx","@dptr,a");
6477 emitcode("lcall","__gptrput");
6480 emitcode ("inc","%s",rname);
6485 /* last last was not complete */
6487 /* save the byte & read byte */
6490 emitcode ("mov","b,a");
6491 emitcode("mov","a,@%s",rname);
6495 emitcode ("mov","b,a");
6496 emitcode("movx","a,@dptr");
6500 emitcode ("push","b");
6501 emitcode ("push","acc");
6502 emitcode ("lcall","__gptrget");
6503 emitcode ("pop","b");
6507 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
6508 emitcode ("orl","a,b");
6511 if (p_type == GPOINTER)
6512 emitcode("pop","b");
6517 emitcode("mov","@%s,a",rname);
6521 emitcode("movx","@dptr,a");
6525 emitcode("lcall","__gptrput");
6529 /*-----------------------------------------------------------------*/
6530 /* genDataPointerSet - remat pointer to data space */
6531 /*-----------------------------------------------------------------*/
6532 static void genDataPointerSet(operand *right,
6536 int size, offset = 0 ;
6537 char *l, buffer[256];
6539 aopOp(right,ic,FALSE);
6541 l = aopGet(AOP(result),0,FALSE,TRUE);
6542 size = AOP_SIZE(right);
6545 sprintf(buffer,"(%s + %d)",l+1,offset);
6547 sprintf(buffer,"%s",l+1);
6548 emitcode("mov","%s,%s",buffer,
6549 aopGet(AOP(right),offset++,FALSE,FALSE));
6552 freeAsmop(right,NULL,ic,TRUE);
6553 freeAsmop(result,NULL,ic,TRUE);
6556 /*-----------------------------------------------------------------*/
6557 /* genNearPointerSet - emitcode for near pointer put */
6558 /*-----------------------------------------------------------------*/
6559 static void genNearPointerSet (operand *right,
6567 link *ptype = operandType(result);
6569 retype= getSpec(operandType(right));
6571 aopOp(result,ic,FALSE);
6573 /* if the result is rematerializable &
6574 in data space & not a bit variable */
6575 if (AOP_TYPE(result) == AOP_IMMD &&
6576 DCL_TYPE(ptype) == POINTER &&
6577 !IS_BITVAR(retype)) {
6578 genDataPointerSet (right,result,ic);
6582 /* if the value is already in a pointer register
6583 then don't need anything more */
6584 if (!AOP_INPREG(AOP(result))) {
6585 /* otherwise get a free pointer register */
6587 preg = getFreePtr(ic,&aop,FALSE);
6588 emitcode("mov","%s,%s",
6590 aopGet(AOP(result),0,FALSE,TRUE));
6591 rname = preg->name ;
6593 rname = aopGet(AOP(result),0,FALSE,FALSE);
6595 freeAsmop(result,NULL,ic,TRUE);
6596 aopOp (right,ic,FALSE);
6598 /* if bitfield then unpack the bits */
6599 if (IS_BITVAR(retype))
6600 genPackBits (retype,right,rname,POINTER);
6602 /* we have can just get the values */
6603 int size = AOP_SIZE(right);
6607 l = aopGet(AOP(right),offset,FALSE,TRUE);
6610 emitcode("mov","@%s,a",rname);
6612 emitcode("mov","@%s,%s",rname,l);
6614 emitcode("inc","%s",rname);
6619 /* now some housekeeping stuff */
6621 /* we had to allocate for this iCode */
6622 freeAsmop(NULL,aop,ic,TRUE);
6624 /* we did not allocate which means left
6625 already in a pointer register, then
6626 if size > 0 && this could be used again
6627 we have to point it back to where it
6629 if (AOP_SIZE(right) > 1 &&
6630 !OP_SYMBOL(result)->remat &&
6631 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6633 int size = AOP_SIZE(right) - 1;
6635 emitcode("dec","%s",rname);
6640 freeAsmop(right,NULL,ic,TRUE);
6645 /*-----------------------------------------------------------------*/
6646 /* genPagedPointerSet - emitcode for Paged pointer put */
6647 /*-----------------------------------------------------------------*/
6648 static void genPagedPointerSet (operand *right,
6657 retype= getSpec(operandType(right));
6659 aopOp(result,ic,FALSE);
6661 /* if the value is already in a pointer register
6662 then don't need anything more */
6663 if (!AOP_INPREG(AOP(result))) {
6664 /* otherwise get a free pointer register */
6666 preg = getFreePtr(ic,&aop,FALSE);
6667 emitcode("mov","%s,%s",
6669 aopGet(AOP(result),0,FALSE,TRUE));
6670 rname = preg->name ;
6672 rname = aopGet(AOP(result),0,FALSE,FALSE);
6674 freeAsmop(result,NULL,ic,TRUE);
6675 aopOp (right,ic,FALSE);
6677 /* if bitfield then unpack the bits */
6678 if (IS_BITVAR(retype))
6679 genPackBits (retype,right,rname,PPOINTER);
6681 /* we have can just get the values */
6682 int size = AOP_SIZE(right);
6686 l = aopGet(AOP(right),offset,FALSE,TRUE);
6689 emitcode("movx","@%s,a",rname);
6692 emitcode("inc","%s",rname);
6698 /* now some housekeeping stuff */
6700 /* we had to allocate for this iCode */
6701 freeAsmop(NULL,aop,ic,TRUE);
6703 /* we did not allocate which means left
6704 already in a pointer register, then
6705 if size > 0 && this could be used again
6706 we have to point it back to where it
6708 if (AOP_SIZE(right) > 1 &&
6709 !OP_SYMBOL(result)->remat &&
6710 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6712 int size = AOP_SIZE(right) - 1;
6714 emitcode("dec","%s",rname);
6719 freeAsmop(right,NULL,ic,TRUE);
6724 /*-----------------------------------------------------------------*/
6725 /* genFarPointerSet - set value from far space */
6726 /*-----------------------------------------------------------------*/
6727 static void genFarPointerSet (operand *right,
6728 operand *result, iCode *ic)
6731 link *retype = getSpec(operandType(right));
6733 aopOp(result,ic,FALSE);
6735 /* if the operand is already in dptr
6736 then we do nothing else we move the value to dptr */
6737 if (AOP_TYPE(result) != AOP_STR) {
6738 /* if this is remateriazable */
6739 if (AOP_TYPE(result) == AOP_IMMD)
6740 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6741 else { /* we need to get it byte by byte */
6742 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6743 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6744 if (options.model == MODEL_FLAT24)
6746 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6750 /* so dptr know contains the address */
6751 freeAsmop(result,NULL,ic,TRUE);
6752 aopOp(right,ic,FALSE);
6754 /* if bit then unpack */
6755 if (IS_BITVAR(retype))
6756 genPackBits(retype,right,"dptr",FPOINTER);
6758 size = AOP_SIZE(right);
6762 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6764 emitcode("movx","@dptr,a");
6766 emitcode("inc","dptr");
6770 freeAsmop(right,NULL,ic,TRUE);
6773 /*-----------------------------------------------------------------*/
6774 /* genGenPointerSet - set value from generic pointer space */
6775 /*-----------------------------------------------------------------*/
6776 static void genGenPointerSet (operand *right,
6777 operand *result, iCode *ic)
6780 link *retype = getSpec(operandType(right));
6782 aopOp(result,ic,FALSE);
6784 /* if the operand is already in dptr
6785 then we do nothing else we move the value to dptr */
6786 if (AOP_TYPE(result) != AOP_STR) {
6787 /* if this is remateriazable */
6788 if (AOP_TYPE(result) == AOP_IMMD) {
6789 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6790 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
6792 else { /* we need to get it byte by byte */
6793 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6794 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6795 if (options.model == MODEL_FLAT24)
6797 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6798 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
6802 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
6806 /* so dptr know contains the address */
6807 freeAsmop(result,NULL,ic,TRUE);
6808 aopOp(right,ic,FALSE);
6810 /* if bit then unpack */
6811 if (IS_BITVAR(retype))
6812 genPackBits(retype,right,"dptr",GPOINTER);
6814 size = AOP_SIZE(right);
6818 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6820 emitcode("lcall","__gptrput");
6822 emitcode("inc","dptr");
6826 freeAsmop(right,NULL,ic,TRUE);
6829 /*-----------------------------------------------------------------*/
6830 /* genPointerSet - stores the value into a pointer location */
6831 /*-----------------------------------------------------------------*/
6832 static void genPointerSet (iCode *ic)
6834 operand *right, *result ;
6838 right = IC_RIGHT(ic);
6839 result = IC_RESULT(ic) ;
6841 /* depending on the type of pointer we need to
6842 move it to the correct pointer register */
6843 type = operandType(result);
6844 etype = getSpec(type);
6845 /* if left is of type of pointer then it is simple */
6846 if (IS_PTR(type) && !IS_FUNC(type->next)) {
6847 p_type = DCL_TYPE(type);
6850 /* we have to go by the storage class */
6851 p_type = PTR_TYPE(SPEC_OCLS(etype));
6853 /* if (SPEC_OCLS(etype)->codesp ) { */
6854 /* p_type = CPOINTER ; */
6857 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6858 /* p_type = FPOINTER ; */
6860 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6861 /* p_type = PPOINTER ; */
6863 /* if (SPEC_OCLS(etype) == idata ) */
6864 /* p_type = IPOINTER ; */
6866 /* p_type = POINTER ; */
6869 /* now that we have the pointer type we assign
6870 the pointer values */
6875 genNearPointerSet (right,result,ic);
6879 genPagedPointerSet (right,result,ic);
6883 genFarPointerSet (right,result,ic);
6887 genGenPointerSet (right,result,ic);
6893 /*-----------------------------------------------------------------*/
6894 /* genIfx - generate code for Ifx statement */
6895 /*-----------------------------------------------------------------*/
6896 static void genIfx (iCode *ic, iCode *popIc)
6898 operand *cond = IC_COND(ic);
6901 aopOp(cond,ic,FALSE);
6903 /* get the value into acc */
6904 if (AOP_TYPE(cond) != AOP_CRY)
6908 /* the result is now in the accumulator */
6909 freeAsmop(cond,NULL,ic,TRUE);
6911 /* if there was something to be popped then do it */
6915 /* if the condition is a bit variable */
6916 if (isbit && IS_ITEMP(cond) &&
6918 genIfxJump(ic,SPIL_LOC(cond)->rname);
6920 if (isbit && !IS_ITEMP(cond))
6921 genIfxJump(ic,OP_SYMBOL(cond)->rname);
6928 /*-----------------------------------------------------------------*/
6929 /* genAddrOf - generates code for address of */
6930 /*-----------------------------------------------------------------*/
6931 static void genAddrOf (iCode *ic)
6933 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
6936 aopOp(IC_RESULT(ic),ic,FALSE);
6938 /* if the operand is on the stack then we
6939 need to get the stack offset of this
6942 /* if it has an offset then we need to compute
6945 emitcode("mov","a,_bp");
6946 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
6947 aopPut(AOP(IC_RESULT(ic)),"a",0);
6949 /* we can just move _bp */
6950 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
6952 /* fill the result with zero */
6953 size = AOP_SIZE(IC_RESULT(ic)) - 1;
6956 if (options.stack10bit && size < (FPTRSIZE - 1))
6959 "*** warning: pointer to stack var truncated.\n");
6966 if (options.stack10bit && offset == 2)
6968 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
6972 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
6979 /* object not on stack then we need the name */
6980 size = AOP_SIZE(IC_RESULT(ic));
6984 char s[SDCC_NAME_MAX];
6986 sprintf(s,"#(%s >> %d)",
6990 sprintf(s,"#%s",sym->rname);
6991 aopPut(AOP(IC_RESULT(ic)),s,offset++);
6995 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
6999 /*-----------------------------------------------------------------*/
7000 /* genFarFarAssign - assignment when both are in far space */
7001 /*-----------------------------------------------------------------*/
7002 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7004 int size = AOP_SIZE(right);
7007 /* first push the right side on to the stack */
7009 l = aopGet(AOP(right),offset++,FALSE,FALSE);
7011 emitcode ("push","acc");
7014 freeAsmop(right,NULL,ic,FALSE);
7015 /* now assign DPTR to result */
7016 aopOp(result,ic,FALSE);
7017 size = AOP_SIZE(result);
7019 emitcode ("pop","acc");
7020 aopPut(AOP(result),"a",--offset);
7022 freeAsmop(result,NULL,ic,FALSE);
7026 /*-----------------------------------------------------------------*/
7027 /* genAssign - generate code for assignment */
7028 /*-----------------------------------------------------------------*/
7029 static void genAssign (iCode *ic)
7031 operand *result, *right;
7033 unsigned long lit = 0L;
7035 result = IC_RESULT(ic);
7036 right = IC_RIGHT(ic) ;
7038 /* if they are the same */
7039 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7042 aopOp(right,ic,FALSE);
7044 /* special case both in far space */
7045 if ((AOP_TYPE(right) == AOP_DPTR ||
7046 AOP_TYPE(right) == AOP_DPTR2) &&
7047 IS_TRUE_SYMOP(result) &&
7048 isOperandInFarSpace(result)) {
7050 genFarFarAssign (result,right,ic);
7054 aopOp(result,ic,TRUE);
7056 /* if they are the same registers */
7057 if (sameRegs(AOP(right),AOP(result)))
7060 /* if the result is a bit */
7061 if (AOP_TYPE(result) == AOP_CRY) {
7063 /* if the right size is a literal then
7064 we know what the value is */
7065 if (AOP_TYPE(right) == AOP_LIT) {
7066 if (((int) operandLitValue(right)))
7067 aopPut(AOP(result),one,0);
7069 aopPut(AOP(result),zero,0);
7073 /* the right is also a bit variable */
7074 if (AOP_TYPE(right) == AOP_CRY) {
7075 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7076 aopPut(AOP(result),"c",0);
7082 aopPut(AOP(result),"a",0);
7086 /* bit variables done */
7088 size = AOP_SIZE(result);
7090 if(AOP_TYPE(right) == AOP_LIT)
7091 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7093 (AOP_TYPE(result) != AOP_REG) &&
7094 (AOP_TYPE(right) == AOP_LIT) &&
7095 !IS_FLOAT(operandType(right)) &&
7097 emitcode("clr","a");
7099 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7100 aopPut(AOP(result),"a",size);
7103 aopGet(AOP(right),size,FALSE,FALSE),
7109 aopGet(AOP(right),offset,FALSE,FALSE),
7116 freeAsmop (right,NULL,ic,FALSE);
7117 freeAsmop (result,NULL,ic,TRUE);
7120 /*-----------------------------------------------------------------*/
7121 /* genJumpTab - genrates code for jump table */
7122 /*-----------------------------------------------------------------*/
7123 static void genJumpTab (iCode *ic)
7128 aopOp(IC_JTCOND(ic),ic,FALSE);
7129 /* get the condition into accumulator */
7130 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
7132 /* multiply by three */
7133 emitcode("add","a,acc");
7134 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
7135 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7137 jtab = newiTempLabel(NULL);
7138 emitcode("mov","dptr,#%05d$",jtab->key+100);
7139 emitcode("jmp","@a+dptr");
7140 emitcode("","%05d$:",jtab->key+100);
7141 /* now generate the jump labels */
7142 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
7143 jtab = setNextItem(IC_JTLABELS(ic)))
7144 emitcode("ljmp","%05d$",jtab->key+100);
7148 /*-----------------------------------------------------------------*/
7149 /* genCast - gen code for casting */
7150 /*-----------------------------------------------------------------*/
7151 static void genCast (iCode *ic)
7153 operand *result = IC_RESULT(ic);
7154 link *ctype = operandType(IC_LEFT(ic));
7155 operand *right = IC_RIGHT(ic);
7158 /* if they are equivalent then do nothing */
7159 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
7162 aopOp(right,ic,FALSE) ;
7163 aopOp(result,ic,FALSE);
7165 /* if the result is a bit */
7166 if (AOP_TYPE(result) == AOP_CRY) {
7167 /* if the right size is a literal then
7168 we know what the value is */
7169 if (AOP_TYPE(right) == AOP_LIT) {
7170 if (((int) operandLitValue(right)))
7171 aopPut(AOP(result),one,0);
7173 aopPut(AOP(result),zero,0);
7178 /* the right is also a bit variable */
7179 if (AOP_TYPE(right) == AOP_CRY) {
7180 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7181 aopPut(AOP(result),"c",0);
7187 aopPut(AOP(result),"a",0);
7191 /* if they are the same size : or less */
7192 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
7194 /* if they are in the same place */
7195 if (sameRegs(AOP(right),AOP(result)))
7198 /* if they in different places then copy */
7199 size = AOP_SIZE(result);
7203 aopGet(AOP(right),offset,FALSE,FALSE),
7211 /* if the result is of type pointer */
7212 if (IS_PTR(ctype)) {
7215 link *type = operandType(right);
7216 link *etype = getSpec(type);
7218 /* pointer to generic pointer */
7219 if (IS_GENPTR(ctype)) {
7223 p_type = DCL_TYPE(type);
7225 /* we have to go by the storage class */
7226 p_type = PTR_TYPE(SPEC_OCLS(etype));
7228 /* if (SPEC_OCLS(etype)->codesp ) */
7229 /* p_type = CPOINTER ; */
7231 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7232 /* p_type = FPOINTER ; */
7234 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7235 /* p_type = PPOINTER; */
7237 /* if (SPEC_OCLS(etype) == idata ) */
7238 /* p_type = IPOINTER ; */
7240 /* p_type = POINTER ; */
7243 /* the first two bytes are known */
7244 size = GPTRSIZE - 1;
7248 aopGet(AOP(right),offset,FALSE,FALSE),
7252 /* the last byte depending on type */
7269 /* this should never happen */
7270 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7271 "got unknown pointer type");
7274 aopPut(AOP(result),l, GPTRSIZE - 1);
7278 /* just copy the pointers */
7279 size = AOP_SIZE(result);
7283 aopGet(AOP(right),offset,FALSE,FALSE),
7290 /* so we now know that the size of destination is greater
7291 than the size of the source */
7292 /* we move to result for the size of source */
7293 size = AOP_SIZE(right);
7297 aopGet(AOP(right),offset,FALSE,FALSE),
7302 /* now depending on the sign of the destination */
7303 size = AOP_SIZE(result) - AOP_SIZE(right);
7304 /* if unsigned or not an integral type */
7305 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
7307 aopPut(AOP(result),zero,offset++);
7309 /* we need to extend the sign :{ */
7310 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
7313 emitcode("rlc","a");
7314 emitcode("subb","a,acc");
7316 aopPut(AOP(result),"a",offset++);
7319 /* we are done hurray !!!! */
7322 freeAsmop(right,NULL,ic,TRUE);
7323 freeAsmop(result,NULL,ic,TRUE);
7327 /*-----------------------------------------------------------------*/
7328 /* genDjnz - generate decrement & jump if not zero instrucion */
7329 /*-----------------------------------------------------------------*/
7330 static int genDjnz (iCode *ic, iCode *ifx)
7336 /* if the if condition has a false label
7337 then we cannot save */
7341 /* if the minus is not of the form
7343 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
7344 !IS_OP_LITERAL(IC_RIGHT(ic)))
7347 if (operandLitValue(IC_RIGHT(ic)) != 1)
7350 /* if the size of this greater than one then no
7352 if (getSize(operandType(IC_RESULT(ic))) > 1)
7355 /* otherwise we can save BIG */
7356 lbl = newiTempLabel(NULL);
7357 lbl1= newiTempLabel(NULL);
7359 aopOp(IC_RESULT(ic),ic,FALSE);
7361 if (IS_AOP_PREG(IC_RESULT(ic))) {
7362 emitcode("dec","%s",
7363 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7364 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7365 emitcode("jnz","%05d$",lbl->key+100);
7367 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
7370 emitcode ("sjmp","%05d$",lbl1->key+100);
7371 emitcode ("","%05d$:",lbl->key+100);
7372 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
7373 emitcode ("","%05d$:",lbl1->key+100);
7375 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7380 /*-----------------------------------------------------------------*/
7381 /* genReceive - generate code for a receive iCode */
7382 /*-----------------------------------------------------------------*/
7383 static void genReceive (iCode *ic)
7385 if (isOperandInFarSpace(IC_RESULT(ic)) &&
7386 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
7387 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
7389 int size = getSize(operandType(IC_RESULT(ic)));
7390 int offset = fReturnSize - size;
7392 emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
7393 fReturn[fReturnSize - offset - 1] : "acc"));
7396 aopOp(IC_RESULT(ic),ic,FALSE);
7397 size = AOP_SIZE(IC_RESULT(ic));
7400 emitcode ("pop","acc");
7401 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
7406 aopOp(IC_RESULT(ic),ic,FALSE);
7408 assignResultValue(IC_RESULT(ic));
7411 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7414 /*-----------------------------------------------------------------*/
7415 /* gen51Code - generate code for 8051 based controllers */
7416 /*-----------------------------------------------------------------*/
7417 void gen51Code (iCode *lic)
7422 lineHead = lineCurr = NULL;
7424 /* if debug information required */
7425 /* if (options.debug && currFunc) { */
7427 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
7429 if (IS_STATIC(currFunc->etype))
7430 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
7432 emitcode("","G$%s$0$0 ==.",currFunc->name);
7435 /* stack pointer name */
7436 if (options.useXstack)
7442 for (ic = lic ; ic ; ic = ic->next ) {
7444 if ( cln != ic->lineno ) {
7445 if ( options.debug ) {
7447 emitcode("","C$%s$%d$%d$%d ==.",
7448 ic->filename,ic->lineno,
7449 ic->level,ic->block);
7452 emitcode(";","%s %d",ic->filename,ic->lineno);
7455 /* if the result is marked as
7456 spilt and rematerializable or code for
7457 this has already been generated then
7459 if (resultRemat(ic) || ic->generated )
7462 /* depending on the operation */
7481 /* IPOP happens only when trying to restore a
7482 spilt live range, if there is an ifx statement
7483 following this pop then the if statement might
7484 be using some of the registers being popped which
7485 would destory the contents of the register so
7486 we need to check for this condition and handle it */
7488 ic->next->op == IFX &&
7489 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
7490 genIfx (ic->next,ic);
7508 genEndFunction (ic);
7528 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
7545 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
7549 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
7556 /* note these two are xlated by algebraic equivalence
7557 during parsing SDCC.y */
7558 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7559 "got '>=' or '<=' shouldn't have come here");
7563 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
7575 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
7579 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
7583 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
7610 case GET_VALUE_AT_ADDRESS:
7615 if (POINTER_SET(ic))
7642 addSet(&_G.sendSet,ic);
7647 /* piCode(ic,stdout); */
7653 /* now we are ready to call the
7654 peep hole optimizer */
7655 if (!options.nopeep)
7656 peepHole (&lineHead);
7658 /* now do the actual printing */
7659 printLine (lineHead,codeOutFile);