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
330 emitcode("push","acc");
332 emitcode("mov","a,_bp");
333 emitcode("add","a,#0x%02x",
335 ((char)(sym->stack - _G.nRegsSaved )) :
336 ((char)sym->stack)) & 0xff);
339 emitcode ("mov","dpx1,#0x40");
340 emitcode ("mov","dph1,#0x00");
341 emitcode ("mov","dpl1, a");
345 emitcode("pop","acc");
347 sym->aop = aop = newAsmop(AOP_DPTR2);
348 aop->size = getSize(sym->type);
352 /* if in bit space */
353 if (IN_BITSPACE(space)) {
354 sym->aop = aop = newAsmop (AOP_CRY);
355 aop->aopu.aop_dir = sym->rname ;
356 aop->size = getSize(sym->type);
359 /* if it is in direct space */
360 if (IN_DIRSPACE(space)) {
361 sym->aop = aop = newAsmop (AOP_DIR);
362 aop->aopu.aop_dir = sym->rname ;
363 aop->size = getSize(sym->type);
367 /* special case for a function */
368 if (IS_FUNC(sym->type)) {
369 sym->aop = aop = newAsmop(AOP_IMMD);
370 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
371 strcpy(aop->aopu.aop_immd,sym->rname);
372 aop->size = FPTRSIZE;
376 /* only remaining is far space */
377 /* in which case DPTR gets the address */
378 sym->aop = aop = newAsmop(AOP_DPTR);
379 emitcode ("mov","dptr,#%s", sym->rname);
380 aop->size = getSize(sym->type);
382 /* if it is in code space */
383 if (IN_CODESPACE(space))
389 /*-----------------------------------------------------------------*/
390 /* aopForRemat - rematerialzes an object */
391 /*-----------------------------------------------------------------*/
392 static asmop *aopForRemat (symbol *sym)
395 iCode *ic = sym->rematiCode;
396 asmop *aop = newAsmop(AOP_IMMD);
400 /* if plus or minus print the right hand side */
401 if (ic->op == '+' || ic->op == '-') {
402 sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
405 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
409 /* we reached the end */
410 sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
414 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
415 strcpy(aop->aopu.aop_immd,buffer);
419 /*-----------------------------------------------------------------*/
420 /* regsInCommon - two operands have some registers in common */
421 /*-----------------------------------------------------------------*/
422 static bool regsInCommon (operand *op1, operand *op2)
427 /* if they have registers in common */
428 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
431 sym1 = OP_SYMBOL(op1);
432 sym2 = OP_SYMBOL(op2);
434 if (sym1->nRegs == 0 || sym2->nRegs == 0)
437 for (i = 0 ; i < sym1->nRegs ; i++) {
442 for (j = 0 ; j < sym2->nRegs ;j++ ) {
446 if (sym2->regs[j] == sym1->regs[i])
454 /*-----------------------------------------------------------------*/
455 /* operandsEqu - equivalent */
456 /*-----------------------------------------------------------------*/
457 static bool operandsEqu ( operand *op1, operand *op2)
461 /* if they not symbols */
462 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
465 sym1 = OP_SYMBOL(op1);
466 sym2 = OP_SYMBOL(op2);
468 /* if both are itemps & one is spilt
469 and the other is not then false */
470 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
471 sym1->isspilt != sym2->isspilt )
474 /* if they are the same */
478 if (strcmp(sym1->rname,sym2->rname) == 0)
482 /* if left is a tmp & right is not */
486 (sym1->usl.spillLoc == sym2))
493 (sym2->usl.spillLoc == sym1))
499 /*-----------------------------------------------------------------*/
500 /* sameRegs - two asmops have the same registers */
501 /*-----------------------------------------------------------------*/
502 static bool sameRegs (asmop *aop1, asmop *aop2 )
509 if (aop1->type != AOP_REG ||
510 aop2->type != AOP_REG )
513 if (aop1->size != aop2->size )
516 for (i = 0 ; i < aop1->size ; i++ )
517 if (aop1->aopu.aop_reg[i] !=
518 aop2->aopu.aop_reg[i] )
524 /*-----------------------------------------------------------------*/
525 /* aopOp - allocates an asmop for an operand : */
526 /*-----------------------------------------------------------------*/
527 static void aopOp (operand *op, iCode *ic, bool result)
536 /* if this a literal */
537 if (IS_OP_LITERAL(op)) {
538 op->aop = aop = newAsmop(AOP_LIT);
539 aop->aopu.aop_lit = op->operand.valOperand;
540 aop->size = getSize(operandType(op));
544 /* if already has a asmop then continue */
548 /* if the underlying symbol has a aop */
549 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
550 op->aop = OP_SYMBOL(op)->aop;
554 /* if this is a true symbol */
555 if (IS_TRUE_SYMOP(op)) {
556 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
560 /* this is a temporary : this has
566 e) can be a return use only */
571 /* if the type is a conditional */
572 if (sym->regType == REG_CND) {
573 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
578 /* if it is spilt then two situations
580 b) has a spill location */
581 if (sym->isspilt || sym->nRegs == 0) {
583 /* rematerialize it NOW */
585 sym->aop = op->aop = aop =
587 aop->size = getSize(sym->type);
593 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
594 aop->size = getSize(sym->type);
595 for ( i = 0 ; i < 2 ; i++ )
596 aop->aopu.aop_str[i] = accUse[i];
602 aop = op->aop = sym->aop = newAsmop(AOP_STR);
603 aop->size = getSize(sym->type);
604 for ( i = 0 ; i < fReturnSize ; i++ )
605 aop->aopu.aop_str[i] = fReturn[i];
609 /* else spill location */
610 sym->aop = op->aop = aop =
611 aopForSym(ic,sym->usl.spillLoc,result);
612 aop->size = getSize(sym->type);
616 /* must be in a register */
617 sym->aop = op->aop = aop = newAsmop(AOP_REG);
618 aop->size = sym->nRegs;
619 for ( i = 0 ; i < sym->nRegs ;i++)
620 aop->aopu.aop_reg[i] = sym->regs[i];
623 /*-----------------------------------------------------------------*/
624 /* freeAsmop - free up the asmop given to an operand */
625 /*----------------------------------------------------------------*/
626 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
643 /* depending on the asmop type only three cases need work AOP_RO
644 , AOP_R1 && AOP_STK */
649 emitcode ("pop","ar0");
653 bitVectUnSetBit(ic->rUsed,R0_IDX);
659 emitcode ("pop","ar1");
663 bitVectUnSetBit(ic->rUsed,R1_IDX);
669 int stk = aop->aopu.aop_stk + aop->size;
670 bitVectUnSetBit(ic->rUsed,R0_IDX);
671 bitVectUnSetBit(ic->rUsed,R1_IDX);
673 getFreePtr(ic,&aop,FALSE);
675 if (options.stack10bit)
677 /* I'm not sure what to do here yet... */
680 "*** Warning: probably generating bad code for "
681 "10 bit stack mode.\n");
685 emitcode ("mov","a,_bp");
686 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
687 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
689 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
693 emitcode("pop","acc");
694 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
696 emitcode("dec","%s",aop->aopu.aop_ptr->name);
699 freeAsmop(op,NULL,ic,TRUE);
701 emitcode("pop","ar0");
706 emitcode("pop","ar1");
713 /* all other cases just dealloc */
717 OP_SYMBOL(op)->aop = NULL;
718 /* if the symbol has a spill */
720 SPIL_LOC(op)->aop = NULL;
725 /*-----------------------------------------------------------------*/
726 /* aopGet - for fetching value of the aop */
727 /*-----------------------------------------------------------------*/
728 static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
733 /* offset is greater than
735 if (offset > (aop->size - 1) &&
736 aop->type != AOP_LIT)
739 /* depending on type */
744 /* if we need to increment it */
745 while (offset > aop->coff) {
746 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
750 while (offset < aop->coff) {
751 emitcode("dec","%s",aop->aopu.aop_ptr->name);
757 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
758 return (dname ? "acc" : "a");
760 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
761 ALLOC_ATOMIC(rs,strlen(s)+1);
768 if (aop->type == AOP_DPTR2)
773 while (offset > aop->coff) {
774 emitcode ("inc","dptr");
778 while (offset < aop->coff) {
779 emitcode("lcall","__decdptr");
786 emitcode("movc","a,@a+dptr");
789 emitcode("movx","a,@dptr");
792 if (aop->type == AOP_DPTR2)
797 return (dname ? "acc" : "a");
802 sprintf (s,"#(%s)",aop->aopu.aop_immd);
805 sprintf(s,"#(%s >> %d)",
811 ALLOC_ATOMIC(rs,strlen(s)+1);
817 sprintf(s,"(%s + %d)",
821 sprintf(s,"%s",aop->aopu.aop_dir);
822 ALLOC_ATOMIC(rs,strlen(s)+1);
828 return aop->aopu.aop_reg[offset]->dname;
830 return aop->aopu.aop_reg[offset]->name;
834 emitcode("mov","c,%s",aop->aopu.aop_dir);
835 emitcode("rlc","a") ;
836 return (dname ? "acc" : "a");
839 if (!offset && dname)
841 return aop->aopu.aop_str[offset];
844 return aopLiteral (aop->aopu.aop_lit,offset);
848 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
852 return aop->aopu.aop_str[offset];
856 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
857 "aopget got unsupported aop->type");
860 /*-----------------------------------------------------------------*/
861 /* aopPut - puts a string for a aop */
862 /*-----------------------------------------------------------------*/
863 static void aopPut (asmop *aop, char *s, int offset)
868 if (aop->size && offset > ( aop->size - 1)) {
869 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
870 "aopPut got offset > aop->size");
874 /* will assign value to value */
875 /* depending on where it is ofcourse */
879 sprintf(d,"(%s + %d)",
880 aop->aopu.aop_dir,offset);
882 sprintf(d,"%s",aop->aopu.aop_dir);
885 emitcode("mov","%s,%s",d,s);
890 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
891 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
893 strcmp(s,"r0") == 0 ||
894 strcmp(s,"r1") == 0 ||
895 strcmp(s,"r2") == 0 ||
896 strcmp(s,"r3") == 0 ||
897 strcmp(s,"r4") == 0 ||
898 strcmp(s,"r5") == 0 ||
899 strcmp(s,"r6") == 0 ||
900 strcmp(s,"r7") == 0 )
901 emitcode("mov","%s,%s",
902 aop->aopu.aop_reg[offset]->dname,s);
904 emitcode("mov","%s,%s",
905 aop->aopu.aop_reg[offset]->name,s);
912 if (aop->type == AOP_DPTR2)
918 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
919 "aopPut writting to code space");
923 while (offset > aop->coff) {
925 emitcode ("inc","dptr");
928 while (offset < aop->coff) {
930 emitcode("lcall","__decdptr");
935 /* if not in accumulater */
938 emitcode ("movx","@dptr,a");
940 if (aop->type == AOP_DPTR2)
948 while (offset > aop->coff) {
950 emitcode("inc","%s",aop->aopu.aop_ptr->name);
952 while (offset < aop->coff) {
954 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
960 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
965 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
967 if (strcmp(s,"r0") == 0 ||
968 strcmp(s,"r1") == 0 ||
969 strcmp(s,"r2") == 0 ||
970 strcmp(s,"r3") == 0 ||
971 strcmp(s,"r4") == 0 ||
972 strcmp(s,"r5") == 0 ||
973 strcmp(s,"r6") == 0 ||
974 strcmp(s,"r7") == 0 ) {
976 sprintf(buffer,"a%s",s);
977 emitcode("mov","@%s,%s",
978 aop->aopu.aop_ptr->name,buffer);
980 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
985 if (strcmp(s,"a") == 0)
986 emitcode("push","acc");
988 emitcode("push","%s",s);
993 /* if bit variable */
994 if (!aop->aopu.aop_dir) {
999 emitcode("clr","%s",aop->aopu.aop_dir);
1002 emitcode("setb","%s",aop->aopu.aop_dir);
1005 emitcode("mov","%s,c",aop->aopu.aop_dir);
1007 lbl = newiTempLabel(NULL);
1009 if (strcmp(s,"a")) {
1012 emitcode("clr","c");
1013 emitcode("jz","%05d$",lbl->key+100);
1014 emitcode("cpl","c");
1015 emitcode("","%05d$:",lbl->key+100);
1016 emitcode("mov","%s,c",aop->aopu.aop_dir);
1023 if (strcmp(aop->aopu.aop_str[offset],s))
1024 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1029 if (!offset && (strcmp(s,"acc") == 0))
1032 if (strcmp(aop->aopu.aop_str[offset],s))
1033 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1037 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1038 "aopPut got unsupported aop->type");
1046 /*-----------------------------------------------------------------*/
1047 /* pointToEnd :- points to the last byte of the operand */
1048 /*-----------------------------------------------------------------*/
1049 static void pointToEnd (asmop *aop)
1055 aop->coff = count = (aop->size - 1);
1056 switch (aop->type) {
1060 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1064 emitcode("inc","dptr");
1071 /*-----------------------------------------------------------------*/
1072 /* reAdjustPreg - points a register back to where it should */
1073 /*-----------------------------------------------------------------*/
1074 static void reAdjustPreg (asmop *aop)
1079 if ((size = aop->size) <= 1)
1082 switch (aop->type) {
1086 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1090 if (aop->type == AOP_DPTR2)
1096 emitcode("lcall","__decdptr");
1099 if (aop->type == AOP_DPTR2)
1109 #define AOP(op) op->aop
1110 #define AOP_TYPE(op) AOP(op)->type
1111 #define AOP_SIZE(op) AOP(op)->size
1112 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1113 AOP_TYPE(x) == AOP_R0))
1115 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1116 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1119 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1120 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1121 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1123 /*-----------------------------------------------------------------*/
1124 /* genNotFloat - generates not for float operations */
1125 /*-----------------------------------------------------------------*/
1126 static void genNotFloat (operand *op, operand *res)
1132 /* we will put 127 in the first byte of
1134 aopPut(AOP(res),"#127",0);
1135 size = AOP_SIZE(op) - 1;
1138 l = aopGet(op->aop,offset++,FALSE,FALSE);
1142 emitcode("orl","a,%s",
1144 offset++,FALSE,FALSE));
1146 tlbl = newiTempLabel(NULL);
1148 tlbl = newiTempLabel(NULL);
1149 aopPut(res->aop,one,1);
1150 emitcode("jz","%05d$",(tlbl->key+100));
1151 aopPut(res->aop,zero,1);
1152 emitcode("","%05d$:",(tlbl->key+100));
1154 size = res->aop->size - 2;
1156 /* put zeros in the rest */
1158 aopPut(res->aop,zero,offset++);
1161 /*-----------------------------------------------------------------*/
1162 /* opIsGptr: returns non-zero if the passed operand is */
1163 /* a generic pointer type. */
1164 /*-----------------------------------------------------------------*/
1165 static int opIsGptr(operand *op)
1167 link *type = operandType(op);
1169 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1176 /*-----------------------------------------------------------------*/
1177 /* getDataSize - get the operand data size */
1178 /*-----------------------------------------------------------------*/
1179 static int getDataSize(operand *op)
1182 size = AOP_SIZE(op);
1183 if (size == GPTRSIZE)
1185 link *type = operandType(op);
1186 if (IS_GENPTR(type))
1188 /* generic pointer; arithmetic operations
1189 * should ignore the high byte (pointer type).
1197 /*-----------------------------------------------------------------*/
1198 /* outAcc - output Acc */
1199 /*-----------------------------------------------------------------*/
1200 static void outAcc(operand *result)
1203 size = getDataSize(result);
1205 aopPut(AOP(result),"a",0);
1208 /* unsigned or positive */
1210 aopPut(AOP(result),zero,offset++);
1215 /*-----------------------------------------------------------------*/
1216 /* outBitC - output a bit C */
1217 /*-----------------------------------------------------------------*/
1218 static void outBitC(operand *result)
1220 /* if the result is bit */
1221 if (AOP_TYPE(result) == AOP_CRY)
1222 aopPut(AOP(result),"c",0);
1224 emitcode("clr","a");
1225 emitcode("rlc","a");
1230 /*-----------------------------------------------------------------*/
1231 /* toBoolean - emit code for orl a,operator(sizeop) */
1232 /*-----------------------------------------------------------------*/
1233 static void toBoolean(operand *oper)
1235 int size = AOP_SIZE(oper) - 1;
1237 MOVA(aopGet(AOP(oper),0,FALSE,FALSE));
1239 emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE));
1243 /*-----------------------------------------------------------------*/
1244 /* genNot - generate code for ! operation */
1245 /*-----------------------------------------------------------------*/
1246 static void genNot (iCode *ic)
1249 link *optype = operandType(IC_LEFT(ic));
1251 /* assign asmOps to operand & result */
1252 aopOp (IC_LEFT(ic),ic,FALSE);
1253 aopOp (IC_RESULT(ic),ic,TRUE);
1255 /* if in bit space then a special case */
1256 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1257 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1258 emitcode("cpl","c");
1259 outBitC(IC_RESULT(ic));
1263 /* if type float then do float */
1264 if (IS_FLOAT(optype)) {
1265 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1269 toBoolean(IC_LEFT(ic));
1271 tlbl = newiTempLabel(NULL);
1272 emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1273 emitcode("","%05d$:",tlbl->key+100);
1274 outBitC(IC_RESULT(ic));
1277 /* release the aops */
1278 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1279 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1283 /*-----------------------------------------------------------------*/
1284 /* genCpl - generate code for complement */
1285 /*-----------------------------------------------------------------*/
1286 static void genCpl (iCode *ic)
1292 /* assign asmOps to operand & result */
1293 aopOp (IC_LEFT(ic),ic,FALSE);
1294 aopOp (IC_RESULT(ic),ic,TRUE);
1296 /* if both are in bit space then
1298 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1299 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1301 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1302 emitcode("cpl","c");
1303 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1307 size = AOP_SIZE(IC_RESULT(ic));
1309 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1311 emitcode("cpl","a");
1312 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1317 /* release the aops */
1318 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1319 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1322 /*-----------------------------------------------------------------*/
1323 /* genUminusFloat - unary minus for floating points */
1324 /*-----------------------------------------------------------------*/
1325 static void genUminusFloat(operand *op,operand *result)
1327 int size ,offset =0 ;
1329 /* for this we just need to flip the
1330 first it then copy the rest in place */
1331 size = AOP_SIZE(op) - 1;
1332 l = aopGet(AOP(op),3,FALSE,FALSE);
1336 emitcode("cpl","acc.7");
1337 aopPut(AOP(result),"a",3);
1341 aopGet(AOP(op),offset,FALSE,FALSE),
1347 /*-----------------------------------------------------------------*/
1348 /* genUminus - unary minus code generation */
1349 /*-----------------------------------------------------------------*/
1350 static void genUminus (iCode *ic)
1353 link *optype, *rtype;
1357 aopOp(IC_LEFT(ic),ic,FALSE);
1358 aopOp(IC_RESULT(ic),ic,TRUE);
1360 /* if both in bit space then special
1362 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1363 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1365 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1366 emitcode("cpl","c");
1367 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1371 optype = operandType(IC_LEFT(ic));
1372 rtype = operandType(IC_RESULT(ic));
1374 /* if float then do float stuff */
1375 if (IS_FLOAT(optype)) {
1376 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1380 /* otherwise subtract from zero */
1381 size = AOP_SIZE(IC_LEFT(ic));
1385 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1386 if (!strcmp(l,"a")) {
1387 emitcode("cpl","a");
1388 emitcode("inc","a");
1390 emitcode("clr","a");
1391 emitcode("subb","a,%s",l);
1393 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1396 /* if any remaining bytes in the result */
1397 /* we just need to propagate the sign */
1398 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1399 emitcode("rlc","a");
1400 emitcode("subb","a,acc");
1402 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1406 /* release the aops */
1407 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1408 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1411 /*-----------------------------------------------------------------*/
1412 /* saveRegisters - will look for a call and save the registers */
1413 /*-----------------------------------------------------------------*/
1414 static void saveRegisters(iCode *lic)
1422 for (ic = lic ; ic ; ic = ic->next)
1423 if (ic->op == CALL || ic->op == PCALL)
1427 fprintf(stderr,"found parameter push with no function call\n");
1431 /* if the registers have been saved already then
1433 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1436 /* find the registers in use at this time
1437 and push them away to safety */
1438 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1442 if (options.useXstack) {
1443 if (bitVectBitValue(rsave,R0_IDX))
1444 emitcode("mov","b,r0");
1445 emitcode("mov","r0,%s",spname);
1446 for (i = 0 ; i < mcs51_nRegs ; i++) {
1447 if (bitVectBitValue(rsave,i)) {
1449 emitcode("mov","a,b");
1451 emitcode("mov","a,%s",mcs51_regWithIdx(i)->name);
1452 emitcode("movx","@r0,a");
1453 emitcode("inc","r0");
1456 emitcode("mov","%s,r0",spname);
1457 if (bitVectBitValue(rsave,R0_IDX))
1458 emitcode("mov","r0,b");
1460 for (i = 0 ; i < mcs51_nRegs ; i++) {
1461 if (bitVectBitValue(rsave,i))
1462 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
1465 detype = getSpec(operandType(IC_LEFT(ic)));
1467 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1468 IS_ISR(currFunc->etype) &&
1471 saverbank(SPEC_BANK(detype),ic,TRUE);
1474 /*-----------------------------------------------------------------*/
1475 /* unsaveRegisters - pop the pushed registers */
1476 /*-----------------------------------------------------------------*/
1477 static void unsaveRegisters (iCode *ic)
1481 /* find the registers in use at this time
1482 and push them away to safety */
1483 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1486 if (options.useXstack) {
1487 emitcode("mov","r0,%s",spname);
1488 for (i = mcs51_nRegs ; i >= 0 ; i--) {
1489 if (bitVectBitValue(rsave,i)) {
1490 emitcode("dec","r0");
1491 emitcode("movx","a,@r0");
1493 emitcode("mov","b,a");
1495 emitcode("mov","%s,a",mcs51_regWithIdx(i)->name);
1499 emitcode("mov","%s,r0",spname);
1500 if (bitVectBitValue(rsave,R0_IDX))
1501 emitcode("mov","r0,b");
1503 for (i = mcs51_nRegs ; i >= 0 ; i--) {
1504 if (bitVectBitValue(rsave,i))
1505 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
1511 /*-----------------------------------------------------------------*/
1513 /*-----------------------------------------------------------------*/
1514 static void pushSide(operand * oper, int size)
1518 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1519 if (AOP_TYPE(oper) != AOP_REG &&
1520 AOP_TYPE(oper) != AOP_DIR &&
1522 emitcode("mov","a,%s",l);
1523 emitcode("push","acc");
1525 emitcode("push","%s",l);
1529 /*-----------------------------------------------------------------*/
1530 /* assignResultValue - */
1531 /*-----------------------------------------------------------------*/
1532 static void assignResultValue(operand * oper)
1535 int size = AOP_SIZE(oper);
1537 aopPut(AOP(oper),fReturn[offset],offset);
1543 /*-----------------------------------------------------------------*/
1544 /* genXpush - pushes onto the external stack */
1545 /*-----------------------------------------------------------------*/
1546 static void genXpush (iCode *ic)
1548 asmop *aop = newAsmop(0);
1550 int size,offset = 0;
1552 aopOp(IC_LEFT(ic),ic,FALSE);
1553 r = getFreePtr(ic,&aop,FALSE);
1556 emitcode("mov","%s,_spx",r->name);
1558 size = AOP_SIZE(IC_LEFT(ic));
1561 char *l = aopGet(AOP(IC_LEFT(ic)),
1562 offset++,FALSE,FALSE);
1564 emitcode("movx","@%s,a",r->name);
1565 emitcode("inc","%s",r->name);
1570 emitcode("mov","_spx,%s",r->name);
1572 freeAsmop(NULL,aop,ic,TRUE);
1573 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1576 /*-----------------------------------------------------------------*/
1577 /* genIpush - genrate code for pushing this gets a little complex */
1578 /*-----------------------------------------------------------------*/
1579 static void genIpush (iCode *ic)
1581 int size, offset = 0 ;
1585 /* if this is not a parm push : ie. it is spill push
1586 and spill push is always done on the local stack */
1587 if (!ic->parmPush) {
1589 /* and the item is spilt then do nothing */
1590 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1593 aopOp(IC_LEFT(ic),ic,FALSE);
1594 size = AOP_SIZE(IC_LEFT(ic));
1595 /* push it on the stack */
1597 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1602 emitcode("push","%s",l);
1607 /* this is a paramter push: in this case we call
1608 the routine to find the call and save those
1609 registers that need to be saved */
1612 /* if use external stack then call the external
1613 stack pushing routine */
1614 if (options.useXstack) {
1619 /* then do the push */
1620 aopOp(IC_LEFT(ic),ic,FALSE);
1623 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1624 size = AOP_SIZE(IC_LEFT(ic));
1627 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1628 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1629 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1631 emitcode("mov","a,%s",l);
1632 emitcode("push","acc");
1634 emitcode("push","%s",l);
1637 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1640 /*-----------------------------------------------------------------*/
1641 /* genIpop - recover the registers: can happen only for spilling */
1642 /*-----------------------------------------------------------------*/
1643 static void genIpop (iCode *ic)
1648 /* if the temp was not pushed then */
1649 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1652 aopOp(IC_LEFT(ic),ic,FALSE);
1653 size = AOP_SIZE(IC_LEFT(ic));
1656 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1659 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1662 /*-----------------------------------------------------------------*/
1663 /* unsaverbank - restores the resgister bank from stack */
1664 /*-----------------------------------------------------------------*/
1665 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1672 if (options.useXstack) {
1674 r = getFreePtr(ic,&aop,FALSE);
1677 emitcode("mov","%s,_spx",r->name);
1678 emitcode("movx","a,@%s",r->name);
1679 emitcode("mov","psw,a");
1680 emitcode("dec","%s",r->name);
1683 emitcode ("pop","psw");
1686 for (i = (mcs51_nRegs - 1) ; i >= 0 ;i--) {
1687 if (options.useXstack) {
1688 emitcode("movx","a,@%s",r->name);
1689 emitcode("mov","(%s+%d),a",
1690 regs8051[i].base,8*bank+regs8051[i].offset);
1691 emitcode("dec","%s",r->name);
1694 emitcode("pop","(%s+%d)",
1695 regs8051[i].base,8*bank+regs8051[i].offset);
1698 if (options.useXstack) {
1700 emitcode("mov","_spx,%s",r->name);
1701 freeAsmop(NULL,aop,ic,TRUE);
1706 /*-----------------------------------------------------------------*/
1707 /* saverbank - saves an entire register bank on the stack */
1708 /*-----------------------------------------------------------------*/
1709 static void saverbank (int bank, iCode *ic, bool pushPsw)
1715 if (options.useXstack) {
1718 r = getFreePtr(ic,&aop,FALSE);
1719 emitcode("mov","%s,_spx",r->name);
1723 for (i = 0 ; i < mcs51_nRegs ;i++) {
1724 if (options.useXstack) {
1725 emitcode("inc","%s",r->name);
1726 emitcode("mov","a,(%s+%d)",
1727 regs8051[i].base,8*bank+regs8051[i].offset);
1728 emitcode("movx","@%s,a",r->name);
1730 emitcode("push","(%s+%d)",
1731 regs8051[i].base,8*bank+regs8051[i].offset);
1735 if (options.useXstack) {
1736 emitcode("mov","a,psw");
1737 emitcode("movx","@%s,a",r->name);
1738 emitcode("inc","%s",r->name);
1739 emitcode("mov","_spx,%s",r->name);
1740 freeAsmop (NULL,aop,ic,TRUE);
1743 emitcode("push","psw");
1745 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1751 /*-----------------------------------------------------------------*/
1752 /* genCall - generates a call statement */
1753 /*-----------------------------------------------------------------*/
1754 static void genCall (iCode *ic)
1758 /* if caller saves & we have not saved then */
1762 /* if we are calling a function that is not using
1763 the same register bank then we need to save the
1764 destination registers on the stack */
1765 detype = getSpec(operandType(IC_LEFT(ic)));
1767 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1768 IS_ISR(currFunc->etype) &&
1771 saverbank(SPEC_BANK(detype),ic,TRUE);
1773 /* if send set is not empty the assign */
1777 for (sic = setFirstItem(_G.sendSet) ; sic ;
1778 sic = setNextItem(_G.sendSet)) {
1779 int size, offset = 0;
1780 aopOp(IC_LEFT(sic),sic,FALSE);
1781 size = AOP_SIZE(IC_LEFT(sic));
1783 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1785 if (strcmp(l,fReturn[offset]))
1786 emitcode("mov","%s,%s",
1791 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1796 emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1797 OP_SYMBOL(IC_LEFT(ic))->rname :
1798 OP_SYMBOL(IC_LEFT(ic))->name));
1800 /* if we need assign a result value */
1801 if ((IS_ITEMP(IC_RESULT(ic)) &&
1802 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1803 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1804 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1807 aopOp(IC_RESULT(ic),ic,FALSE);
1810 assignResultValue(IC_RESULT(ic));
1812 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1815 /* adjust the stack for parameters if
1817 if (IC_LEFT(ic)->parmBytes) {
1819 if (IC_LEFT(ic)->parmBytes > 3) {
1820 emitcode("mov","a,%s",spname);
1821 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1822 emitcode("mov","%s,a",spname);
1824 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1825 emitcode("dec","%s",spname);
1829 /* if register bank was saved then pop them */
1831 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1833 /* if we hade saved some registers then unsave them */
1834 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1835 unsaveRegisters (ic);
1840 /*-----------------------------------------------------------------*/
1841 /* genPcall - generates a call by pointer statement */
1842 /*-----------------------------------------------------------------*/
1843 static void genPcall (iCode *ic)
1846 symbol *rlbl = newiTempLabel(NULL);
1849 /* if caller saves & we have not saved then */
1853 /* if we are calling a function that is not using
1854 the same register bank then we need to save the
1855 destination registers on the stack */
1856 detype = getSpec(operandType(IC_LEFT(ic)));
1858 IS_ISR(currFunc->etype) &&
1859 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
1860 saverbank(SPEC_BANK(detype),ic,TRUE);
1863 /* push the return address on to the stack */
1864 emitcode("mov","a,#%05d$",(rlbl->key+100));
1865 emitcode("push","acc");
1866 emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
1867 emitcode("push","acc");
1869 if (options.model == MODEL_FLAT24)
1871 emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
1872 emitcode("push","acc");
1875 /* now push the calling address */
1876 aopOp(IC_LEFT(ic),ic,FALSE);
1878 pushSide(IC_LEFT(ic), FPTRSIZE);
1880 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1882 /* if send set is not empty the assign */
1886 for (sic = setFirstItem(_G.sendSet) ; sic ;
1887 sic = setNextItem(_G.sendSet)) {
1888 int size, offset = 0;
1889 aopOp(IC_LEFT(sic),sic,FALSE);
1890 size = AOP_SIZE(IC_LEFT(sic));
1892 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1894 if (strcmp(l,fReturn[offset]))
1895 emitcode("mov","%s,%s",
1900 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1906 emitcode("","%05d$:",(rlbl->key+100));
1909 /* if we need assign a result value */
1910 if ((IS_ITEMP(IC_RESULT(ic)) &&
1911 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1912 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
1913 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1916 aopOp(IC_RESULT(ic),ic,FALSE);
1919 assignResultValue(IC_RESULT(ic));
1921 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1924 /* adjust the stack for parameters if
1926 if (IC_LEFT(ic)->parmBytes) {
1928 if (IC_LEFT(ic)->parmBytes > 3) {
1929 emitcode("mov","a,%s",spname);
1930 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1931 emitcode("mov","%s,a",spname);
1933 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1934 emitcode("dec","%s",spname);
1938 /* if register bank was saved then unsave them */
1940 (SPEC_BANK(currFunc->etype) !=
1942 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1944 /* if we hade saved some registers then
1947 unsaveRegisters (ic);
1951 /*-----------------------------------------------------------------*/
1952 /* resultRemat - result is rematerializable */
1953 /*-----------------------------------------------------------------*/
1954 static int resultRemat (iCode *ic)
1956 if (SKIP_IC(ic) || ic->op == IFX)
1959 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1960 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1961 if (sym->remat && !POINTER_SET(ic))
1969 #define STRCASECMP stricmp
1971 #define STRCASECMP strcasecmp
1974 /*-----------------------------------------------------------------*/
1975 /* inExcludeList - return 1 if the string is in exclude Reg list */
1976 /*-----------------------------------------------------------------*/
1977 static bool inExcludeList(char *s)
1981 if (options.excludeRegs[i] &&
1982 STRCASECMP(options.excludeRegs[i],"none") == 0)
1985 for ( i = 0 ; options.excludeRegs[i]; i++) {
1986 if (options.excludeRegs[i] &&
1987 STRCASECMP(s,options.excludeRegs[i]) == 0)
1993 /*-----------------------------------------------------------------*/
1994 /* genFunction - generated code for function entry */
1995 /*-----------------------------------------------------------------*/
1996 static void genFunction (iCode *ic)
2002 /* create the function header */
2003 emitcode(";","-----------------------------------------");
2004 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2005 emitcode(";","-----------------------------------------");
2007 emitcode("","%s:",sym->rname);
2008 fetype = getSpec(operandType(IC_LEFT(ic)));
2010 /* if critical function then turn interrupts off */
2011 if (SPEC_CRTCL(fetype))
2012 emitcode("clr","ea");
2014 /* here we need to generate the equates for the
2015 register bank if required */
2016 if (SPEC_BANK(fetype) != rbank) {
2019 rbank = SPEC_BANK(fetype);
2020 for ( i = 0 ; i < mcs51_nRegs ; i++ ) {
2021 if (strcmp(regs8051[i].base,"0") == 0)
2022 emitcode("","%s = 0x%02x",
2024 8*rbank+regs8051[i].offset);
2026 emitcode ("","%s = %s + 0x%02x",
2029 8*rbank+regs8051[i].offset);
2033 /* if this is an interrupt service routine then
2034 save acc, b, dpl, dph */
2035 if (IS_ISR(sym->etype)) {
2037 if (!inExcludeList("acc"))
2038 emitcode ("push","acc");
2039 if (!inExcludeList("b"))
2040 emitcode ("push","b");
2041 if (!inExcludeList("dpl"))
2042 emitcode ("push","dpl");
2043 if (!inExcludeList("dph"))
2044 emitcode ("push","dph");
2045 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2047 emitcode ("push", "dpx");
2048 /* Make sure we're using standard DPTR */
2049 emitcode ("push", "dps");
2050 emitcode ("mov", "dps, #0x00");
2051 if (options.stack10bit)
2053 /* This ISR could conceivably use DPTR2. Better save it. */
2054 emitcode ("push", "dpl1");
2055 emitcode ("push", "dph1");
2056 emitcode ("push", "dpx1");
2059 /* if this isr has no bank i.e. is going to
2060 run with bank 0 , then we need to save more
2062 if (!SPEC_BANK(sym->etype)) {
2064 /* if this function does not call any other
2065 function then we can be economical and
2066 save only those registers that are used */
2067 if (! sym->hasFcall) {
2070 /* if any registers used */
2071 if (sym->regsUsed) {
2072 /* save the registers used */
2073 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2074 if (bitVectBitValue(sym->regsUsed,i) ||
2075 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2076 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
2081 /* this function has a function call cannot
2082 determines register usage so we will have the
2084 saverbank(0,ic,FALSE);
2088 /* if callee-save to be used for this function
2089 then save the registers being used in this function */
2090 if (sym->calleeSave) {
2093 /* if any registers used */
2094 if (sym->regsUsed) {
2095 /* save the registers used */
2096 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2097 if (bitVectBitValue(sym->regsUsed,i) ||
2098 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2099 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
2107 /* set the register bank to the desired value */
2108 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2109 emitcode("push","psw");
2110 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2113 if (IS_RENT(sym->etype) || options.stackAuto) {
2115 if (options.useXstack) {
2116 emitcode("mov","r0,%s",spname);
2117 emitcode("mov","a,_bp");
2118 emitcode("movx","@r0,a");
2119 emitcode("inc","%s",spname);
2123 /* set up the stack */
2124 emitcode ("push","_bp"); /* save the callers stack */
2126 emitcode ("mov","_bp,%s",spname);
2129 /* adjust the stack for the function */
2134 werror(W_STACK_OVERFLOW,sym->name);
2136 if (i > 3 && sym->recvSize < 4) {
2138 emitcode ("mov","a,sp");
2139 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2140 emitcode ("mov","sp,a");
2145 emitcode("inc","sp");
2150 emitcode ("mov","a,_spx");
2151 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2152 emitcode ("mov","_spx,a");
2157 /*-----------------------------------------------------------------*/
2158 /* genEndFunction - generates epilogue for functions */
2159 /*-----------------------------------------------------------------*/
2160 static void genEndFunction (iCode *ic)
2162 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2164 if (IS_RENT(sym->etype) || options.stackAuto)
2166 emitcode ("mov","%s,_bp",spname);
2169 /* if use external stack but some variables were
2170 added to the local stack then decrement the
2172 if (options.useXstack && sym->stack) {
2173 emitcode("mov","a,sp");
2174 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2175 emitcode("mov","sp,a");
2179 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2180 if (options.useXstack) {
2181 emitcode("mov","r0,%s",spname);
2182 emitcode("movx","a,@r0");
2183 emitcode("mov","_bp,a");
2184 emitcode("dec","%s",spname);
2188 emitcode ("pop","_bp");
2192 /* restore the register bank */
2193 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2194 emitcode ("pop","psw");
2196 if (IS_ISR(sym->etype)) {
2198 /* now we need to restore the registers */
2199 /* if this isr has no bank i.e. is going to
2200 run with bank 0 , then we need to save more
2202 if (!SPEC_BANK(sym->etype)) {
2204 /* if this function does not call any other
2205 function then we can be economical and
2206 save only those registers that are used */
2207 if (! sym->hasFcall) {
2210 /* if any registers used */
2211 if (sym->regsUsed) {
2212 /* save the registers used */
2213 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2214 if (bitVectBitValue(sym->regsUsed,i) ||
2215 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2216 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
2221 /* this function has a function call cannot
2222 determines register usage so we will have the
2224 unsaverbank(0,ic,FALSE);
2228 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2230 if (options.stack10bit)
2232 emitcode ("pop", "dpx1");
2233 emitcode ("pop", "dph1");
2234 emitcode ("pop", "dpl1");
2236 emitcode ("pop", "dps");
2237 emitcode ("pop", "dpx");
2239 if (!inExcludeList("dph"))
2240 emitcode ("pop","dph");
2241 if (!inExcludeList("dpl"))
2242 emitcode ("pop","dpl");
2243 if (!inExcludeList("b"))
2244 emitcode ("pop","b");
2245 if (!inExcludeList("acc"))
2246 emitcode ("pop","acc");
2248 if (SPEC_CRTCL(sym->etype))
2249 emitcode("setb","ea");
2251 /* if debug then send end of function */
2252 /* if (options.debug && currFunc) { */
2255 emitcode("","C$%s$%d$%d$%d ==.",
2256 ic->filename,currFunc->lastLine,
2257 ic->level,ic->block);
2258 if (IS_STATIC(currFunc->etype))
2259 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2261 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2265 emitcode ("reti","");
2268 if (SPEC_CRTCL(sym->etype))
2269 emitcode("setb","ea");
2271 if (sym->calleeSave) {
2274 /* if any registers used */
2275 if (sym->regsUsed) {
2276 /* save the registers used */
2277 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2278 if (bitVectBitValue(sym->regsUsed,i) ||
2279 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2280 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
2286 /* if debug then send end of function */
2287 /* if (options.debug && currFunc) { */
2290 emitcode("","C$%s$%d$%d$%d ==.",
2291 ic->filename,currFunc->lastLine,
2292 ic->level,ic->block);
2293 if (IS_STATIC(currFunc->etype))
2294 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2296 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2300 emitcode ("ret","");
2305 /*-----------------------------------------------------------------*/
2306 /* genRet - generate code for return statement */
2307 /*-----------------------------------------------------------------*/
2308 static void genRet (iCode *ic)
2310 int size,offset = 0 , pushed = 0;
2312 /* if we have no return value then
2313 just generate the "ret" */
2317 /* we have something to return then
2318 move the return value into place */
2319 aopOp(IC_LEFT(ic),ic,FALSE);
2320 size = AOP_SIZE(IC_LEFT(ic));
2324 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2326 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2328 emitcode("push","%s",l);
2331 l = aopGet(AOP(IC_LEFT(ic)),offset,
2333 if (strcmp(fReturn[offset],l))
2334 emitcode("mov","%s,%s",fReturn[offset++],l);
2341 if (strcmp(fReturn[pushed],"a"))
2342 emitcode("pop",fReturn[pushed]);
2344 emitcode("pop","acc");
2347 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2350 /* generate a jump to the return label
2351 if the next is not the return statement */
2352 if (!(ic->next && ic->next->op == LABEL &&
2353 IC_LABEL(ic->next) == returnLabel))
2355 emitcode("ljmp","%05d$",(returnLabel->key+100));
2359 /*-----------------------------------------------------------------*/
2360 /* genLabel - generates a label */
2361 /*-----------------------------------------------------------------*/
2362 static void genLabel (iCode *ic)
2364 /* special case never generate */
2365 if (IC_LABEL(ic) == entryLabel)
2368 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2371 /*-----------------------------------------------------------------*/
2372 /* genGoto - generates a ljmp */
2373 /*-----------------------------------------------------------------*/
2374 static void genGoto (iCode *ic)
2376 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2379 /*-----------------------------------------------------------------*/
2380 /* findLabelBackwards: walks back through the iCode chain looking */
2381 /* for the given label. Returns number of iCode instructions */
2382 /* between that label and given ic. */
2383 /* Returns zero if label not found. */
2384 /*-----------------------------------------------------------------*/
2385 static int findLabelBackwards(iCode *ic, int key)
2394 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2396 /* printf("findLabelBackwards = %d\n", count); */
2401 /* printf("findLabelBackwards: not found.\n"); */
2406 /*-----------------------------------------------------------------*/
2407 /* genPlusIncr :- does addition with increment if possible */
2408 /*-----------------------------------------------------------------*/
2409 static bool genPlusIncr (iCode *ic)
2411 unsigned int icount ;
2412 unsigned int size = getDataSize(IC_RESULT(ic));
2414 /* will try to generate an increment */
2415 /* if the right side is not a literal
2417 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2420 /* if the literal value of the right hand side
2421 is greater than 4 then it is not worth it */
2422 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2425 /* if increment 16 bits in register */
2426 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2433 /* If the next instruction is a goto and the goto target
2434 * is < 10 instructions previous to this, we can generate
2435 * jumps straight to that target.
2437 if (ic->next && ic->next->op == GOTO
2438 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2439 && labelRange <= 10 )
2441 emitcode(";", "tail increment optimized");
2442 tlbl = IC_LABEL(ic->next);
2447 tlbl = newiTempLabel(NULL);
2450 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2451 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2452 IS_AOP_PREG(IC_RESULT(ic)))
2453 emitcode("cjne","%s,#0x00,%05d$"
2454 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2457 emitcode("clr","a");
2458 emitcode("cjne","a,%s,%05d$"
2459 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2463 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2466 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2467 IS_AOP_PREG(IC_RESULT(ic)))
2468 emitcode("cjne","%s,#0x00,%05d$"
2469 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2472 emitcode("cjne","a,%s,%05d$"
2473 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2476 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2480 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2481 IS_AOP_PREG(IC_RESULT(ic)))
2482 emitcode("cjne","%s,#0x00,%05d$"
2483 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2486 emitcode("cjne","a,%s,%05d$"
2487 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2490 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2495 emitcode("","%05d$:",tlbl->key+100);
2500 /* if the sizes are greater than 1 then we cannot */
2501 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2502 AOP_SIZE(IC_LEFT(ic)) > 1 )
2505 /* we can if the aops of the left & result match or
2506 if they are in registers and the registers are the
2508 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2511 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2512 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2513 aopPut(AOP(IC_RESULT(ic)),"a",0);
2517 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2526 /*-----------------------------------------------------------------*/
2527 /* outBitAcc - output a bit in acc */
2528 /*-----------------------------------------------------------------*/
2529 static void outBitAcc(operand *result)
2531 symbol *tlbl = newiTempLabel(NULL);
2532 /* if the result is a bit */
2533 if (AOP_TYPE(result) == AOP_CRY){
2534 aopPut(AOP(result),"a",0);
2537 emitcode("jz","%05d$",tlbl->key+100);
2538 emitcode("mov","a,%s",one);
2539 emitcode("","%05d$:",tlbl->key+100);
2544 /*-----------------------------------------------------------------*/
2545 /* genPlusBits - generates code for addition of two bits */
2546 /*-----------------------------------------------------------------*/
2547 static void genPlusBits (iCode *ic)
2549 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2550 symbol *lbl = newiTempLabel(NULL);
2551 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2552 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2553 emitcode("cpl","c");
2554 emitcode("","%05d$:",(lbl->key+100));
2555 outBitC(IC_RESULT(ic));
2558 emitcode("clr","a");
2559 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2560 emitcode("rlc","a");
2561 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2562 emitcode("addc","a,#0x00");
2563 outAcc(IC_RESULT(ic));
2568 /* This is the original version of this code.
2570 * This is being kept around for reference,
2571 * because I am not entirely sure I got it right...
2573 static void adjustArithmeticResult(iCode *ic)
2575 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2576 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2577 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2578 aopPut(AOP(IC_RESULT(ic)),
2579 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2582 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2583 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
2584 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2585 aopPut(AOP(IC_RESULT(ic)),
2586 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2589 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2590 AOP_SIZE(IC_LEFT(ic)) < 3 &&
2591 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
2592 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2593 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2595 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2596 aopPut(AOP(IC_RESULT(ic)),buffer,2);
2600 /* This is the pure and virtuous version of this code.
2601 * I'm pretty certain it's right, but not enough to toss the old
2604 static void adjustArithmeticResult(iCode *ic)
2606 if (opIsGptr(IC_RESULT(ic)) &&
2607 opIsGptr(IC_LEFT(ic)) &&
2608 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2610 aopPut(AOP(IC_RESULT(ic)),
2611 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
2615 if (opIsGptr(IC_RESULT(ic)) &&
2616 opIsGptr(IC_RIGHT(ic)) &&
2617 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2619 aopPut(AOP(IC_RESULT(ic)),
2620 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
2624 if (opIsGptr(IC_RESULT(ic)) &&
2625 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2626 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2627 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2628 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2630 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2631 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2636 /*-----------------------------------------------------------------*/
2637 /* genPlus - generates code for addition */
2638 /*-----------------------------------------------------------------*/
2639 static void genPlus (iCode *ic)
2641 int size, offset = 0;
2643 /* special cases :- */
2645 aopOp (IC_LEFT(ic),ic,FALSE);
2646 aopOp (IC_RIGHT(ic),ic,FALSE);
2647 aopOp (IC_RESULT(ic),ic,TRUE);
2649 /* if literal, literal on the right or
2650 if left requires ACC or right is already
2652 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2653 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2654 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2655 operand *t = IC_RIGHT(ic);
2656 IC_RIGHT(ic) = IC_LEFT(ic);
2660 /* if both left & right are in bit
2662 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2663 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2668 /* if left in bit space & right literal */
2669 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2670 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2671 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2672 /* if result in bit space */
2673 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2674 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
2675 emitcode("cpl","c");
2676 outBitC(IC_RESULT(ic));
2678 size = getDataSize(IC_RESULT(ic));
2680 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2681 emitcode("addc","a,#00");
2682 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2688 /* if I can do an increment instead
2689 of add then GOOD for ME */
2690 if (genPlusIncr (ic) == TRUE)
2693 size = getDataSize(IC_RESULT(ic));
2696 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2697 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2699 emitcode("add","a,%s",
2700 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2702 emitcode("addc","a,%s",
2703 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2705 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2707 emitcode("add","a,%s",
2708 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2710 emitcode("addc","a,%s",
2711 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2713 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2716 adjustArithmeticResult(ic);
2719 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2720 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2721 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2724 /*-----------------------------------------------------------------*/
2725 /* genMinusDec :- does subtraction with deccrement if possible */
2726 /*-----------------------------------------------------------------*/
2727 static bool genMinusDec (iCode *ic)
2729 unsigned int icount ;
2730 unsigned int size = getDataSize(IC_RESULT(ic));
2732 /* will try to generate an increment */
2733 /* if the right side is not a literal
2735 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2738 /* if the literal value of the right hand side
2739 is greater than 4 then it is not worth it */
2740 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2743 /* if decrement 16 bits in register */
2744 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2751 /* If the next instruction is a goto and the goto target
2752 * is <= 10 instructions previous to this, we can generate
2753 * jumps straight to that target.
2755 if (ic->next && ic->next->op == GOTO
2756 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2757 && labelRange <= 10 )
2759 emitcode(";", "tail decrement optimized");
2760 tlbl = IC_LABEL(ic->next);
2765 tlbl = newiTempLabel(NULL);
2769 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2770 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2771 IS_AOP_PREG(IC_RESULT(ic)))
2772 emitcode("cjne","%s,#0xff,%05d$"
2773 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2776 emitcode("mov","a,#0xff");
2777 emitcode("cjne","a,%s,%05d$"
2778 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2781 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2784 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2785 IS_AOP_PREG(IC_RESULT(ic)))
2786 emitcode("cjne","%s,#0xff,%05d$"
2787 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2790 emitcode("cjne","a,%s,%05d$"
2791 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2794 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2798 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2799 IS_AOP_PREG(IC_RESULT(ic)))
2800 emitcode("cjne","%s,#0xff,%05d$"
2801 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2804 emitcode("cjne","a,%s,%05d$"
2805 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2808 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2812 emitcode("","%05d$:",tlbl->key+100);
2817 /* if the sizes are greater than 1 then we cannot */
2818 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2819 AOP_SIZE(IC_LEFT(ic)) > 1 )
2822 /* we can if the aops of the left & result match or
2823 if they are in registers and the registers are the
2825 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2828 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2836 /*-----------------------------------------------------------------*/
2837 /* addSign - complete with sign */
2838 /*-----------------------------------------------------------------*/
2839 static void addSign(operand *result, int offset, int sign)
2841 int size = (getDataSize(result) - offset);
2844 emitcode("rlc","a");
2845 emitcode("subb","a,acc");
2847 aopPut(AOP(result),"a",offset++);
2850 aopPut(AOP(result),zero,offset++);
2854 /*-----------------------------------------------------------------*/
2855 /* genMinusBits - generates code for subtraction of two bits */
2856 /*-----------------------------------------------------------------*/
2857 static void genMinusBits (iCode *ic)
2859 symbol *lbl = newiTempLabel(NULL);
2860 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2861 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2862 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2863 emitcode("cpl","c");
2864 emitcode("","%05d$:",(lbl->key+100));
2865 outBitC(IC_RESULT(ic));
2868 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2869 emitcode("subb","a,acc");
2870 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
2871 emitcode("inc","a");
2872 emitcode("","%05d$:",(lbl->key+100));
2873 aopPut(AOP(IC_RESULT(ic)),"a",0);
2874 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
2878 /*-----------------------------------------------------------------*/
2879 /* genMinus - generates code for subtraction */
2880 /*-----------------------------------------------------------------*/
2881 static void genMinus (iCode *ic)
2883 int size, offset = 0;
2884 unsigned long lit = 0L;
2886 aopOp (IC_LEFT(ic),ic,FALSE);
2887 aopOp (IC_RIGHT(ic),ic,FALSE);
2888 aopOp (IC_RESULT(ic),ic,TRUE);
2890 /* special cases :- */
2891 /* if both left & right are in bit space */
2892 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2893 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2898 /* if I can do an decrement instead
2899 of subtract then GOOD for ME */
2900 if (genMinusDec (ic) == TRUE)
2903 size = getDataSize(IC_RESULT(ic));
2905 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
2909 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2913 /* if literal, add a,#-lit, else normal subb */
2915 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2916 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2917 emitcode("subb","a,%s",
2918 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2920 /* first add without previous c */
2922 emitcode("add","a,#0x%02x",
2923 (unsigned int)(lit & 0x0FFL));
2925 emitcode("addc","a,#0x%02x",
2926 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
2928 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2931 adjustArithmeticResult(ic);
2934 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2935 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2936 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2940 /*-----------------------------------------------------------------*/
2941 /* genMultbits :- multiplication of bits */
2942 /*-----------------------------------------------------------------*/
2943 static void genMultbits (operand *left,
2947 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2948 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
2953 /*-----------------------------------------------------------------*/
2954 /* genMultOneByte : 8 bit multiplication & division */
2955 /*-----------------------------------------------------------------*/
2956 static void genMultOneByte (operand *left,
2960 link *opetype = operandType(result);
2965 /* (if two literals, the value is computed before) */
2966 /* if one literal, literal on the right */
2967 if (AOP_TYPE(left) == AOP_LIT){
2973 size = AOP_SIZE(result);
2974 /* signed or unsigned */
2975 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2976 l = aopGet(AOP(left),0,FALSE,FALSE);
2978 emitcode("mul","ab");
2979 /* if result size = 1, mul signed = mul unsigned */
2980 aopPut(AOP(result),"a",0);
2982 if (SPEC_USIGN(opetype)){
2983 aopPut(AOP(result),"b",1);
2985 /* for filling the MSBs */
2986 emitcode("clr","a");
2989 emitcode("mov","a,b");
2991 /* adjust the MSB if left or right neg */
2993 /* if one literal */
2994 if (AOP_TYPE(right) == AOP_LIT){
2995 /* AND literal negative */
2996 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
2997 /* adjust MSB (c==0 after mul) */
2998 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3002 lbl = newiTempLabel(NULL);
3003 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3004 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3005 emitcode("","%05d$:",(lbl->key+100));
3006 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3007 lbl = newiTempLabel(NULL);
3008 emitcode("jc","%05d$",(lbl->key+100));
3009 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3010 emitcode("","%05d$:",(lbl->key+100));
3013 lbl = newiTempLabel(NULL);
3014 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3015 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3016 emitcode("","%05d$:",(lbl->key+100));
3017 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3018 lbl = newiTempLabel(NULL);
3019 emitcode("jc","%05d$",(lbl->key+100));
3020 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
3021 emitcode("","%05d$:",(lbl->key+100));
3023 aopPut(AOP(result),"a",1);
3026 emitcode("rlc","a");
3027 emitcode("subb","a,acc");
3034 aopPut(AOP(result),"a",offset++);
3038 /*-----------------------------------------------------------------*/
3039 /* genMult - generates code for multiplication */
3040 /*-----------------------------------------------------------------*/
3041 static void genMult (iCode *ic)
3043 operand *left = IC_LEFT(ic);
3044 operand *right = IC_RIGHT(ic);
3045 operand *result= IC_RESULT(ic);
3047 /* assign the amsops */
3048 aopOp (left,ic,FALSE);
3049 aopOp (right,ic,FALSE);
3050 aopOp (result,ic,TRUE);
3052 /* special cases first */
3054 if (AOP_TYPE(left) == AOP_CRY &&
3055 AOP_TYPE(right)== AOP_CRY) {
3056 genMultbits(left,right,result);
3060 /* if both are of size == 1 */
3061 if (AOP_SIZE(left) == 1 &&
3062 AOP_SIZE(right) == 1 ) {
3063 genMultOneByte(left,right,result);
3067 /* should have been converted to function call */
3071 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3072 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3073 freeAsmop(result,NULL,ic,TRUE);
3076 /*-----------------------------------------------------------------*/
3077 /* genDivbits :- division of bits */
3078 /*-----------------------------------------------------------------*/
3079 static void genDivbits (operand *left,
3086 /* the result must be bit */
3087 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3088 l = aopGet(AOP(left),0,FALSE,FALSE);
3092 emitcode("div","ab");
3093 emitcode("rrc","a");
3094 aopPut(AOP(result),"c",0);
3097 /*-----------------------------------------------------------------*/
3098 /* genDivOneByte : 8 bit division */
3099 /*-----------------------------------------------------------------*/
3100 static void genDivOneByte (operand *left,
3104 link *opetype = operandType(result);
3109 size = AOP_SIZE(result) - 1;
3111 /* signed or unsigned */
3112 if (SPEC_USIGN(opetype)) {
3113 /* unsigned is easy */
3114 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3115 l = aopGet(AOP(left),0,FALSE,FALSE);
3117 emitcode("div","ab");
3118 aopPut(AOP(result),"a",0);
3120 aopPut(AOP(result),zero,offset++);
3124 /* signed is a little bit more difficult */
3126 /* save the signs of the operands */
3127 l = aopGet(AOP(left),0,FALSE,FALSE);
3129 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3130 emitcode("push","acc"); /* save it on the stack */
3132 /* now sign adjust for both left & right */
3133 l = aopGet(AOP(right),0,FALSE,FALSE);
3135 lbl = newiTempLabel(NULL);
3136 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3137 emitcode("cpl","a");
3138 emitcode("inc","a");
3139 emitcode("","%05d$:",(lbl->key+100));
3140 emitcode("mov","b,a");
3142 /* sign adjust left side */
3143 l = aopGet(AOP(left),0,FALSE,FALSE);
3146 lbl = newiTempLabel(NULL);
3147 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3148 emitcode("cpl","a");
3149 emitcode("inc","a");
3150 emitcode("","%05d$:",(lbl->key+100));
3152 /* now the division */
3153 emitcode("div","ab");
3154 /* we are interested in the lower order
3156 emitcode("mov","b,a");
3157 lbl = newiTempLabel(NULL);
3158 emitcode("pop","acc");
3159 /* if there was an over flow we don't
3160 adjust the sign of the result */
3161 emitcode("jb","ov,%05d$",(lbl->key+100));
3162 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3164 emitcode("clr","a");
3165 emitcode("subb","a,b");
3166 emitcode("mov","b,a");
3167 emitcode("","%05d$:",(lbl->key+100));
3169 /* now we are done */
3170 aopPut(AOP(result),"b",0);
3172 emitcode("mov","c,b.7");
3173 emitcode("subb","a,acc");
3176 aopPut(AOP(result),"a",offset++);
3180 /*-----------------------------------------------------------------*/
3181 /* genDiv - generates code for division */
3182 /*-----------------------------------------------------------------*/
3183 static void genDiv (iCode *ic)
3185 operand *left = IC_LEFT(ic);
3186 operand *right = IC_RIGHT(ic);
3187 operand *result= IC_RESULT(ic);
3189 /* assign the amsops */
3190 aopOp (left,ic,FALSE);
3191 aopOp (right,ic,FALSE);
3192 aopOp (result,ic,TRUE);
3194 /* special cases first */
3196 if (AOP_TYPE(left) == AOP_CRY &&
3197 AOP_TYPE(right)== AOP_CRY) {
3198 genDivbits(left,right,result);
3202 /* if both are of size == 1 */
3203 if (AOP_SIZE(left) == 1 &&
3204 AOP_SIZE(right) == 1 ) {
3205 genDivOneByte(left,right,result);
3209 /* should have been converted to function call */
3212 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3213 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3214 freeAsmop(result,NULL,ic,TRUE);
3217 /*-----------------------------------------------------------------*/
3218 /* genModbits :- modulus of bits */
3219 /*-----------------------------------------------------------------*/
3220 static void genModbits (operand *left,
3227 /* the result must be bit */
3228 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3229 l = aopGet(AOP(left),0,FALSE,FALSE);
3233 emitcode("div","ab");
3234 emitcode("mov","a,b");
3235 emitcode("rrc","a");
3236 aopPut(AOP(result),"c",0);
3239 /*-----------------------------------------------------------------*/
3240 /* genModOneByte : 8 bit modulus */
3241 /*-----------------------------------------------------------------*/
3242 static void genModOneByte (operand *left,
3246 link *opetype = operandType(result);
3250 /* signed or unsigned */
3251 if (SPEC_USIGN(opetype)) {
3252 /* unsigned is easy */
3253 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3254 l = aopGet(AOP(left),0,FALSE,FALSE);
3256 emitcode("div","ab");
3257 aopPut(AOP(result),"b",0);
3261 /* signed is a little bit more difficult */
3263 /* save the signs of the operands */
3264 l = aopGet(AOP(left),0,FALSE,FALSE);
3267 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3268 emitcode("push","acc"); /* save it on the stack */
3270 /* now sign adjust for both left & right */
3271 l = aopGet(AOP(right),0,FALSE,FALSE);
3274 lbl = newiTempLabel(NULL);
3275 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3276 emitcode("cpl","a");
3277 emitcode("inc","a");
3278 emitcode("","%05d$:",(lbl->key+100));
3279 emitcode("mov","b,a");
3281 /* sign adjust left side */
3282 l = aopGet(AOP(left),0,FALSE,FALSE);
3285 lbl = newiTempLabel(NULL);
3286 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3287 emitcode("cpl","a");
3288 emitcode("inc","a");
3289 emitcode("","%05d$:",(lbl->key+100));
3291 /* now the multiplication */
3292 emitcode("div","ab");
3293 /* we are interested in the lower order
3295 lbl = newiTempLabel(NULL);
3296 emitcode("pop","acc");
3297 /* if there was an over flow we don't
3298 adjust the sign of the result */
3299 emitcode("jb","ov,%05d$",(lbl->key+100));
3300 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3302 emitcode("clr","a");
3303 emitcode("subb","a,b");
3304 emitcode("mov","b,a");
3305 emitcode("","%05d$:",(lbl->key+100));
3307 /* now we are done */
3308 aopPut(AOP(result),"b",0);
3312 /*-----------------------------------------------------------------*/
3313 /* genMod - generates code for division */
3314 /*-----------------------------------------------------------------*/
3315 static void genMod (iCode *ic)
3317 operand *left = IC_LEFT(ic);
3318 operand *right = IC_RIGHT(ic);
3319 operand *result= IC_RESULT(ic);
3321 /* assign the amsops */
3322 aopOp (left,ic,FALSE);
3323 aopOp (right,ic,FALSE);
3324 aopOp (result,ic,TRUE);
3326 /* special cases first */
3328 if (AOP_TYPE(left) == AOP_CRY &&
3329 AOP_TYPE(right)== AOP_CRY) {
3330 genModbits(left,right,result);
3334 /* if both are of size == 1 */
3335 if (AOP_SIZE(left) == 1 &&
3336 AOP_SIZE(right) == 1 ) {
3337 genModOneByte(left,right,result);
3341 /* should have been converted to function call */
3345 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3346 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3347 freeAsmop(result,NULL,ic,TRUE);
3350 /*-----------------------------------------------------------------*/
3351 /* genIfxJump :- will create a jump depending on the ifx */
3352 /*-----------------------------------------------------------------*/
3353 static void genIfxJump (iCode *ic, char *jval)
3356 symbol *tlbl = newiTempLabel(NULL);
3359 /* if true label then we jump if condition
3361 if ( IC_TRUE(ic) ) {
3363 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3364 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3367 /* false label is present */
3368 jlbl = IC_FALSE(ic) ;
3369 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3370 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3372 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3373 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3375 emitcode(inst,"%05d$",tlbl->key+100);
3376 emitcode("ljmp","%05d$",jlbl->key+100);
3377 emitcode("","%05d$:",tlbl->key+100);
3379 /* mark the icode as generated */
3383 /*-----------------------------------------------------------------*/
3384 /* genCmp :- greater or less than comparison */
3385 /*-----------------------------------------------------------------*/
3386 static void genCmp (operand *left,operand *right,
3387 operand *result, iCode *ifx, int sign)
3389 int size, offset = 0 ;
3390 unsigned long lit = 0L;
3392 /* if left & right are bit variables */
3393 if (AOP_TYPE(left) == AOP_CRY &&
3394 AOP_TYPE(right) == AOP_CRY ) {
3395 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3396 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3398 /* subtract right from left if at the
3399 end the carry flag is set then we know that
3400 left is greater than right */
3401 size = max(AOP_SIZE(left),AOP_SIZE(right));
3403 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3404 if((size == 1) && !sign &&
3405 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3406 symbol *lbl = newiTempLabel(NULL);
3407 emitcode("cjne","%s,%s,%05d$",
3408 aopGet(AOP(left),offset,FALSE,FALSE),
3409 aopGet(AOP(right),offset,FALSE,FALSE),
3411 emitcode("","%05d$:",lbl->key+100);
3413 if(AOP_TYPE(right) == AOP_LIT){
3414 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3415 /* optimize if(x < 0) or if(x >= 0) */
3421 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE));
3422 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3423 genIfxJump (ifx,"acc.7");
3427 emitcode("rlc","a");
3434 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3435 if (sign && size == 0) {
3436 emitcode("xrl","a,#0x80");
3437 if (AOP_TYPE(right) == AOP_LIT){
3438 unsigned long lit = (unsigned long)
3439 floatFromVal(AOP(right)->aopu.aop_lit);
3440 emitcode("subb","a,#0x%02x",
3441 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3443 emitcode("mov","b,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3444 emitcode("xrl","b,#0x80");
3445 emitcode("subb","a,b");
3448 emitcode("subb","a,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3454 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3457 /* if the result is used in the next
3458 ifx conditional branch then generate
3459 code a little differently */
3461 genIfxJump (ifx,"c");
3464 /* leave the result in acc */
3468 /*-----------------------------------------------------------------*/
3469 /* genCmpGt :- greater than comparison */
3470 /*-----------------------------------------------------------------*/
3471 static void genCmpGt (iCode *ic, iCode *ifx)
3473 operand *left, *right, *result;
3474 link *letype , *retype;
3478 right= IC_RIGHT(ic);
3479 result = IC_RESULT(ic);
3481 letype = getSpec(operandType(left));
3482 retype =getSpec(operandType(right));
3483 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3484 /* assign the amsops */
3485 aopOp (left,ic,FALSE);
3486 aopOp (right,ic,FALSE);
3487 aopOp (result,ic,TRUE);
3489 genCmp(right, left, result, ifx, sign);
3491 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3492 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3493 freeAsmop(result,NULL,ic,TRUE);
3496 /*-----------------------------------------------------------------*/
3497 /* genCmpLt - less than comparisons */
3498 /*-----------------------------------------------------------------*/
3499 static void genCmpLt (iCode *ic, iCode *ifx)
3501 operand *left, *right, *result;
3502 link *letype , *retype;
3506 right= IC_RIGHT(ic);
3507 result = IC_RESULT(ic);
3509 letype = getSpec(operandType(left));
3510 retype =getSpec(operandType(right));
3511 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3513 /* assign the amsops */
3514 aopOp (left,ic,FALSE);
3515 aopOp (right,ic,FALSE);
3516 aopOp (result,ic,TRUE);
3518 genCmp(left, right, result, ifx, sign);
3520 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3521 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3522 freeAsmop(result,NULL,ic,TRUE);
3525 /*-----------------------------------------------------------------*/
3526 /* gencjneshort - compare and jump if not equal */
3527 /*-----------------------------------------------------------------*/
3528 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3530 int size = max(AOP_SIZE(left),AOP_SIZE(right));
3532 unsigned long lit = 0L;
3534 /* if the left side is a literal or
3535 if the right is in a pointer register and left
3537 if ((AOP_TYPE(left) == AOP_LIT) ||
3538 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3543 if(AOP_TYPE(right) == AOP_LIT)
3544 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3546 /* if the right side is a literal then anything goes */
3547 if (AOP_TYPE(right) == AOP_LIT &&
3548 AOP_TYPE(left) != AOP_DIR ) {
3550 emitcode("cjne","%s,%s,%05d$",
3551 aopGet(AOP(left),offset,FALSE,FALSE),
3552 aopGet(AOP(right),offset,FALSE,FALSE),
3558 /* if the right side is in a register or in direct space or
3559 if the left is a pointer register & right is not */
3560 else if (AOP_TYPE(right) == AOP_REG ||
3561 AOP_TYPE(right) == AOP_DIR ||
3562 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3563 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3565 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3566 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3567 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
3568 emitcode("jnz","%05d$",lbl->key+100);
3570 emitcode("cjne","a,%s,%05d$",
3571 aopGet(AOP(right),offset,FALSE,TRUE),
3576 /* right is a pointer reg need both a & b */
3578 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
3580 emitcode("mov","b,%s",l);
3581 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3582 emitcode("cjne","a,b,%05d$",lbl->key+100);
3588 /*-----------------------------------------------------------------*/
3589 /* gencjne - compare and jump if not equal */
3590 /*-----------------------------------------------------------------*/
3591 static void gencjne(operand *left, operand *right, symbol *lbl)
3593 symbol *tlbl = newiTempLabel(NULL);
3595 gencjneshort(left, right, lbl);
3597 emitcode("mov","a,%s",one);
3598 emitcode("sjmp","%05d$",tlbl->key+100);
3599 emitcode("","%05d$:",lbl->key+100);
3600 emitcode("clr","a");
3601 emitcode("","%05d$:",tlbl->key+100);
3604 /*-----------------------------------------------------------------*/
3605 /* genCmpEq - generates code for equal to */
3606 /*-----------------------------------------------------------------*/
3607 static void genCmpEq (iCode *ic, iCode *ifx)
3609 operand *left, *right, *result;
3611 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3612 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3613 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3615 /* if literal, literal on the right or
3616 if the right is in a pointer register and left
3618 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
3619 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3620 operand *t = IC_RIGHT(ic);
3621 IC_RIGHT(ic) = IC_LEFT(ic);
3625 if(ifx && !AOP_SIZE(result)){
3627 /* if they are both bit variables */
3628 if (AOP_TYPE(left) == AOP_CRY &&
3629 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3630 if(AOP_TYPE(right) == AOP_LIT){
3631 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3633 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3634 emitcode("cpl","c");
3635 } else if(lit == 1L) {
3636 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3638 emitcode("clr","c");
3640 /* AOP_TYPE(right) == AOP_CRY */
3642 symbol *lbl = newiTempLabel(NULL);
3643 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3644 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3645 emitcode("cpl","c");
3646 emitcode("","%05d$:",(lbl->key+100));
3648 /* if true label then we jump if condition
3650 tlbl = newiTempLabel(NULL);
3651 if ( IC_TRUE(ifx) ) {
3652 emitcode("jnc","%05d$",tlbl->key+100);
3653 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3655 emitcode("jc","%05d$",tlbl->key+100);
3656 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3658 emitcode("","%05d$:",tlbl->key+100);
3660 tlbl = newiTempLabel(NULL);
3661 gencjneshort(left, right, tlbl);
3662 if ( IC_TRUE(ifx) ) {
3663 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3664 emitcode("","%05d$:",tlbl->key+100);
3666 symbol *lbl = newiTempLabel(NULL);
3667 emitcode("sjmp","%05d$",lbl->key+100);
3668 emitcode("","%05d$:",tlbl->key+100);
3669 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3670 emitcode("","%05d$:",lbl->key+100);
3673 /* mark the icode as generated */
3678 /* if they are both bit variables */
3679 if (AOP_TYPE(left) == AOP_CRY &&
3680 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3681 if(AOP_TYPE(right) == AOP_LIT){
3682 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3684 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3685 emitcode("cpl","c");
3686 } else if(lit == 1L) {
3687 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3689 emitcode("clr","c");
3691 /* AOP_TYPE(right) == AOP_CRY */
3693 symbol *lbl = newiTempLabel(NULL);
3694 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3695 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3696 emitcode("cpl","c");
3697 emitcode("","%05d$:",(lbl->key+100));
3700 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
3705 genIfxJump (ifx,"c");
3708 /* if the result is used in an arithmetic operation
3709 then put the result in place */
3712 gencjne(left,right,newiTempLabel(NULL));
3713 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3714 aopPut(AOP(result),"a",0);
3718 genIfxJump (ifx,"a");
3721 /* if the result is used in an arithmetic operation
3722 then put the result in place */
3723 if (AOP_TYPE(result) != AOP_CRY)
3725 /* leave the result in acc */
3729 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3730 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3731 freeAsmop(result,NULL,ic,TRUE);
3734 /*-----------------------------------------------------------------*/
3735 /* ifxForOp - returns the icode containing the ifx for operand */
3736 /*-----------------------------------------------------------------*/
3737 static iCode *ifxForOp ( operand *op, iCode *ic )
3739 /* if true symbol then needs to be assigned */
3740 if (IS_TRUE_SYMOP(op))
3743 /* if this has register type condition and
3744 the next instruction is ifx with the same operand
3745 and live to of the operand is upto the ifx only then */
3747 ic->next->op == IFX &&
3748 IC_COND(ic->next)->key == op->key &&
3749 OP_SYMBOL(op)->liveTo <= ic->next->seq )
3754 /*-----------------------------------------------------------------*/
3755 /* genAndOp - for && operation */
3756 /*-----------------------------------------------------------------*/
3757 static void genAndOp (iCode *ic)
3759 operand *left,*right, *result;
3762 /* note here that && operations that are in an
3763 if statement are taken away by backPatchLabels
3764 only those used in arthmetic operations remain */
3765 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3766 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3767 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3769 /* if both are bit variables */
3770 if (AOP_TYPE(left) == AOP_CRY &&
3771 AOP_TYPE(right) == AOP_CRY ) {
3772 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3773 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3776 tlbl = newiTempLabel(NULL);
3778 emitcode("jz","%05d$",tlbl->key+100);
3780 emitcode("","%05d$:",tlbl->key+100);
3784 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3785 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3786 freeAsmop(result,NULL,ic,TRUE);
3790 /*-----------------------------------------------------------------*/
3791 /* genOrOp - for || operation */
3792 /*-----------------------------------------------------------------*/
3793 static void genOrOp (iCode *ic)
3795 operand *left,*right, *result;
3798 /* note here that || operations that are in an
3799 if statement are taken away by backPatchLabels
3800 only those used in arthmetic operations remain */
3801 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3802 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3803 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3805 /* if both are bit variables */
3806 if (AOP_TYPE(left) == AOP_CRY &&
3807 AOP_TYPE(right) == AOP_CRY ) {
3808 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3809 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
3812 tlbl = newiTempLabel(NULL);
3814 emitcode("jnz","%05d$",tlbl->key+100);
3816 emitcode("","%05d$:",tlbl->key+100);
3820 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3821 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3822 freeAsmop(result,NULL,ic,TRUE);
3825 /*-----------------------------------------------------------------*/
3826 /* isLiteralBit - test if lit == 2^n */
3827 /*-----------------------------------------------------------------*/
3828 static int isLiteralBit(unsigned long lit)
3830 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
3831 0x100L,0x200L,0x400L,0x800L,
3832 0x1000L,0x2000L,0x4000L,0x8000L,
3833 0x10000L,0x20000L,0x40000L,0x80000L,
3834 0x100000L,0x200000L,0x400000L,0x800000L,
3835 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
3836 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
3839 for(idx = 0; idx < 32; idx++)
3845 /*-----------------------------------------------------------------*/
3846 /* continueIfTrue - */
3847 /*-----------------------------------------------------------------*/
3848 static void continueIfTrue (iCode *ic)
3851 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3855 /*-----------------------------------------------------------------*/
3857 /*-----------------------------------------------------------------*/
3858 static void jumpIfTrue (iCode *ic)
3861 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3865 /*-----------------------------------------------------------------*/
3866 /* jmpTrueOrFalse - */
3867 /*-----------------------------------------------------------------*/
3868 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
3870 // ugly but optimized by peephole
3872 symbol *nlbl = newiTempLabel(NULL);
3873 emitcode("sjmp","%05d$",nlbl->key+100);
3874 emitcode("","%05d$:",tlbl->key+100);
3875 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3876 emitcode("","%05d$:",nlbl->key+100);
3879 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3880 emitcode("","%05d$:",tlbl->key+100);
3885 /*-----------------------------------------------------------------*/
3886 /* genAnd - code for and */
3887 /*-----------------------------------------------------------------*/
3888 static void genAnd (iCode *ic, iCode *ifx)
3890 operand *left, *right, *result;
3892 unsigned long lit = 0L;
3896 aopOp((left = IC_LEFT(ic)),ic,FALSE);
3897 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3898 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3901 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3903 AOP_TYPE(left), AOP_TYPE(right));
3904 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3906 AOP_SIZE(left), AOP_SIZE(right));
3909 /* if left is a literal & right is not then exchange them */
3910 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3911 AOP_NEEDSACC(left)) {
3912 operand *tmp = right ;
3917 /* if result = right then exchange them */
3918 if(sameRegs(AOP(result),AOP(right))){
3919 operand *tmp = right ;
3924 /* if right is bit then exchange them */
3925 if (AOP_TYPE(right) == AOP_CRY &&
3926 AOP_TYPE(left) != AOP_CRY){
3927 operand *tmp = right ;
3931 if(AOP_TYPE(right) == AOP_LIT)
3932 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3934 size = AOP_SIZE(result);
3937 // result = bit & yy;
3938 if (AOP_TYPE(left) == AOP_CRY){
3939 // c = bit & literal;
3940 if(AOP_TYPE(right) == AOP_LIT){
3942 if(size && sameRegs(AOP(result),AOP(left)))
3945 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3948 if(size && (AOP_TYPE(result) == AOP_CRY)){
3949 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
3952 if((AOP_TYPE(result) == AOP_CRY) && ifx){
3956 emitcode("clr","c");
3959 if (AOP_TYPE(right) == AOP_CRY){
3961 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3962 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3965 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
3967 emitcode("rrc","a");
3968 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3976 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
3977 genIfxJump(ifx, "c");
3981 // if(val & 0xZZ) - size = 0, ifx != FALSE -
3982 // bit = val & 0xZZ - size = 1, ifx = FALSE -
3983 if((AOP_TYPE(right) == AOP_LIT) &&
3984 (AOP_TYPE(result) == AOP_CRY) &&
3985 (AOP_TYPE(left) != AOP_CRY)){
3986 int posbit = isLiteralBit(lit);
3990 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
3993 emitcode("mov","c,acc.%d",posbit&0x07);
3997 sprintf(buffer,"acc.%d",posbit&0x07);
3998 genIfxJump(ifx, buffer);
4003 symbol *tlbl = newiTempLabel(NULL);
4004 int sizel = AOP_SIZE(left);
4006 emitcode("setb","c");
4008 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4009 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
4011 if((posbit = isLiteralBit(bytelit)) != 0)
4012 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
4014 if(bytelit != 0x0FFL)
4015 emitcode("anl","a,%s",
4016 aopGet(AOP(right),offset,FALSE,TRUE));
4017 emitcode("jnz","%05d$",tlbl->key+100);
4022 // bit = left & literal
4024 emitcode("clr","c");
4025 emitcode("","%05d$:",tlbl->key+100);
4027 // if(left & literal)
4030 jmpTrueOrFalse(ifx, tlbl);
4038 /* if left is same as result */
4039 if(sameRegs(AOP(result),AOP(left))){
4040 for(;size--; offset++) {
4041 if(AOP_TYPE(right) == AOP_LIT){
4042 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4046 aopPut(AOP(result),zero,offset);
4048 if (IS_AOP_PREG(result)) {
4049 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4050 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4051 aopPut(AOP(result),"a",offset);
4053 emitcode("anl","%s,%s",
4054 aopGet(AOP(left),offset,FALSE,TRUE),
4055 aopGet(AOP(right),offset,FALSE,FALSE));
4057 if (AOP_TYPE(left) == AOP_ACC)
4058 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4060 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4061 if (IS_AOP_PREG(result)) {
4062 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4063 aopPut(AOP(result),"a",offset);
4066 emitcode("anl","%s,a",
4067 aopGet(AOP(left),offset,FALSE,TRUE));
4072 // left & result in different registers
4073 if(AOP_TYPE(result) == AOP_CRY){
4075 // if(size), result in bit
4076 // if(!size && ifx), conditional oper: if(left & right)
4077 symbol *tlbl = newiTempLabel(NULL);
4078 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4080 emitcode("setb","c");
4082 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4083 emitcode("anl","a,%s",
4084 aopGet(AOP(left),offset,FALSE,FALSE));
4085 emitcode("jnz","%05d$",tlbl->key+100);
4090 emitcode("","%05d$:",tlbl->key+100);
4093 jmpTrueOrFalse(ifx, tlbl);
4095 for(;(size--);offset++) {
4097 // result = left & right
4098 if(AOP_TYPE(right) == AOP_LIT){
4099 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
4101 aopGet(AOP(left),offset,FALSE,FALSE),
4104 } else if(bytelit == 0){
4105 aopPut(AOP(result),zero,offset);
4109 // faster than result <- left, anl result,right
4110 // and better if result is SFR
4111 if (AOP_TYPE(left) == AOP_ACC)
4112 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4114 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4115 emitcode("anl","a,%s",
4116 aopGet(AOP(left),offset,FALSE,FALSE));
4118 aopPut(AOP(result),"a",offset);
4124 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4125 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4126 freeAsmop(result,NULL,ic,TRUE);
4129 /*-----------------------------------------------------------------*/
4130 /* genOr - code for or */
4131 /*-----------------------------------------------------------------*/
4132 static void genOr (iCode *ic, iCode *ifx)
4134 operand *left, *right, *result;
4136 unsigned long lit = 0L;
4138 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4139 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4140 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4143 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4145 AOP_TYPE(left), AOP_TYPE(right));
4146 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4148 AOP_SIZE(left), AOP_SIZE(right));
4151 /* if left is a literal & right is not then exchange them */
4152 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4153 AOP_NEEDSACC(left)) {
4154 operand *tmp = right ;
4159 /* if result = right then exchange them */
4160 if(sameRegs(AOP(result),AOP(right))){
4161 operand *tmp = right ;
4166 /* if right is bit then exchange them */
4167 if (AOP_TYPE(right) == AOP_CRY &&
4168 AOP_TYPE(left) != AOP_CRY){
4169 operand *tmp = right ;
4173 if(AOP_TYPE(right) == AOP_LIT)
4174 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4176 size = AOP_SIZE(result);
4180 if (AOP_TYPE(left) == AOP_CRY){
4181 if(AOP_TYPE(right) == AOP_LIT){
4182 // c = bit & literal;
4184 // lit != 0 => result = 1
4185 if(AOP_TYPE(result) == AOP_CRY){
4187 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4189 continueIfTrue(ifx);
4192 emitcode("setb","c");
4194 // lit == 0 => result = left
4195 if(size && sameRegs(AOP(result),AOP(left)))
4197 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4200 if (AOP_TYPE(right) == AOP_CRY){
4202 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4203 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4207 symbol *tlbl = newiTempLabel(NULL);
4208 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4209 emitcode("setb","c");
4210 emitcode("jb","%s,%05d$",
4211 AOP(left)->aopu.aop_dir,tlbl->key+100);
4213 emitcode("jnz","%05d$",tlbl->key+100);
4214 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4215 jmpTrueOrFalse(ifx, tlbl);
4219 emitcode("","%05d$:",tlbl->key+100);
4228 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4229 genIfxJump(ifx, "c");
4233 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4234 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4235 if((AOP_TYPE(right) == AOP_LIT) &&
4236 (AOP_TYPE(result) == AOP_CRY) &&
4237 (AOP_TYPE(left) != AOP_CRY)){
4241 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4243 continueIfTrue(ifx);
4246 // lit = 0, result = boolean(left)
4248 emitcode("setb","c");
4251 symbol *tlbl = newiTempLabel(NULL);
4252 emitcode("jnz","%05d$",tlbl->key+100);
4254 emitcode("","%05d$:",tlbl->key+100);
4256 genIfxJump (ifx,"a");
4264 /* if left is same as result */
4265 if(sameRegs(AOP(result),AOP(left))){
4266 for(;size--; offset++) {
4267 if(AOP_TYPE(right) == AOP_LIT){
4268 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4271 if (IS_AOP_PREG(left)) {
4272 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4273 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4274 aopPut(AOP(result),"a",offset);
4276 emitcode("orl","%s,%s",
4277 aopGet(AOP(left),offset,FALSE,TRUE),
4278 aopGet(AOP(right),offset,FALSE,FALSE));
4280 if (AOP_TYPE(left) == AOP_ACC)
4281 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4283 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4284 if (IS_AOP_PREG(left)) {
4285 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4286 aopPut(AOP(result),"a",offset);
4288 emitcode("orl","%s,a",
4289 aopGet(AOP(left),offset,FALSE,TRUE));
4294 // left & result in different registers
4295 if(AOP_TYPE(result) == AOP_CRY){
4297 // if(size), result in bit
4298 // if(!size && ifx), conditional oper: if(left | right)
4299 symbol *tlbl = newiTempLabel(NULL);
4300 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4302 emitcode("setb","c");
4304 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4305 emitcode("orl","a,%s",
4306 aopGet(AOP(left),offset,FALSE,FALSE));
4307 emitcode("jnz","%05d$",tlbl->key+100);
4312 emitcode("","%05d$:",tlbl->key+100);
4315 jmpTrueOrFalse(ifx, tlbl);
4316 } else for(;(size--);offset++){
4318 // result = left & right
4319 if(AOP_TYPE(right) == AOP_LIT){
4320 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4322 aopGet(AOP(left),offset,FALSE,FALSE),
4327 // faster than result <- left, anl result,right
4328 // and better if result is SFR
4329 if (AOP_TYPE(left) == AOP_ACC)
4330 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4332 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4333 emitcode("orl","a,%s",
4334 aopGet(AOP(left),offset,FALSE,FALSE));
4336 aopPut(AOP(result),"a",offset);
4341 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4342 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4343 freeAsmop(result,NULL,ic,TRUE);
4346 /*-----------------------------------------------------------------*/
4347 /* genXor - code for xclusive or */
4348 /*-----------------------------------------------------------------*/
4349 static void genXor (iCode *ic, iCode *ifx)
4351 operand *left, *right, *result;
4353 unsigned long lit = 0L;
4355 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4356 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4357 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4360 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4362 AOP_TYPE(left), AOP_TYPE(right));
4363 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4365 AOP_SIZE(left), AOP_SIZE(right));
4368 /* if left is a literal & right is not ||
4369 if left needs acc & right does not */
4370 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4371 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4372 operand *tmp = right ;
4377 /* if result = right then exchange them */
4378 if(sameRegs(AOP(result),AOP(right))){
4379 operand *tmp = right ;
4384 /* if right is bit then exchange them */
4385 if (AOP_TYPE(right) == AOP_CRY &&
4386 AOP_TYPE(left) != AOP_CRY){
4387 operand *tmp = right ;
4391 if(AOP_TYPE(right) == AOP_LIT)
4392 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4394 size = AOP_SIZE(result);
4398 if (AOP_TYPE(left) == AOP_CRY){
4399 if(AOP_TYPE(right) == AOP_LIT){
4400 // c = bit & literal;
4402 // lit>>1 != 0 => result = 1
4403 if(AOP_TYPE(result) == AOP_CRY){
4405 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4407 continueIfTrue(ifx);
4410 emitcode("setb","c");
4414 // lit == 0, result = left
4415 if(size && sameRegs(AOP(result),AOP(left)))
4417 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4419 // lit == 1, result = not(left)
4420 if(size && sameRegs(AOP(result),AOP(left))){
4421 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4424 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4425 emitcode("cpl","c");
4432 symbol *tlbl = newiTempLabel(NULL);
4433 if (AOP_TYPE(right) == AOP_CRY){
4435 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4438 int sizer = AOP_SIZE(right);
4440 // if val>>1 != 0, result = 1
4441 emitcode("setb","c");
4443 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
4445 // test the msb of the lsb
4446 emitcode("anl","a,#0xfe");
4447 emitcode("jnz","%05d$",tlbl->key+100);
4451 emitcode("rrc","a");
4453 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4454 emitcode("cpl","c");
4455 emitcode("","%05d$:",(tlbl->key+100));
4462 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4463 genIfxJump(ifx, "c");
4467 if(sameRegs(AOP(result),AOP(left))){
4468 /* if left is same as result */
4469 for(;size--; offset++) {
4470 if(AOP_TYPE(right) == AOP_LIT){
4471 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4474 if (IS_AOP_PREG(left)) {
4475 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4476 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4477 aopPut(AOP(result),"a",offset);
4479 emitcode("xrl","%s,%s",
4480 aopGet(AOP(left),offset,FALSE,TRUE),
4481 aopGet(AOP(right),offset,FALSE,FALSE));
4483 if (AOP_TYPE(left) == AOP_ACC)
4484 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4486 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4487 if (IS_AOP_PREG(left)) {
4488 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4489 aopPut(AOP(result),"a",offset);
4491 emitcode("xrl","%s,a",
4492 aopGet(AOP(left),offset,FALSE,TRUE));
4497 // left & result in different registers
4498 if(AOP_TYPE(result) == AOP_CRY){
4500 // if(size), result in bit
4501 // if(!size && ifx), conditional oper: if(left ^ right)
4502 symbol *tlbl = newiTempLabel(NULL);
4503 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4505 emitcode("setb","c");
4507 if((AOP_TYPE(right) == AOP_LIT) &&
4508 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4509 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4511 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4512 emitcode("xrl","a,%s",
4513 aopGet(AOP(left),offset,FALSE,FALSE));
4515 emitcode("jnz","%05d$",tlbl->key+100);
4520 emitcode("","%05d$:",tlbl->key+100);
4523 jmpTrueOrFalse(ifx, tlbl);
4524 } else for(;(size--);offset++){
4526 // result = left & right
4527 if(AOP_TYPE(right) == AOP_LIT){
4528 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4530 aopGet(AOP(left),offset,FALSE,FALSE),
4535 // faster than result <- left, anl result,right
4536 // and better if result is SFR
4537 if (AOP_TYPE(left) == AOP_ACC)
4538 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4540 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4541 emitcode("xrl","a,%s",
4542 aopGet(AOP(left),offset,FALSE,TRUE));
4544 aopPut(AOP(result),"a",offset);
4549 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4550 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4551 freeAsmop(result,NULL,ic,TRUE);
4554 /*-----------------------------------------------------------------*/
4555 /* genInline - write the inline code out */
4556 /*-----------------------------------------------------------------*/
4557 static void genInline (iCode *ic)
4559 char buffer[MAX_INLINEASM];
4563 _G.inLine += (!options.asmpeep);
4564 strcpy(buffer,IC_INLINE(ic));
4566 /* emit each line as a code */
4585 /* emitcode("",buffer); */
4586 _G.inLine -= (!options.asmpeep);
4589 /*-----------------------------------------------------------------*/
4590 /* genRRC - rotate right with carry */
4591 /*-----------------------------------------------------------------*/
4592 static void genRRC (iCode *ic)
4594 operand *left , *result ;
4595 int size, offset = 0;
4598 /* rotate right with carry */
4600 result=IC_RESULT(ic);
4601 aopOp (left,ic,FALSE);
4602 aopOp (result,ic,FALSE);
4604 /* move it to the result */
4605 size = AOP_SIZE(result);
4609 l = aopGet(AOP(left),offset,FALSE,FALSE);
4611 emitcode("rrc","a");
4612 if (AOP_SIZE(result) > 1)
4613 aopPut(AOP(result),"a",offset--);
4615 /* now we need to put the carry into the
4616 highest order byte of the result */
4617 if (AOP_SIZE(result) > 1) {
4618 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
4621 emitcode("mov","acc.7,c");
4622 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
4623 freeAsmop(left,NULL,ic,TRUE);
4624 freeAsmop(result,NULL,ic,TRUE);
4627 /*-----------------------------------------------------------------*/
4628 /* genRLC - generate code for rotate left with carry */
4629 /*-----------------------------------------------------------------*/
4630 static void genRLC (iCode *ic)
4632 operand *left , *result ;
4633 int size, offset = 0;
4636 /* rotate right with carry */
4638 result=IC_RESULT(ic);
4639 aopOp (left,ic,FALSE);
4640 aopOp (result,ic,FALSE);
4642 /* move it to the result */
4643 size = AOP_SIZE(result);
4646 l = aopGet(AOP(left),offset,FALSE,FALSE);
4648 emitcode("add","a,acc");
4649 if (AOP_SIZE(result) > 1)
4650 aopPut(AOP(result),"a",offset++);
4652 l = aopGet(AOP(left),offset,FALSE,FALSE);
4654 emitcode("rlc","a");
4655 if (AOP_SIZE(result) > 1)
4656 aopPut(AOP(result),"a",offset++);
4659 /* now we need to put the carry into the
4660 highest order byte of the result */
4661 if (AOP_SIZE(result) > 1) {
4662 l = aopGet(AOP(result),0,FALSE,FALSE);
4665 emitcode("mov","acc.0,c");
4666 aopPut(AOP(result),"a",0);
4667 freeAsmop(left,NULL,ic,TRUE);
4668 freeAsmop(result,NULL,ic,TRUE);
4671 /*-----------------------------------------------------------------*/
4672 /* genGetHbit - generates code get highest order bit */
4673 /*-----------------------------------------------------------------*/
4674 static void genGetHbit (iCode *ic)
4676 operand *left, *result;
4678 result=IC_RESULT(ic);
4679 aopOp (left,ic,FALSE);
4680 aopOp (result,ic,FALSE);
4682 /* get the highest order byte into a */
4683 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
4684 if(AOP_TYPE(result) == AOP_CRY){
4685 emitcode("rlc","a");
4690 emitcode("anl","a,#0x01");
4695 freeAsmop(left,NULL,ic,TRUE);
4696 freeAsmop(result,NULL,ic,TRUE);
4699 /*-----------------------------------------------------------------*/
4700 /* AccRol - rotate left accumulator by known count */
4701 /*-----------------------------------------------------------------*/
4702 static void AccRol (int shCount)
4704 shCount &= 0x0007; // shCount : 0..7
4716 emitcode("swap","a");
4720 emitcode("swap","a");
4723 emitcode("swap","a");
4736 /*-----------------------------------------------------------------*/
4737 /* AccLsh - left shift accumulator by known count */
4738 /*-----------------------------------------------------------------*/
4739 static void AccLsh (int shCount)
4743 emitcode("add","a,acc");
4746 emitcode("add","a,acc");
4747 emitcode("add","a,acc");
4749 /* rotate left accumulator */
4751 /* and kill the lower order bits */
4752 emitcode("anl","a,#0x%02x", SLMask[shCount]);
4757 /*-----------------------------------------------------------------*/
4758 /* AccRsh - right shift accumulator by known count */
4759 /*-----------------------------------------------------------------*/
4760 static void AccRsh (int shCount)
4765 emitcode("rrc","a");
4767 /* rotate right accumulator */
4768 AccRol(8 - shCount);
4769 /* and kill the higher order bits */
4770 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4775 /*-----------------------------------------------------------------*/
4776 /* AccSRsh - signed right shift accumulator by known count */
4777 /*-----------------------------------------------------------------*/
4778 static void AccSRsh (int shCount)
4783 emitcode("mov","c,acc.7");
4784 emitcode("rrc","a");
4785 } else if(shCount == 2){
4786 emitcode("mov","c,acc.7");
4787 emitcode("rrc","a");
4788 emitcode("mov","c,acc.7");
4789 emitcode("rrc","a");
4791 tlbl = newiTempLabel(NULL);
4792 /* rotate right accumulator */
4793 AccRol(8 - shCount);
4794 /* and kill the higher order bits */
4795 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4796 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4797 emitcode("orl","a,#0x%02x",
4798 (unsigned char)~SRMask[shCount]);
4799 emitcode("","%05d$:",tlbl->key+100);
4804 /*-----------------------------------------------------------------*/
4805 /* shiftR1Left2Result - shift right one byte from left to result */
4806 /*-----------------------------------------------------------------*/
4807 static void shiftR1Left2Result (operand *left, int offl,
4808 operand *result, int offr,
4809 int shCount, int sign)
4811 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4812 /* shift right accumulator */
4817 aopPut(AOP(result),"a",offr);
4820 /*-----------------------------------------------------------------*/
4821 /* shiftL1Left2Result - shift left one byte from left to result */
4822 /*-----------------------------------------------------------------*/
4823 static void shiftL1Left2Result (operand *left, int offl,
4824 operand *result, int offr, int shCount)
4827 l = aopGet(AOP(left),offl,FALSE,FALSE);
4829 /* shift left accumulator */
4831 aopPut(AOP(result),"a",offr);
4834 /*-----------------------------------------------------------------*/
4835 /* movLeft2Result - move byte from left to result */
4836 /*-----------------------------------------------------------------*/
4837 static void movLeft2Result (operand *left, int offl,
4838 operand *result, int offr, int sign)
4841 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
4842 l = aopGet(AOP(left),offl,FALSE,FALSE);
4844 if (*l == '@' && (IS_AOP_PREG(result))) {
4845 emitcode("mov","a,%s",l);
4846 aopPut(AOP(result),"a",offr);
4849 aopPut(AOP(result),l,offr);
4851 /* MSB sign in acc.7 ! */
4852 if(getDataSize(left) == offl+1){
4853 emitcode("mov","a,%s",l);
4854 aopPut(AOP(result),"a",offr);
4861 /*-----------------------------------------------------------------*/
4862 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
4863 /*-----------------------------------------------------------------*/
4864 static void AccAXRrl1 (char *x)
4866 emitcode("rrc","a");
4867 emitcode("xch","a,%s", x);
4868 emitcode("rrc","a");
4869 emitcode("xch","a,%s", x);
4872 /*-----------------------------------------------------------------*/
4873 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
4874 /*-----------------------------------------------------------------*/
4875 static void AccAXLrl1 (char *x)
4877 emitcode("xch","a,%s",x);
4878 emitcode("rlc","a");
4879 emitcode("xch","a,%s",x);
4880 emitcode("rlc","a");
4883 /*-----------------------------------------------------------------*/
4884 /* AccAXLsh1 - left shift a:x<-0 by 1 */
4885 /*-----------------------------------------------------------------*/
4886 static void AccAXLsh1 (char *x)
4888 emitcode("xch","a,%s",x);
4889 emitcode("add","a,acc");
4890 emitcode("xch","a,%s",x);
4891 emitcode("rlc","a");
4894 /*-----------------------------------------------------------------*/
4895 /* AccAXLsh - left shift a:x by known count (0..7) */
4896 /*-----------------------------------------------------------------*/
4897 static void AccAXLsh (char *x, int shCount)
4911 case 5 : // AAAAABBB:CCCCCDDD
4912 AccRol(shCount); // BBBAAAAA:CCCCCDDD
4913 emitcode("anl","a,#0x%02x",
4914 SLMask[shCount]); // BBB00000:CCCCCDDD
4915 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
4916 AccRol(shCount); // DDDCCCCC:BBB00000
4917 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
4918 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
4919 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
4920 emitcode("anl","a,#0x%02x",
4921 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
4922 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
4923 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
4925 case 6 : // AAAAAABB:CCCCCCDD
4926 emitcode("anl","a,#0x%02x",
4927 SRMask[shCount]); // 000000BB:CCCCCCDD
4928 emitcode("mov","c,acc.0"); // c = B
4929 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
4930 AccAXRrl1(x); // BCCCCCCD:D000000B
4931 AccAXRrl1(x); // BBCCCCCC:DD000000
4933 case 7 : // a:x <<= 7
4934 emitcode("anl","a,#0x%02x",
4935 SRMask[shCount]); // 0000000B:CCCCCCCD
4936 emitcode("mov","c,acc.0"); // c = B
4937 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
4938 AccAXRrl1(x); // BCCCCCCC:D0000000
4945 /*-----------------------------------------------------------------*/
4946 /* AccAXRsh - right shift a:x known count (0..7) */
4947 /*-----------------------------------------------------------------*/
4948 static void AccAXRsh (char *x, int shCount)
4955 AccAXRrl1(x); // 0->a:x
4959 AccAXRrl1(x); // 0->a:x
4961 AccAXRrl1(x); // 0->a:x
4965 case 5 : // AAAAABBB:CCCCCDDD = a:x
4966 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
4967 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
4968 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
4969 emitcode("anl","a,#0x%02x",
4970 SRMask[shCount]); // 000CCCCC:BBBAAAAA
4971 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
4972 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
4973 emitcode("anl","a,#0x%02x",
4974 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
4975 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
4976 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
4977 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
4979 case 6 : // AABBBBBB:CCDDDDDD
4980 emitcode("mov","c,acc.7");
4981 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
4982 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
4983 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
4984 emitcode("anl","a,#0x%02x",
4985 SRMask[shCount]); // 000000AA:BBBBBBCC
4987 case 7 : // ABBBBBBB:CDDDDDDD
4988 emitcode("mov","c,acc.7"); // c = A
4989 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
4990 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
4991 emitcode("anl","a,#0x%02x",
4992 SRMask[shCount]); // 0000000A:BBBBBBBC
4999 /*-----------------------------------------------------------------*/
5000 /* AccAXRshS - right shift signed a:x known count (0..7) */
5001 /*-----------------------------------------------------------------*/
5002 static void AccAXRshS (char *x, int shCount)
5009 emitcode("mov","c,acc.7");
5010 AccAXRrl1(x); // s->a:x
5013 emitcode("mov","c,acc.7");
5014 AccAXRrl1(x); // s->a:x
5015 emitcode("mov","c,acc.7");
5016 AccAXRrl1(x); // s->a:x
5020 case 5 : // AAAAABBB:CCCCCDDD = a:x
5021 tlbl = newiTempLabel(NULL);
5022 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5023 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5024 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5025 emitcode("anl","a,#0x%02x",
5026 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5027 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5028 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5029 emitcode("anl","a,#0x%02x",
5030 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5031 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5032 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5033 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5034 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5035 emitcode("orl","a,#0x%02x",
5036 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5037 emitcode("","%05d$:",tlbl->key+100);
5038 break; // SSSSAAAA:BBBCCCCC
5039 case 6 : // AABBBBBB:CCDDDDDD
5040 tlbl = newiTempLabel(NULL);
5041 emitcode("mov","c,acc.7");
5042 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5043 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5044 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5045 emitcode("anl","a,#0x%02x",
5046 SRMask[shCount]); // 000000AA:BBBBBBCC
5047 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5048 emitcode("orl","a,#0x%02x",
5049 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5050 emitcode("","%05d$:",tlbl->key+100);
5052 case 7 : // ABBBBBBB:CDDDDDDD
5053 tlbl = newiTempLabel(NULL);
5054 emitcode("mov","c,acc.7"); // c = A
5055 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5056 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5057 emitcode("anl","a,#0x%02x",
5058 SRMask[shCount]); // 0000000A:BBBBBBBC
5059 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5060 emitcode("orl","a,#0x%02x",
5061 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5062 emitcode("","%05d$:",tlbl->key+100);
5069 /*-----------------------------------------------------------------*/
5070 /* shiftL2Left2Result - shift left two bytes from left to result */
5071 /*-----------------------------------------------------------------*/
5072 static void shiftL2Left2Result (operand *left, int offl,
5073 operand *result, int offr, int shCount)
5075 if(sameRegs(AOP(result), AOP(left)) &&
5076 ((offl + MSB16) == offr)){
5077 /* don't crash result[offr] */
5078 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5079 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5081 movLeft2Result(left,offl, result, offr, 0);
5082 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5084 /* ax << shCount (x = lsb(result))*/
5085 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5086 aopPut(AOP(result),"a",offr+MSB16);
5090 /*-----------------------------------------------------------------*/
5091 /* shiftR2Left2Result - shift right two bytes from left to result */
5092 /*-----------------------------------------------------------------*/
5093 static void shiftR2Left2Result (operand *left, int offl,
5094 operand *result, int offr,
5095 int shCount, int sign)
5097 if(sameRegs(AOP(result), AOP(left)) &&
5098 ((offl + MSB16) == offr)){
5099 /* don't crash result[offr] */
5100 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5101 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5103 movLeft2Result(left,offl, result, offr, 0);
5104 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5106 /* a:x >> shCount (x = lsb(result))*/
5108 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5110 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5111 if(getDataSize(result) > 1)
5112 aopPut(AOP(result),"a",offr+MSB16);
5115 /*-----------------------------------------------------------------*/
5116 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5117 /*-----------------------------------------------------------------*/
5118 static void shiftLLeftOrResult (operand *left, int offl,
5119 operand *result, int offr, int shCount)
5121 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5122 /* shift left accumulator */
5124 /* or with result */
5125 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5126 /* back to result */
5127 aopPut(AOP(result),"a",offr);
5130 /*-----------------------------------------------------------------*/
5131 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5132 /*-----------------------------------------------------------------*/
5133 static void shiftRLeftOrResult (operand *left, int offl,
5134 operand *result, int offr, int shCount)
5136 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5137 /* shift right accumulator */
5139 /* or with result */
5140 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5141 /* back to result */
5142 aopPut(AOP(result),"a",offr);
5145 /*-----------------------------------------------------------------*/
5146 /* genlshOne - left shift a one byte quantity by known count */
5147 /*-----------------------------------------------------------------*/
5148 static void genlshOne (operand *result, operand *left, int shCount)
5150 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5153 /*-----------------------------------------------------------------*/
5154 /* genlshTwo - left shift two bytes by known amount != 0 */
5155 /*-----------------------------------------------------------------*/
5156 static void genlshTwo (operand *result,operand *left, int shCount)
5160 size = getDataSize(result);
5162 /* if shCount >= 8 */
5168 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5170 movLeft2Result(left, LSB, result, MSB16, 0);
5172 aopPut(AOP(result),zero,LSB);
5175 /* 1 <= shCount <= 7 */
5178 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5180 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5184 /*-----------------------------------------------------------------*/
5185 /* shiftLLong - shift left one long from left to result */
5186 /* offl = LSB or MSB16 */
5187 /*-----------------------------------------------------------------*/
5188 static void shiftLLong (operand *left, operand *result, int offr )
5191 int size = AOP_SIZE(result);
5193 if(size >= LSB+offr){
5194 l = aopGet(AOP(left),LSB,FALSE,FALSE);
5196 emitcode("add","a,acc");
5197 if (sameRegs(AOP(left),AOP(result)) &&
5198 size >= MSB16+offr && offr != LSB )
5199 emitcode("xch","a,%s",
5200 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
5202 aopPut(AOP(result),"a",LSB+offr);
5205 if(size >= MSB16+offr){
5206 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5207 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
5210 emitcode("rlc","a");
5211 if (sameRegs(AOP(left),AOP(result)) &&
5212 size >= MSB24+offr && offr != LSB)
5213 emitcode("xch","a,%s",
5214 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
5216 aopPut(AOP(result),"a",MSB16+offr);
5219 if(size >= MSB24+offr){
5220 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5221 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
5224 emitcode("rlc","a");
5225 if (sameRegs(AOP(left),AOP(result)) &&
5226 size >= MSB32+offr && offr != LSB )
5227 emitcode("xch","a,%s",
5228 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
5230 aopPut(AOP(result),"a",MSB24+offr);
5233 if(size > MSB32+offr){
5234 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5235 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
5238 emitcode("rlc","a");
5239 aopPut(AOP(result),"a",MSB32+offr);
5242 aopPut(AOP(result),zero,LSB);
5245 /*-----------------------------------------------------------------*/
5246 /* genlshFour - shift four byte by a known amount != 0 */
5247 /*-----------------------------------------------------------------*/
5248 static void genlshFour (operand *result, operand *left, int shCount)
5252 size = AOP_SIZE(result);
5254 /* if shifting more that 3 bytes */
5255 if (shCount >= 24 ) {
5258 /* lowest order of left goes to the highest
5259 order of the destination */
5260 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5262 movLeft2Result(left, LSB, result, MSB32, 0);
5263 aopPut(AOP(result),zero,LSB);
5264 aopPut(AOP(result),zero,MSB16);
5265 aopPut(AOP(result),zero,MSB32);
5269 /* more than two bytes */
5270 else if ( shCount >= 16 ) {
5271 /* lower order two bytes goes to higher order two bytes */
5273 /* if some more remaining */
5275 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5277 movLeft2Result(left, MSB16, result, MSB32, 0);
5278 movLeft2Result(left, LSB, result, MSB24, 0);
5280 aopPut(AOP(result),zero,MSB16);
5281 aopPut(AOP(result),zero,LSB);
5285 /* if more than 1 byte */
5286 else if ( shCount >= 8 ) {
5287 /* lower order three bytes goes to higher order three bytes */
5291 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5293 movLeft2Result(left, LSB, result, MSB16, 0);
5295 else{ /* size = 4 */
5297 movLeft2Result(left, MSB24, result, MSB32, 0);
5298 movLeft2Result(left, MSB16, result, MSB24, 0);
5299 movLeft2Result(left, LSB, result, MSB16, 0);
5300 aopPut(AOP(result),zero,LSB);
5302 else if(shCount == 1)
5303 shiftLLong(left, result, MSB16);
5305 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5306 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5307 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5308 aopPut(AOP(result),zero,LSB);
5313 /* 1 <= shCount <= 7 */
5314 else if(shCount <= 2){
5315 shiftLLong(left, result, LSB);
5317 shiftLLong(result, result, LSB);
5319 /* 3 <= shCount <= 7, optimize */
5321 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5322 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5323 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5327 /*-----------------------------------------------------------------*/
5328 /* genLeftShiftLiteral - left shifting by known count */
5329 /*-----------------------------------------------------------------*/
5330 static void genLeftShiftLiteral (operand *left,
5335 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5338 freeAsmop(right,NULL,ic,TRUE);
5340 aopOp(left,ic,FALSE);
5341 aopOp(result,ic,FALSE);
5343 size = getSize(operandType(result));
5346 emitcode("; shift left ","result %d, left %d",size,
5350 /* I suppose that the left size >= result size */
5353 movLeft2Result(left, size, result, size, 0);
5357 else if(shCount >= (size * 8))
5359 aopPut(AOP(result),zero,size);
5363 genlshOne (result,left,shCount);
5368 genlshTwo (result,left,shCount);
5372 genlshFour (result,left,shCount);
5376 freeAsmop(left,NULL,ic,TRUE);
5377 freeAsmop(result,NULL,ic,TRUE);
5380 /*-----------------------------------------------------------------*/
5381 /* genLeftShift - generates code for left shifting */
5382 /*-----------------------------------------------------------------*/
5383 static void genLeftShift (iCode *ic)
5385 operand *left,*right, *result;
5388 symbol *tlbl , *tlbl1;
5390 right = IC_RIGHT(ic);
5392 result = IC_RESULT(ic);
5394 aopOp(right,ic,FALSE);
5396 /* if the shift count is known then do it
5397 as efficiently as possible */
5398 if (AOP_TYPE(right) == AOP_LIT) {
5399 genLeftShiftLiteral (left,right,result,ic);
5403 /* shift count is unknown then we have to form
5404 a loop get the loop count in B : Note: we take
5405 only the lower order byte since shifting
5406 more that 32 bits make no sense anyway, ( the
5407 largest size of an object can be only 32 bits ) */
5409 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5410 emitcode("inc","b");
5411 freeAsmop (right,NULL,ic,TRUE);
5412 aopOp(left,ic,FALSE);
5413 aopOp(result,ic,FALSE);
5415 /* now move the left to the result if they are not the
5417 if (!sameRegs(AOP(left),AOP(result)) &&
5418 AOP_SIZE(result) > 1) {
5420 size = AOP_SIZE(result);
5423 l = aopGet(AOP(left),offset,FALSE,TRUE);
5424 if (*l == '@' && (IS_AOP_PREG(result))) {
5426 emitcode("mov","a,%s",l);
5427 aopPut(AOP(result),"a",offset);
5429 aopPut(AOP(result),l,offset);
5434 tlbl = newiTempLabel(NULL);
5435 size = AOP_SIZE(result);
5437 tlbl1 = newiTempLabel(NULL);
5439 /* if it is only one byte then */
5441 symbol *tlbl1 = newiTempLabel(NULL);
5443 l = aopGet(AOP(left),0,FALSE,FALSE);
5445 emitcode("sjmp","%05d$",tlbl1->key+100);
5446 emitcode("","%05d$:",tlbl->key+100);
5447 emitcode("add","a,acc");
5448 emitcode("","%05d$:",tlbl1->key+100);
5449 emitcode("djnz","b,%05d$",tlbl->key+100);
5450 aopPut(AOP(result),"a",0);
5454 reAdjustPreg(AOP(result));
5456 emitcode("sjmp","%05d$",tlbl1->key+100);
5457 emitcode("","%05d$:",tlbl->key+100);
5458 l = aopGet(AOP(result),offset,FALSE,FALSE);
5460 emitcode("add","a,acc");
5461 aopPut(AOP(result),"a",offset++);
5463 l = aopGet(AOP(result),offset,FALSE,FALSE);
5465 emitcode("rlc","a");
5466 aopPut(AOP(result),"a",offset++);
5468 reAdjustPreg(AOP(result));
5470 emitcode("","%05d$:",tlbl1->key+100);
5471 emitcode("djnz","b,%05d$",tlbl->key+100);
5473 freeAsmop(left,NULL,ic,TRUE);
5474 freeAsmop(result,NULL,ic,TRUE);
5477 /*-----------------------------------------------------------------*/
5478 /* genrshOne - right shift a one byte quantity by known count */
5479 /*-----------------------------------------------------------------*/
5480 static void genrshOne (operand *result, operand *left,
5481 int shCount, int sign)
5483 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
5486 /*-----------------------------------------------------------------*/
5487 /* genrshTwo - right shift two bytes by known amount != 0 */
5488 /*-----------------------------------------------------------------*/
5489 static void genrshTwo (operand *result,operand *left,
5490 int shCount, int sign)
5492 /* if shCount >= 8 */
5496 shiftR1Left2Result(left, MSB16, result, LSB,
5499 movLeft2Result(left, MSB16, result, LSB, sign);
5500 addSign(result, MSB16, sign);
5503 /* 1 <= shCount <= 7 */
5505 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
5508 /*-----------------------------------------------------------------*/
5509 /* shiftRLong - shift right one long from left to result */
5510 /* offl = LSB or MSB16 */
5511 /*-----------------------------------------------------------------*/
5512 static void shiftRLong (operand *left, int offl,
5513 operand *result, int sign)
5516 emitcode("clr","c");
5517 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
5519 emitcode("mov","c,acc.7");
5520 emitcode("rrc","a");
5521 aopPut(AOP(result),"a",MSB32-offl);
5523 /* add sign of "a" */
5524 addSign(result, MSB32, sign);
5526 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
5527 emitcode("rrc","a");
5528 aopPut(AOP(result),"a",MSB24-offl);
5530 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
5531 emitcode("rrc","a");
5532 aopPut(AOP(result),"a",MSB16-offl);
5535 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
5536 emitcode("rrc","a");
5537 aopPut(AOP(result),"a",LSB);
5541 /*-----------------------------------------------------------------*/
5542 /* genrshFour - shift four byte by a known amount != 0 */
5543 /*-----------------------------------------------------------------*/
5544 static void genrshFour (operand *result, operand *left,
5545 int shCount, int sign)
5547 /* if shifting more that 3 bytes */
5548 if(shCount >= 24 ) {
5551 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
5553 movLeft2Result(left, MSB32, result, LSB, sign);
5554 addSign(result, MSB16, sign);
5556 else if(shCount >= 16){
5559 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
5561 movLeft2Result(left, MSB24, result, LSB, 0);
5562 movLeft2Result(left, MSB32, result, MSB16, sign);
5564 addSign(result, MSB24, sign);
5566 else if(shCount >= 8){
5569 shiftRLong(left, MSB16, result, sign);
5570 else if(shCount == 0){
5571 movLeft2Result(left, MSB16, result, LSB, 0);
5572 movLeft2Result(left, MSB24, result, MSB16, 0);
5573 movLeft2Result(left, MSB32, result, MSB24, sign);
5574 addSign(result, MSB32, sign);
5577 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
5578 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
5579 /* the last shift is signed */
5580 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
5581 addSign(result, MSB32, sign);
5584 else{ /* 1 <= shCount <= 7 */
5586 shiftRLong(left, LSB, result, sign);
5588 shiftRLong(result, LSB, result, sign);
5591 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
5592 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
5593 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
5598 /*-----------------------------------------------------------------*/
5599 /* genRightShiftLiteral - right shifting by known count */
5600 /*-----------------------------------------------------------------*/
5601 static void genRightShiftLiteral (operand *left,
5607 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5610 freeAsmop(right,NULL,ic,TRUE);
5612 aopOp(left,ic,FALSE);
5613 aopOp(result,ic,FALSE);
5616 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
5620 size = getDataSize(left);
5621 /* test the LEFT size !!! */
5623 /* I suppose that the left size >= result size */
5625 size = getDataSize(result);
5627 movLeft2Result(left, size, result, size, 0);
5630 else if(shCount >= (size * 8)){
5632 /* get sign in acc.7 */
5633 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
5634 addSign(result, LSB, sign);
5638 genrshOne (result,left,shCount,sign);
5642 genrshTwo (result,left,shCount,sign);
5646 genrshFour (result,left,shCount,sign);
5652 freeAsmop(left,NULL,ic,TRUE);
5653 freeAsmop(result,NULL,ic,TRUE);
5657 /*-----------------------------------------------------------------*/
5658 /* genSignedRightShift - right shift of signed number */
5659 /*-----------------------------------------------------------------*/
5660 static void genSignedRightShift (iCode *ic)
5662 operand *right, *left, *result;
5665 symbol *tlbl, *tlbl1 ;
5667 /* we do it the hard way put the shift count in b
5668 and loop thru preserving the sign */
5670 right = IC_RIGHT(ic);
5672 result = IC_RESULT(ic);
5674 aopOp(right,ic,FALSE);
5677 if ( AOP_TYPE(right) == AOP_LIT) {
5678 genRightShiftLiteral (left,right,result,ic,1);
5681 /* shift count is unknown then we have to form
5682 a loop get the loop count in B : Note: we take
5683 only the lower order byte since shifting
5684 more that 32 bits make no sense anyway, ( the
5685 largest size of an object can be only 32 bits ) */
5687 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5688 emitcode("inc","b");
5689 freeAsmop (right,NULL,ic,TRUE);
5690 aopOp(left,ic,FALSE);
5691 aopOp(result,ic,FALSE);
5693 /* now move the left to the result if they are not the
5695 if (!sameRegs(AOP(left),AOP(result)) &&
5696 AOP_SIZE(result) > 1) {
5698 size = AOP_SIZE(result);
5701 l = aopGet(AOP(left),offset,FALSE,TRUE);
5702 if (*l == '@' && IS_AOP_PREG(result)) {
5704 emitcode("mov","a,%s",l);
5705 aopPut(AOP(result),"a",offset);
5707 aopPut(AOP(result),l,offset);
5712 /* mov the highest order bit to OVR */
5713 tlbl = newiTempLabel(NULL);
5714 tlbl1= newiTempLabel(NULL);
5716 size = AOP_SIZE(result);
5718 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
5719 emitcode("rlc","a");
5720 emitcode("mov","ov,c");
5721 /* if it is only one byte then */
5723 l = aopGet(AOP(left),0,FALSE,FALSE);
5725 emitcode("sjmp","%05d$",tlbl1->key+100);
5726 emitcode("","%05d$:",tlbl->key+100);
5727 emitcode("mov","c,ov");
5728 emitcode("rrc","a");
5729 emitcode("","%05d$:",tlbl1->key+100);
5730 emitcode("djnz","b,%05d$",tlbl->key+100);
5731 aopPut(AOP(result),"a",0);
5735 reAdjustPreg(AOP(result));
5736 emitcode("sjmp","%05d$",tlbl1->key+100);
5737 emitcode("","%05d$:",tlbl->key+100);
5738 emitcode("mov","c,ov");
5740 l = aopGet(AOP(result),offset,FALSE,FALSE);
5742 emitcode("rrc","a");
5743 aopPut(AOP(result),"a",offset--);
5745 reAdjustPreg(AOP(result));
5746 emitcode("","%05d$:",tlbl1->key+100);
5747 emitcode("djnz","b,%05d$",tlbl->key+100);
5750 freeAsmop(left,NULL,ic,TRUE);
5751 freeAsmop(result,NULL,ic,TRUE);
5754 /*-----------------------------------------------------------------*/
5755 /* genRightShift - generate code for right shifting */
5756 /*-----------------------------------------------------------------*/
5757 static void genRightShift (iCode *ic)
5759 operand *right, *left, *result;
5763 symbol *tlbl, *tlbl1 ;
5765 /* if signed then we do it the hard way preserve the
5766 sign bit moving it inwards */
5767 retype = getSpec(operandType(IC_RESULT(ic)));
5769 if (!SPEC_USIGN(retype)) {
5770 genSignedRightShift (ic);
5774 /* signed & unsigned types are treated the same : i.e. the
5775 signed is NOT propagated inwards : quoting from the
5776 ANSI - standard : "for E1 >> E2, is equivalent to division
5777 by 2**E2 if unsigned or if it has a non-negative value,
5778 otherwise the result is implementation defined ", MY definition
5779 is that the sign does not get propagated */
5781 right = IC_RIGHT(ic);
5783 result = IC_RESULT(ic);
5785 aopOp(right,ic,FALSE);
5787 /* if the shift count is known then do it
5788 as efficiently as possible */
5789 if (AOP_TYPE(right) == AOP_LIT) {
5790 genRightShiftLiteral (left,right,result,ic, 0);
5794 /* shift count is unknown then we have to form
5795 a loop get the loop count in B : Note: we take
5796 only the lower order byte since shifting
5797 more that 32 bits make no sense anyway, ( the
5798 largest size of an object can be only 32 bits ) */
5800 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5801 emitcode("inc","b");
5802 freeAsmop (right,NULL,ic,TRUE);
5803 aopOp(left,ic,FALSE);
5804 aopOp(result,ic,FALSE);
5806 /* now move the left to the result if they are not the
5808 if (!sameRegs(AOP(left),AOP(result)) &&
5809 AOP_SIZE(result) > 1) {
5811 size = AOP_SIZE(result);
5814 l = aopGet(AOP(left),offset,FALSE,TRUE);
5815 if (*l == '@' && IS_AOP_PREG(result)) {
5817 emitcode("mov","a,%s",l);
5818 aopPut(AOP(result),"a",offset);
5820 aopPut(AOP(result),l,offset);
5825 tlbl = newiTempLabel(NULL);
5826 tlbl1= newiTempLabel(NULL);
5827 size = AOP_SIZE(result);
5830 /* if it is only one byte then */
5832 l = aopGet(AOP(left),0,FALSE,FALSE);
5834 emitcode("sjmp","%05d$",tlbl1->key+100);
5835 emitcode("","%05d$:",tlbl->key+100);
5837 emitcode("rrc","a");
5838 emitcode("","%05d$:",tlbl1->key+100);
5839 emitcode("djnz","b,%05d$",tlbl->key+100);
5840 aopPut(AOP(result),"a",0);
5844 reAdjustPreg(AOP(result));
5845 emitcode("sjmp","%05d$",tlbl1->key+100);
5846 emitcode("","%05d$:",tlbl->key+100);
5849 l = aopGet(AOP(result),offset,FALSE,FALSE);
5851 emitcode("rrc","a");
5852 aopPut(AOP(result),"a",offset--);
5854 reAdjustPreg(AOP(result));
5856 emitcode("","%05d$:",tlbl1->key+100);
5857 emitcode("djnz","b,%05d$",tlbl->key+100);
5860 freeAsmop(left,NULL,ic,TRUE);
5861 freeAsmop(result,NULL,ic,TRUE);
5864 /*-----------------------------------------------------------------*/
5865 /* genUnpackBits - generates code for unpacking bits */
5866 /*-----------------------------------------------------------------*/
5867 static void genUnpackBits (operand *result, char *rname, int ptype)
5874 etype = getSpec(operandType(result));
5876 /* read the first byte */
5881 emitcode("mov","a,@%s",rname);
5885 emitcode("movx","a,@%s",rname);
5889 emitcode("movx","a,@dptr");
5893 emitcode("clr","a");
5894 emitcode("movc","a","@a+dptr");
5898 emitcode("lcall","__gptrget");
5902 /* if we have bitdisplacement then it fits */
5903 /* into this byte completely or if length is */
5904 /* less than a byte */
5905 if ((shCnt = SPEC_BSTR(etype)) ||
5906 (SPEC_BLEN(etype) <= 8)) {
5908 /* shift right acc */
5911 emitcode("anl","a,#0x%02x",
5912 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
5913 aopPut(AOP(result),"a",offset);
5917 /* bit field did not fit in a byte */
5918 rlen = SPEC_BLEN(etype) - 8;
5919 aopPut(AOP(result),"a",offset++);
5926 emitcode("inc","%s",rname);
5927 emitcode("mov","a,@%s",rname);
5931 emitcode("inc","%s",rname);
5932 emitcode("movx","a,@%s",rname);
5936 emitcode("inc","dptr");
5937 emitcode("movx","a,@dptr");
5941 emitcode("clr","a");
5942 emitcode("inc","dptr");
5943 emitcode("movc","a","@a+dptr");
5947 emitcode("inc","dptr");
5948 emitcode("lcall","__gptrget");
5953 /* if we are done */
5957 aopPut(AOP(result),"a",offset++);
5962 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
5963 aopPut(AOP(result),"a",offset);
5970 /*-----------------------------------------------------------------*/
5971 /* genDataPointerGet - generates code when ptr offset is known */
5972 /*-----------------------------------------------------------------*/
5973 static void genDataPointerGet (operand *left,
5979 int size , offset = 0;
5980 aopOp(result,ic,TRUE);
5982 /* get the string representation of the name */
5983 l = aopGet(AOP(left),0,FALSE,TRUE);
5984 size = AOP_SIZE(result);
5987 sprintf(buffer,"(%s + %d)",l+1,offset);
5989 sprintf(buffer,"%s",l+1);
5990 aopPut(AOP(result),buffer,offset++);
5993 freeAsmop(left,NULL,ic,TRUE);
5994 freeAsmop(result,NULL,ic,TRUE);
5997 /*-----------------------------------------------------------------*/
5998 /* genNearPointerGet - emitcode for near pointer fetch */
5999 /*-----------------------------------------------------------------*/
6000 static void genNearPointerGet (operand *left,
6007 link *rtype, *retype;
6008 link *ltype = operandType(left);
6011 rtype = operandType(result);
6012 retype= getSpec(rtype);
6014 aopOp(left,ic,FALSE);
6016 /* if left is rematerialisable and
6017 result is not bit variable type and
6018 the left is pointer to data space i.e
6019 lower 128 bytes of space */
6020 if (AOP_TYPE(left) == AOP_IMMD &&
6021 !IS_BITVAR(retype) &&
6022 DCL_TYPE(ltype) == POINTER) {
6023 genDataPointerGet (left,result,ic);
6027 /* if the value is already in a pointer register
6028 then don't need anything more */
6029 if (!AOP_INPREG(AOP(left))) {
6030 /* otherwise get a free pointer register */
6032 preg = getFreePtr(ic,&aop,FALSE);
6033 emitcode("mov","%s,%s",
6035 aopGet(AOP(left),0,FALSE,TRUE));
6036 rname = preg->name ;
6038 rname = aopGet(AOP(left),0,FALSE,FALSE);
6040 freeAsmop(left,NULL,ic,TRUE);
6041 aopOp (result,ic,FALSE);
6043 /* if bitfield then unpack the bits */
6044 if (IS_BITVAR(retype))
6045 genUnpackBits (result,rname,POINTER);
6047 /* we have can just get the values */
6048 int size = AOP_SIZE(result);
6052 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6054 emitcode("mov","a,@%s",rname);
6055 aopPut(AOP(result),"a",offset);
6057 sprintf(buffer,"@%s",rname);
6058 aopPut(AOP(result),buffer,offset);
6062 emitcode("inc","%s",rname);
6066 /* now some housekeeping stuff */
6068 /* we had to allocate for this iCode */
6069 freeAsmop(NULL,aop,ic,TRUE);
6071 /* we did not allocate which means left
6072 already in a pointer register, then
6073 if size > 0 && this could be used again
6074 we have to point it back to where it
6076 if (AOP_SIZE(result) > 1 &&
6077 !OP_SYMBOL(left)->remat &&
6078 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6080 int size = AOP_SIZE(result) - 1;
6082 emitcode("dec","%s",rname);
6087 freeAsmop(result,NULL,ic,TRUE);
6091 /*-----------------------------------------------------------------*/
6092 /* genPagedPointerGet - emitcode for paged pointer fetch */
6093 /*-----------------------------------------------------------------*/
6094 static void genPagedPointerGet (operand *left,
6101 link *rtype, *retype;
6103 rtype = operandType(result);
6104 retype= getSpec(rtype);
6106 aopOp(left,ic,FALSE);
6108 /* if the value is already in a pointer register
6109 then don't need anything more */
6110 if (!AOP_INPREG(AOP(left))) {
6111 /* otherwise get a free pointer register */
6113 preg = getFreePtr(ic,&aop,FALSE);
6114 emitcode("mov","%s,%s",
6116 aopGet(AOP(left),0,FALSE,TRUE));
6117 rname = preg->name ;
6119 rname = aopGet(AOP(left),0,FALSE,FALSE);
6121 freeAsmop(left,NULL,ic,TRUE);
6122 aopOp (result,ic,FALSE);
6124 /* if bitfield then unpack the bits */
6125 if (IS_BITVAR(retype))
6126 genUnpackBits (result,rname,PPOINTER);
6128 /* we have can just get the values */
6129 int size = AOP_SIZE(result);
6134 emitcode("movx","a,@%s",rname);
6135 aopPut(AOP(result),"a",offset);
6140 emitcode("inc","%s",rname);
6144 /* now some housekeeping stuff */
6146 /* we had to allocate for this iCode */
6147 freeAsmop(NULL,aop,ic,TRUE);
6149 /* we did not allocate which means left
6150 already in a pointer register, then
6151 if size > 0 && this could be used again
6152 we have to point it back to where it
6154 if (AOP_SIZE(result) > 1 &&
6155 !OP_SYMBOL(left)->remat &&
6156 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6158 int size = AOP_SIZE(result) - 1;
6160 emitcode("dec","%s",rname);
6165 freeAsmop(result,NULL,ic,TRUE);
6170 /*-----------------------------------------------------------------*/
6171 /* genFarPointerGet - gget value from far space */
6172 /*-----------------------------------------------------------------*/
6173 static void genFarPointerGet (operand *left,
6174 operand *result, iCode *ic)
6177 link *retype = getSpec(operandType(result));
6179 aopOp(left,ic,FALSE);
6181 /* if the operand is already in dptr
6182 then we do nothing else we move the value to dptr */
6183 if (AOP_TYPE(left) != AOP_STR) {
6184 /* if this is remateriazable */
6185 if (AOP_TYPE(left) == AOP_IMMD)
6186 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6187 else { /* we need to get it byte by byte */
6188 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6189 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6190 if (options.model == MODEL_FLAT24)
6192 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6196 /* so dptr know contains the address */
6197 freeAsmop(left,NULL,ic,TRUE);
6198 aopOp(result,ic,FALSE);
6200 /* if bit then unpack */
6201 if (IS_BITVAR(retype))
6202 genUnpackBits(result,"dptr",FPOINTER);
6204 size = AOP_SIZE(result);
6208 emitcode("movx","a,@dptr");
6209 aopPut(AOP(result),"a",offset++);
6211 emitcode("inc","dptr");
6215 freeAsmop(result,NULL,ic,TRUE);
6218 /*-----------------------------------------------------------------*/
6219 /* emitcodePointerGet - gget value from code space */
6220 /*-----------------------------------------------------------------*/
6221 static void emitcodePointerGet (operand *left,
6222 operand *result, iCode *ic)
6225 link *retype = getSpec(operandType(result));
6227 aopOp(left,ic,FALSE);
6229 /* if the operand is already in dptr
6230 then we do nothing else we move the value to dptr */
6231 if (AOP_TYPE(left) != AOP_STR) {
6232 /* if this is remateriazable */
6233 if (AOP_TYPE(left) == AOP_IMMD)
6234 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6235 else { /* we need to get it byte by byte */
6236 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6237 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6238 if (options.model == MODEL_FLAT24)
6240 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6244 /* so dptr know contains the address */
6245 freeAsmop(left,NULL,ic,TRUE);
6246 aopOp(result,ic,FALSE);
6248 /* if bit then unpack */
6249 if (IS_BITVAR(retype))
6250 genUnpackBits(result,"dptr",CPOINTER);
6252 size = AOP_SIZE(result);
6256 emitcode("clr","a");
6257 emitcode("movc","a,@a+dptr");
6258 aopPut(AOP(result),"a",offset++);
6260 emitcode("inc","dptr");
6264 freeAsmop(result,NULL,ic,TRUE);
6267 /*-----------------------------------------------------------------*/
6268 /* genGenPointerGet - gget value from generic pointer space */
6269 /*-----------------------------------------------------------------*/
6270 static void genGenPointerGet (operand *left,
6271 operand *result, iCode *ic)
6274 link *retype = getSpec(operandType(result));
6276 aopOp(left,ic,FALSE);
6278 /* if the operand is already in dptr
6279 then we do nothing else we move the value to dptr */
6280 if (AOP_TYPE(left) != AOP_STR) {
6281 /* if this is remateriazable */
6282 if (AOP_TYPE(left) == AOP_IMMD) {
6283 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6284 emitcode("mov","b,#%d",pointerCode(retype));
6286 else { /* we need to get it byte by byte */
6287 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6288 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6289 if (options.model == MODEL_FLAT24)
6291 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6292 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
6296 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
6300 /* so dptr know contains the address */
6301 freeAsmop(left,NULL,ic,TRUE);
6302 aopOp(result,ic,FALSE);
6304 /* if bit then unpack */
6305 if (IS_BITVAR(retype))
6306 genUnpackBits(result,"dptr",GPOINTER);
6308 size = AOP_SIZE(result);
6312 emitcode("lcall","__gptrget");
6313 aopPut(AOP(result),"a",offset++);
6315 emitcode("inc","dptr");
6319 freeAsmop(result,NULL,ic,TRUE);
6322 /*-----------------------------------------------------------------*/
6323 /* genPointerGet - generate code for pointer get */
6324 /*-----------------------------------------------------------------*/
6325 static void genPointerGet (iCode *ic)
6327 operand *left, *result ;
6332 result = IC_RESULT(ic) ;
6334 /* depending on the type of pointer we need to
6335 move it to the correct pointer register */
6336 type = operandType(left);
6337 etype = getSpec(type);
6338 /* if left is of type of pointer then it is simple */
6339 if (IS_PTR(type) && !IS_FUNC(type->next))
6340 p_type = DCL_TYPE(type);
6342 /* we have to go by the storage class */
6343 p_type = PTR_TYPE(SPEC_OCLS(etype));
6345 /* if (SPEC_OCLS(etype)->codesp ) { */
6346 /* p_type = CPOINTER ; */
6349 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6350 /* p_type = FPOINTER ; */
6352 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6353 /* p_type = PPOINTER; */
6355 /* if (SPEC_OCLS(etype) == idata ) */
6356 /* p_type = IPOINTER; */
6358 /* p_type = POINTER ; */
6361 /* now that we have the pointer type we assign
6362 the pointer values */
6367 genNearPointerGet (left,result,ic);
6371 genPagedPointerGet(left,result,ic);
6375 genFarPointerGet (left,result,ic);
6379 emitcodePointerGet (left,result,ic);
6383 genGenPointerGet (left,result,ic);
6389 /*-----------------------------------------------------------------*/
6390 /* genPackBits - generates code for packed bit storage */
6391 /*-----------------------------------------------------------------*/
6392 static void genPackBits (link *etype ,
6394 char *rname, int p_type)
6402 blen = SPEC_BLEN(etype);
6403 bstr = SPEC_BSTR(etype);
6405 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6408 /* if the bit lenth is less than or */
6409 /* it exactly fits a byte then */
6410 if (SPEC_BLEN(etype) <= 8 ) {
6411 shCount = SPEC_BSTR(etype) ;
6413 /* shift left acc */
6416 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6421 emitcode ("mov","b,a");
6422 emitcode("mov","a,@%s",rname);
6426 emitcode ("mov","b,a");
6427 emitcode("movx","a,@dptr");
6431 emitcode ("push","b");
6432 emitcode ("push","acc");
6433 emitcode ("lcall","__gptrget");
6434 emitcode ("pop","b");
6438 emitcode ("anl","a,#0x%02x",(unsigned char)
6439 ((unsigned char)(0xFF << (blen+bstr)) |
6440 (unsigned char)(0xFF >> (8-bstr)) ) );
6441 emitcode ("orl","a,b");
6442 if (p_type == GPOINTER)
6443 emitcode("pop","b");
6449 emitcode("mov","@%s,a",rname);
6453 emitcode("movx","@dptr,a");
6457 emitcode("lcall","__gptrput");
6462 if ( SPEC_BLEN(etype) <= 8 )
6465 emitcode("inc","%s",rname);
6466 rLen = SPEC_BLEN(etype) ;
6468 /* now generate for lengths greater than one byte */
6471 l = aopGet(AOP(right),offset++,FALSE,TRUE);
6481 emitcode("mov","@%s,a",rname);
6483 emitcode("mov","@%s,%s",rname,l);
6488 emitcode("movx","@dptr,a");
6493 emitcode("lcall","__gptrput");
6496 emitcode ("inc","%s",rname);
6501 /* last last was not complete */
6503 /* save the byte & read byte */
6506 emitcode ("mov","b,a");
6507 emitcode("mov","a,@%s",rname);
6511 emitcode ("mov","b,a");
6512 emitcode("movx","a,@dptr");
6516 emitcode ("push","b");
6517 emitcode ("push","acc");
6518 emitcode ("lcall","__gptrget");
6519 emitcode ("pop","b");
6523 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
6524 emitcode ("orl","a,b");
6527 if (p_type == GPOINTER)
6528 emitcode("pop","b");
6533 emitcode("mov","@%s,a",rname);
6537 emitcode("movx","@dptr,a");
6541 emitcode("lcall","__gptrput");
6545 /*-----------------------------------------------------------------*/
6546 /* genDataPointerSet - remat pointer to data space */
6547 /*-----------------------------------------------------------------*/
6548 static void genDataPointerSet(operand *right,
6552 int size, offset = 0 ;
6553 char *l, buffer[256];
6555 aopOp(right,ic,FALSE);
6557 l = aopGet(AOP(result),0,FALSE,TRUE);
6558 size = AOP_SIZE(right);
6561 sprintf(buffer,"(%s + %d)",l+1,offset);
6563 sprintf(buffer,"%s",l+1);
6564 emitcode("mov","%s,%s",buffer,
6565 aopGet(AOP(right),offset++,FALSE,FALSE));
6568 freeAsmop(right,NULL,ic,TRUE);
6569 freeAsmop(result,NULL,ic,TRUE);
6572 /*-----------------------------------------------------------------*/
6573 /* genNearPointerSet - emitcode for near pointer put */
6574 /*-----------------------------------------------------------------*/
6575 static void genNearPointerSet (operand *right,
6583 link *ptype = operandType(result);
6585 retype= getSpec(operandType(right));
6587 aopOp(result,ic,FALSE);
6589 /* if the result is rematerializable &
6590 in data space & not a bit variable */
6591 if (AOP_TYPE(result) == AOP_IMMD &&
6592 DCL_TYPE(ptype) == POINTER &&
6593 !IS_BITVAR(retype)) {
6594 genDataPointerSet (right,result,ic);
6598 /* if the value is already in a pointer register
6599 then don't need anything more */
6600 if (!AOP_INPREG(AOP(result))) {
6601 /* otherwise get a free pointer register */
6603 preg = getFreePtr(ic,&aop,FALSE);
6604 emitcode("mov","%s,%s",
6606 aopGet(AOP(result),0,FALSE,TRUE));
6607 rname = preg->name ;
6609 rname = aopGet(AOP(result),0,FALSE,FALSE);
6611 freeAsmop(result,NULL,ic,TRUE);
6612 aopOp (right,ic,FALSE);
6614 /* if bitfield then unpack the bits */
6615 if (IS_BITVAR(retype))
6616 genPackBits (retype,right,rname,POINTER);
6618 /* we have can just get the values */
6619 int size = AOP_SIZE(right);
6623 l = aopGet(AOP(right),offset,FALSE,TRUE);
6626 emitcode("mov","@%s,a",rname);
6628 emitcode("mov","@%s,%s",rname,l);
6630 emitcode("inc","%s",rname);
6635 /* now some housekeeping stuff */
6637 /* we had to allocate for this iCode */
6638 freeAsmop(NULL,aop,ic,TRUE);
6640 /* we did not allocate which means left
6641 already in a pointer register, then
6642 if size > 0 && this could be used again
6643 we have to point it back to where it
6645 if (AOP_SIZE(right) > 1 &&
6646 !OP_SYMBOL(result)->remat &&
6647 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6649 int size = AOP_SIZE(right) - 1;
6651 emitcode("dec","%s",rname);
6656 freeAsmop(right,NULL,ic,TRUE);
6661 /*-----------------------------------------------------------------*/
6662 /* genPagedPointerSet - emitcode for Paged pointer put */
6663 /*-----------------------------------------------------------------*/
6664 static void genPagedPointerSet (operand *right,
6673 retype= getSpec(operandType(right));
6675 aopOp(result,ic,FALSE);
6677 /* if the value is already in a pointer register
6678 then don't need anything more */
6679 if (!AOP_INPREG(AOP(result))) {
6680 /* otherwise get a free pointer register */
6682 preg = getFreePtr(ic,&aop,FALSE);
6683 emitcode("mov","%s,%s",
6685 aopGet(AOP(result),0,FALSE,TRUE));
6686 rname = preg->name ;
6688 rname = aopGet(AOP(result),0,FALSE,FALSE);
6690 freeAsmop(result,NULL,ic,TRUE);
6691 aopOp (right,ic,FALSE);
6693 /* if bitfield then unpack the bits */
6694 if (IS_BITVAR(retype))
6695 genPackBits (retype,right,rname,PPOINTER);
6697 /* we have can just get the values */
6698 int size = AOP_SIZE(right);
6702 l = aopGet(AOP(right),offset,FALSE,TRUE);
6705 emitcode("movx","@%s,a",rname);
6708 emitcode("inc","%s",rname);
6714 /* now some housekeeping stuff */
6716 /* we had to allocate for this iCode */
6717 freeAsmop(NULL,aop,ic,TRUE);
6719 /* we did not allocate which means left
6720 already in a pointer register, then
6721 if size > 0 && this could be used again
6722 we have to point it back to where it
6724 if (AOP_SIZE(right) > 1 &&
6725 !OP_SYMBOL(result)->remat &&
6726 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6728 int size = AOP_SIZE(right) - 1;
6730 emitcode("dec","%s",rname);
6735 freeAsmop(right,NULL,ic,TRUE);
6740 /*-----------------------------------------------------------------*/
6741 /* genFarPointerSet - set value from far space */
6742 /*-----------------------------------------------------------------*/
6743 static void genFarPointerSet (operand *right,
6744 operand *result, iCode *ic)
6747 link *retype = getSpec(operandType(right));
6749 aopOp(result,ic,FALSE);
6751 /* if the operand is already in dptr
6752 then we do nothing else we move the value to dptr */
6753 if (AOP_TYPE(result) != AOP_STR) {
6754 /* if this is remateriazable */
6755 if (AOP_TYPE(result) == AOP_IMMD)
6756 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6757 else { /* we need to get it byte by byte */
6758 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6759 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6760 if (options.model == MODEL_FLAT24)
6762 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6766 /* so dptr know contains the address */
6767 freeAsmop(result,NULL,ic,TRUE);
6768 aopOp(right,ic,FALSE);
6770 /* if bit then unpack */
6771 if (IS_BITVAR(retype))
6772 genPackBits(retype,right,"dptr",FPOINTER);
6774 size = AOP_SIZE(right);
6778 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6780 emitcode("movx","@dptr,a");
6782 emitcode("inc","dptr");
6786 freeAsmop(right,NULL,ic,TRUE);
6789 /*-----------------------------------------------------------------*/
6790 /* genGenPointerSet - set value from generic pointer space */
6791 /*-----------------------------------------------------------------*/
6792 static void genGenPointerSet (operand *right,
6793 operand *result, iCode *ic)
6796 link *retype = getSpec(operandType(right));
6798 aopOp(result,ic,FALSE);
6800 /* if the operand is already in dptr
6801 then we do nothing else we move the value to dptr */
6802 if (AOP_TYPE(result) != AOP_STR) {
6803 /* if this is remateriazable */
6804 if (AOP_TYPE(result) == AOP_IMMD) {
6805 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6806 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
6808 else { /* we need to get it byte by byte */
6809 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6810 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6811 if (options.model == MODEL_FLAT24)
6813 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6814 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
6818 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
6822 /* so dptr know contains the address */
6823 freeAsmop(result,NULL,ic,TRUE);
6824 aopOp(right,ic,FALSE);
6826 /* if bit then unpack */
6827 if (IS_BITVAR(retype))
6828 genPackBits(retype,right,"dptr",GPOINTER);
6830 size = AOP_SIZE(right);
6834 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6836 emitcode("lcall","__gptrput");
6838 emitcode("inc","dptr");
6842 freeAsmop(right,NULL,ic,TRUE);
6845 /*-----------------------------------------------------------------*/
6846 /* genPointerSet - stores the value into a pointer location */
6847 /*-----------------------------------------------------------------*/
6848 static void genPointerSet (iCode *ic)
6850 operand *right, *result ;
6854 right = IC_RIGHT(ic);
6855 result = IC_RESULT(ic) ;
6857 /* depending on the type of pointer we need to
6858 move it to the correct pointer register */
6859 type = operandType(result);
6860 etype = getSpec(type);
6861 /* if left is of type of pointer then it is simple */
6862 if (IS_PTR(type) && !IS_FUNC(type->next)) {
6863 p_type = DCL_TYPE(type);
6866 /* we have to go by the storage class */
6867 p_type = PTR_TYPE(SPEC_OCLS(etype));
6869 /* if (SPEC_OCLS(etype)->codesp ) { */
6870 /* p_type = CPOINTER ; */
6873 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6874 /* p_type = FPOINTER ; */
6876 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6877 /* p_type = PPOINTER ; */
6879 /* if (SPEC_OCLS(etype) == idata ) */
6880 /* p_type = IPOINTER ; */
6882 /* p_type = POINTER ; */
6885 /* now that we have the pointer type we assign
6886 the pointer values */
6891 genNearPointerSet (right,result,ic);
6895 genPagedPointerSet (right,result,ic);
6899 genFarPointerSet (right,result,ic);
6903 genGenPointerSet (right,result,ic);
6909 /*-----------------------------------------------------------------*/
6910 /* genIfx - generate code for Ifx statement */
6911 /*-----------------------------------------------------------------*/
6912 static void genIfx (iCode *ic, iCode *popIc)
6914 operand *cond = IC_COND(ic);
6917 aopOp(cond,ic,FALSE);
6919 /* get the value into acc */
6920 if (AOP_TYPE(cond) != AOP_CRY)
6924 /* the result is now in the accumulator */
6925 freeAsmop(cond,NULL,ic,TRUE);
6927 /* if there was something to be popped then do it */
6931 /* if the condition is a bit variable */
6932 if (isbit && IS_ITEMP(cond) &&
6934 genIfxJump(ic,SPIL_LOC(cond)->rname);
6936 if (isbit && !IS_ITEMP(cond))
6937 genIfxJump(ic,OP_SYMBOL(cond)->rname);
6944 /*-----------------------------------------------------------------*/
6945 /* genAddrOf - generates code for address of */
6946 /*-----------------------------------------------------------------*/
6947 static void genAddrOf (iCode *ic)
6949 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
6952 aopOp(IC_RESULT(ic),ic,FALSE);
6954 /* if the operand is on the stack then we
6955 need to get the stack offset of this
6958 /* if it has an offset then we need to compute
6961 emitcode("mov","a,_bp");
6962 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
6963 aopPut(AOP(IC_RESULT(ic)),"a",0);
6965 /* we can just move _bp */
6966 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
6968 /* fill the result with zero */
6969 size = AOP_SIZE(IC_RESULT(ic)) - 1;
6972 if (options.stack10bit && size < (FPTRSIZE - 1))
6975 "*** warning: pointer to stack var truncated.\n");
6982 if (options.stack10bit && offset == 2)
6984 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
6988 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
6995 /* object not on stack then we need the name */
6996 size = AOP_SIZE(IC_RESULT(ic));
7000 char s[SDCC_NAME_MAX];
7002 sprintf(s,"#(%s >> %d)",
7006 sprintf(s,"#%s",sym->rname);
7007 aopPut(AOP(IC_RESULT(ic)),s,offset++);
7011 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7015 /*-----------------------------------------------------------------*/
7016 /* genFarFarAssign - assignment when both are in far space */
7017 /*-----------------------------------------------------------------*/
7018 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7020 int size = AOP_SIZE(right);
7023 /* first push the right side on to the stack */
7025 l = aopGet(AOP(right),offset++,FALSE,FALSE);
7027 emitcode ("push","acc");
7030 freeAsmop(right,NULL,ic,FALSE);
7031 /* now assign DPTR to result */
7032 aopOp(result,ic,FALSE);
7033 size = AOP_SIZE(result);
7035 emitcode ("pop","acc");
7036 aopPut(AOP(result),"a",--offset);
7038 freeAsmop(result,NULL,ic,FALSE);
7042 /*-----------------------------------------------------------------*/
7043 /* genAssign - generate code for assignment */
7044 /*-----------------------------------------------------------------*/
7045 static void genAssign (iCode *ic)
7047 operand *result, *right;
7049 unsigned long lit = 0L;
7051 result = IC_RESULT(ic);
7052 right = IC_RIGHT(ic) ;
7054 /* if they are the same */
7055 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7058 aopOp(right,ic,FALSE);
7060 /* special case both in far space */
7061 if ((AOP_TYPE(right) == AOP_DPTR ||
7062 AOP_TYPE(right) == AOP_DPTR2) &&
7063 IS_TRUE_SYMOP(result) &&
7064 isOperandInFarSpace(result)) {
7066 genFarFarAssign (result,right,ic);
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);