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)
256 return PTR_TYPE(SPEC_OCLS(etype));
258 /* if (SPEC_OCLS(etype)->codesp ) { */
259 /* p_type = CPOINTER ; */
262 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
263 /* p_type = FPOINTER ; */
265 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
266 /* p_type = PPOINTER; */
268 /* if (SPEC_OCLS(etype) == idata ) */
269 /* p_type = IPOINTER; */
271 /* p_type = POINTER ; */
275 /*-----------------------------------------------------------------*/
276 /* aopForSym - for a true symbol */
277 /*-----------------------------------------------------------------*/
278 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
281 memmap *space= SPEC_OCLS(sym->etype);
283 /* if already has one */
287 /* assign depending on the storage class */
288 /* if it is on the stack or indirectly addressable */
289 /* space we need to assign either r0 or r1 to it */
290 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
291 sym->aop = aop = newAsmop(0);
292 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
293 aop->size = getSize(sym->type);
295 /* now assign the address of the variable to
296 the pointer register */
297 if (aop->type != AOP_STK) {
301 emitcode("push","acc");
303 emitcode("mov","a,_bp");
304 emitcode("add","a,#0x%02x",
306 ((char)(sym->stack - _G.nRegsSaved )) :
307 ((char)sym->stack)) & 0xff);
308 emitcode("mov","%s,a",
309 aop->aopu.aop_ptr->name);
312 emitcode("pop","acc");
314 emitcode("mov","%s,#%s",
315 aop->aopu.aop_ptr->name,
317 aop->paged = space->paged;
319 aop->aopu.aop_stk = sym->stack;
323 if (sym->onStack && options.stack10bit)
325 /* It's on the 10 bit stack, which is located in
332 "*** Internal error: 10 bit stack var used as result.\n");
333 emitcode(";", "look at me!");
338 emitcode("push","acc");
340 emitcode("mov","a,_bp");
341 emitcode("add","a,#0x%02x",
343 ((char)(sym->stack - _G.nRegsSaved )) :
344 ((char)sym->stack)) & 0xff);
347 emitcode ("mov","dpx1,#0x40");
348 emitcode ("mov","dph1,#0x00");
349 emitcode ("mov","dpl1, a");
353 emitcode("pop","acc");
355 sym->aop = aop = newAsmop(AOP_DPTR2);
356 aop->size = getSize(sym->type);
360 /* if in bit space */
361 if (IN_BITSPACE(space)) {
362 sym->aop = aop = newAsmop (AOP_CRY);
363 aop->aopu.aop_dir = sym->rname ;
364 aop->size = getSize(sym->type);
367 /* if it is in direct space */
368 if (IN_DIRSPACE(space)) {
369 sym->aop = aop = newAsmop (AOP_DIR);
370 aop->aopu.aop_dir = sym->rname ;
371 aop->size = getSize(sym->type);
375 /* special case for a function */
376 if (IS_FUNC(sym->type)) {
377 sym->aop = aop = newAsmop(AOP_IMMD);
378 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
379 strcpy(aop->aopu.aop_immd,sym->rname);
380 aop->size = FPTRSIZE;
384 /* only remaining is far space */
385 /* in which case DPTR gets the address */
386 sym->aop = aop = newAsmop(AOP_DPTR);
387 emitcode ("mov","dptr,#%s", sym->rname);
388 aop->size = getSize(sym->type);
390 /* if it is in code space */
391 if (IN_CODESPACE(space))
397 /*-----------------------------------------------------------------*/
398 /* aopForRemat - rematerialzes an object */
399 /*-----------------------------------------------------------------*/
400 static asmop *aopForRemat (symbol *sym)
403 iCode *ic = sym->rematiCode;
404 asmop *aop = newAsmop(AOP_IMMD);
408 /* if plus or minus print the right hand side */
409 if (ic->op == '+' || ic->op == '-') {
410 sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
413 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
417 /* we reached the end */
418 sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
422 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
423 strcpy(aop->aopu.aop_immd,buffer);
427 /*-----------------------------------------------------------------*/
428 /* regsInCommon - two operands have some registers in common */
429 /*-----------------------------------------------------------------*/
430 static bool regsInCommon (operand *op1, operand *op2)
435 /* if they have registers in common */
436 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
439 sym1 = OP_SYMBOL(op1);
440 sym2 = OP_SYMBOL(op2);
442 if (sym1->nRegs == 0 || sym2->nRegs == 0)
445 for (i = 0 ; i < sym1->nRegs ; i++) {
450 for (j = 0 ; j < sym2->nRegs ;j++ ) {
454 if (sym2->regs[j] == sym1->regs[i])
462 /*-----------------------------------------------------------------*/
463 /* operandsEqu - equivalent */
464 /*-----------------------------------------------------------------*/
465 static bool operandsEqu ( operand *op1, operand *op2)
469 /* if they not symbols */
470 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
473 sym1 = OP_SYMBOL(op1);
474 sym2 = OP_SYMBOL(op2);
476 /* if both are itemps & one is spilt
477 and the other is not then false */
478 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
479 sym1->isspilt != sym2->isspilt )
482 /* if they are the same */
486 if (strcmp(sym1->rname,sym2->rname) == 0)
490 /* if left is a tmp & right is not */
494 (sym1->usl.spillLoc == sym2))
501 (sym2->usl.spillLoc == sym1))
507 /*-----------------------------------------------------------------*/
508 /* sameRegs - two asmops have the same registers */
509 /*-----------------------------------------------------------------*/
510 static bool sameRegs (asmop *aop1, asmop *aop2 )
517 if (aop1->type != AOP_REG ||
518 aop2->type != AOP_REG )
521 if (aop1->size != aop2->size )
524 for (i = 0 ; i < aop1->size ; i++ )
525 if (aop1->aopu.aop_reg[i] !=
526 aop2->aopu.aop_reg[i] )
532 /*-----------------------------------------------------------------*/
533 /* aopOp - allocates an asmop for an operand : */
534 /*-----------------------------------------------------------------*/
535 static void aopOp (operand *op, iCode *ic, bool result)
544 /* if this a literal */
545 if (IS_OP_LITERAL(op)) {
546 op->aop = aop = newAsmop(AOP_LIT);
547 aop->aopu.aop_lit = op->operand.valOperand;
548 aop->size = getSize(operandType(op));
552 /* if already has a asmop then continue */
556 /* if the underlying symbol has a aop */
557 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
558 op->aop = OP_SYMBOL(op)->aop;
562 /* if this is a true symbol */
563 if (IS_TRUE_SYMOP(op)) {
564 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
568 /* this is a temporary : this has
574 e) can be a return use only */
579 /* if the type is a conditional */
580 if (sym->regType == REG_CND) {
581 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
586 /* if it is spilt then two situations
588 b) has a spill location */
589 if (sym->isspilt || sym->nRegs == 0) {
591 /* rematerialize it NOW */
593 sym->aop = op->aop = aop =
595 aop->size = getSize(sym->type);
601 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
602 aop->size = getSize(sym->type);
603 for ( i = 0 ; i < 2 ; i++ )
604 aop->aopu.aop_str[i] = accUse[i];
610 aop = op->aop = sym->aop = newAsmop(AOP_STR);
611 aop->size = getSize(sym->type);
612 for ( i = 0 ; i < fReturnSize ; i++ )
613 aop->aopu.aop_str[i] = fReturn[i];
617 /* else spill location */
618 sym->aop = op->aop = aop =
619 aopForSym(ic,sym->usl.spillLoc,result);
620 aop->size = getSize(sym->type);
624 /* must be in a register */
625 sym->aop = op->aop = aop = newAsmop(AOP_REG);
626 aop->size = sym->nRegs;
627 for ( i = 0 ; i < sym->nRegs ;i++)
628 aop->aopu.aop_reg[i] = sym->regs[i];
631 /*-----------------------------------------------------------------*/
632 /* freeAsmop - free up the asmop given to an operand */
633 /*----------------------------------------------------------------*/
634 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
651 /* depending on the asmop type only three cases need work AOP_RO
652 , AOP_R1 && AOP_STK */
657 emitcode ("pop","ar0");
661 bitVectUnSetBit(ic->rUsed,R0_IDX);
667 emitcode ("pop","ar1");
671 bitVectUnSetBit(ic->rUsed,R1_IDX);
677 int stk = aop->aopu.aop_stk + aop->size;
678 bitVectUnSetBit(ic->rUsed,R0_IDX);
679 bitVectUnSetBit(ic->rUsed,R1_IDX);
681 getFreePtr(ic,&aop,FALSE);
683 if (options.stack10bit)
685 /* I'm not sure what to do here yet... */
688 "*** Warning: probably generating bad code for "
689 "10 bit stack mode.\n");
693 emitcode ("mov","a,_bp");
694 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
695 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
697 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
701 emitcode("pop","acc");
702 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
704 emitcode("dec","%s",aop->aopu.aop_ptr->name);
707 freeAsmop(op,NULL,ic,TRUE);
709 emitcode("pop","ar0");
714 emitcode("pop","ar1");
721 /* all other cases just dealloc */
725 OP_SYMBOL(op)->aop = NULL;
726 /* if the symbol has a spill */
728 SPIL_LOC(op)->aop = NULL;
733 /*-----------------------------------------------------------------*/
734 /* aopGet - for fetching value of the aop */
735 /*-----------------------------------------------------------------*/
736 static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
741 /* offset is greater than
743 if (offset > (aop->size - 1) &&
744 aop->type != AOP_LIT)
747 /* depending on type */
752 /* if we need to increment it */
753 while (offset > aop->coff) {
754 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
758 while (offset < aop->coff) {
759 emitcode("dec","%s",aop->aopu.aop_ptr->name);
765 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
766 return (dname ? "acc" : "a");
768 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
769 ALLOC_ATOMIC(rs,strlen(s)+1);
776 if (aop->type == AOP_DPTR2)
781 while (offset > aop->coff) {
782 emitcode ("inc","dptr");
786 while (offset < aop->coff) {
787 emitcode("lcall","__decdptr");
794 emitcode("movc","a,@a+dptr");
797 emitcode("movx","a,@dptr");
800 if (aop->type == AOP_DPTR2)
805 return (dname ? "acc" : "a");
810 sprintf (s,"#(%s)",aop->aopu.aop_immd);
813 sprintf(s,"#(%s >> %d)",
819 ALLOC_ATOMIC(rs,strlen(s)+1);
825 sprintf(s,"(%s + %d)",
829 sprintf(s,"%s",aop->aopu.aop_dir);
830 ALLOC_ATOMIC(rs,strlen(s)+1);
836 return aop->aopu.aop_reg[offset]->dname;
838 return aop->aopu.aop_reg[offset]->name;
842 emitcode("mov","c,%s",aop->aopu.aop_dir);
843 emitcode("rlc","a") ;
844 return (dname ? "acc" : "a");
847 if (!offset && dname)
849 return aop->aopu.aop_str[offset];
852 return aopLiteral (aop->aopu.aop_lit,offset);
856 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
860 return aop->aopu.aop_str[offset];
864 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
865 "aopget got unsupported aop->type");
868 /*-----------------------------------------------------------------*/
869 /* aopPut - puts a string for a aop */
870 /*-----------------------------------------------------------------*/
871 static void aopPut (asmop *aop, char *s, int offset)
876 if (aop->size && offset > ( aop->size - 1)) {
877 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
878 "aopPut got offset > aop->size");
882 /* will assign value to value */
883 /* depending on where it is ofcourse */
887 sprintf(d,"(%s + %d)",
888 aop->aopu.aop_dir,offset);
890 sprintf(d,"%s",aop->aopu.aop_dir);
893 emitcode("mov","%s,%s",d,s);
898 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
899 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
901 strcmp(s,"r0") == 0 ||
902 strcmp(s,"r1") == 0 ||
903 strcmp(s,"r2") == 0 ||
904 strcmp(s,"r3") == 0 ||
905 strcmp(s,"r4") == 0 ||
906 strcmp(s,"r5") == 0 ||
907 strcmp(s,"r6") == 0 ||
908 strcmp(s,"r7") == 0 )
909 emitcode("mov","%s,%s",
910 aop->aopu.aop_reg[offset]->dname,s);
912 emitcode("mov","%s,%s",
913 aop->aopu.aop_reg[offset]->name,s);
920 if (aop->type == AOP_DPTR2)
926 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
927 "aopPut writting to code space");
931 while (offset > aop->coff) {
933 emitcode ("inc","dptr");
936 while (offset < aop->coff) {
938 emitcode("lcall","__decdptr");
943 /* if not in accumulater */
946 emitcode ("movx","@dptr,a");
948 if (aop->type == AOP_DPTR2)
956 while (offset > aop->coff) {
958 emitcode("inc","%s",aop->aopu.aop_ptr->name);
960 while (offset < aop->coff) {
962 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
968 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
973 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
975 if (strcmp(s,"r0") == 0 ||
976 strcmp(s,"r1") == 0 ||
977 strcmp(s,"r2") == 0 ||
978 strcmp(s,"r3") == 0 ||
979 strcmp(s,"r4") == 0 ||
980 strcmp(s,"r5") == 0 ||
981 strcmp(s,"r6") == 0 ||
982 strcmp(s,"r7") == 0 ) {
984 sprintf(buffer,"a%s",s);
985 emitcode("mov","@%s,%s",
986 aop->aopu.aop_ptr->name,buffer);
988 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
993 if (strcmp(s,"a") == 0)
994 emitcode("push","acc");
996 emitcode("push","%s",s);
1001 /* if bit variable */
1002 if (!aop->aopu.aop_dir) {
1003 emitcode("clr","a");
1004 emitcode("rlc","a");
1007 emitcode("clr","%s",aop->aopu.aop_dir);
1010 emitcode("setb","%s",aop->aopu.aop_dir);
1013 emitcode("mov","%s,c",aop->aopu.aop_dir);
1015 lbl = newiTempLabel(NULL);
1017 if (strcmp(s,"a")) {
1020 emitcode("clr","c");
1021 emitcode("jz","%05d$",lbl->key+100);
1022 emitcode("cpl","c");
1023 emitcode("","%05d$:",lbl->key+100);
1024 emitcode("mov","%s,c",aop->aopu.aop_dir);
1031 if (strcmp(aop->aopu.aop_str[offset],s))
1032 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1037 if (!offset && (strcmp(s,"acc") == 0))
1040 if (strcmp(aop->aopu.aop_str[offset],s))
1041 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1045 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1046 "aopPut got unsupported aop->type");
1054 /*-----------------------------------------------------------------*/
1055 /* pointToEnd :- points to the last byte of the operand */
1056 /*-----------------------------------------------------------------*/
1057 static void pointToEnd (asmop *aop)
1063 aop->coff = count = (aop->size - 1);
1064 switch (aop->type) {
1068 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1072 emitcode("inc","dptr");
1079 /*-----------------------------------------------------------------*/
1080 /* reAdjustPreg - points a register back to where it should */
1081 /*-----------------------------------------------------------------*/
1082 static void reAdjustPreg (asmop *aop)
1087 if ((size = aop->size) <= 1)
1090 switch (aop->type) {
1094 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1098 if (aop->type == AOP_DPTR2)
1104 emitcode("lcall","__decdptr");
1107 if (aop->type == AOP_DPTR2)
1117 #define AOP(op) op->aop
1118 #define AOP_TYPE(op) AOP(op)->type
1119 #define AOP_SIZE(op) AOP(op)->size
1120 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1121 AOP_TYPE(x) == AOP_R0))
1123 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1124 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1127 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1128 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1129 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1131 /*-----------------------------------------------------------------*/
1132 /* genNotFloat - generates not for float operations */
1133 /*-----------------------------------------------------------------*/
1134 static void genNotFloat (operand *op, operand *res)
1140 /* we will put 127 in the first byte of
1142 aopPut(AOP(res),"#127",0);
1143 size = AOP_SIZE(op) - 1;
1146 l = aopGet(op->aop,offset++,FALSE,FALSE);
1150 emitcode("orl","a,%s",
1152 offset++,FALSE,FALSE));
1154 tlbl = newiTempLabel(NULL);
1156 tlbl = newiTempLabel(NULL);
1157 aopPut(res->aop,one,1);
1158 emitcode("jz","%05d$",(tlbl->key+100));
1159 aopPut(res->aop,zero,1);
1160 emitcode("","%05d$:",(tlbl->key+100));
1162 size = res->aop->size - 2;
1164 /* put zeros in the rest */
1166 aopPut(res->aop,zero,offset++);
1169 /*-----------------------------------------------------------------*/
1170 /* opIsGptr: returns non-zero if the passed operand is */
1171 /* a generic pointer type. */
1172 /*-----------------------------------------------------------------*/
1173 static int opIsGptr(operand *op)
1175 link *type = operandType(op);
1177 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1184 /*-----------------------------------------------------------------*/
1185 /* getDataSize - get the operand data size */
1186 /*-----------------------------------------------------------------*/
1187 static int getDataSize(operand *op)
1190 size = AOP_SIZE(op);
1191 if (size == GPTRSIZE)
1193 link *type = operandType(op);
1194 if (IS_GENPTR(type))
1196 /* generic pointer; arithmetic operations
1197 * should ignore the high byte (pointer type).
1205 /*-----------------------------------------------------------------*/
1206 /* outAcc - output Acc */
1207 /*-----------------------------------------------------------------*/
1208 static void outAcc(operand *result)
1211 size = getDataSize(result);
1213 aopPut(AOP(result),"a",0);
1216 /* unsigned or positive */
1218 aopPut(AOP(result),zero,offset++);
1223 /*-----------------------------------------------------------------*/
1224 /* outBitC - output a bit C */
1225 /*-----------------------------------------------------------------*/
1226 static void outBitC(operand *result)
1228 /* if the result is bit */
1229 if (AOP_TYPE(result) == AOP_CRY)
1230 aopPut(AOP(result),"c",0);
1232 emitcode("clr","a");
1233 emitcode("rlc","a");
1238 /*-----------------------------------------------------------------*/
1239 /* toBoolean - emit code for orl a,operator(sizeop) */
1240 /*-----------------------------------------------------------------*/
1241 static void toBoolean(operand *oper)
1243 int size = AOP_SIZE(oper) - 1;
1245 MOVA(aopGet(AOP(oper),0,FALSE,FALSE));
1247 emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE));
1251 /*-----------------------------------------------------------------*/
1252 /* genNot - generate code for ! operation */
1253 /*-----------------------------------------------------------------*/
1254 static void genNot (iCode *ic)
1257 link *optype = operandType(IC_LEFT(ic));
1259 /* assign asmOps to operand & result */
1260 aopOp (IC_LEFT(ic),ic,FALSE);
1261 aopOp (IC_RESULT(ic),ic,TRUE);
1263 /* if in bit space then a special case */
1264 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1265 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1266 emitcode("cpl","c");
1267 outBitC(IC_RESULT(ic));
1271 /* if type float then do float */
1272 if (IS_FLOAT(optype)) {
1273 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1277 toBoolean(IC_LEFT(ic));
1279 tlbl = newiTempLabel(NULL);
1280 emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1281 emitcode("","%05d$:",tlbl->key+100);
1282 outBitC(IC_RESULT(ic));
1285 /* release the aops */
1286 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1287 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1291 /*-----------------------------------------------------------------*/
1292 /* genCpl - generate code for complement */
1293 /*-----------------------------------------------------------------*/
1294 static void genCpl (iCode *ic)
1300 /* assign asmOps to operand & result */
1301 aopOp (IC_LEFT(ic),ic,FALSE);
1302 aopOp (IC_RESULT(ic),ic,TRUE);
1304 /* if both are in bit space then
1306 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1307 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1309 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1310 emitcode("cpl","c");
1311 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1315 size = AOP_SIZE(IC_RESULT(ic));
1317 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1319 emitcode("cpl","a");
1320 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1325 /* release the aops */
1326 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1327 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1330 /*-----------------------------------------------------------------*/
1331 /* genUminusFloat - unary minus for floating points */
1332 /*-----------------------------------------------------------------*/
1333 static void genUminusFloat(operand *op,operand *result)
1335 int size ,offset =0 ;
1337 /* for this we just need to flip the
1338 first it then copy the rest in place */
1339 size = AOP_SIZE(op) - 1;
1340 l = aopGet(AOP(op),3,FALSE,FALSE);
1344 emitcode("cpl","acc.7");
1345 aopPut(AOP(result),"a",3);
1349 aopGet(AOP(op),offset,FALSE,FALSE),
1355 /*-----------------------------------------------------------------*/
1356 /* genUminus - unary minus code generation */
1357 /*-----------------------------------------------------------------*/
1358 static void genUminus (iCode *ic)
1361 link *optype, *rtype;
1365 aopOp(IC_LEFT(ic),ic,FALSE);
1366 aopOp(IC_RESULT(ic),ic,TRUE);
1368 /* if both in bit space then special
1370 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1371 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1373 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1374 emitcode("cpl","c");
1375 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1379 optype = operandType(IC_LEFT(ic));
1380 rtype = operandType(IC_RESULT(ic));
1382 /* if float then do float stuff */
1383 if (IS_FLOAT(optype)) {
1384 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1388 /* otherwise subtract from zero */
1389 size = AOP_SIZE(IC_LEFT(ic));
1393 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1394 if (!strcmp(l,"a")) {
1395 emitcode("cpl","a");
1396 emitcode("inc","a");
1398 emitcode("clr","a");
1399 emitcode("subb","a,%s",l);
1401 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1404 /* if any remaining bytes in the result */
1405 /* we just need to propagate the sign */
1406 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1407 emitcode("rlc","a");
1408 emitcode("subb","a,acc");
1410 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1414 /* release the aops */
1415 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1416 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1419 /*-----------------------------------------------------------------*/
1420 /* saveRegisters - will look for a call and save the registers */
1421 /*-----------------------------------------------------------------*/
1422 static void saveRegisters(iCode *lic)
1430 for (ic = lic ; ic ; ic = ic->next)
1431 if (ic->op == CALL || ic->op == PCALL)
1435 fprintf(stderr,"found parameter push with no function call\n");
1439 /* if the registers have been saved already then
1441 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1444 /* find the registers in use at this time
1445 and push them away to safety */
1446 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1450 if (options.useXstack) {
1451 if (bitVectBitValue(rsave,R0_IDX))
1452 emitcode("mov","b,r0");
1453 emitcode("mov","r0,%s",spname);
1454 for (i = 0 ; i < mcs51_nRegs ; i++) {
1455 if (bitVectBitValue(rsave,i)) {
1457 emitcode("mov","a,b");
1459 emitcode("mov","a,%s",mcs51_regWithIdx(i)->name);
1460 emitcode("movx","@r0,a");
1461 emitcode("inc","r0");
1464 emitcode("mov","%s,r0",spname);
1465 if (bitVectBitValue(rsave,R0_IDX))
1466 emitcode("mov","r0,b");
1468 for (i = 0 ; i < mcs51_nRegs ; i++) {
1469 if (bitVectBitValue(rsave,i))
1470 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
1473 detype = getSpec(operandType(IC_LEFT(ic)));
1475 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1476 IS_ISR(currFunc->etype) &&
1479 saverbank(SPEC_BANK(detype),ic,TRUE);
1482 /*-----------------------------------------------------------------*/
1483 /* unsaveRegisters - pop the pushed registers */
1484 /*-----------------------------------------------------------------*/
1485 static void unsaveRegisters (iCode *ic)
1489 /* find the registers in use at this time
1490 and push them away to safety */
1491 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1494 if (options.useXstack) {
1495 emitcode("mov","r0,%s",spname);
1496 for (i = mcs51_nRegs ; i >= 0 ; i--) {
1497 if (bitVectBitValue(rsave,i)) {
1498 emitcode("dec","r0");
1499 emitcode("movx","a,@r0");
1501 emitcode("mov","b,a");
1503 emitcode("mov","%s,a",mcs51_regWithIdx(i)->name);
1507 emitcode("mov","%s,r0",spname);
1508 if (bitVectBitValue(rsave,R0_IDX))
1509 emitcode("mov","r0,b");
1511 for (i = mcs51_nRegs ; i >= 0 ; i--) {
1512 if (bitVectBitValue(rsave,i))
1513 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
1519 /*-----------------------------------------------------------------*/
1521 /*-----------------------------------------------------------------*/
1522 static void pushSide(operand * oper, int size)
1526 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1527 if (AOP_TYPE(oper) != AOP_REG &&
1528 AOP_TYPE(oper) != AOP_DIR &&
1530 emitcode("mov","a,%s",l);
1531 emitcode("push","acc");
1533 emitcode("push","%s",l);
1537 /*-----------------------------------------------------------------*/
1538 /* assignResultValue - */
1539 /*-----------------------------------------------------------------*/
1540 static void assignResultValue(operand * oper)
1543 int size = AOP_SIZE(oper);
1545 aopPut(AOP(oper),fReturn[offset],offset);
1551 /*-----------------------------------------------------------------*/
1552 /* genXpush - pushes onto the external stack */
1553 /*-----------------------------------------------------------------*/
1554 static void genXpush (iCode *ic)
1556 asmop *aop = newAsmop(0);
1558 int size,offset = 0;
1560 aopOp(IC_LEFT(ic),ic,FALSE);
1561 r = getFreePtr(ic,&aop,FALSE);
1564 emitcode("mov","%s,_spx",r->name);
1566 size = AOP_SIZE(IC_LEFT(ic));
1569 char *l = aopGet(AOP(IC_LEFT(ic)),
1570 offset++,FALSE,FALSE);
1572 emitcode("movx","@%s,a",r->name);
1573 emitcode("inc","%s",r->name);
1578 emitcode("mov","_spx,%s",r->name);
1580 freeAsmop(NULL,aop,ic,TRUE);
1581 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1584 /*-----------------------------------------------------------------*/
1585 /* genIpush - genrate code for pushing this gets a little complex */
1586 /*-----------------------------------------------------------------*/
1587 static void genIpush (iCode *ic)
1589 int size, offset = 0 ;
1593 /* if this is not a parm push : ie. it is spill push
1594 and spill push is always done on the local stack */
1595 if (!ic->parmPush) {
1597 /* and the item is spilt then do nothing */
1598 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1601 aopOp(IC_LEFT(ic),ic,FALSE);
1602 size = AOP_SIZE(IC_LEFT(ic));
1603 /* push it on the stack */
1605 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1610 emitcode("push","%s",l);
1615 /* this is a paramter push: in this case we call
1616 the routine to find the call and save those
1617 registers that need to be saved */
1620 /* if use external stack then call the external
1621 stack pushing routine */
1622 if (options.useXstack) {
1627 /* then do the push */
1628 aopOp(IC_LEFT(ic),ic,FALSE);
1631 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1632 size = AOP_SIZE(IC_LEFT(ic));
1635 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1636 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1637 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1639 emitcode("mov","a,%s",l);
1640 emitcode("push","acc");
1642 emitcode("push","%s",l);
1645 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1648 /*-----------------------------------------------------------------*/
1649 /* genIpop - recover the registers: can happen only for spilling */
1650 /*-----------------------------------------------------------------*/
1651 static void genIpop (iCode *ic)
1656 /* if the temp was not pushed then */
1657 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1660 aopOp(IC_LEFT(ic),ic,FALSE);
1661 size = AOP_SIZE(IC_LEFT(ic));
1664 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1667 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1670 /*-----------------------------------------------------------------*/
1671 /* unsaverbank - restores the resgister bank from stack */
1672 /*-----------------------------------------------------------------*/
1673 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1680 if (options.useXstack) {
1682 r = getFreePtr(ic,&aop,FALSE);
1685 emitcode("mov","%s,_spx",r->name);
1686 emitcode("movx","a,@%s",r->name);
1687 emitcode("mov","psw,a");
1688 emitcode("dec","%s",r->name);
1691 emitcode ("pop","psw");
1694 for (i = (mcs51_nRegs - 1) ; i >= 0 ;i--) {
1695 if (options.useXstack) {
1696 emitcode("movx","a,@%s",r->name);
1697 emitcode("mov","(%s+%d),a",
1698 regs8051[i].base,8*bank+regs8051[i].offset);
1699 emitcode("dec","%s",r->name);
1702 emitcode("pop","(%s+%d)",
1703 regs8051[i].base,8*bank+regs8051[i].offset);
1706 if (options.useXstack) {
1708 emitcode("mov","_spx,%s",r->name);
1709 freeAsmop(NULL,aop,ic,TRUE);
1714 /*-----------------------------------------------------------------*/
1715 /* saverbank - saves an entire register bank on the stack */
1716 /*-----------------------------------------------------------------*/
1717 static void saverbank (int bank, iCode *ic, bool pushPsw)
1723 if (options.useXstack) {
1726 r = getFreePtr(ic,&aop,FALSE);
1727 emitcode("mov","%s,_spx",r->name);
1731 for (i = 0 ; i < mcs51_nRegs ;i++) {
1732 if (options.useXstack) {
1733 emitcode("inc","%s",r->name);
1734 emitcode("mov","a,(%s+%d)",
1735 regs8051[i].base,8*bank+regs8051[i].offset);
1736 emitcode("movx","@%s,a",r->name);
1738 emitcode("push","(%s+%d)",
1739 regs8051[i].base,8*bank+regs8051[i].offset);
1743 if (options.useXstack) {
1744 emitcode("mov","a,psw");
1745 emitcode("movx","@%s,a",r->name);
1746 emitcode("inc","%s",r->name);
1747 emitcode("mov","_spx,%s",r->name);
1748 freeAsmop (NULL,aop,ic,TRUE);
1751 emitcode("push","psw");
1753 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1759 /*-----------------------------------------------------------------*/
1760 /* genCall - generates a call statement */
1761 /*-----------------------------------------------------------------*/
1762 static void genCall (iCode *ic)
1766 /* if caller saves & we have not saved then */
1770 /* if we are calling a function that is not using
1771 the same register bank then we need to save the
1772 destination registers on the stack */
1773 detype = getSpec(operandType(IC_LEFT(ic)));
1775 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1776 IS_ISR(currFunc->etype) &&
1779 saverbank(SPEC_BANK(detype),ic,TRUE);
1781 /* if send set is not empty the assign */
1785 for (sic = setFirstItem(_G.sendSet) ; sic ;
1786 sic = setNextItem(_G.sendSet)) {
1787 int size, offset = 0;
1788 aopOp(IC_LEFT(sic),sic,FALSE);
1789 size = AOP_SIZE(IC_LEFT(sic));
1791 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1793 if (strcmp(l,fReturn[offset]))
1794 emitcode("mov","%s,%s",
1799 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1804 emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1805 OP_SYMBOL(IC_LEFT(ic))->rname :
1806 OP_SYMBOL(IC_LEFT(ic))->name));
1808 /* if we need assign a result value */
1809 if ((IS_ITEMP(IC_RESULT(ic)) &&
1810 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1811 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1812 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1815 aopOp(IC_RESULT(ic),ic,FALSE);
1818 assignResultValue(IC_RESULT(ic));
1820 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1823 /* adjust the stack for parameters if
1825 if (IC_LEFT(ic)->parmBytes) {
1827 if (IC_LEFT(ic)->parmBytes > 3) {
1828 emitcode("mov","a,%s",spname);
1829 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1830 emitcode("mov","%s,a",spname);
1832 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1833 emitcode("dec","%s",spname);
1837 /* if register bank was saved then pop them */
1839 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1841 /* if we hade saved some registers then unsave them */
1842 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1843 unsaveRegisters (ic);
1848 /*-----------------------------------------------------------------*/
1849 /* genPcall - generates a call by pointer statement */
1850 /*-----------------------------------------------------------------*/
1851 static void genPcall (iCode *ic)
1854 symbol *rlbl = newiTempLabel(NULL);
1857 /* if caller saves & we have not saved then */
1861 /* if we are calling a function that is not using
1862 the same register bank then we need to save the
1863 destination registers on the stack */
1864 detype = getSpec(operandType(IC_LEFT(ic)));
1866 IS_ISR(currFunc->etype) &&
1867 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
1868 saverbank(SPEC_BANK(detype),ic,TRUE);
1871 /* push the return address on to the stack */
1872 emitcode("mov","a,#%05d$",(rlbl->key+100));
1873 emitcode("push","acc");
1874 emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
1875 emitcode("push","acc");
1877 if (options.model == MODEL_FLAT24)
1879 emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
1880 emitcode("push","acc");
1883 /* now push the calling address */
1884 aopOp(IC_LEFT(ic),ic,FALSE);
1886 pushSide(IC_LEFT(ic), FPTRSIZE);
1888 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1890 /* if send set is not empty the assign */
1894 for (sic = setFirstItem(_G.sendSet) ; sic ;
1895 sic = setNextItem(_G.sendSet)) {
1896 int size, offset = 0;
1897 aopOp(IC_LEFT(sic),sic,FALSE);
1898 size = AOP_SIZE(IC_LEFT(sic));
1900 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1902 if (strcmp(l,fReturn[offset]))
1903 emitcode("mov","%s,%s",
1908 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1914 emitcode("","%05d$:",(rlbl->key+100));
1917 /* if we need assign a result value */
1918 if ((IS_ITEMP(IC_RESULT(ic)) &&
1919 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1920 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
1921 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1924 aopOp(IC_RESULT(ic),ic,FALSE);
1927 assignResultValue(IC_RESULT(ic));
1929 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1932 /* adjust the stack for parameters if
1934 if (IC_LEFT(ic)->parmBytes) {
1936 if (IC_LEFT(ic)->parmBytes > 3) {
1937 emitcode("mov","a,%s",spname);
1938 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1939 emitcode("mov","%s,a",spname);
1941 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1942 emitcode("dec","%s",spname);
1946 /* if register bank was saved then unsave them */
1948 (SPEC_BANK(currFunc->etype) !=
1950 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1952 /* if we hade saved some registers then
1955 unsaveRegisters (ic);
1959 /*-----------------------------------------------------------------*/
1960 /* resultRemat - result is rematerializable */
1961 /*-----------------------------------------------------------------*/
1962 static int resultRemat (iCode *ic)
1964 if (SKIP_IC(ic) || ic->op == IFX)
1967 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1968 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1969 if (sym->remat && !POINTER_SET(ic))
1977 #define STRCASECMP stricmp
1979 #define STRCASECMP strcasecmp
1982 /*-----------------------------------------------------------------*/
1983 /* inExcludeList - return 1 if the string is in exclude Reg list */
1984 /*-----------------------------------------------------------------*/
1985 static bool inExcludeList(char *s)
1989 if (options.excludeRegs[i] &&
1990 STRCASECMP(options.excludeRegs[i],"none") == 0)
1993 for ( i = 0 ; options.excludeRegs[i]; i++) {
1994 if (options.excludeRegs[i] &&
1995 STRCASECMP(s,options.excludeRegs[i]) == 0)
2001 /*-----------------------------------------------------------------*/
2002 /* genFunction - generated code for function entry */
2003 /*-----------------------------------------------------------------*/
2004 static void genFunction (iCode *ic)
2010 /* create the function header */
2011 emitcode(";","-----------------------------------------");
2012 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2013 emitcode(";","-----------------------------------------");
2015 emitcode("","%s:",sym->rname);
2016 fetype = getSpec(operandType(IC_LEFT(ic)));
2018 /* if critical function then turn interrupts off */
2019 if (SPEC_CRTCL(fetype))
2020 emitcode("clr","ea");
2022 /* here we need to generate the equates for the
2023 register bank if required */
2024 if (SPEC_BANK(fetype) != rbank) {
2027 rbank = SPEC_BANK(fetype);
2028 for ( i = 0 ; i < mcs51_nRegs ; i++ ) {
2029 if (strcmp(regs8051[i].base,"0") == 0)
2030 emitcode("","%s = 0x%02x",
2032 8*rbank+regs8051[i].offset);
2034 emitcode ("","%s = %s + 0x%02x",
2037 8*rbank+regs8051[i].offset);
2041 /* if this is an interrupt service routine then
2042 save acc, b, dpl, dph */
2043 if (IS_ISR(sym->etype)) {
2045 if (!inExcludeList("acc"))
2046 emitcode ("push","acc");
2047 if (!inExcludeList("b"))
2048 emitcode ("push","b");
2049 if (!inExcludeList("dpl"))
2050 emitcode ("push","dpl");
2051 if (!inExcludeList("dph"))
2052 emitcode ("push","dph");
2053 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2054 emitcode ("push", "dpx");
2055 /* if this isr has no bank i.e. is going to
2056 run with bank 0 , then we need to save more
2058 if (!SPEC_BANK(sym->etype)) {
2060 /* if this function does not call any other
2061 function then we can be economical and
2062 save only those registers that are used */
2063 if (! sym->hasFcall) {
2066 /* if any registers used */
2067 if (sym->regsUsed) {
2068 /* save the registers used */
2069 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2070 if (bitVectBitValue(sym->regsUsed,i) ||
2071 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2072 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
2077 /* this function has a function call cannot
2078 determines register usage so we will have the
2080 saverbank(0,ic,FALSE);
2084 /* if callee-save to be used for this function
2085 then save the registers being used in this function */
2086 if (sym->calleeSave) {
2089 /* if any registers used */
2090 if (sym->regsUsed) {
2091 /* save the registers used */
2092 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2093 if (bitVectBitValue(sym->regsUsed,i) ||
2094 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2095 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
2103 /* set the register bank to the desired value */
2104 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2105 emitcode("push","psw");
2106 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2109 if (IS_RENT(sym->etype) || options.stackAuto) {
2111 if (options.useXstack) {
2112 emitcode("mov","r0,%s",spname);
2113 emitcode("mov","a,_bp");
2114 emitcode("movx","@r0,a");
2115 emitcode("inc","%s",spname);
2119 /* set up the stack */
2120 emitcode ("push","_bp"); /* save the callers stack */
2122 emitcode ("mov","_bp,%s",spname);
2125 /* adjust the stack for the function */
2130 werror(W_STACK_OVERFLOW,sym->name);
2132 if (i > 3 && sym->recvSize < 4) {
2134 emitcode ("mov","a,sp");
2135 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2136 emitcode ("mov","sp,a");
2141 emitcode("inc","sp");
2146 emitcode ("mov","a,_spx");
2147 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2148 emitcode ("mov","_spx,a");
2153 /*-----------------------------------------------------------------*/
2154 /* genEndFunction - generates epilogue for functions */
2155 /*-----------------------------------------------------------------*/
2156 static void genEndFunction (iCode *ic)
2158 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2160 if (IS_RENT(sym->etype) || options.stackAuto)
2162 emitcode ("mov","%s,_bp",spname);
2165 /* if use external stack but some variables were
2166 added to the local stack then decrement the
2168 if (options.useXstack && sym->stack) {
2169 emitcode("mov","a,sp");
2170 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2171 emitcode("mov","sp,a");
2175 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2176 if (options.useXstack) {
2177 emitcode("mov","r0,%s",spname);
2178 emitcode("movx","a,@r0");
2179 emitcode("mov","_bp,a");
2180 emitcode("dec","%s",spname);
2184 emitcode ("pop","_bp");
2188 /* restore the register bank */
2189 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2190 emitcode ("pop","psw");
2192 if (IS_ISR(sym->etype)) {
2194 /* now we need to restore the registers */
2195 /* if this isr has no bank i.e. is going to
2196 run with bank 0 , then we need to save more
2198 if (!SPEC_BANK(sym->etype)) {
2200 /* if this function does not call any other
2201 function then we can be economical and
2202 save only those registers that are used */
2203 if (! sym->hasFcall) {
2206 /* if any registers used */
2207 if (sym->regsUsed) {
2208 /* save the registers used */
2209 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2210 if (bitVectBitValue(sym->regsUsed,i) ||
2211 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2212 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
2217 /* this function has a function call cannot
2218 determines register usage so we will have the
2220 unsaverbank(0,ic,FALSE);
2224 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2225 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 */
2274 /* if (options.debug && currFunc) { */
2277 emitcode("","C$%s$%d$%d$%d ==.",
2278 ic->filename,currFunc->lastLine,
2279 ic->level,ic->block);
2280 if (IS_STATIC(currFunc->etype))
2281 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2283 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2287 emitcode ("ret","");
2292 /*-----------------------------------------------------------------*/
2293 /* genRet - generate code for return statement */
2294 /*-----------------------------------------------------------------*/
2295 static void genRet (iCode *ic)
2297 int size,offset = 0 , pushed = 0;
2299 /* if we have no return value then
2300 just generate the "ret" */
2304 /* we have something to return then
2305 move the return value into place */
2306 aopOp(IC_LEFT(ic),ic,FALSE);
2307 size = AOP_SIZE(IC_LEFT(ic));
2311 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2313 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2315 emitcode("push","%s",l);
2318 l = aopGet(AOP(IC_LEFT(ic)),offset,
2320 if (strcmp(fReturn[offset],l))
2321 emitcode("mov","%s,%s",fReturn[offset++],l);
2328 if (strcmp(fReturn[pushed],"a"))
2329 emitcode("pop",fReturn[pushed]);
2331 emitcode("pop","acc");
2334 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2337 /* generate a jump to the return label
2338 if the next is not the return statement */
2339 if (!(ic->next && ic->next->op == LABEL &&
2340 IC_LABEL(ic->next) == returnLabel))
2342 emitcode("ljmp","%05d$",(returnLabel->key+100));
2346 /*-----------------------------------------------------------------*/
2347 /* genLabel - generates a label */
2348 /*-----------------------------------------------------------------*/
2349 static void genLabel (iCode *ic)
2351 /* special case never generate */
2352 if (IC_LABEL(ic) == entryLabel)
2355 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2358 /*-----------------------------------------------------------------*/
2359 /* genGoto - generates a ljmp */
2360 /*-----------------------------------------------------------------*/
2361 static void genGoto (iCode *ic)
2363 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2366 /*-----------------------------------------------------------------*/
2367 /* findLabelBackwards: walks back through the iCode chain looking */
2368 /* for the given label. Returns number of iCode instructions */
2369 /* between that label and given ic. */
2370 /* Returns zero if label not found. */
2371 /*-----------------------------------------------------------------*/
2372 static int findLabelBackwards(iCode *ic, int key)
2381 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2383 /* printf("findLabelBackwards = %d\n", count); */
2388 /* printf("findLabelBackwards: not found.\n"); */
2393 /*-----------------------------------------------------------------*/
2394 /* genPlusIncr :- does addition with increment if possible */
2395 /*-----------------------------------------------------------------*/
2396 static bool genPlusIncr (iCode *ic)
2398 unsigned int icount ;
2399 unsigned int size = getDataSize(IC_RESULT(ic));
2401 /* will try to generate an increment */
2402 /* if the right side is not a literal
2404 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2407 /* if the literal value of the right hand side
2408 is greater than 4 then it is not worth it */
2409 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2412 /* if increment 16 bits in register */
2413 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2420 /* If the next instruction is a goto and the goto target
2421 * is < 10 instructions previous to this, we can generate
2422 * jumps straight to that target.
2424 if (ic->next && ic->next->op == GOTO
2425 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2426 && labelRange <= 10 )
2428 emitcode(";", "tail increment optimized");
2429 tlbl = IC_LABEL(ic->next);
2434 tlbl = newiTempLabel(NULL);
2437 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2438 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2439 IS_AOP_PREG(IC_RESULT(ic)))
2440 emitcode("cjne","%s,#0x00,%05d$"
2441 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2444 emitcode("clr","a");
2445 emitcode("cjne","a,%s,%05d$"
2446 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2450 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2453 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2454 IS_AOP_PREG(IC_RESULT(ic)))
2455 emitcode("cjne","%s,#0x00,%05d$"
2456 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2459 emitcode("cjne","a,%s,%05d$"
2460 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2463 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2467 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2468 IS_AOP_PREG(IC_RESULT(ic)))
2469 emitcode("cjne","%s,#0x00,%05d$"
2470 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2473 emitcode("cjne","a,%s,%05d$"
2474 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2477 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2482 emitcode("","%05d$:",tlbl->key+100);
2487 /* if the sizes are greater than 1 then we cannot */
2488 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2489 AOP_SIZE(IC_LEFT(ic)) > 1 )
2492 /* we can if the aops of the left & result match or
2493 if they are in registers and the registers are the
2495 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2498 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2499 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2500 aopPut(AOP(IC_RESULT(ic)),"a",0);
2504 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2513 /*-----------------------------------------------------------------*/
2514 /* outBitAcc - output a bit in acc */
2515 /*-----------------------------------------------------------------*/
2516 static void outBitAcc(operand *result)
2518 symbol *tlbl = newiTempLabel(NULL);
2519 /* if the result is a bit */
2520 if (AOP_TYPE(result) == AOP_CRY){
2521 aopPut(AOP(result),"a",0);
2524 emitcode("jz","%05d$",tlbl->key+100);
2525 emitcode("mov","a,%s",one);
2526 emitcode("","%05d$:",tlbl->key+100);
2531 /*-----------------------------------------------------------------*/
2532 /* genPlusBits - generates code for addition of two bits */
2533 /*-----------------------------------------------------------------*/
2534 static void genPlusBits (iCode *ic)
2536 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2537 symbol *lbl = newiTempLabel(NULL);
2538 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2539 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2540 emitcode("cpl","c");
2541 emitcode("","%05d$:",(lbl->key+100));
2542 outBitC(IC_RESULT(ic));
2545 emitcode("clr","a");
2546 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2547 emitcode("rlc","a");
2548 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2549 emitcode("addc","a,#0x00");
2550 outAcc(IC_RESULT(ic));
2555 /* This is the original version of this code.
2557 * This is being kept around for reference,
2558 * because I am not entirely sure I got it right...
2560 static void adjustArithmeticResult(iCode *ic)
2562 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2563 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2564 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2565 aopPut(AOP(IC_RESULT(ic)),
2566 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2569 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2570 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
2571 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2572 aopPut(AOP(IC_RESULT(ic)),
2573 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2576 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2577 AOP_SIZE(IC_LEFT(ic)) < 3 &&
2578 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
2579 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2580 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2582 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2583 aopPut(AOP(IC_RESULT(ic)),buffer,2);
2587 /* This is the pure and virtuous version of this code.
2588 * I'm pretty certain it's right, but not enough to toss the old
2591 static void adjustArithmeticResult(iCode *ic)
2593 if (opIsGptr(IC_RESULT(ic)) &&
2594 opIsGptr(IC_LEFT(ic)) &&
2595 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2597 aopPut(AOP(IC_RESULT(ic)),
2598 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
2602 if (opIsGptr(IC_RESULT(ic)) &&
2603 opIsGptr(IC_RIGHT(ic)) &&
2604 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2606 aopPut(AOP(IC_RESULT(ic)),
2607 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
2611 if (opIsGptr(IC_RESULT(ic)) &&
2612 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2613 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2614 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2615 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2617 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2618 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2623 /*-----------------------------------------------------------------*/
2624 /* genPlus - generates code for addition */
2625 /*-----------------------------------------------------------------*/
2626 static void genPlus (iCode *ic)
2628 int size, offset = 0;
2630 /* special cases :- */
2632 aopOp (IC_LEFT(ic),ic,FALSE);
2633 aopOp (IC_RIGHT(ic),ic,FALSE);
2634 aopOp (IC_RESULT(ic),ic,TRUE);
2636 /* if literal, literal on the right or
2637 if left requires ACC or right is already
2639 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2640 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2641 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2642 operand *t = IC_RIGHT(ic);
2643 IC_RIGHT(ic) = IC_LEFT(ic);
2647 /* if both left & right are in bit
2649 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2650 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2655 /* if left in bit space & right literal */
2656 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2657 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2658 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2659 /* if result in bit space */
2660 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2661 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
2662 emitcode("cpl","c");
2663 outBitC(IC_RESULT(ic));
2665 size = getDataSize(IC_RESULT(ic));
2667 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2668 emitcode("addc","a,#00");
2669 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2675 /* if I can do an increment instead
2676 of add then GOOD for ME */
2677 if (genPlusIncr (ic) == TRUE)
2680 size = getDataSize(IC_RESULT(ic));
2683 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2684 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2686 emitcode("add","a,%s",
2687 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2689 emitcode("addc","a,%s",
2690 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2692 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2694 emitcode("add","a,%s",
2695 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2697 emitcode("addc","a,%s",
2698 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2700 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2703 adjustArithmeticResult(ic);
2706 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2707 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2708 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2711 /*-----------------------------------------------------------------*/
2712 /* genMinusDec :- does subtraction with deccrement if possible */
2713 /*-----------------------------------------------------------------*/
2714 static bool genMinusDec (iCode *ic)
2716 unsigned int icount ;
2717 unsigned int size = getDataSize(IC_RESULT(ic));
2719 /* will try to generate an increment */
2720 /* if the right side is not a literal
2722 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2725 /* if the literal value of the right hand side
2726 is greater than 4 then it is not worth it */
2727 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2730 /* if decrement 16 bits in register */
2731 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2738 /* If the next instruction is a goto and the goto target
2739 * is <= 10 instructions previous to this, we can generate
2740 * jumps straight to that target.
2742 if (ic->next && ic->next->op == GOTO
2743 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2744 && labelRange <= 10 )
2746 emitcode(";", "tail decrement optimized");
2747 tlbl = IC_LABEL(ic->next);
2752 tlbl = newiTempLabel(NULL);
2756 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2757 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2758 IS_AOP_PREG(IC_RESULT(ic)))
2759 emitcode("cjne","%s,#0xff,%05d$"
2760 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2763 emitcode("mov","a,#0xff");
2764 emitcode("cjne","a,%s,%05d$"
2765 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2768 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2771 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2772 IS_AOP_PREG(IC_RESULT(ic)))
2773 emitcode("cjne","%s,#0xff,%05d$"
2774 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2777 emitcode("cjne","a,%s,%05d$"
2778 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2781 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2785 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2786 IS_AOP_PREG(IC_RESULT(ic)))
2787 emitcode("cjne","%s,#0xff,%05d$"
2788 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2791 emitcode("cjne","a,%s,%05d$"
2792 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2795 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2799 emitcode("","%05d$:",tlbl->key+100);
2804 /* if the sizes are greater than 1 then we cannot */
2805 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2806 AOP_SIZE(IC_LEFT(ic)) > 1 )
2809 /* we can if the aops of the left & result match or
2810 if they are in registers and the registers are the
2812 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2815 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2823 /*-----------------------------------------------------------------*/
2824 /* addSign - complete with sign */
2825 /*-----------------------------------------------------------------*/
2826 static void addSign(operand *result, int offset, int sign)
2828 int size = (getDataSize(result) - offset);
2831 emitcode("rlc","a");
2832 emitcode("subb","a,acc");
2834 aopPut(AOP(result),"a",offset++);
2837 aopPut(AOP(result),zero,offset++);
2841 /*-----------------------------------------------------------------*/
2842 /* genMinusBits - generates code for subtraction of two bits */
2843 /*-----------------------------------------------------------------*/
2844 static void genMinusBits (iCode *ic)
2846 symbol *lbl = newiTempLabel(NULL);
2847 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2848 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2849 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2850 emitcode("cpl","c");
2851 emitcode("","%05d$:",(lbl->key+100));
2852 outBitC(IC_RESULT(ic));
2855 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2856 emitcode("subb","a,acc");
2857 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
2858 emitcode("inc","a");
2859 emitcode("","%05d$:",(lbl->key+100));
2860 aopPut(AOP(IC_RESULT(ic)),"a",0);
2861 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
2865 /*-----------------------------------------------------------------*/
2866 /* genMinus - generates code for subtraction */
2867 /*-----------------------------------------------------------------*/
2868 static void genMinus (iCode *ic)
2870 int size, offset = 0;
2871 unsigned long lit = 0L;
2873 aopOp (IC_LEFT(ic),ic,FALSE);
2874 aopOp (IC_RIGHT(ic),ic,FALSE);
2875 aopOp (IC_RESULT(ic),ic,TRUE);
2877 /* special cases :- */
2878 /* if both left & right are in bit space */
2879 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2880 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2885 /* if I can do an decrement instead
2886 of subtract then GOOD for ME */
2887 if (genMinusDec (ic) == TRUE)
2890 size = getDataSize(IC_RESULT(ic));
2892 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
2896 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2900 /* if literal, add a,#-lit, else normal subb */
2902 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2903 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2904 emitcode("subb","a,%s",
2905 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2907 /* first add without previous c */
2909 emitcode("add","a,#0x%02x",
2910 (unsigned int)(lit & 0x0FFL));
2912 emitcode("addc","a,#0x%02x",
2913 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
2915 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2918 adjustArithmeticResult(ic);
2921 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2922 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2923 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2927 /*-----------------------------------------------------------------*/
2928 /* genMultbits :- multiplication of bits */
2929 /*-----------------------------------------------------------------*/
2930 static void genMultbits (operand *left,
2934 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2935 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
2940 /*-----------------------------------------------------------------*/
2941 /* genMultOneByte : 8 bit multiplication & division */
2942 /*-----------------------------------------------------------------*/
2943 static void genMultOneByte (operand *left,
2947 link *opetype = operandType(result);
2952 /* (if two literals, the value is computed before) */
2953 /* if one literal, literal on the right */
2954 if (AOP_TYPE(left) == AOP_LIT){
2960 size = AOP_SIZE(result);
2961 /* signed or unsigned */
2962 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2963 l = aopGet(AOP(left),0,FALSE,FALSE);
2965 emitcode("mul","ab");
2966 /* if result size = 1, mul signed = mul unsigned */
2967 aopPut(AOP(result),"a",0);
2969 if (SPEC_USIGN(opetype)){
2970 aopPut(AOP(result),"b",1);
2972 /* for filling the MSBs */
2973 emitcode("clr","a");
2976 emitcode("mov","a,b");
2978 /* adjust the MSB if left or right neg */
2980 /* if one literal */
2981 if (AOP_TYPE(right) == AOP_LIT){
2982 /* AND literal negative */
2983 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
2984 /* adjust MSB (c==0 after mul) */
2985 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2989 lbl = newiTempLabel(NULL);
2990 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2991 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
2992 emitcode("","%05d$:",(lbl->key+100));
2993 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2994 lbl = newiTempLabel(NULL);
2995 emitcode("jc","%05d$",(lbl->key+100));
2996 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2997 emitcode("","%05d$:",(lbl->key+100));
3000 lbl = newiTempLabel(NULL);
3001 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3002 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3003 emitcode("","%05d$:",(lbl->key+100));
3004 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3005 lbl = newiTempLabel(NULL);
3006 emitcode("jc","%05d$",(lbl->key+100));
3007 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
3008 emitcode("","%05d$:",(lbl->key+100));
3010 aopPut(AOP(result),"a",1);
3013 emitcode("rlc","a");
3014 emitcode("subb","a,acc");
3021 aopPut(AOP(result),"a",offset++);
3025 /*-----------------------------------------------------------------*/
3026 /* genMult - generates code for multiplication */
3027 /*-----------------------------------------------------------------*/
3028 static void genMult (iCode *ic)
3030 operand *left = IC_LEFT(ic);
3031 operand *right = IC_RIGHT(ic);
3032 operand *result= IC_RESULT(ic);
3034 /* assign the amsops */
3035 aopOp (left,ic,FALSE);
3036 aopOp (right,ic,FALSE);
3037 aopOp (result,ic,TRUE);
3039 /* special cases first */
3041 if (AOP_TYPE(left) == AOP_CRY &&
3042 AOP_TYPE(right)== AOP_CRY) {
3043 genMultbits(left,right,result);
3047 /* if both are of size == 1 */
3048 if (AOP_SIZE(left) == 1 &&
3049 AOP_SIZE(right) == 1 ) {
3050 genMultOneByte(left,right,result);
3054 /* should have been converted to function call */
3058 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3059 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3060 freeAsmop(result,NULL,ic,TRUE);
3063 /*-----------------------------------------------------------------*/
3064 /* genDivbits :- division of bits */
3065 /*-----------------------------------------------------------------*/
3066 static void genDivbits (operand *left,
3073 /* the result must be bit */
3074 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3075 l = aopGet(AOP(left),0,FALSE,FALSE);
3079 emitcode("div","ab");
3080 emitcode("rrc","a");
3081 aopPut(AOP(result),"c",0);
3084 /*-----------------------------------------------------------------*/
3085 /* genDivOneByte : 8 bit division */
3086 /*-----------------------------------------------------------------*/
3087 static void genDivOneByte (operand *left,
3091 link *opetype = operandType(result);
3096 size = AOP_SIZE(result) - 1;
3098 /* signed or unsigned */
3099 if (SPEC_USIGN(opetype)) {
3100 /* unsigned is easy */
3101 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3102 l = aopGet(AOP(left),0,FALSE,FALSE);
3104 emitcode("div","ab");
3105 aopPut(AOP(result),"a",0);
3107 aopPut(AOP(result),zero,offset++);
3111 /* signed is a little bit more difficult */
3113 /* save the signs of the operands */
3114 l = aopGet(AOP(left),0,FALSE,FALSE);
3116 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3117 emitcode("push","acc"); /* save it on the stack */
3119 /* now sign adjust for both left & right */
3120 l = aopGet(AOP(right),0,FALSE,FALSE);
3122 lbl = newiTempLabel(NULL);
3123 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3124 emitcode("cpl","a");
3125 emitcode("inc","a");
3126 emitcode("","%05d$:",(lbl->key+100));
3127 emitcode("mov","b,a");
3129 /* sign adjust left side */
3130 l = aopGet(AOP(left),0,FALSE,FALSE);
3133 lbl = newiTempLabel(NULL);
3134 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3135 emitcode("cpl","a");
3136 emitcode("inc","a");
3137 emitcode("","%05d$:",(lbl->key+100));
3139 /* now the division */
3140 emitcode("div","ab");
3141 /* we are interested in the lower order
3143 emitcode("mov","b,a");
3144 lbl = newiTempLabel(NULL);
3145 emitcode("pop","acc");
3146 /* if there was an over flow we don't
3147 adjust the sign of the result */
3148 emitcode("jb","ov,%05d$",(lbl->key+100));
3149 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3151 emitcode("clr","a");
3152 emitcode("subb","a,b");
3153 emitcode("mov","b,a");
3154 emitcode("","%05d$:",(lbl->key+100));
3156 /* now we are done */
3157 aopPut(AOP(result),"b",0);
3159 emitcode("mov","c,b.7");
3160 emitcode("subb","a,acc");
3163 aopPut(AOP(result),"a",offset++);
3167 /*-----------------------------------------------------------------*/
3168 /* genDiv - generates code for division */
3169 /*-----------------------------------------------------------------*/
3170 static void genDiv (iCode *ic)
3172 operand *left = IC_LEFT(ic);
3173 operand *right = IC_RIGHT(ic);
3174 operand *result= IC_RESULT(ic);
3176 /* assign the amsops */
3177 aopOp (left,ic,FALSE);
3178 aopOp (right,ic,FALSE);
3179 aopOp (result,ic,TRUE);
3181 /* special cases first */
3183 if (AOP_TYPE(left) == AOP_CRY &&
3184 AOP_TYPE(right)== AOP_CRY) {
3185 genDivbits(left,right,result);
3189 /* if both are of size == 1 */
3190 if (AOP_SIZE(left) == 1 &&
3191 AOP_SIZE(right) == 1 ) {
3192 genDivOneByte(left,right,result);
3196 /* should have been converted to function call */
3199 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3200 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3201 freeAsmop(result,NULL,ic,TRUE);
3204 /*-----------------------------------------------------------------*/
3205 /* genModbits :- modulus of bits */
3206 /*-----------------------------------------------------------------*/
3207 static void genModbits (operand *left,
3214 /* the result must be bit */
3215 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3216 l = aopGet(AOP(left),0,FALSE,FALSE);
3220 emitcode("div","ab");
3221 emitcode("mov","a,b");
3222 emitcode("rrc","a");
3223 aopPut(AOP(result),"c",0);
3226 /*-----------------------------------------------------------------*/
3227 /* genModOneByte : 8 bit modulus */
3228 /*-----------------------------------------------------------------*/
3229 static void genModOneByte (operand *left,
3233 link *opetype = operandType(result);
3237 /* signed or unsigned */
3238 if (SPEC_USIGN(opetype)) {
3239 /* unsigned is easy */
3240 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3241 l = aopGet(AOP(left),0,FALSE,FALSE);
3243 emitcode("div","ab");
3244 aopPut(AOP(result),"b",0);
3248 /* signed is a little bit more difficult */
3250 /* save the signs of the operands */
3251 l = aopGet(AOP(left),0,FALSE,FALSE);
3254 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3255 emitcode("push","acc"); /* save it on the stack */
3257 /* now sign adjust for both left & right */
3258 l = aopGet(AOP(right),0,FALSE,FALSE);
3261 lbl = newiTempLabel(NULL);
3262 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3263 emitcode("cpl","a");
3264 emitcode("inc","a");
3265 emitcode("","%05d$:",(lbl->key+100));
3266 emitcode("mov","b,a");
3268 /* sign adjust left side */
3269 l = aopGet(AOP(left),0,FALSE,FALSE);
3272 lbl = newiTempLabel(NULL);
3273 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3274 emitcode("cpl","a");
3275 emitcode("inc","a");
3276 emitcode("","%05d$:",(lbl->key+100));
3278 /* now the multiplication */
3279 emitcode("div","ab");
3280 /* we are interested in the lower order
3282 lbl = newiTempLabel(NULL);
3283 emitcode("pop","acc");
3284 /* if there was an over flow we don't
3285 adjust the sign of the result */
3286 emitcode("jb","ov,%05d$",(lbl->key+100));
3287 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3289 emitcode("clr","a");
3290 emitcode("subb","a,b");
3291 emitcode("mov","b,a");
3292 emitcode("","%05d$:",(lbl->key+100));
3294 /* now we are done */
3295 aopPut(AOP(result),"b",0);
3299 /*-----------------------------------------------------------------*/
3300 /* genMod - generates code for division */
3301 /*-----------------------------------------------------------------*/
3302 static void genMod (iCode *ic)
3304 operand *left = IC_LEFT(ic);
3305 operand *right = IC_RIGHT(ic);
3306 operand *result= IC_RESULT(ic);
3308 /* assign the amsops */
3309 aopOp (left,ic,FALSE);
3310 aopOp (right,ic,FALSE);
3311 aopOp (result,ic,TRUE);
3313 /* special cases first */
3315 if (AOP_TYPE(left) == AOP_CRY &&
3316 AOP_TYPE(right)== AOP_CRY) {
3317 genModbits(left,right,result);
3321 /* if both are of size == 1 */
3322 if (AOP_SIZE(left) == 1 &&
3323 AOP_SIZE(right) == 1 ) {
3324 genModOneByte(left,right,result);
3328 /* should have been converted to function call */
3332 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3333 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3334 freeAsmop(result,NULL,ic,TRUE);
3337 /*-----------------------------------------------------------------*/
3338 /* genIfxJump :- will create a jump depending on the ifx */
3339 /*-----------------------------------------------------------------*/
3340 static void genIfxJump (iCode *ic, char *jval)
3343 symbol *tlbl = newiTempLabel(NULL);
3346 /* if true label then we jump if condition
3348 if ( IC_TRUE(ic) ) {
3350 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3351 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3354 /* false label is present */
3355 jlbl = IC_FALSE(ic) ;
3356 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3357 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3359 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3360 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3362 emitcode(inst,"%05d$",tlbl->key+100);
3363 emitcode("ljmp","%05d$",jlbl->key+100);
3364 emitcode("","%05d$:",tlbl->key+100);
3366 /* mark the icode as generated */
3370 /*-----------------------------------------------------------------*/
3371 /* genCmp :- greater or less than comparison */
3372 /*-----------------------------------------------------------------*/
3373 static void genCmp (operand *left,operand *right,
3374 operand *result, iCode *ifx, int sign)
3376 int size, offset = 0 ;
3377 unsigned long lit = 0L;
3379 /* if left & right are bit variables */
3380 if (AOP_TYPE(left) == AOP_CRY &&
3381 AOP_TYPE(right) == AOP_CRY ) {
3382 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3383 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3385 /* subtract right from left if at the
3386 end the carry flag is set then we know that
3387 left is greater than right */
3388 size = max(AOP_SIZE(left),AOP_SIZE(right));
3390 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3391 if((size == 1) && !sign &&
3392 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3393 symbol *lbl = newiTempLabel(NULL);
3394 emitcode("cjne","%s,%s,%05d$",
3395 aopGet(AOP(left),offset,FALSE,FALSE),
3396 aopGet(AOP(right),offset,FALSE,FALSE),
3398 emitcode("","%05d$:",lbl->key+100);
3400 if(AOP_TYPE(right) == AOP_LIT){
3401 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3402 /* optimize if(x < 0) or if(x >= 0) */
3408 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE));
3409 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3410 genIfxJump (ifx,"acc.7");
3414 emitcode("rlc","a");
3421 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3422 if (sign && size == 0) {
3423 emitcode("xrl","a,#0x80");
3424 if (AOP_TYPE(right) == AOP_LIT){
3425 unsigned long lit = (unsigned long)
3426 floatFromVal(AOP(right)->aopu.aop_lit);
3427 emitcode("subb","a,#0x%02x",
3428 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3430 emitcode("mov","b,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3431 emitcode("xrl","b,#0x80");
3432 emitcode("subb","a,b");
3435 emitcode("subb","a,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3441 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3444 /* if the result is used in the next
3445 ifx conditional branch then generate
3446 code a little differently */
3448 genIfxJump (ifx,"c");
3451 /* leave the result in acc */
3455 /*-----------------------------------------------------------------*/
3456 /* genCmpGt :- greater than comparison */
3457 /*-----------------------------------------------------------------*/
3458 static void genCmpGt (iCode *ic, iCode *ifx)
3460 operand *left, *right, *result;
3461 link *letype , *retype;
3465 right= IC_RIGHT(ic);
3466 result = IC_RESULT(ic);
3468 letype = getSpec(operandType(left));
3469 retype =getSpec(operandType(right));
3470 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3471 /* assign the amsops */
3472 aopOp (left,ic,FALSE);
3473 aopOp (right,ic,FALSE);
3474 aopOp (result,ic,TRUE);
3476 genCmp(right, left, result, ifx, sign);
3478 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3479 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3480 freeAsmop(result,NULL,ic,TRUE);
3483 /*-----------------------------------------------------------------*/
3484 /* genCmpLt - less than comparisons */
3485 /*-----------------------------------------------------------------*/
3486 static void genCmpLt (iCode *ic, iCode *ifx)
3488 operand *left, *right, *result;
3489 link *letype , *retype;
3493 right= IC_RIGHT(ic);
3494 result = IC_RESULT(ic);
3496 letype = getSpec(operandType(left));
3497 retype =getSpec(operandType(right));
3498 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3500 /* assign the amsops */
3501 aopOp (left,ic,FALSE);
3502 aopOp (right,ic,FALSE);
3503 aopOp (result,ic,TRUE);
3505 genCmp(left, right, result, ifx, sign);
3507 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3508 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3509 freeAsmop(result,NULL,ic,TRUE);
3512 /*-----------------------------------------------------------------*/
3513 /* gencjneshort - compare and jump if not equal */
3514 /*-----------------------------------------------------------------*/
3515 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3517 int size = max(AOP_SIZE(left),AOP_SIZE(right));
3519 unsigned long lit = 0L;
3521 /* if the left side is a literal or
3522 if the right is in a pointer register and left
3524 if ((AOP_TYPE(left) == AOP_LIT) ||
3525 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3530 if(AOP_TYPE(right) == AOP_LIT)
3531 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3533 /* if the right side is a literal then anything goes */
3534 if (AOP_TYPE(right) == AOP_LIT &&
3535 AOP_TYPE(left) != AOP_DIR ) {
3537 emitcode("cjne","%s,%s,%05d$",
3538 aopGet(AOP(left),offset,FALSE,FALSE),
3539 aopGet(AOP(right),offset,FALSE,FALSE),
3545 /* if the right side is in a register or in direct space or
3546 if the left is a pointer register & right is not */
3547 else if (AOP_TYPE(right) == AOP_REG ||
3548 AOP_TYPE(right) == AOP_DIR ||
3549 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3550 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3552 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3553 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3554 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
3555 emitcode("jnz","%05d$",lbl->key+100);
3557 emitcode("cjne","a,%s,%05d$",
3558 aopGet(AOP(right),offset,FALSE,TRUE),
3563 /* right is a pointer reg need both a & b */
3565 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
3567 emitcode("mov","b,%s",l);
3568 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3569 emitcode("cjne","a,b,%05d$",lbl->key+100);
3575 /*-----------------------------------------------------------------*/
3576 /* gencjne - compare and jump if not equal */
3577 /*-----------------------------------------------------------------*/
3578 static void gencjne(operand *left, operand *right, symbol *lbl)
3580 symbol *tlbl = newiTempLabel(NULL);
3582 gencjneshort(left, right, lbl);
3584 emitcode("mov","a,%s",one);
3585 emitcode("sjmp","%05d$",tlbl->key+100);
3586 emitcode("","%05d$:",lbl->key+100);
3587 emitcode("clr","a");
3588 emitcode("","%05d$:",tlbl->key+100);
3591 /*-----------------------------------------------------------------*/
3592 /* genCmpEq - generates code for equal to */
3593 /*-----------------------------------------------------------------*/
3594 static void genCmpEq (iCode *ic, iCode *ifx)
3596 operand *left, *right, *result;
3598 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3599 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3600 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3602 /* if literal, literal on the right or
3603 if the right is in a pointer register and left
3605 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
3606 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3607 operand *t = IC_RIGHT(ic);
3608 IC_RIGHT(ic) = IC_LEFT(ic);
3612 if(ifx && !AOP_SIZE(result)){
3614 /* if they are both bit variables */
3615 if (AOP_TYPE(left) == AOP_CRY &&
3616 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3617 if(AOP_TYPE(right) == AOP_LIT){
3618 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3620 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3621 emitcode("cpl","c");
3622 } else if(lit == 1L) {
3623 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3625 emitcode("clr","c");
3627 /* AOP_TYPE(right) == AOP_CRY */
3629 symbol *lbl = newiTempLabel(NULL);
3630 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3631 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3632 emitcode("cpl","c");
3633 emitcode("","%05d$:",(lbl->key+100));
3635 /* if true label then we jump if condition
3637 tlbl = newiTempLabel(NULL);
3638 if ( IC_TRUE(ifx) ) {
3639 emitcode("jnc","%05d$",tlbl->key+100);
3640 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3642 emitcode("jc","%05d$",tlbl->key+100);
3643 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3645 emitcode("","%05d$:",tlbl->key+100);
3647 tlbl = newiTempLabel(NULL);
3648 gencjneshort(left, right, tlbl);
3649 if ( IC_TRUE(ifx) ) {
3650 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3651 emitcode("","%05d$:",tlbl->key+100);
3653 symbol *lbl = newiTempLabel(NULL);
3654 emitcode("sjmp","%05d$",lbl->key+100);
3655 emitcode("","%05d$:",tlbl->key+100);
3656 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3657 emitcode("","%05d$:",lbl->key+100);
3660 /* mark the icode as generated */
3665 /* if they are both bit variables */
3666 if (AOP_TYPE(left) == AOP_CRY &&
3667 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3668 if(AOP_TYPE(right) == AOP_LIT){
3669 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3671 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3672 emitcode("cpl","c");
3673 } else if(lit == 1L) {
3674 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3676 emitcode("clr","c");
3678 /* AOP_TYPE(right) == AOP_CRY */
3680 symbol *lbl = newiTempLabel(NULL);
3681 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3682 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3683 emitcode("cpl","c");
3684 emitcode("","%05d$:",(lbl->key+100));
3687 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
3692 genIfxJump (ifx,"c");
3695 /* if the result is used in an arithmetic operation
3696 then put the result in place */
3699 gencjne(left,right,newiTempLabel(NULL));
3700 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3701 aopPut(AOP(result),"a",0);
3705 genIfxJump (ifx,"a");
3708 /* if the result is used in an arithmetic operation
3709 then put the result in place */
3710 if (AOP_TYPE(result) != AOP_CRY)
3712 /* leave the result in acc */
3716 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3717 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3718 freeAsmop(result,NULL,ic,TRUE);
3721 /*-----------------------------------------------------------------*/
3722 /* ifxForOp - returns the icode containing the ifx for operand */
3723 /*-----------------------------------------------------------------*/
3724 static iCode *ifxForOp ( operand *op, iCode *ic )
3726 /* if true symbol then needs to be assigned */
3727 if (IS_TRUE_SYMOP(op))
3730 /* if this has register type condition and
3731 the next instruction is ifx with the same operand
3732 and live to of the operand is upto the ifx only then */
3734 ic->next->op == IFX &&
3735 IC_COND(ic->next)->key == op->key &&
3736 OP_SYMBOL(op)->liveTo <= ic->next->seq )
3741 /*-----------------------------------------------------------------*/
3742 /* genAndOp - for && operation */
3743 /*-----------------------------------------------------------------*/
3744 static void genAndOp (iCode *ic)
3746 operand *left,*right, *result;
3749 /* note here that && operations that are in an
3750 if statement are taken away by backPatchLabels
3751 only those used in arthmetic operations remain */
3752 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3753 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3754 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3756 /* if both are bit variables */
3757 if (AOP_TYPE(left) == AOP_CRY &&
3758 AOP_TYPE(right) == AOP_CRY ) {
3759 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3760 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3763 tlbl = newiTempLabel(NULL);
3765 emitcode("jz","%05d$",tlbl->key+100);
3767 emitcode("","%05d$:",tlbl->key+100);
3771 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3772 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3773 freeAsmop(result,NULL,ic,TRUE);
3777 /*-----------------------------------------------------------------*/
3778 /* genOrOp - for || operation */
3779 /*-----------------------------------------------------------------*/
3780 static void genOrOp (iCode *ic)
3782 operand *left,*right, *result;
3785 /* note here that || operations that are in an
3786 if statement are taken away by backPatchLabels
3787 only those used in arthmetic operations remain */
3788 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3789 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3790 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3792 /* if both are bit variables */
3793 if (AOP_TYPE(left) == AOP_CRY &&
3794 AOP_TYPE(right) == AOP_CRY ) {
3795 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3796 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
3799 tlbl = newiTempLabel(NULL);
3801 emitcode("jnz","%05d$",tlbl->key+100);
3803 emitcode("","%05d$:",tlbl->key+100);
3807 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3808 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3809 freeAsmop(result,NULL,ic,TRUE);
3812 /*-----------------------------------------------------------------*/
3813 /* isLiteralBit - test if lit == 2^n */
3814 /*-----------------------------------------------------------------*/
3815 static int isLiteralBit(unsigned long lit)
3817 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
3818 0x100L,0x200L,0x400L,0x800L,
3819 0x1000L,0x2000L,0x4000L,0x8000L,
3820 0x10000L,0x20000L,0x40000L,0x80000L,
3821 0x100000L,0x200000L,0x400000L,0x800000L,
3822 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
3823 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
3826 for(idx = 0; idx < 32; idx++)
3832 /*-----------------------------------------------------------------*/
3833 /* continueIfTrue - */
3834 /*-----------------------------------------------------------------*/
3835 static void continueIfTrue (iCode *ic)
3838 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3842 /*-----------------------------------------------------------------*/
3844 /*-----------------------------------------------------------------*/
3845 static void jumpIfTrue (iCode *ic)
3848 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3852 /*-----------------------------------------------------------------*/
3853 /* jmpTrueOrFalse - */
3854 /*-----------------------------------------------------------------*/
3855 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
3857 // ugly but optimized by peephole
3859 symbol *nlbl = newiTempLabel(NULL);
3860 emitcode("sjmp","%05d$",nlbl->key+100);
3861 emitcode("","%05d$:",tlbl->key+100);
3862 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3863 emitcode("","%05d$:",nlbl->key+100);
3866 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3867 emitcode("","%05d$:",tlbl->key+100);
3872 /*-----------------------------------------------------------------*/
3873 /* genAnd - code for and */
3874 /*-----------------------------------------------------------------*/
3875 static void genAnd (iCode *ic, iCode *ifx)
3877 operand *left, *right, *result;
3879 unsigned long lit = 0L;
3883 aopOp((left = IC_LEFT(ic)),ic,FALSE);
3884 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3885 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3888 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3890 AOP_TYPE(left), AOP_TYPE(right));
3891 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3893 AOP_SIZE(left), AOP_SIZE(right));
3896 /* if left is a literal & right is not then exchange them */
3897 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3898 AOP_NEEDSACC(left)) {
3899 operand *tmp = right ;
3904 /* if result = right then exchange them */
3905 if(sameRegs(AOP(result),AOP(right))){
3906 operand *tmp = right ;
3911 /* if right is bit then exchange them */
3912 if (AOP_TYPE(right) == AOP_CRY &&
3913 AOP_TYPE(left) != AOP_CRY){
3914 operand *tmp = right ;
3918 if(AOP_TYPE(right) == AOP_LIT)
3919 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3921 size = AOP_SIZE(result);
3924 // result = bit & yy;
3925 if (AOP_TYPE(left) == AOP_CRY){
3926 // c = bit & literal;
3927 if(AOP_TYPE(right) == AOP_LIT){
3929 if(size && sameRegs(AOP(result),AOP(left)))
3932 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3935 if(size && (AOP_TYPE(result) == AOP_CRY)){
3936 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
3939 if((AOP_TYPE(result) == AOP_CRY) && ifx){
3943 emitcode("clr","c");
3946 if (AOP_TYPE(right) == AOP_CRY){
3948 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3949 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3952 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
3954 emitcode("rrc","a");
3955 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3963 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
3964 genIfxJump(ifx, "c");
3968 // if(val & 0xZZ) - size = 0, ifx != FALSE -
3969 // bit = val & 0xZZ - size = 1, ifx = FALSE -
3970 if((AOP_TYPE(right) == AOP_LIT) &&
3971 (AOP_TYPE(result) == AOP_CRY) &&
3972 (AOP_TYPE(left) != AOP_CRY)){
3973 int posbit = isLiteralBit(lit);
3977 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
3980 emitcode("mov","c,acc.%d",posbit&0x07);
3984 sprintf(buffer,"acc.%d",posbit&0x07);
3985 genIfxJump(ifx, buffer);
3990 symbol *tlbl = newiTempLabel(NULL);
3991 int sizel = AOP_SIZE(left);
3993 emitcode("setb","c");
3995 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
3996 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
3998 if((posbit = isLiteralBit(bytelit)) != 0)
3999 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
4001 if(bytelit != 0x0FFL)
4002 emitcode("anl","a,%s",
4003 aopGet(AOP(right),offset,FALSE,TRUE));
4004 emitcode("jnz","%05d$",tlbl->key+100);
4009 // bit = left & literal
4011 emitcode("clr","c");
4012 emitcode("","%05d$:",tlbl->key+100);
4014 // if(left & literal)
4017 jmpTrueOrFalse(ifx, tlbl);
4025 /* if left is same as result */
4026 if(sameRegs(AOP(result),AOP(left))){
4027 for(;size--; offset++) {
4028 if(AOP_TYPE(right) == AOP_LIT){
4029 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4033 aopPut(AOP(result),zero,offset);
4035 if (IS_AOP_PREG(result)) {
4036 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4037 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4038 aopPut(AOP(result),"a",offset);
4040 emitcode("anl","%s,%s",
4041 aopGet(AOP(left),offset,FALSE,TRUE),
4042 aopGet(AOP(right),offset,FALSE,FALSE));
4044 if (AOP_TYPE(left) == AOP_ACC)
4045 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4047 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4048 if (IS_AOP_PREG(result)) {
4049 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4050 aopPut(AOP(result),"a",offset);
4053 emitcode("anl","%s,a",
4054 aopGet(AOP(left),offset,FALSE,TRUE));
4059 // left & result in different registers
4060 if(AOP_TYPE(result) == AOP_CRY){
4062 // if(size), result in bit
4063 // if(!size && ifx), conditional oper: if(left & right)
4064 symbol *tlbl = newiTempLabel(NULL);
4065 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4067 emitcode("setb","c");
4069 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4070 emitcode("anl","a,%s",
4071 aopGet(AOP(left),offset,FALSE,FALSE));
4072 emitcode("jnz","%05d$",tlbl->key+100);
4077 emitcode("","%05d$:",tlbl->key+100);
4080 jmpTrueOrFalse(ifx, tlbl);
4082 for(;(size--);offset++) {
4084 // result = left & right
4085 if(AOP_TYPE(right) == AOP_LIT){
4086 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
4088 aopGet(AOP(left),offset,FALSE,FALSE),
4091 } else if(bytelit == 0){
4092 aopPut(AOP(result),zero,offset);
4096 // faster than result <- left, anl result,right
4097 // and better if result is SFR
4098 if (AOP_TYPE(left) == AOP_ACC)
4099 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4101 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4102 emitcode("anl","a,%s",
4103 aopGet(AOP(left),offset,FALSE,FALSE));
4105 aopPut(AOP(result),"a",offset);
4111 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4112 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4113 freeAsmop(result,NULL,ic,TRUE);
4116 /*-----------------------------------------------------------------*/
4117 /* genOr - code for or */
4118 /*-----------------------------------------------------------------*/
4119 static void genOr (iCode *ic, iCode *ifx)
4121 operand *left, *right, *result;
4123 unsigned long lit = 0L;
4125 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4126 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4127 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4130 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4132 AOP_TYPE(left), AOP_TYPE(right));
4133 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4135 AOP_SIZE(left), AOP_SIZE(right));
4138 /* if left is a literal & right is not then exchange them */
4139 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4140 AOP_NEEDSACC(left)) {
4141 operand *tmp = right ;
4146 /* if result = right then exchange them */
4147 if(sameRegs(AOP(result),AOP(right))){
4148 operand *tmp = right ;
4153 /* if right is bit then exchange them */
4154 if (AOP_TYPE(right) == AOP_CRY &&
4155 AOP_TYPE(left) != AOP_CRY){
4156 operand *tmp = right ;
4160 if(AOP_TYPE(right) == AOP_LIT)
4161 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4163 size = AOP_SIZE(result);
4167 if (AOP_TYPE(left) == AOP_CRY){
4168 if(AOP_TYPE(right) == AOP_LIT){
4169 // c = bit & literal;
4171 // lit != 0 => result = 1
4172 if(AOP_TYPE(result) == AOP_CRY){
4174 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4176 continueIfTrue(ifx);
4179 emitcode("setb","c");
4181 // lit == 0 => result = left
4182 if(size && sameRegs(AOP(result),AOP(left)))
4184 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4187 if (AOP_TYPE(right) == AOP_CRY){
4189 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4190 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4194 symbol *tlbl = newiTempLabel(NULL);
4195 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4196 emitcode("setb","c");
4197 emitcode("jb","%s,%05d$",
4198 AOP(left)->aopu.aop_dir,tlbl->key+100);
4200 emitcode("jnz","%05d$",tlbl->key+100);
4201 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4202 jmpTrueOrFalse(ifx, tlbl);
4206 emitcode("","%05d$:",tlbl->key+100);
4215 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4216 genIfxJump(ifx, "c");
4220 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4221 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4222 if((AOP_TYPE(right) == AOP_LIT) &&
4223 (AOP_TYPE(result) == AOP_CRY) &&
4224 (AOP_TYPE(left) != AOP_CRY)){
4228 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4230 continueIfTrue(ifx);
4233 // lit = 0, result = boolean(left)
4235 emitcode("setb","c");
4238 symbol *tlbl = newiTempLabel(NULL);
4239 emitcode("jnz","%05d$",tlbl->key+100);
4241 emitcode("","%05d$:",tlbl->key+100);
4243 genIfxJump (ifx,"a");
4251 /* if left is same as result */
4252 if(sameRegs(AOP(result),AOP(left))){
4253 for(;size--; offset++) {
4254 if(AOP_TYPE(right) == AOP_LIT){
4255 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4258 if (IS_AOP_PREG(left)) {
4259 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4260 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4261 aopPut(AOP(result),"a",offset);
4263 emitcode("orl","%s,%s",
4264 aopGet(AOP(left),offset,FALSE,TRUE),
4265 aopGet(AOP(right),offset,FALSE,FALSE));
4267 if (AOP_TYPE(left) == AOP_ACC)
4268 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4270 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4271 if (IS_AOP_PREG(left)) {
4272 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4273 aopPut(AOP(result),"a",offset);
4275 emitcode("orl","%s,a",
4276 aopGet(AOP(left),offset,FALSE,TRUE));
4281 // left & result in different registers
4282 if(AOP_TYPE(result) == AOP_CRY){
4284 // if(size), result in bit
4285 // if(!size && ifx), conditional oper: if(left | right)
4286 symbol *tlbl = newiTempLabel(NULL);
4287 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4289 emitcode("setb","c");
4291 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4292 emitcode("orl","a,%s",
4293 aopGet(AOP(left),offset,FALSE,FALSE));
4294 emitcode("jnz","%05d$",tlbl->key+100);
4299 emitcode("","%05d$:",tlbl->key+100);
4302 jmpTrueOrFalse(ifx, tlbl);
4303 } else for(;(size--);offset++){
4305 // result = left & right
4306 if(AOP_TYPE(right) == AOP_LIT){
4307 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4309 aopGet(AOP(left),offset,FALSE,FALSE),
4314 // faster than result <- left, anl result,right
4315 // and better if result is SFR
4316 if (AOP_TYPE(left) == AOP_ACC)
4317 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4319 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4320 emitcode("orl","a,%s",
4321 aopGet(AOP(left),offset,FALSE,FALSE));
4323 aopPut(AOP(result),"a",offset);
4328 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4329 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4330 freeAsmop(result,NULL,ic,TRUE);
4333 /*-----------------------------------------------------------------*/
4334 /* genXor - code for xclusive or */
4335 /*-----------------------------------------------------------------*/
4336 static void genXor (iCode *ic, iCode *ifx)
4338 operand *left, *right, *result;
4340 unsigned long lit = 0L;
4342 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4343 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4344 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4347 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4349 AOP_TYPE(left), AOP_TYPE(right));
4350 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4352 AOP_SIZE(left), AOP_SIZE(right));
4355 /* if left is a literal & right is not ||
4356 if left needs acc & right does not */
4357 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4358 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4359 operand *tmp = right ;
4364 /* if result = right then exchange them */
4365 if(sameRegs(AOP(result),AOP(right))){
4366 operand *tmp = right ;
4371 /* if right is bit then exchange them */
4372 if (AOP_TYPE(right) == AOP_CRY &&
4373 AOP_TYPE(left) != AOP_CRY){
4374 operand *tmp = right ;
4378 if(AOP_TYPE(right) == AOP_LIT)
4379 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4381 size = AOP_SIZE(result);
4385 if (AOP_TYPE(left) == AOP_CRY){
4386 if(AOP_TYPE(right) == AOP_LIT){
4387 // c = bit & literal;
4389 // lit>>1 != 0 => result = 1
4390 if(AOP_TYPE(result) == AOP_CRY){
4392 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4394 continueIfTrue(ifx);
4397 emitcode("setb","c");
4401 // lit == 0, result = left
4402 if(size && sameRegs(AOP(result),AOP(left)))
4404 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4406 // lit == 1, result = not(left)
4407 if(size && sameRegs(AOP(result),AOP(left))){
4408 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4411 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4412 emitcode("cpl","c");
4419 symbol *tlbl = newiTempLabel(NULL);
4420 if (AOP_TYPE(right) == AOP_CRY){
4422 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4425 int sizer = AOP_SIZE(right);
4427 // if val>>1 != 0, result = 1
4428 emitcode("setb","c");
4430 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
4432 // test the msb of the lsb
4433 emitcode("anl","a,#0xfe");
4434 emitcode("jnz","%05d$",tlbl->key+100);
4438 emitcode("rrc","a");
4440 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4441 emitcode("cpl","c");
4442 emitcode("","%05d$:",(tlbl->key+100));
4449 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4450 genIfxJump(ifx, "c");
4454 if(sameRegs(AOP(result),AOP(left))){
4455 /* if left is same as result */
4456 for(;size--; offset++) {
4457 if(AOP_TYPE(right) == AOP_LIT){
4458 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4461 if (IS_AOP_PREG(left)) {
4462 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4463 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4464 aopPut(AOP(result),"a",offset);
4466 emitcode("xrl","%s,%s",
4467 aopGet(AOP(left),offset,FALSE,TRUE),
4468 aopGet(AOP(right),offset,FALSE,FALSE));
4470 if (AOP_TYPE(left) == AOP_ACC)
4471 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4473 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4474 if (IS_AOP_PREG(left)) {
4475 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4476 aopPut(AOP(result),"a",offset);
4478 emitcode("xrl","%s,a",
4479 aopGet(AOP(left),offset,FALSE,TRUE));
4484 // left & result in different registers
4485 if(AOP_TYPE(result) == AOP_CRY){
4487 // if(size), result in bit
4488 // if(!size && ifx), conditional oper: if(left ^ right)
4489 symbol *tlbl = newiTempLabel(NULL);
4490 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4492 emitcode("setb","c");
4494 if((AOP_TYPE(right) == AOP_LIT) &&
4495 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4496 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4498 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4499 emitcode("xrl","a,%s",
4500 aopGet(AOP(left),offset,FALSE,FALSE));
4502 emitcode("jnz","%05d$",tlbl->key+100);
4507 emitcode("","%05d$:",tlbl->key+100);
4510 jmpTrueOrFalse(ifx, tlbl);
4511 } else for(;(size--);offset++){
4513 // result = left & right
4514 if(AOP_TYPE(right) == AOP_LIT){
4515 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4517 aopGet(AOP(left),offset,FALSE,FALSE),
4522 // faster than result <- left, anl result,right
4523 // and better if result is SFR
4524 if (AOP_TYPE(left) == AOP_ACC)
4525 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4527 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4528 emitcode("xrl","a,%s",
4529 aopGet(AOP(left),offset,FALSE,TRUE));
4531 aopPut(AOP(result),"a",offset);
4536 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4537 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4538 freeAsmop(result,NULL,ic,TRUE);
4541 /*-----------------------------------------------------------------*/
4542 /* genInline - write the inline code out */
4543 /*-----------------------------------------------------------------*/
4544 static void genInline (iCode *ic)
4546 char buffer[MAX_INLINEASM];
4550 _G.inLine += (!options.asmpeep);
4551 strcpy(buffer,IC_INLINE(ic));
4553 /* emit each line as a code */
4572 /* emitcode("",buffer); */
4573 _G.inLine -= (!options.asmpeep);
4576 /*-----------------------------------------------------------------*/
4577 /* genRRC - rotate right with carry */
4578 /*-----------------------------------------------------------------*/
4579 static void genRRC (iCode *ic)
4581 operand *left , *result ;
4582 int size, offset = 0;
4585 /* rotate right with carry */
4587 result=IC_RESULT(ic);
4588 aopOp (left,ic,FALSE);
4589 aopOp (result,ic,FALSE);
4591 /* move it to the result */
4592 size = AOP_SIZE(result);
4596 l = aopGet(AOP(left),offset,FALSE,FALSE);
4598 emitcode("rrc","a");
4599 if (AOP_SIZE(result) > 1)
4600 aopPut(AOP(result),"a",offset--);
4602 /* now we need to put the carry into the
4603 highest order byte of the result */
4604 if (AOP_SIZE(result) > 1) {
4605 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
4608 emitcode("mov","acc.7,c");
4609 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
4610 freeAsmop(left,NULL,ic,TRUE);
4611 freeAsmop(result,NULL,ic,TRUE);
4614 /*-----------------------------------------------------------------*/
4615 /* genRLC - generate code for rotate left with carry */
4616 /*-----------------------------------------------------------------*/
4617 static void genRLC (iCode *ic)
4619 operand *left , *result ;
4620 int size, offset = 0;
4623 /* rotate right with carry */
4625 result=IC_RESULT(ic);
4626 aopOp (left,ic,FALSE);
4627 aopOp (result,ic,FALSE);
4629 /* move it to the result */
4630 size = AOP_SIZE(result);
4633 l = aopGet(AOP(left),offset,FALSE,FALSE);
4635 emitcode("add","a,acc");
4636 if (AOP_SIZE(result) > 1)
4637 aopPut(AOP(result),"a",offset++);
4639 l = aopGet(AOP(left),offset,FALSE,FALSE);
4641 emitcode("rlc","a");
4642 if (AOP_SIZE(result) > 1)
4643 aopPut(AOP(result),"a",offset++);
4646 /* now we need to put the carry into the
4647 highest order byte of the result */
4648 if (AOP_SIZE(result) > 1) {
4649 l = aopGet(AOP(result),0,FALSE,FALSE);
4652 emitcode("mov","acc.0,c");
4653 aopPut(AOP(result),"a",0);
4654 freeAsmop(left,NULL,ic,TRUE);
4655 freeAsmop(result,NULL,ic,TRUE);
4658 /*-----------------------------------------------------------------*/
4659 /* genGetHbit - generates code get highest order bit */
4660 /*-----------------------------------------------------------------*/
4661 static void genGetHbit (iCode *ic)
4663 operand *left, *result;
4665 result=IC_RESULT(ic);
4666 aopOp (left,ic,FALSE);
4667 aopOp (result,ic,FALSE);
4669 /* get the highest order byte into a */
4670 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
4671 if(AOP_TYPE(result) == AOP_CRY){
4672 emitcode("rlc","a");
4677 emitcode("anl","a,#0x01");
4682 freeAsmop(left,NULL,ic,TRUE);
4683 freeAsmop(result,NULL,ic,TRUE);
4686 /*-----------------------------------------------------------------*/
4687 /* AccRol - rotate left accumulator by known count */
4688 /*-----------------------------------------------------------------*/
4689 static void AccRol (int shCount)
4691 shCount &= 0x0007; // shCount : 0..7
4703 emitcode("swap","a");
4707 emitcode("swap","a");
4710 emitcode("swap","a");
4723 /*-----------------------------------------------------------------*/
4724 /* AccLsh - left shift accumulator by known count */
4725 /*-----------------------------------------------------------------*/
4726 static void AccLsh (int shCount)
4730 emitcode("add","a,acc");
4733 emitcode("add","a,acc");
4734 emitcode("add","a,acc");
4736 /* rotate left accumulator */
4738 /* and kill the lower order bits */
4739 emitcode("anl","a,#0x%02x", SLMask[shCount]);
4744 /*-----------------------------------------------------------------*/
4745 /* AccRsh - right shift accumulator by known count */
4746 /*-----------------------------------------------------------------*/
4747 static void AccRsh (int shCount)
4752 emitcode("rrc","a");
4754 /* rotate right accumulator */
4755 AccRol(8 - shCount);
4756 /* and kill the higher order bits */
4757 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4762 /*-----------------------------------------------------------------*/
4763 /* AccSRsh - signed right shift accumulator by known count */
4764 /*-----------------------------------------------------------------*/
4765 static void AccSRsh (int shCount)
4770 emitcode("mov","c,acc.7");
4771 emitcode("rrc","a");
4772 } else if(shCount == 2){
4773 emitcode("mov","c,acc.7");
4774 emitcode("rrc","a");
4775 emitcode("mov","c,acc.7");
4776 emitcode("rrc","a");
4778 tlbl = newiTempLabel(NULL);
4779 /* rotate right accumulator */
4780 AccRol(8 - shCount);
4781 /* and kill the higher order bits */
4782 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4783 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4784 emitcode("orl","a,#0x%02x",
4785 (unsigned char)~SRMask[shCount]);
4786 emitcode("","%05d$:",tlbl->key+100);
4791 /*-----------------------------------------------------------------*/
4792 /* shiftR1Left2Result - shift right one byte from left to result */
4793 /*-----------------------------------------------------------------*/
4794 static void shiftR1Left2Result (operand *left, int offl,
4795 operand *result, int offr,
4796 int shCount, int sign)
4798 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4799 /* shift right accumulator */
4804 aopPut(AOP(result),"a",offr);
4807 /*-----------------------------------------------------------------*/
4808 /* shiftL1Left2Result - shift left one byte from left to result */
4809 /*-----------------------------------------------------------------*/
4810 static void shiftL1Left2Result (operand *left, int offl,
4811 operand *result, int offr, int shCount)
4814 l = aopGet(AOP(left),offl,FALSE,FALSE);
4816 /* shift left accumulator */
4818 aopPut(AOP(result),"a",offr);
4821 /*-----------------------------------------------------------------*/
4822 /* movLeft2Result - move byte from left to result */
4823 /*-----------------------------------------------------------------*/
4824 static void movLeft2Result (operand *left, int offl,
4825 operand *result, int offr, int sign)
4828 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
4829 l = aopGet(AOP(left),offl,FALSE,FALSE);
4831 if (*l == '@' && (IS_AOP_PREG(result))) {
4832 emitcode("mov","a,%s",l);
4833 aopPut(AOP(result),"a",offr);
4836 aopPut(AOP(result),l,offr);
4838 /* MSB sign in acc.7 ! */
4839 if(getDataSize(left) == offl+1){
4840 emitcode("mov","a,%s",l);
4841 aopPut(AOP(result),"a",offr);
4848 /*-----------------------------------------------------------------*/
4849 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
4850 /*-----------------------------------------------------------------*/
4851 static void AccAXRrl1 (char *x)
4853 emitcode("rrc","a");
4854 emitcode("xch","a,%s", x);
4855 emitcode("rrc","a");
4856 emitcode("xch","a,%s", x);
4859 /*-----------------------------------------------------------------*/
4860 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
4861 /*-----------------------------------------------------------------*/
4862 static void AccAXLrl1 (char *x)
4864 emitcode("xch","a,%s",x);
4865 emitcode("rlc","a");
4866 emitcode("xch","a,%s",x);
4867 emitcode("rlc","a");
4870 /*-----------------------------------------------------------------*/
4871 /* AccAXLsh1 - left shift a:x<-0 by 1 */
4872 /*-----------------------------------------------------------------*/
4873 static void AccAXLsh1 (char *x)
4875 emitcode("xch","a,%s",x);
4876 emitcode("add","a,acc");
4877 emitcode("xch","a,%s",x);
4878 emitcode("rlc","a");
4881 /*-----------------------------------------------------------------*/
4882 /* AccAXLsh - left shift a:x by known count (0..7) */
4883 /*-----------------------------------------------------------------*/
4884 static void AccAXLsh (char *x, int shCount)
4898 case 5 : // AAAAABBB:CCCCCDDD
4899 AccRol(shCount); // BBBAAAAA:CCCCCDDD
4900 emitcode("anl","a,#0x%02x",
4901 SLMask[shCount]); // BBB00000:CCCCCDDD
4902 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
4903 AccRol(shCount); // DDDCCCCC:BBB00000
4904 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
4905 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
4906 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
4907 emitcode("anl","a,#0x%02x",
4908 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
4909 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
4910 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
4912 case 6 : // AAAAAABB:CCCCCCDD
4913 emitcode("anl","a,#0x%02x",
4914 SRMask[shCount]); // 000000BB:CCCCCCDD
4915 emitcode("mov","c,acc.0"); // c = B
4916 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
4917 AccAXRrl1(x); // BCCCCCCD:D000000B
4918 AccAXRrl1(x); // BBCCCCCC:DD000000
4920 case 7 : // a:x <<= 7
4921 emitcode("anl","a,#0x%02x",
4922 SRMask[shCount]); // 0000000B:CCCCCCCD
4923 emitcode("mov","c,acc.0"); // c = B
4924 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
4925 AccAXRrl1(x); // BCCCCCCC:D0000000
4932 /*-----------------------------------------------------------------*/
4933 /* AccAXRsh - right shift a:x known count (0..7) */
4934 /*-----------------------------------------------------------------*/
4935 static void AccAXRsh (char *x, int shCount)
4942 AccAXRrl1(x); // 0->a:x
4946 AccAXRrl1(x); // 0->a:x
4948 AccAXRrl1(x); // 0->a:x
4952 case 5 : // AAAAABBB:CCCCCDDD = a:x
4953 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
4954 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
4955 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
4956 emitcode("anl","a,#0x%02x",
4957 SRMask[shCount]); // 000CCCCC:BBBAAAAA
4958 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
4959 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
4960 emitcode("anl","a,#0x%02x",
4961 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
4962 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
4963 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
4964 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
4966 case 6 : // AABBBBBB:CCDDDDDD
4967 emitcode("mov","c,acc.7");
4968 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
4969 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
4970 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
4971 emitcode("anl","a,#0x%02x",
4972 SRMask[shCount]); // 000000AA:BBBBBBCC
4974 case 7 : // ABBBBBBB:CDDDDDDD
4975 emitcode("mov","c,acc.7"); // c = A
4976 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
4977 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
4978 emitcode("anl","a,#0x%02x",
4979 SRMask[shCount]); // 0000000A:BBBBBBBC
4986 /*-----------------------------------------------------------------*/
4987 /* AccAXRshS - right shift signed a:x known count (0..7) */
4988 /*-----------------------------------------------------------------*/
4989 static void AccAXRshS (char *x, int shCount)
4996 emitcode("mov","c,acc.7");
4997 AccAXRrl1(x); // s->a:x
5000 emitcode("mov","c,acc.7");
5001 AccAXRrl1(x); // s->a:x
5002 emitcode("mov","c,acc.7");
5003 AccAXRrl1(x); // s->a:x
5007 case 5 : // AAAAABBB:CCCCCDDD = a:x
5008 tlbl = newiTempLabel(NULL);
5009 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5010 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5011 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5012 emitcode("anl","a,#0x%02x",
5013 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5014 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5015 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5016 emitcode("anl","a,#0x%02x",
5017 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5018 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5019 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5020 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5021 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5022 emitcode("orl","a,#0x%02x",
5023 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5024 emitcode("","%05d$:",tlbl->key+100);
5025 break; // SSSSAAAA:BBBCCCCC
5026 case 6 : // AABBBBBB:CCDDDDDD
5027 tlbl = newiTempLabel(NULL);
5028 emitcode("mov","c,acc.7");
5029 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5030 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5031 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5032 emitcode("anl","a,#0x%02x",
5033 SRMask[shCount]); // 000000AA:BBBBBBCC
5034 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5035 emitcode("orl","a,#0x%02x",
5036 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5037 emitcode("","%05d$:",tlbl->key+100);
5039 case 7 : // ABBBBBBB:CDDDDDDD
5040 tlbl = newiTempLabel(NULL);
5041 emitcode("mov","c,acc.7"); // c = A
5042 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5043 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5044 emitcode("anl","a,#0x%02x",
5045 SRMask[shCount]); // 0000000A:BBBBBBBC
5046 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5047 emitcode("orl","a,#0x%02x",
5048 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5049 emitcode("","%05d$:",tlbl->key+100);
5056 /*-----------------------------------------------------------------*/
5057 /* shiftL2Left2Result - shift left two bytes from left to result */
5058 /*-----------------------------------------------------------------*/
5059 static void shiftL2Left2Result (operand *left, int offl,
5060 operand *result, int offr, int shCount)
5062 if(sameRegs(AOP(result), AOP(left)) &&
5063 ((offl + MSB16) == offr)){
5064 /* don't crash result[offr] */
5065 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5066 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5068 movLeft2Result(left,offl, result, offr, 0);
5069 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5071 /* ax << shCount (x = lsb(result))*/
5072 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5073 aopPut(AOP(result),"a",offr+MSB16);
5077 /*-----------------------------------------------------------------*/
5078 /* shiftR2Left2Result - shift right two bytes from left to result */
5079 /*-----------------------------------------------------------------*/
5080 static void shiftR2Left2Result (operand *left, int offl,
5081 operand *result, int offr,
5082 int shCount, int sign)
5084 if(sameRegs(AOP(result), AOP(left)) &&
5085 ((offl + MSB16) == offr)){
5086 /* don't crash result[offr] */
5087 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5088 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5090 movLeft2Result(left,offl, result, offr, 0);
5091 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5093 /* a:x >> shCount (x = lsb(result))*/
5095 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5097 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5098 if(getDataSize(result) > 1)
5099 aopPut(AOP(result),"a",offr+MSB16);
5102 /*-----------------------------------------------------------------*/
5103 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5104 /*-----------------------------------------------------------------*/
5105 static void shiftLLeftOrResult (operand *left, int offl,
5106 operand *result, int offr, int shCount)
5108 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5109 /* shift left accumulator */
5111 /* or with result */
5112 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5113 /* back to result */
5114 aopPut(AOP(result),"a",offr);
5117 /*-----------------------------------------------------------------*/
5118 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5119 /*-----------------------------------------------------------------*/
5120 static void shiftRLeftOrResult (operand *left, int offl,
5121 operand *result, int offr, int shCount)
5123 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5124 /* shift right accumulator */
5126 /* or with result */
5127 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5128 /* back to result */
5129 aopPut(AOP(result),"a",offr);
5132 /*-----------------------------------------------------------------*/
5133 /* genlshOne - left shift a one byte quantity by known count */
5134 /*-----------------------------------------------------------------*/
5135 static void genlshOne (operand *result, operand *left, int shCount)
5137 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5140 /*-----------------------------------------------------------------*/
5141 /* genlshTwo - left shift two bytes by known amount != 0 */
5142 /*-----------------------------------------------------------------*/
5143 static void genlshTwo (operand *result,operand *left, int shCount)
5147 size = getDataSize(result);
5149 /* if shCount >= 8 */
5155 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5157 movLeft2Result(left, LSB, result, MSB16, 0);
5159 aopPut(AOP(result),zero,LSB);
5162 /* 1 <= shCount <= 7 */
5165 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5167 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5171 /*-----------------------------------------------------------------*/
5172 /* shiftLLong - shift left one long from left to result */
5173 /* offl = LSB or MSB16 */
5174 /*-----------------------------------------------------------------*/
5175 static void shiftLLong (operand *left, operand *result, int offr )
5178 int size = AOP_SIZE(result);
5180 if(size >= LSB+offr){
5181 l = aopGet(AOP(left),LSB,FALSE,FALSE);
5183 emitcode("add","a,acc");
5184 if (sameRegs(AOP(left),AOP(result)) &&
5185 size >= MSB16+offr && offr != LSB )
5186 emitcode("xch","a,%s",
5187 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
5189 aopPut(AOP(result),"a",LSB+offr);
5192 if(size >= MSB16+offr){
5193 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5194 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
5197 emitcode("rlc","a");
5198 if (sameRegs(AOP(left),AOP(result)) &&
5199 size >= MSB24+offr && offr != LSB)
5200 emitcode("xch","a,%s",
5201 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
5203 aopPut(AOP(result),"a",MSB16+offr);
5206 if(size >= MSB24+offr){
5207 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5208 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
5211 emitcode("rlc","a");
5212 if (sameRegs(AOP(left),AOP(result)) &&
5213 size >= MSB32+offr && offr != LSB )
5214 emitcode("xch","a,%s",
5215 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
5217 aopPut(AOP(result),"a",MSB24+offr);
5220 if(size > MSB32+offr){
5221 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5222 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
5225 emitcode("rlc","a");
5226 aopPut(AOP(result),"a",MSB32+offr);
5229 aopPut(AOP(result),zero,LSB);
5232 /*-----------------------------------------------------------------*/
5233 /* genlshFour - shift four byte by a known amount != 0 */
5234 /*-----------------------------------------------------------------*/
5235 static void genlshFour (operand *result, operand *left, int shCount)
5239 size = AOP_SIZE(result);
5241 /* if shifting more that 3 bytes */
5242 if (shCount >= 24 ) {
5245 /* lowest order of left goes to the highest
5246 order of the destination */
5247 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5249 movLeft2Result(left, LSB, result, MSB32, 0);
5250 aopPut(AOP(result),zero,LSB);
5251 aopPut(AOP(result),zero,MSB16);
5252 aopPut(AOP(result),zero,MSB32);
5256 /* more than two bytes */
5257 else if ( shCount >= 16 ) {
5258 /* lower order two bytes goes to higher order two bytes */
5260 /* if some more remaining */
5262 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5264 movLeft2Result(left, MSB16, result, MSB32, 0);
5265 movLeft2Result(left, LSB, result, MSB24, 0);
5267 aopPut(AOP(result),zero,MSB16);
5268 aopPut(AOP(result),zero,LSB);
5272 /* if more than 1 byte */
5273 else if ( shCount >= 8 ) {
5274 /* lower order three bytes goes to higher order three bytes */
5278 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5280 movLeft2Result(left, LSB, result, MSB16, 0);
5282 else{ /* size = 4 */
5284 movLeft2Result(left, MSB24, result, MSB32, 0);
5285 movLeft2Result(left, MSB16, result, MSB24, 0);
5286 movLeft2Result(left, LSB, result, MSB16, 0);
5287 aopPut(AOP(result),zero,LSB);
5289 else if(shCount == 1)
5290 shiftLLong(left, result, MSB16);
5292 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5293 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5294 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5295 aopPut(AOP(result),zero,LSB);
5300 /* 1 <= shCount <= 7 */
5301 else if(shCount <= 2){
5302 shiftLLong(left, result, LSB);
5304 shiftLLong(result, result, LSB);
5306 /* 3 <= shCount <= 7, optimize */
5308 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5309 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5310 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5314 /*-----------------------------------------------------------------*/
5315 /* genLeftShiftLiteral - left shifting by known count */
5316 /*-----------------------------------------------------------------*/
5317 static void genLeftShiftLiteral (operand *left,
5322 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5325 freeAsmop(right,NULL,ic,TRUE);
5327 aopOp(left,ic,FALSE);
5328 aopOp(result,ic,FALSE);
5330 size = getSize(operandType(result));
5333 emitcode("; shift left ","result %d, left %d",size,
5337 /* I suppose that the left size >= result size */
5340 movLeft2Result(left, size, result, size, 0);
5344 else if(shCount >= (size * 8))
5346 aopPut(AOP(result),zero,size);
5350 genlshOne (result,left,shCount);
5355 genlshTwo (result,left,shCount);
5359 genlshFour (result,left,shCount);
5363 freeAsmop(left,NULL,ic,TRUE);
5364 freeAsmop(result,NULL,ic,TRUE);
5367 /*-----------------------------------------------------------------*/
5368 /* genLeftShift - generates code for left shifting */
5369 /*-----------------------------------------------------------------*/
5370 static void genLeftShift (iCode *ic)
5372 operand *left,*right, *result;
5375 symbol *tlbl , *tlbl1;
5377 right = IC_RIGHT(ic);
5379 result = IC_RESULT(ic);
5381 aopOp(right,ic,FALSE);
5383 /* if the shift count is known then do it
5384 as efficiently as possible */
5385 if (AOP_TYPE(right) == AOP_LIT) {
5386 genLeftShiftLiteral (left,right,result,ic);
5390 /* shift count is unknown then we have to form
5391 a loop get the loop count in B : Note: we take
5392 only the lower order byte since shifting
5393 more that 32 bits make no sense anyway, ( the
5394 largest size of an object can be only 32 bits ) */
5396 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5397 emitcode("inc","b");
5398 freeAsmop (right,NULL,ic,TRUE);
5399 aopOp(left,ic,FALSE);
5400 aopOp(result,ic,FALSE);
5402 /* now move the left to the result if they are not the
5404 if (!sameRegs(AOP(left),AOP(result)) &&
5405 AOP_SIZE(result) > 1) {
5407 size = AOP_SIZE(result);
5410 l = aopGet(AOP(left),offset,FALSE,TRUE);
5411 if (*l == '@' && (IS_AOP_PREG(result))) {
5413 emitcode("mov","a,%s",l);
5414 aopPut(AOP(result),"a",offset);
5416 aopPut(AOP(result),l,offset);
5421 tlbl = newiTempLabel(NULL);
5422 size = AOP_SIZE(result);
5424 tlbl1 = newiTempLabel(NULL);
5426 /* if it is only one byte then */
5428 symbol *tlbl1 = newiTempLabel(NULL);
5430 l = aopGet(AOP(left),0,FALSE,FALSE);
5432 emitcode("sjmp","%05d$",tlbl1->key+100);
5433 emitcode("","%05d$:",tlbl->key+100);
5434 emitcode("add","a,acc");
5435 emitcode("","%05d$:",tlbl1->key+100);
5436 emitcode("djnz","b,%05d$",tlbl->key+100);
5437 aopPut(AOP(result),"a",0);
5441 reAdjustPreg(AOP(result));
5443 emitcode("sjmp","%05d$",tlbl1->key+100);
5444 emitcode("","%05d$:",tlbl->key+100);
5445 l = aopGet(AOP(result),offset,FALSE,FALSE);
5447 emitcode("add","a,acc");
5448 aopPut(AOP(result),"a",offset++);
5450 l = aopGet(AOP(result),offset,FALSE,FALSE);
5452 emitcode("rlc","a");
5453 aopPut(AOP(result),"a",offset++);
5455 reAdjustPreg(AOP(result));
5457 emitcode("","%05d$:",tlbl1->key+100);
5458 emitcode("djnz","b,%05d$",tlbl->key+100);
5460 freeAsmop(left,NULL,ic,TRUE);
5461 freeAsmop(result,NULL,ic,TRUE);
5464 /*-----------------------------------------------------------------*/
5465 /* genrshOne - right shift a one byte quantity by known count */
5466 /*-----------------------------------------------------------------*/
5467 static void genrshOne (operand *result, operand *left,
5468 int shCount, int sign)
5470 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
5473 /*-----------------------------------------------------------------*/
5474 /* genrshTwo - right shift two bytes by known amount != 0 */
5475 /*-----------------------------------------------------------------*/
5476 static void genrshTwo (operand *result,operand *left,
5477 int shCount, int sign)
5479 /* if shCount >= 8 */
5483 shiftR1Left2Result(left, MSB16, result, LSB,
5486 movLeft2Result(left, MSB16, result, LSB, sign);
5487 addSign(result, MSB16, sign);
5490 /* 1 <= shCount <= 7 */
5492 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
5495 /*-----------------------------------------------------------------*/
5496 /* shiftRLong - shift right one long from left to result */
5497 /* offl = LSB or MSB16 */
5498 /*-----------------------------------------------------------------*/
5499 static void shiftRLong (operand *left, int offl,
5500 operand *result, int sign)
5503 emitcode("clr","c");
5504 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
5506 emitcode("mov","c,acc.7");
5507 emitcode("rrc","a");
5508 aopPut(AOP(result),"a",MSB32-offl);
5510 /* add sign of "a" */
5511 addSign(result, MSB32, sign);
5513 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
5514 emitcode("rrc","a");
5515 aopPut(AOP(result),"a",MSB24-offl);
5517 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
5518 emitcode("rrc","a");
5519 aopPut(AOP(result),"a",MSB16-offl);
5522 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
5523 emitcode("rrc","a");
5524 aopPut(AOP(result),"a",LSB);
5528 /*-----------------------------------------------------------------*/
5529 /* genrshFour - shift four byte by a known amount != 0 */
5530 /*-----------------------------------------------------------------*/
5531 static void genrshFour (operand *result, operand *left,
5532 int shCount, int sign)
5534 /* if shifting more that 3 bytes */
5535 if(shCount >= 24 ) {
5538 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
5540 movLeft2Result(left, MSB32, result, LSB, sign);
5541 addSign(result, MSB16, sign);
5543 else if(shCount >= 16){
5546 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
5548 movLeft2Result(left, MSB24, result, LSB, 0);
5549 movLeft2Result(left, MSB32, result, MSB16, sign);
5551 addSign(result, MSB24, sign);
5553 else if(shCount >= 8){
5556 shiftRLong(left, MSB16, result, sign);
5557 else if(shCount == 0){
5558 movLeft2Result(left, MSB16, result, LSB, 0);
5559 movLeft2Result(left, MSB24, result, MSB16, 0);
5560 movLeft2Result(left, MSB32, result, MSB24, sign);
5561 addSign(result, MSB32, sign);
5564 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
5565 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
5566 /* the last shift is signed */
5567 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
5568 addSign(result, MSB32, sign);
5571 else{ /* 1 <= shCount <= 7 */
5573 shiftRLong(left, LSB, result, sign);
5575 shiftRLong(result, LSB, result, sign);
5578 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
5579 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
5580 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
5585 /*-----------------------------------------------------------------*/
5586 /* genRightShiftLiteral - right shifting by known count */
5587 /*-----------------------------------------------------------------*/
5588 static void genRightShiftLiteral (operand *left,
5594 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5597 freeAsmop(right,NULL,ic,TRUE);
5599 aopOp(left,ic,FALSE);
5600 aopOp(result,ic,FALSE);
5603 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
5607 size = getDataSize(left);
5608 /* test the LEFT size !!! */
5610 /* I suppose that the left size >= result size */
5612 size = getDataSize(result);
5614 movLeft2Result(left, size, result, size, 0);
5617 else if(shCount >= (size * 8)){
5619 /* get sign in acc.7 */
5620 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
5621 addSign(result, LSB, sign);
5625 genrshOne (result,left,shCount,sign);
5629 genrshTwo (result,left,shCount,sign);
5633 genrshFour (result,left,shCount,sign);
5639 freeAsmop(left,NULL,ic,TRUE);
5640 freeAsmop(result,NULL,ic,TRUE);
5644 /*-----------------------------------------------------------------*/
5645 /* genSignedRightShift - right shift of signed number */
5646 /*-----------------------------------------------------------------*/
5647 static void genSignedRightShift (iCode *ic)
5649 operand *right, *left, *result;
5652 symbol *tlbl, *tlbl1 ;
5654 /* we do it the hard way put the shift count in b
5655 and loop thru preserving the sign */
5657 right = IC_RIGHT(ic);
5659 result = IC_RESULT(ic);
5661 aopOp(right,ic,FALSE);
5664 if ( AOP_TYPE(right) == AOP_LIT) {
5665 genRightShiftLiteral (left,right,result,ic,1);
5668 /* shift count is unknown then we have to form
5669 a loop get the loop count in B : Note: we take
5670 only the lower order byte since shifting
5671 more that 32 bits make no sense anyway, ( the
5672 largest size of an object can be only 32 bits ) */
5674 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5675 emitcode("inc","b");
5676 freeAsmop (right,NULL,ic,TRUE);
5677 aopOp(left,ic,FALSE);
5678 aopOp(result,ic,FALSE);
5680 /* now move the left to the result if they are not the
5682 if (!sameRegs(AOP(left),AOP(result)) &&
5683 AOP_SIZE(result) > 1) {
5685 size = AOP_SIZE(result);
5688 l = aopGet(AOP(left),offset,FALSE,TRUE);
5689 if (*l == '@' && IS_AOP_PREG(result)) {
5691 emitcode("mov","a,%s",l);
5692 aopPut(AOP(result),"a",offset);
5694 aopPut(AOP(result),l,offset);
5699 /* mov the highest order bit to OVR */
5700 tlbl = newiTempLabel(NULL);
5701 tlbl1= newiTempLabel(NULL);
5703 size = AOP_SIZE(result);
5705 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
5706 emitcode("rlc","a");
5707 emitcode("mov","ov,c");
5708 /* if it is only one byte then */
5710 l = aopGet(AOP(left),0,FALSE,FALSE);
5712 emitcode("sjmp","%05d$",tlbl1->key+100);
5713 emitcode("","%05d$:",tlbl->key+100);
5714 emitcode("mov","c,ov");
5715 emitcode("rrc","a");
5716 emitcode("","%05d$:",tlbl1->key+100);
5717 emitcode("djnz","b,%05d$",tlbl->key+100);
5718 aopPut(AOP(result),"a",0);
5722 reAdjustPreg(AOP(result));
5723 emitcode("sjmp","%05d$",tlbl1->key+100);
5724 emitcode("","%05d$:",tlbl->key+100);
5725 emitcode("mov","c,ov");
5727 l = aopGet(AOP(result),offset,FALSE,FALSE);
5729 emitcode("rrc","a");
5730 aopPut(AOP(result),"a",offset--);
5732 reAdjustPreg(AOP(result));
5733 emitcode("","%05d$:",tlbl1->key+100);
5734 emitcode("djnz","b,%05d$",tlbl->key+100);
5737 freeAsmop(left,NULL,ic,TRUE);
5738 freeAsmop(result,NULL,ic,TRUE);
5741 /*-----------------------------------------------------------------*/
5742 /* genRightShift - generate code for right shifting */
5743 /*-----------------------------------------------------------------*/
5744 static void genRightShift (iCode *ic)
5746 operand *right, *left, *result;
5750 symbol *tlbl, *tlbl1 ;
5752 /* if signed then we do it the hard way preserve the
5753 sign bit moving it inwards */
5754 retype = getSpec(operandType(IC_RESULT(ic)));
5756 if (!SPEC_USIGN(retype)) {
5757 genSignedRightShift (ic);
5761 /* signed & unsigned types are treated the same : i.e. the
5762 signed is NOT propagated inwards : quoting from the
5763 ANSI - standard : "for E1 >> E2, is equivalent to division
5764 by 2**E2 if unsigned or if it has a non-negative value,
5765 otherwise the result is implementation defined ", MY definition
5766 is that the sign does not get propagated */
5768 right = IC_RIGHT(ic);
5770 result = IC_RESULT(ic);
5772 aopOp(right,ic,FALSE);
5774 /* if the shift count is known then do it
5775 as efficiently as possible */
5776 if (AOP_TYPE(right) == AOP_LIT) {
5777 genRightShiftLiteral (left,right,result,ic, 0);
5781 /* shift count is unknown then we have to form
5782 a loop get the loop count in B : Note: we take
5783 only the lower order byte since shifting
5784 more that 32 bits make no sense anyway, ( the
5785 largest size of an object can be only 32 bits ) */
5787 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5788 emitcode("inc","b");
5789 freeAsmop (right,NULL,ic,TRUE);
5790 aopOp(left,ic,FALSE);
5791 aopOp(result,ic,FALSE);
5793 /* now move the left to the result if they are not the
5795 if (!sameRegs(AOP(left),AOP(result)) &&
5796 AOP_SIZE(result) > 1) {
5798 size = AOP_SIZE(result);
5801 l = aopGet(AOP(left),offset,FALSE,TRUE);
5802 if (*l == '@' && IS_AOP_PREG(result)) {
5804 emitcode("mov","a,%s",l);
5805 aopPut(AOP(result),"a",offset);
5807 aopPut(AOP(result),l,offset);
5812 tlbl = newiTempLabel(NULL);
5813 tlbl1= newiTempLabel(NULL);
5814 size = AOP_SIZE(result);
5817 /* if it is only one byte then */
5819 l = aopGet(AOP(left),0,FALSE,FALSE);
5821 emitcode("sjmp","%05d$",tlbl1->key+100);
5822 emitcode("","%05d$:",tlbl->key+100);
5824 emitcode("rrc","a");
5825 emitcode("","%05d$:",tlbl1->key+100);
5826 emitcode("djnz","b,%05d$",tlbl->key+100);
5827 aopPut(AOP(result),"a",0);
5831 reAdjustPreg(AOP(result));
5832 emitcode("sjmp","%05d$",tlbl1->key+100);
5833 emitcode("","%05d$:",tlbl->key+100);
5836 l = aopGet(AOP(result),offset,FALSE,FALSE);
5838 emitcode("rrc","a");
5839 aopPut(AOP(result),"a",offset--);
5841 reAdjustPreg(AOP(result));
5843 emitcode("","%05d$:",tlbl1->key+100);
5844 emitcode("djnz","b,%05d$",tlbl->key+100);
5847 freeAsmop(left,NULL,ic,TRUE);
5848 freeAsmop(result,NULL,ic,TRUE);
5851 /*-----------------------------------------------------------------*/
5852 /* genUnpackBits - generates code for unpacking bits */
5853 /*-----------------------------------------------------------------*/
5854 static void genUnpackBits (operand *result, char *rname, int ptype)
5861 etype = getSpec(operandType(result));
5863 /* read the first byte */
5868 emitcode("mov","a,@%s",rname);
5872 emitcode("movx","a,@%s",rname);
5876 emitcode("movx","a,@dptr");
5880 emitcode("clr","a");
5881 emitcode("movc","a","@a+dptr");
5885 emitcode("lcall","__gptrget");
5889 /* if we have bitdisplacement then it fits */
5890 /* into this byte completely or if length is */
5891 /* less than a byte */
5892 if ((shCnt = SPEC_BSTR(etype)) ||
5893 (SPEC_BLEN(etype) <= 8)) {
5895 /* shift right acc */
5898 emitcode("anl","a,#0x%02x",
5899 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
5900 aopPut(AOP(result),"a",offset);
5904 /* bit field did not fit in a byte */
5905 rlen = SPEC_BLEN(etype) - 8;
5906 aopPut(AOP(result),"a",offset++);
5913 emitcode("inc","%s",rname);
5914 emitcode("mov","a,@%s",rname);
5918 emitcode("inc","%s",rname);
5919 emitcode("movx","a,@%s",rname);
5923 emitcode("inc","dptr");
5924 emitcode("movx","a,@dptr");
5928 emitcode("clr","a");
5929 emitcode("inc","dptr");
5930 emitcode("movc","a","@a+dptr");
5934 emitcode("inc","dptr");
5935 emitcode("lcall","__gptrget");
5940 /* if we are done */
5944 aopPut(AOP(result),"a",offset++);
5949 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
5950 aopPut(AOP(result),"a",offset);
5957 /*-----------------------------------------------------------------*/
5958 /* genDataPointerGet - generates code when ptr offset is known */
5959 /*-----------------------------------------------------------------*/
5960 static void genDataPointerGet (operand *left,
5966 int size , offset = 0;
5967 aopOp(result,ic,TRUE);
5969 /* get the string representation of the name */
5970 l = aopGet(AOP(left),0,FALSE,TRUE);
5971 size = AOP_SIZE(result);
5974 sprintf(buffer,"(%s + %d)",l+1,offset);
5976 sprintf(buffer,"%s",l+1);
5977 aopPut(AOP(result),buffer,offset++);
5980 freeAsmop(left,NULL,ic,TRUE);
5981 freeAsmop(result,NULL,ic,TRUE);
5984 /*-----------------------------------------------------------------*/
5985 /* genNearPointerGet - emitcode for near pointer fetch */
5986 /*-----------------------------------------------------------------*/
5987 static void genNearPointerGet (operand *left,
5994 link *rtype, *retype;
5995 link *ltype = operandType(left);
5998 rtype = operandType(result);
5999 retype= getSpec(rtype);
6001 aopOp(left,ic,FALSE);
6003 /* if left is rematerialisable and
6004 result is not bit variable type and
6005 the left is pointer to data space i.e
6006 lower 128 bytes of space */
6007 if (AOP_TYPE(left) == AOP_IMMD &&
6008 !IS_BITVAR(retype) &&
6009 DCL_TYPE(ltype) == POINTER) {
6010 genDataPointerGet (left,result,ic);
6014 /* if the value is already in a pointer register
6015 then don't need anything more */
6016 if (!AOP_INPREG(AOP(left))) {
6017 /* otherwise get a free pointer register */
6019 preg = getFreePtr(ic,&aop,FALSE);
6020 emitcode("mov","%s,%s",
6022 aopGet(AOP(left),0,FALSE,TRUE));
6023 rname = preg->name ;
6025 rname = aopGet(AOP(left),0,FALSE,FALSE);
6027 freeAsmop(left,NULL,ic,TRUE);
6028 aopOp (result,ic,FALSE);
6030 /* if bitfield then unpack the bits */
6031 if (IS_BITVAR(retype))
6032 genUnpackBits (result,rname,POINTER);
6034 /* we have can just get the values */
6035 int size = AOP_SIZE(result);
6039 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6041 emitcode("mov","a,@%s",rname);
6042 aopPut(AOP(result),"a",offset);
6044 sprintf(buffer,"@%s",rname);
6045 aopPut(AOP(result),buffer,offset);
6049 emitcode("inc","%s",rname);
6053 /* now some housekeeping stuff */
6055 /* we had to allocate for this iCode */
6056 freeAsmop(NULL,aop,ic,TRUE);
6058 /* we did not allocate which means left
6059 already in a pointer register, then
6060 if size > 0 && this could be used again
6061 we have to point it back to where it
6063 if (AOP_SIZE(result) > 1 &&
6064 !OP_SYMBOL(left)->remat &&
6065 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6067 int size = AOP_SIZE(result) - 1;
6069 emitcode("dec","%s",rname);
6074 freeAsmop(result,NULL,ic,TRUE);
6078 /*-----------------------------------------------------------------*/
6079 /* genPagedPointerGet - emitcode for paged pointer fetch */
6080 /*-----------------------------------------------------------------*/
6081 static void genPagedPointerGet (operand *left,
6088 link *rtype, *retype;
6090 rtype = operandType(result);
6091 retype= getSpec(rtype);
6093 aopOp(left,ic,FALSE);
6095 /* if the value is already in a pointer register
6096 then don't need anything more */
6097 if (!AOP_INPREG(AOP(left))) {
6098 /* otherwise get a free pointer register */
6100 preg = getFreePtr(ic,&aop,FALSE);
6101 emitcode("mov","%s,%s",
6103 aopGet(AOP(left),0,FALSE,TRUE));
6104 rname = preg->name ;
6106 rname = aopGet(AOP(left),0,FALSE,FALSE);
6108 freeAsmop(left,NULL,ic,TRUE);
6109 aopOp (result,ic,FALSE);
6111 /* if bitfield then unpack the bits */
6112 if (IS_BITVAR(retype))
6113 genUnpackBits (result,rname,PPOINTER);
6115 /* we have can just get the values */
6116 int size = AOP_SIZE(result);
6121 emitcode("movx","a,@%s",rname);
6122 aopPut(AOP(result),"a",offset);
6127 emitcode("inc","%s",rname);
6131 /* now some housekeeping stuff */
6133 /* we had to allocate for this iCode */
6134 freeAsmop(NULL,aop,ic,TRUE);
6136 /* we did not allocate which means left
6137 already in a pointer register, then
6138 if size > 0 && this could be used again
6139 we have to point it back to where it
6141 if (AOP_SIZE(result) > 1 &&
6142 !OP_SYMBOL(left)->remat &&
6143 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6145 int size = AOP_SIZE(result) - 1;
6147 emitcode("dec","%s",rname);
6152 freeAsmop(result,NULL,ic,TRUE);
6157 /*-----------------------------------------------------------------*/
6158 /* genFarPointerGet - gget value from far space */
6159 /*-----------------------------------------------------------------*/
6160 static void genFarPointerGet (operand *left,
6161 operand *result, iCode *ic)
6164 link *retype = getSpec(operandType(result));
6166 aopOp(left,ic,FALSE);
6168 /* if the operand is already in dptr
6169 then we do nothing else we move the value to dptr */
6170 if (AOP_TYPE(left) != AOP_STR) {
6171 /* if this is remateriazable */
6172 if (AOP_TYPE(left) == AOP_IMMD)
6173 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6174 else { /* we need to get it byte by byte */
6175 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6176 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6177 if (options.model == MODEL_FLAT24)
6179 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6183 /* so dptr know contains the address */
6184 freeAsmop(left,NULL,ic,TRUE);
6185 aopOp(result,ic,FALSE);
6187 /* if bit then unpack */
6188 if (IS_BITVAR(retype))
6189 genUnpackBits(result,"dptr",FPOINTER);
6191 size = AOP_SIZE(result);
6195 emitcode("movx","a,@dptr");
6196 aopPut(AOP(result),"a",offset++);
6198 emitcode("inc","dptr");
6202 freeAsmop(result,NULL,ic,TRUE);
6205 /*-----------------------------------------------------------------*/
6206 /* emitcodePointerGet - gget value from code space */
6207 /*-----------------------------------------------------------------*/
6208 static void emitcodePointerGet (operand *left,
6209 operand *result, iCode *ic)
6212 link *retype = getSpec(operandType(result));
6214 aopOp(left,ic,FALSE);
6216 /* if the operand is already in dptr
6217 then we do nothing else we move the value to dptr */
6218 if (AOP_TYPE(left) != AOP_STR) {
6219 /* if this is remateriazable */
6220 if (AOP_TYPE(left) == AOP_IMMD)
6221 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6222 else { /* we need to get it byte by byte */
6223 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6224 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6225 if (options.model == MODEL_FLAT24)
6227 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6231 /* so dptr know contains the address */
6232 freeAsmop(left,NULL,ic,TRUE);
6233 aopOp(result,ic,FALSE);
6235 /* if bit then unpack */
6236 if (IS_BITVAR(retype))
6237 genUnpackBits(result,"dptr",CPOINTER);
6239 size = AOP_SIZE(result);
6243 emitcode("clr","a");
6244 emitcode("movc","a,@a+dptr");
6245 aopPut(AOP(result),"a",offset++);
6247 emitcode("inc","dptr");
6251 freeAsmop(result,NULL,ic,TRUE);
6254 /*-----------------------------------------------------------------*/
6255 /* genGenPointerGet - gget value from generic pointer space */
6256 /*-----------------------------------------------------------------*/
6257 static void genGenPointerGet (operand *left,
6258 operand *result, iCode *ic)
6261 link *retype = getSpec(operandType(result));
6263 aopOp(left,ic,FALSE);
6265 /* if the operand is already in dptr
6266 then we do nothing else we move the value to dptr */
6267 if (AOP_TYPE(left) != AOP_STR) {
6268 /* if this is remateriazable */
6269 if (AOP_TYPE(left) == AOP_IMMD) {
6270 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6271 emitcode("mov","b,#%d",pointerCode(retype));
6273 else { /* we need to get it byte by byte */
6274 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6275 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6276 if (options.model == MODEL_FLAT24)
6278 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6279 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
6283 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
6287 /* so dptr know contains the address */
6288 freeAsmop(left,NULL,ic,TRUE);
6289 aopOp(result,ic,FALSE);
6291 /* if bit then unpack */
6292 if (IS_BITVAR(retype))
6293 genUnpackBits(result,"dptr",GPOINTER);
6295 size = AOP_SIZE(result);
6299 emitcode("lcall","__gptrget");
6300 aopPut(AOP(result),"a",offset++);
6302 emitcode("inc","dptr");
6306 freeAsmop(result,NULL,ic,TRUE);
6309 /*-----------------------------------------------------------------*/
6310 /* genPointerGet - generate code for pointer get */
6311 /*-----------------------------------------------------------------*/
6312 static void genPointerGet (iCode *ic)
6314 operand *left, *result ;
6319 result = IC_RESULT(ic) ;
6321 /* depending on the type of pointer we need to
6322 move it to the correct pointer register */
6323 type = operandType(left);
6324 etype = getSpec(type);
6325 /* if left is of type of pointer then it is simple */
6326 if (IS_PTR(type) && !IS_FUNC(type->next))
6327 p_type = DCL_TYPE(type);
6329 /* we have to go by the storage class */
6330 p_type = PTR_TYPE(SPEC_OCLS(etype));
6332 /* if (SPEC_OCLS(etype)->codesp ) { */
6333 /* p_type = CPOINTER ; */
6336 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6337 /* p_type = FPOINTER ; */
6339 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6340 /* p_type = PPOINTER; */
6342 /* if (SPEC_OCLS(etype) == idata ) */
6343 /* p_type = IPOINTER; */
6345 /* p_type = POINTER ; */
6348 /* now that we have the pointer type we assign
6349 the pointer values */
6354 genNearPointerGet (left,result,ic);
6358 genPagedPointerGet(left,result,ic);
6362 genFarPointerGet (left,result,ic);
6366 emitcodePointerGet (left,result,ic);
6370 genGenPointerGet (left,result,ic);
6376 /*-----------------------------------------------------------------*/
6377 /* genPackBits - generates code for packed bit storage */
6378 /*-----------------------------------------------------------------*/
6379 static void genPackBits (link *etype ,
6381 char *rname, int p_type)
6389 blen = SPEC_BLEN(etype);
6390 bstr = SPEC_BSTR(etype);
6392 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6395 /* if the bit lenth is less than or */
6396 /* it exactly fits a byte then */
6397 if (SPEC_BLEN(etype) <= 8 ) {
6398 shCount = SPEC_BSTR(etype) ;
6400 /* shift left acc */
6403 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6408 emitcode ("mov","b,a");
6409 emitcode("mov","a,@%s",rname);
6413 emitcode ("mov","b,a");
6414 emitcode("movx","a,@dptr");
6418 emitcode ("push","b");
6419 emitcode ("push","acc");
6420 emitcode ("lcall","__gptrget");
6421 emitcode ("pop","b");
6425 emitcode ("anl","a,#0x%02x",(unsigned char)
6426 ((unsigned char)(0xFF << (blen+bstr)) |
6427 (unsigned char)(0xFF >> (8-bstr)) ) );
6428 emitcode ("orl","a,b");
6429 if (p_type == GPOINTER)
6430 emitcode("pop","b");
6436 emitcode("mov","@%s,a",rname);
6440 emitcode("movx","@dptr,a");
6444 emitcode("lcall","__gptrput");
6449 if ( SPEC_BLEN(etype) <= 8 )
6452 emitcode("inc","%s",rname);
6453 rLen = SPEC_BLEN(etype) ;
6455 /* now generate for lengths greater than one byte */
6458 l = aopGet(AOP(right),offset++,FALSE,TRUE);
6468 emitcode("mov","@%s,a",rname);
6470 emitcode("mov","@%s,%s",rname,l);
6475 emitcode("movx","@dptr,a");
6480 emitcode("lcall","__gptrput");
6483 emitcode ("inc","%s",rname);
6488 /* last last was not complete */
6490 /* save the byte & read byte */
6493 emitcode ("mov","b,a");
6494 emitcode("mov","a,@%s",rname);
6498 emitcode ("mov","b,a");
6499 emitcode("movx","a,@dptr");
6503 emitcode ("push","b");
6504 emitcode ("push","acc");
6505 emitcode ("lcall","__gptrget");
6506 emitcode ("pop","b");
6510 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
6511 emitcode ("orl","a,b");
6514 if (p_type == GPOINTER)
6515 emitcode("pop","b");
6520 emitcode("mov","@%s,a",rname);
6524 emitcode("movx","@dptr,a");
6528 emitcode("lcall","__gptrput");
6532 /*-----------------------------------------------------------------*/
6533 /* genDataPointerSet - remat pointer to data space */
6534 /*-----------------------------------------------------------------*/
6535 static void genDataPointerSet(operand *right,
6539 int size, offset = 0 ;
6540 char *l, buffer[256];
6542 aopOp(right,ic,FALSE);
6544 l = aopGet(AOP(result),0,FALSE,TRUE);
6545 size = AOP_SIZE(right);
6548 sprintf(buffer,"(%s + %d)",l+1,offset);
6550 sprintf(buffer,"%s",l+1);
6551 emitcode("mov","%s,%s",buffer,
6552 aopGet(AOP(right),offset++,FALSE,FALSE));
6555 freeAsmop(right,NULL,ic,TRUE);
6556 freeAsmop(result,NULL,ic,TRUE);
6559 /*-----------------------------------------------------------------*/
6560 /* genNearPointerSet - emitcode for near pointer put */
6561 /*-----------------------------------------------------------------*/
6562 static void genNearPointerSet (operand *right,
6570 link *ptype = operandType(result);
6572 retype= getSpec(operandType(right));
6574 aopOp(result,ic,FALSE);
6576 /* if the result is rematerializable &
6577 in data space & not a bit variable */
6578 if (AOP_TYPE(result) == AOP_IMMD &&
6579 DCL_TYPE(ptype) == POINTER &&
6580 !IS_BITVAR(retype)) {
6581 genDataPointerSet (right,result,ic);
6585 /* if the value is already in a pointer register
6586 then don't need anything more */
6587 if (!AOP_INPREG(AOP(result))) {
6588 /* otherwise get a free pointer register */
6590 preg = getFreePtr(ic,&aop,FALSE);
6591 emitcode("mov","%s,%s",
6593 aopGet(AOP(result),0,FALSE,TRUE));
6594 rname = preg->name ;
6596 rname = aopGet(AOP(result),0,FALSE,FALSE);
6598 freeAsmop(result,NULL,ic,TRUE);
6599 aopOp (right,ic,FALSE);
6601 /* if bitfield then unpack the bits */
6602 if (IS_BITVAR(retype))
6603 genPackBits (retype,right,rname,POINTER);
6605 /* we have can just get the values */
6606 int size = AOP_SIZE(right);
6610 l = aopGet(AOP(right),offset,FALSE,TRUE);
6613 emitcode("mov","@%s,a",rname);
6615 emitcode("mov","@%s,%s",rname,l);
6617 emitcode("inc","%s",rname);
6622 /* now some housekeeping stuff */
6624 /* we had to allocate for this iCode */
6625 freeAsmop(NULL,aop,ic,TRUE);
6627 /* we did not allocate which means left
6628 already in a pointer register, then
6629 if size > 0 && this could be used again
6630 we have to point it back to where it
6632 if (AOP_SIZE(right) > 1 &&
6633 !OP_SYMBOL(result)->remat &&
6634 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6636 int size = AOP_SIZE(right) - 1;
6638 emitcode("dec","%s",rname);
6643 freeAsmop(right,NULL,ic,TRUE);
6648 /*-----------------------------------------------------------------*/
6649 /* genPagedPointerSet - emitcode for Paged pointer put */
6650 /*-----------------------------------------------------------------*/
6651 static void genPagedPointerSet (operand *right,
6660 retype= getSpec(operandType(right));
6662 aopOp(result,ic,FALSE);
6664 /* if the value is already in a pointer register
6665 then don't need anything more */
6666 if (!AOP_INPREG(AOP(result))) {
6667 /* otherwise get a free pointer register */
6669 preg = getFreePtr(ic,&aop,FALSE);
6670 emitcode("mov","%s,%s",
6672 aopGet(AOP(result),0,FALSE,TRUE));
6673 rname = preg->name ;
6675 rname = aopGet(AOP(result),0,FALSE,FALSE);
6677 freeAsmop(result,NULL,ic,TRUE);
6678 aopOp (right,ic,FALSE);
6680 /* if bitfield then unpack the bits */
6681 if (IS_BITVAR(retype))
6682 genPackBits (retype,right,rname,PPOINTER);
6684 /* we have can just get the values */
6685 int size = AOP_SIZE(right);
6689 l = aopGet(AOP(right),offset,FALSE,TRUE);
6692 emitcode("movx","@%s,a",rname);
6695 emitcode("inc","%s",rname);
6701 /* now some housekeeping stuff */
6703 /* we had to allocate for this iCode */
6704 freeAsmop(NULL,aop,ic,TRUE);
6706 /* we did not allocate which means left
6707 already in a pointer register, then
6708 if size > 0 && this could be used again
6709 we have to point it back to where it
6711 if (AOP_SIZE(right) > 1 &&
6712 !OP_SYMBOL(result)->remat &&
6713 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6715 int size = AOP_SIZE(right) - 1;
6717 emitcode("dec","%s",rname);
6722 freeAsmop(right,NULL,ic,TRUE);
6727 /*-----------------------------------------------------------------*/
6728 /* genFarPointerSet - set value from far space */
6729 /*-----------------------------------------------------------------*/
6730 static void genFarPointerSet (operand *right,
6731 operand *result, iCode *ic)
6734 link *retype = getSpec(operandType(right));
6736 aopOp(result,ic,FALSE);
6738 /* if the operand is already in dptr
6739 then we do nothing else we move the value to dptr */
6740 if (AOP_TYPE(result) != AOP_STR) {
6741 /* if this is remateriazable */
6742 if (AOP_TYPE(result) == AOP_IMMD)
6743 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6744 else { /* we need to get it byte by byte */
6745 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6746 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6747 if (options.model == MODEL_FLAT24)
6749 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6753 /* so dptr know contains the address */
6754 freeAsmop(result,NULL,ic,TRUE);
6755 aopOp(right,ic,FALSE);
6757 /* if bit then unpack */
6758 if (IS_BITVAR(retype))
6759 genPackBits(retype,right,"dptr",FPOINTER);
6761 size = AOP_SIZE(right);
6765 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6767 emitcode("movx","@dptr,a");
6769 emitcode("inc","dptr");
6773 freeAsmop(right,NULL,ic,TRUE);
6776 /*-----------------------------------------------------------------*/
6777 /* genGenPointerSet - set value from generic pointer space */
6778 /*-----------------------------------------------------------------*/
6779 static void genGenPointerSet (operand *right,
6780 operand *result, iCode *ic)
6783 link *retype = getSpec(operandType(right));
6785 aopOp(result,ic,FALSE);
6787 /* if the operand is already in dptr
6788 then we do nothing else we move the value to dptr */
6789 if (AOP_TYPE(result) != AOP_STR) {
6790 /* if this is remateriazable */
6791 if (AOP_TYPE(result) == AOP_IMMD) {
6792 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6793 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
6795 else { /* we need to get it byte by byte */
6796 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6797 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6798 if (options.model == MODEL_FLAT24)
6800 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6801 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
6805 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
6809 /* so dptr know contains the address */
6810 freeAsmop(result,NULL,ic,TRUE);
6811 aopOp(right,ic,FALSE);
6813 /* if bit then unpack */
6814 if (IS_BITVAR(retype))
6815 genPackBits(retype,right,"dptr",GPOINTER);
6817 size = AOP_SIZE(right);
6821 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6823 emitcode("lcall","__gptrput");
6825 emitcode("inc","dptr");
6829 freeAsmop(right,NULL,ic,TRUE);
6832 /*-----------------------------------------------------------------*/
6833 /* genPointerSet - stores the value into a pointer location */
6834 /*-----------------------------------------------------------------*/
6835 static void genPointerSet (iCode *ic)
6837 operand *right, *result ;
6841 right = IC_RIGHT(ic);
6842 result = IC_RESULT(ic) ;
6844 /* depending on the type of pointer we need to
6845 move it to the correct pointer register */
6846 type = operandType(result);
6847 etype = getSpec(type);
6848 /* if left is of type of pointer then it is simple */
6849 if (IS_PTR(type) && !IS_FUNC(type->next)) {
6850 p_type = DCL_TYPE(type);
6853 /* we have to go by the storage class */
6854 p_type = PTR_TYPE(SPEC_OCLS(etype));
6856 /* if (SPEC_OCLS(etype)->codesp ) { */
6857 /* p_type = CPOINTER ; */
6860 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6861 /* p_type = FPOINTER ; */
6863 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6864 /* p_type = PPOINTER ; */
6866 /* if (SPEC_OCLS(etype) == idata ) */
6867 /* p_type = IPOINTER ; */
6869 /* p_type = POINTER ; */
6872 /* now that we have the pointer type we assign
6873 the pointer values */
6878 genNearPointerSet (right,result,ic);
6882 genPagedPointerSet (right,result,ic);
6886 genFarPointerSet (right,result,ic);
6890 genGenPointerSet (right,result,ic);
6896 /*-----------------------------------------------------------------*/
6897 /* genIfx - generate code for Ifx statement */
6898 /*-----------------------------------------------------------------*/
6899 static void genIfx (iCode *ic, iCode *popIc)
6901 operand *cond = IC_COND(ic);
6904 aopOp(cond,ic,FALSE);
6906 /* get the value into acc */
6907 if (AOP_TYPE(cond) != AOP_CRY)
6911 /* the result is now in the accumulator */
6912 freeAsmop(cond,NULL,ic,TRUE);
6914 /* if there was something to be popped then do it */
6918 /* if the condition is a bit variable */
6919 if (isbit && IS_ITEMP(cond) &&
6921 genIfxJump(ic,SPIL_LOC(cond)->rname);
6923 if (isbit && !IS_ITEMP(cond))
6924 genIfxJump(ic,OP_SYMBOL(cond)->rname);
6931 /*-----------------------------------------------------------------*/
6932 /* genAddrOf - generates code for address of */
6933 /*-----------------------------------------------------------------*/
6934 static void genAddrOf (iCode *ic)
6936 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
6939 aopOp(IC_RESULT(ic),ic,FALSE);
6941 /* if the operand is on the stack then we
6942 need to get the stack offset of this
6945 /* if it has an offset then we need to compute
6948 emitcode("mov","a,_bp");
6949 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
6950 aopPut(AOP(IC_RESULT(ic)),"a",0);
6952 /* we can just move _bp */
6953 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
6955 /* fill the result with zero */
6956 size = AOP_SIZE(IC_RESULT(ic)) - 1;
6959 if (options.stack10bit && size < (FPTRSIZE - 1))
6962 "*** warning: pointer to stack var truncated.\n");
6969 if (options.stack10bit && offset == 2)
6971 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
6975 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
6982 /* object not on stack then we need the name */
6983 size = AOP_SIZE(IC_RESULT(ic));
6987 char s[SDCC_NAME_MAX];
6989 sprintf(s,"#(%s >> %d)",
6993 sprintf(s,"#%s",sym->rname);
6994 aopPut(AOP(IC_RESULT(ic)),s,offset++);
6998 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7002 /*-----------------------------------------------------------------*/
7003 /* genFarFarAssign - assignment when both are in far space */
7004 /*-----------------------------------------------------------------*/
7005 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7007 int size = AOP_SIZE(right);
7010 /* first push the right side on to the stack */
7012 l = aopGet(AOP(right),offset++,FALSE,FALSE);
7014 emitcode ("push","acc");
7017 freeAsmop(right,NULL,ic,FALSE);
7018 /* now assign DPTR to result */
7019 aopOp(result,ic,FALSE);
7020 size = AOP_SIZE(result);
7022 emitcode ("pop","acc");
7023 aopPut(AOP(result),"a",--offset);
7025 freeAsmop(result,NULL,ic,FALSE);
7029 /*-----------------------------------------------------------------*/
7030 /* genAssign - generate code for assignment */
7031 /*-----------------------------------------------------------------*/
7032 static void genAssign (iCode *ic)
7034 operand *result, *right;
7036 unsigned long lit = 0L;
7038 result = IC_RESULT(ic);
7039 right = IC_RIGHT(ic) ;
7041 /* if they are the same */
7042 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7045 aopOp(right,ic,FALSE);
7047 /* special case both in far space */
7048 /* However, if we are using 10 bit stack mode,
7049 * the result should be held in DPTR2,
7050 * so we can operate without the special case.
7054 if (AOP_TYPE(right) == AOP_DPTR &&
7055 IS_TRUE_SYMOP(result) &&
7056 isOperandInFarSpace(result)) {
7058 if (!options.stack10bit)
7060 genFarFarAssign (result,right,ic);
7065 fprintf(stderr, "*** 10bit stack opt 1\n");
7066 emitcode(";", "look at me: optimization possible?\n");
7070 aopOp(result,ic,TRUE);
7072 /* if they are the same registers */
7073 if (sameRegs(AOP(right),AOP(result)))
7076 /* if the result is a bit */
7077 if (AOP_TYPE(result) == AOP_CRY) {
7079 /* if the right size is a literal then
7080 we know what the value is */
7081 if (AOP_TYPE(right) == AOP_LIT) {
7082 if (((int) operandLitValue(right)))
7083 aopPut(AOP(result),one,0);
7085 aopPut(AOP(result),zero,0);
7089 /* the right is also a bit variable */
7090 if (AOP_TYPE(right) == AOP_CRY) {
7091 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7092 aopPut(AOP(result),"c",0);
7098 aopPut(AOP(result),"a",0);
7102 /* bit variables done */
7104 size = AOP_SIZE(result);
7106 if(AOP_TYPE(right) == AOP_LIT)
7107 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7109 (AOP_TYPE(result) != AOP_REG) &&
7110 (AOP_TYPE(right) == AOP_LIT) &&
7111 !IS_FLOAT(operandType(right)) &&
7113 emitcode("clr","a");
7115 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7116 aopPut(AOP(result),"a",size);
7119 aopGet(AOP(right),size,FALSE,FALSE),
7125 aopGet(AOP(right),offset,FALSE,FALSE),
7132 freeAsmop (right,NULL,ic,FALSE);
7133 freeAsmop (result,NULL,ic,TRUE);
7136 /*-----------------------------------------------------------------*/
7137 /* genJumpTab - genrates code for jump table */
7138 /*-----------------------------------------------------------------*/
7139 static void genJumpTab (iCode *ic)
7144 aopOp(IC_JTCOND(ic),ic,FALSE);
7145 /* get the condition into accumulator */
7146 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
7148 /* multiply by three */
7149 emitcode("add","a,acc");
7150 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
7151 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7153 jtab = newiTempLabel(NULL);
7154 emitcode("mov","dptr,#%05d$",jtab->key+100);
7155 emitcode("jmp","@a+dptr");
7156 emitcode("","%05d$:",jtab->key+100);
7157 /* now generate the jump labels */
7158 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
7159 jtab = setNextItem(IC_JTLABELS(ic)))
7160 emitcode("ljmp","%05d$",jtab->key+100);
7164 /*-----------------------------------------------------------------*/
7165 /* genCast - gen code for casting */
7166 /*-----------------------------------------------------------------*/
7167 static void genCast (iCode *ic)
7169 operand *result = IC_RESULT(ic);
7170 link *ctype = operandType(IC_LEFT(ic));
7171 operand *right = IC_RIGHT(ic);
7174 /* if they are equivalent then do nothing */
7175 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
7178 aopOp(right,ic,FALSE) ;
7179 aopOp(result,ic,FALSE);
7181 /* if the result is a bit */
7182 if (AOP_TYPE(result) == AOP_CRY) {
7183 /* if the right size is a literal then
7184 we know what the value is */
7185 if (AOP_TYPE(right) == AOP_LIT) {
7186 if (((int) operandLitValue(right)))
7187 aopPut(AOP(result),one,0);
7189 aopPut(AOP(result),zero,0);
7194 /* the right is also a bit variable */
7195 if (AOP_TYPE(right) == AOP_CRY) {
7196 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7197 aopPut(AOP(result),"c",0);
7203 aopPut(AOP(result),"a",0);
7207 /* if they are the same size : or less */
7208 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
7210 /* if they are in the same place */
7211 if (sameRegs(AOP(right),AOP(result)))
7214 /* if they in different places then copy */
7215 size = AOP_SIZE(result);
7219 aopGet(AOP(right),offset,FALSE,FALSE),
7227 /* if the result is of type pointer */
7228 if (IS_PTR(ctype)) {
7231 link *type = operandType(right);
7232 link *etype = getSpec(type);
7234 /* pointer to generic pointer */
7235 if (IS_GENPTR(ctype)) {
7239 p_type = DCL_TYPE(type);
7241 /* we have to go by the storage class */
7242 p_type = PTR_TYPE(SPEC_OCLS(etype));
7244 /* if (SPEC_OCLS(etype)->codesp ) */
7245 /* p_type = CPOINTER ; */
7247 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7248 /* p_type = FPOINTER ; */
7250 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7251 /* p_type = PPOINTER; */
7253 /* if (SPEC_OCLS(etype) == idata ) */
7254 /* p_type = IPOINTER ; */
7256 /* p_type = POINTER ; */
7259 /* the first two bytes are known */
7260 size = GPTRSIZE - 1;
7264 aopGet(AOP(right),offset,FALSE,FALSE),
7268 /* the last byte depending on type */
7285 /* this should never happen */
7286 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7287 "got unknown pointer type");
7290 aopPut(AOP(result),l, GPTRSIZE - 1);
7294 /* just copy the pointers */
7295 size = AOP_SIZE(result);
7299 aopGet(AOP(right),offset,FALSE,FALSE),
7306 /* so we now know that the size of destination is greater
7307 than the size of the source */
7308 /* we move to result for the size of source */
7309 size = AOP_SIZE(right);
7313 aopGet(AOP(right),offset,FALSE,FALSE),
7318 /* now depending on the sign of the destination */
7319 size = AOP_SIZE(result) - AOP_SIZE(right);
7320 /* if unsigned or not an integral type */
7321 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
7323 aopPut(AOP(result),zero,offset++);
7325 /* we need to extend the sign :{ */
7326 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
7329 emitcode("rlc","a");
7330 emitcode("subb","a,acc");
7332 aopPut(AOP(result),"a",offset++);
7335 /* we are done hurray !!!! */
7338 freeAsmop(right,NULL,ic,TRUE);
7339 freeAsmop(result,NULL,ic,TRUE);
7343 /*-----------------------------------------------------------------*/
7344 /* genDjnz - generate decrement & jump if not zero instrucion */
7345 /*-----------------------------------------------------------------*/
7346 static int genDjnz (iCode *ic, iCode *ifx)
7352 /* if the if condition has a false label
7353 then we cannot save */
7357 /* if the minus is not of the form
7359 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
7360 !IS_OP_LITERAL(IC_RIGHT(ic)))
7363 if (operandLitValue(IC_RIGHT(ic)) != 1)
7366 /* if the size of this greater than one then no
7368 if (getSize(operandType(IC_RESULT(ic))) > 1)
7371 /* otherwise we can save BIG */
7372 lbl = newiTempLabel(NULL);
7373 lbl1= newiTempLabel(NULL);
7375 aopOp(IC_RESULT(ic),ic,FALSE);
7377 if (IS_AOP_PREG(IC_RESULT(ic))) {
7378 emitcode("dec","%s",
7379 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7380 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7381 emitcode("jnz","%05d$",lbl->key+100);
7383 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
7386 emitcode ("sjmp","%05d$",lbl1->key+100);
7387 emitcode ("","%05d$:",lbl->key+100);
7388 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
7389 emitcode ("","%05d$:",lbl1->key+100);
7391 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7396 /*-----------------------------------------------------------------*/
7397 /* genReceive - generate code for a receive iCode */
7398 /*-----------------------------------------------------------------*/
7399 static void genReceive (iCode *ic)
7401 if (isOperandInFarSpace(IC_RESULT(ic)) &&
7402 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
7403 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
7405 int size = getSize(operandType(IC_RESULT(ic)));
7406 int offset = fReturnSize - size;
7408 emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
7409 fReturn[fReturnSize - offset - 1] : "acc"));
7412 aopOp(IC_RESULT(ic),ic,FALSE);
7413 size = AOP_SIZE(IC_RESULT(ic));
7416 emitcode ("pop","acc");
7417 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
7422 aopOp(IC_RESULT(ic),ic,FALSE);
7424 assignResultValue(IC_RESULT(ic));
7427 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7430 /*-----------------------------------------------------------------*/
7431 /* gen51Code - generate code for 8051 based controllers */
7432 /*-----------------------------------------------------------------*/
7433 void gen51Code (iCode *lic)
7438 lineHead = lineCurr = NULL;
7440 /* if debug information required */
7441 /* if (options.debug && currFunc) { */
7443 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
7445 if (IS_STATIC(currFunc->etype))
7446 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
7448 emitcode("","G$%s$0$0 ==.",currFunc->name);
7451 /* stack pointer name */
7452 if (options.useXstack)
7458 for (ic = lic ; ic ; ic = ic->next ) {
7460 if ( cln != ic->lineno ) {
7461 if ( options.debug ) {
7463 emitcode("","C$%s$%d$%d$%d ==.",
7464 ic->filename,ic->lineno,
7465 ic->level,ic->block);
7468 emitcode(";","%s %d",ic->filename,ic->lineno);
7471 /* if the result is marked as
7472 spilt and rematerializable or code for
7473 this has already been generated then
7475 if (resultRemat(ic) || ic->generated )
7478 /* depending on the operation */
7497 /* IPOP happens only when trying to restore a
7498 spilt live range, if there is an ifx statement
7499 following this pop then the if statement might
7500 be using some of the registers being popped which
7501 would destory the contents of the register so
7502 we need to check for this condition and handle it */
7504 ic->next->op == IFX &&
7505 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
7506 genIfx (ic->next,ic);
7524 genEndFunction (ic);
7544 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
7561 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
7565 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
7572 /* note these two are xlated by algebraic equivalence
7573 during parsing SDCC.y */
7574 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7575 "got '>=' or '<=' shouldn't have come here");
7579 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
7591 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
7595 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
7599 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
7626 case GET_VALUE_AT_ADDRESS:
7631 if (POINTER_SET(ic))
7658 addSet(&_G.sendSet,ic);
7663 /* piCode(ic,stdout); */
7669 /* now we are ready to call the
7670 peep hole optimizer */
7671 if (!options.nopeep)
7672 peepHole (&lineHead);
7674 /* now do the actual printing */
7675 printLine (lineHead,codeOutFile);