1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
35 #include "SDCCglobl.h"
37 #ifdef HAVE_SYS_ISA_DEFS_H
38 #include <sys/isa_defs.h>
44 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
45 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
51 #include "SDCCpeeph.h"
55 char *aopLiteral (value *val, int offset);
57 /* this is the down and dirty file with all kinds of
58 kludgy & hacky stuff. This is what it is all about
59 CODE GENERATION for a specific MCU . some of the
60 routines may be reusable, will have to see */
62 static char *zero = "#0x00";
63 static char *one = "#0x01";
66 char *fReturn8051[] = {"dpl","dph","b","a" };
67 char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
68 unsigned fReturnSize = 4; /* shared with ralloc.c */
69 char **fReturn = fReturn8051;
70 static char *accUse[] = {"a","b"};
72 static short rbank = -1;
84 extern int mcs51_ptrRegReq ;
85 extern int mcs51_nRegs;
86 extern FILE *codeOutFile;
87 static void saverbank (int, iCode *,bool);
88 #define RESULTONSTACK(x) \
89 (IC_RESULT(x) && IC_RESULT(x)->aop && \
90 IC_RESULT(x)->aop->type == AOP_STK )
92 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x);
93 #define CLRC emitcode("clr","c");
95 static lineNode *lineHead = NULL;
96 static lineNode *lineCurr = NULL;
98 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
99 0xE0, 0xC0, 0x80, 0x00};
100 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
101 0x07, 0x03, 0x01, 0x00};
108 /*-----------------------------------------------------------------*/
109 /* emitcode - writes the code into a file : for now it is simple */
110 /*-----------------------------------------------------------------*/
111 static void emitcode (char *inst,char *fmt, ...)
114 char lb[MAX_INLINEASM];
121 sprintf(lb,"%s\t",inst);
123 sprintf(lb,"%s",inst);
124 vsprintf(lb+(strlen(lb)),fmt,ap);
128 while (isspace(*lbp)) lbp++;
131 lineCurr = (lineCurr ?
132 connectLine(lineCurr,newLineNode(lb)) :
133 (lineHead = newLineNode(lb)));
134 lineCurr->isInline = _G.inLine;
135 lineCurr->isDebug = _G.debugLine;
139 /*-----------------------------------------------------------------*/
140 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
141 /*-----------------------------------------------------------------*/
142 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
144 bool r0iu = FALSE , r1iu = FALSE;
145 bool r0ou = FALSE , r1ou = FALSE;
147 /* the logic: if r0 & r1 used in the instruction
148 then we are in trouble otherwise */
150 /* first check if r0 & r1 are used by this
151 instruction, in which case we are in trouble */
152 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
153 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
158 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
159 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
161 /* if no usage of r0 then return it */
162 if (!r0iu && !r0ou) {
163 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
164 (*aopp)->type = AOP_R0;
166 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R0_IDX);
169 /* if no usage of r1 then return it */
170 if (!r1iu && !r1ou) {
171 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
172 (*aopp)->type = AOP_R1;
174 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R1_IDX);
177 /* now we know they both have usage */
178 /* if r0 not used in this instruction */
180 /* push it if not already pushed */
182 emitcode ("push","%s",
183 mcs51_regWithIdx(R0_IDX)->dname);
187 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
188 (*aopp)->type = AOP_R0;
190 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R0_IDX);
193 /* if r1 not used then */
196 /* push it if not already pushed */
198 emitcode ("push","%s",
199 mcs51_regWithIdx(R1_IDX)->dname);
203 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
204 (*aopp)->type = AOP_R1;
205 return mcs51_regWithIdx(R1_IDX);
209 /* I said end of world but not quite end of world yet */
210 /* if this is a result then we can push it on the stack*/
212 (*aopp)->type = AOP_STK;
217 /* other wise this is true end of the world */
218 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
219 "getFreePtr should never reach here");
223 /*-----------------------------------------------------------------*/
224 /* newAsmop - creates a new asmOp */
225 /*-----------------------------------------------------------------*/
226 static asmop *newAsmop (short type)
230 ALLOC(aop,sizeof(asmop));
235 static void genSetDPTR(int n)
239 emitcode(";", "Select standard DPTR");
240 emitcode("mov", "dps, #0x00");
244 emitcode(";", "Select alternate DPTR");
245 emitcode("mov", "dps, #0x01");
249 /*-----------------------------------------------------------------*/
250 /* pointerCode - returns the code for a pointer type */
251 /*-----------------------------------------------------------------*/
252 static int pointerCode (link *etype)
255 return PTR_TYPE(SPEC_OCLS(etype));
259 /*-----------------------------------------------------------------*/
260 /* aopForSym - for a true symbol */
261 /*-----------------------------------------------------------------*/
262 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
265 memmap *space= SPEC_OCLS(sym->etype);
267 /* if already has one */
271 /* assign depending on the storage class */
272 /* if it is on the stack or indirectly addressable */
273 /* space we need to assign either r0 or r1 to it */
274 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
275 sym->aop = aop = newAsmop(0);
276 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
277 aop->size = getSize(sym->type);
279 /* now assign the address of the variable to
280 the pointer register */
281 if (aop->type != AOP_STK) {
285 emitcode("push","acc");
287 emitcode("mov","a,_bp");
288 emitcode("add","a,#0x%02x",
290 ((char)(sym->stack - _G.nRegsSaved )) :
291 ((char)sym->stack)) & 0xff);
292 emitcode("mov","%s,a",
293 aop->aopu.aop_ptr->name);
296 emitcode("pop","acc");
298 emitcode("mov","%s,#%s",
299 aop->aopu.aop_ptr->name,
301 aop->paged = space->paged;
303 aop->aopu.aop_stk = sym->stack;
307 if (sym->onStack && options.stack10bit)
309 /* It's on the 10 bit stack, which is located in
314 emitcode("push","acc");
316 emitcode("mov","a,_bp");
317 emitcode("add","a,#0x%02x",
319 ((char)(sym->stack - _G.nRegsSaved )) :
320 ((char)sym->stack)) & 0xff);
323 emitcode ("mov","dpx1,#0x40");
324 emitcode ("mov","dph1,#0x00");
325 emitcode ("mov","dpl1, a");
329 emitcode("pop","acc");
331 sym->aop = aop = newAsmop(AOP_DPTR2);
332 aop->size = getSize(sym->type);
336 /* if in bit space */
337 if (IN_BITSPACE(space)) {
338 sym->aop = aop = newAsmop (AOP_CRY);
339 aop->aopu.aop_dir = sym->rname ;
340 aop->size = getSize(sym->type);
343 /* if it is in direct space */
344 if (IN_DIRSPACE(space)) {
345 sym->aop = aop = newAsmop (AOP_DIR);
346 aop->aopu.aop_dir = sym->rname ;
347 aop->size = getSize(sym->type);
351 /* special case for a function */
352 if (IS_FUNC(sym->type)) {
353 sym->aop = aop = newAsmop(AOP_IMMD);
354 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
355 strcpy(aop->aopu.aop_immd,sym->rname);
356 aop->size = FPTRSIZE;
360 /* only remaining is far space */
361 /* in which case DPTR gets the address */
362 sym->aop = aop = newAsmop(AOP_DPTR);
363 emitcode ("mov","dptr,#%s", sym->rname);
364 aop->size = getSize(sym->type);
366 /* if it is in code space */
367 if (IN_CODESPACE(space))
373 /*-----------------------------------------------------------------*/
374 /* aopForRemat - rematerialzes an object */
375 /*-----------------------------------------------------------------*/
376 static asmop *aopForRemat (symbol *sym)
379 iCode *ic = sym->rematiCode;
380 asmop *aop = newAsmop(AOP_IMMD);
384 /* if plus or minus print the right hand side */
385 if (ic->op == '+' || ic->op == '-') {
387 sprintf(s,"-0x%04x + ",(int) operandLitValue(IC_RIGHT(ic))) ;
389 sprintf(s,"0x%04x + ",(int) operandLitValue(IC_RIGHT(ic)));
391 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
395 /* we reached the end */
396 sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
400 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
401 strcpy(aop->aopu.aop_immd,buffer);
405 /*-----------------------------------------------------------------*/
406 /* regsInCommon - two operands have some registers in common */
407 /*-----------------------------------------------------------------*/
408 static bool regsInCommon (operand *op1, operand *op2)
413 /* if they have registers in common */
414 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
417 sym1 = OP_SYMBOL(op1);
418 sym2 = OP_SYMBOL(op2);
420 if (sym1->nRegs == 0 || sym2->nRegs == 0)
423 for (i = 0 ; i < sym1->nRegs ; i++) {
428 for (j = 0 ; j < sym2->nRegs ;j++ ) {
432 if (sym2->regs[j] == sym1->regs[i])
440 /*-----------------------------------------------------------------*/
441 /* operandsEqu - equivalent */
442 /*-----------------------------------------------------------------*/
443 static bool operandsEqu ( operand *op1, operand *op2)
447 /* if they not symbols */
448 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
451 sym1 = OP_SYMBOL(op1);
452 sym2 = OP_SYMBOL(op2);
454 /* if both are itemps & one is spilt
455 and the other is not then false */
456 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
457 sym1->isspilt != sym2->isspilt )
460 /* if they are the same */
464 if (strcmp(sym1->rname,sym2->rname) == 0)
468 /* if left is a tmp & right is not */
472 (sym1->usl.spillLoc == sym2))
479 (sym2->usl.spillLoc == sym1))
485 /*-----------------------------------------------------------------*/
486 /* sameRegs - two asmops have the same registers */
487 /*-----------------------------------------------------------------*/
488 static bool sameRegs (asmop *aop1, asmop *aop2 )
495 if (aop1->type != AOP_REG ||
496 aop2->type != AOP_REG )
499 if (aop1->size != aop2->size )
502 for (i = 0 ; i < aop1->size ; i++ )
503 if (aop1->aopu.aop_reg[i] !=
504 aop2->aopu.aop_reg[i] )
510 /*-----------------------------------------------------------------*/
511 /* aopOp - allocates an asmop for an operand : */
512 /*-----------------------------------------------------------------*/
513 static void aopOp (operand *op, iCode *ic, bool result)
522 /* if this a literal */
523 if (IS_OP_LITERAL(op)) {
524 op->aop = aop = newAsmop(AOP_LIT);
525 aop->aopu.aop_lit = op->operand.valOperand;
526 aop->size = getSize(operandType(op));
530 /* if already has a asmop then continue */
534 /* if the underlying symbol has a aop */
535 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
536 op->aop = OP_SYMBOL(op)->aop;
540 /* if this is a true symbol */
541 if (IS_TRUE_SYMOP(op)) {
542 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
546 /* this is a temporary : this has
552 e) can be a return use only */
557 /* if the type is a conditional */
558 if (sym->regType == REG_CND) {
559 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
564 /* if it is spilt then two situations
566 b) has a spill location */
567 if (sym->isspilt || sym->nRegs == 0) {
569 /* rematerialize it NOW */
571 sym->aop = op->aop = aop =
573 aop->size = getSize(sym->type);
579 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
580 aop->size = getSize(sym->type);
581 for ( i = 0 ; i < 2 ; i++ )
582 aop->aopu.aop_str[i] = accUse[i];
588 aop = op->aop = sym->aop = newAsmop(AOP_STR);
589 aop->size = getSize(sym->type);
590 for ( i = 0 ; i < fReturnSize ; i++ )
591 aop->aopu.aop_str[i] = fReturn[i];
595 /* else spill location */
596 sym->aop = op->aop = aop =
597 aopForSym(ic,sym->usl.spillLoc,result);
598 aop->size = getSize(sym->type);
602 /* must be in a register */
603 sym->aop = op->aop = aop = newAsmop(AOP_REG);
604 aop->size = sym->nRegs;
605 for ( i = 0 ; i < sym->nRegs ;i++)
606 aop->aopu.aop_reg[i] = sym->regs[i];
609 /*-----------------------------------------------------------------*/
610 /* freeAsmop - free up the asmop given to an operand */
611 /*----------------------------------------------------------------*/
612 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
629 /* depending on the asmop type only three cases need work AOP_RO
630 , AOP_R1 && AOP_STK */
635 emitcode ("pop","ar0");
639 bitVectUnSetBit(ic->rUsed,R0_IDX);
645 emitcode ("pop","ar1");
649 bitVectUnSetBit(ic->rUsed,R1_IDX);
655 int stk = aop->aopu.aop_stk + aop->size;
656 bitVectUnSetBit(ic->rUsed,R0_IDX);
657 bitVectUnSetBit(ic->rUsed,R1_IDX);
659 getFreePtr(ic,&aop,FALSE);
661 if (options.stack10bit)
663 /* I'm not sure what to do here yet... */
666 "*** Warning: probably generating bad code for "
667 "10 bit stack mode.\n");
671 emitcode ("mov","a,_bp");
672 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
673 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
675 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
679 emitcode("pop","acc");
680 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
682 emitcode("dec","%s",aop->aopu.aop_ptr->name);
685 freeAsmop(op,NULL,ic,TRUE);
687 emitcode("pop","ar0");
692 emitcode("pop","ar1");
699 /* all other cases just dealloc */
703 OP_SYMBOL(op)->aop = NULL;
704 /* if the symbol has a spill */
706 SPIL_LOC(op)->aop = NULL;
711 /*-----------------------------------------------------------------*/
712 /* aopGet - for fetching value of the aop */
713 /*-----------------------------------------------------------------*/
714 static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
719 /* offset is greater than
721 if (offset > (aop->size - 1) &&
722 aop->type != AOP_LIT)
725 /* depending on type */
730 /* if we need to increment it */
731 while (offset > aop->coff) {
732 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
736 while (offset < aop->coff) {
737 emitcode("dec","%s",aop->aopu.aop_ptr->name);
743 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
744 return (dname ? "acc" : "a");
746 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
747 ALLOC_ATOMIC(rs,strlen(s)+1);
754 if (aop->type == AOP_DPTR2)
759 while (offset > aop->coff) {
760 emitcode ("inc","dptr");
764 while (offset < aop->coff) {
765 emitcode("lcall","__decdptr");
772 emitcode("movc","a,@a+dptr");
775 emitcode("movx","a,@dptr");
778 if (aop->type == AOP_DPTR2)
783 return (dname ? "acc" : "a");
788 sprintf (s,"#(%s)",aop->aopu.aop_immd);
791 sprintf(s,"#(%s >> %d)",
797 ALLOC_ATOMIC(rs,strlen(s)+1);
803 sprintf(s,"(%s + %d)",
807 sprintf(s,"%s",aop->aopu.aop_dir);
808 ALLOC_ATOMIC(rs,strlen(s)+1);
814 return aop->aopu.aop_reg[offset]->dname;
816 return aop->aopu.aop_reg[offset]->name;
820 emitcode("mov","c,%s",aop->aopu.aop_dir);
821 emitcode("rlc","a") ;
822 return (dname ? "acc" : "a");
825 if (!offset && dname)
827 return aop->aopu.aop_str[offset];
830 return aopLiteral (aop->aopu.aop_lit,offset);
834 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
838 return aop->aopu.aop_str[offset];
842 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
843 "aopget got unsupported aop->type");
846 /*-----------------------------------------------------------------*/
847 /* aopPut - puts a string for a aop */
848 /*-----------------------------------------------------------------*/
849 static void aopPut (asmop *aop, char *s, int offset)
854 if (aop->size && offset > ( aop->size - 1)) {
855 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
856 "aopPut got offset > aop->size");
860 /* will assign value to value */
861 /* depending on where it is ofcourse */
865 sprintf(d,"(%s + %d)",
866 aop->aopu.aop_dir,offset);
868 sprintf(d,"%s",aop->aopu.aop_dir);
871 emitcode("mov","%s,%s",d,s);
876 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
877 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
879 strcmp(s,"r0") == 0 ||
880 strcmp(s,"r1") == 0 ||
881 strcmp(s,"r2") == 0 ||
882 strcmp(s,"r3") == 0 ||
883 strcmp(s,"r4") == 0 ||
884 strcmp(s,"r5") == 0 ||
885 strcmp(s,"r6") == 0 ||
886 strcmp(s,"r7") == 0 )
887 emitcode("mov","%s,%s",
888 aop->aopu.aop_reg[offset]->dname,s);
890 emitcode("mov","%s,%s",
891 aop->aopu.aop_reg[offset]->name,s);
898 if (aop->type == AOP_DPTR2)
904 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
905 "aopPut writting to code space");
909 while (offset > aop->coff) {
911 emitcode ("inc","dptr");
914 while (offset < aop->coff) {
916 emitcode("lcall","__decdptr");
921 /* if not in accumulater */
924 emitcode ("movx","@dptr,a");
926 if (aop->type == AOP_DPTR2)
934 while (offset > aop->coff) {
936 emitcode("inc","%s",aop->aopu.aop_ptr->name);
938 while (offset < aop->coff) {
940 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
946 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
951 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
953 if (strcmp(s,"r0") == 0 ||
954 strcmp(s,"r1") == 0 ||
955 strcmp(s,"r2") == 0 ||
956 strcmp(s,"r3") == 0 ||
957 strcmp(s,"r4") == 0 ||
958 strcmp(s,"r5") == 0 ||
959 strcmp(s,"r6") == 0 ||
960 strcmp(s,"r7") == 0 ) {
962 sprintf(buffer,"a%s",s);
963 emitcode("mov","@%s,%s",
964 aop->aopu.aop_ptr->name,buffer);
966 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
971 if (strcmp(s,"a") == 0)
972 emitcode("push","acc");
974 emitcode("push","%s",s);
979 /* if bit variable */
980 if (!aop->aopu.aop_dir) {
985 emitcode("clr","%s",aop->aopu.aop_dir);
988 emitcode("setb","%s",aop->aopu.aop_dir);
991 emitcode("mov","%s,c",aop->aopu.aop_dir);
993 lbl = newiTempLabel(NULL);
999 emitcode("jz","%05d$",lbl->key+100);
1000 emitcode("cpl","c");
1001 emitcode("","%05d$:",lbl->key+100);
1002 emitcode("mov","%s,c",aop->aopu.aop_dir);
1009 if (strcmp(aop->aopu.aop_str[offset],s))
1010 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1015 if (!offset && (strcmp(s,"acc") == 0))
1018 if (strcmp(aop->aopu.aop_str[offset],s))
1019 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1023 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1024 "aopPut got unsupported aop->type");
1032 /*-----------------------------------------------------------------*/
1033 /* pointToEnd :- points to the last byte of the operand */
1034 /*-----------------------------------------------------------------*/
1035 static void pointToEnd (asmop *aop)
1041 aop->coff = count = (aop->size - 1);
1042 switch (aop->type) {
1046 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1050 emitcode("inc","dptr");
1057 /*-----------------------------------------------------------------*/
1058 /* reAdjustPreg - points a register back to where it should */
1059 /*-----------------------------------------------------------------*/
1060 static void reAdjustPreg (asmop *aop)
1065 if ((size = aop->size) <= 1)
1068 switch (aop->type) {
1072 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1076 if (aop->type == AOP_DPTR2)
1082 emitcode("lcall","__decdptr");
1085 if (aop->type == AOP_DPTR2)
1095 #define AOP(op) op->aop
1096 #define AOP_TYPE(op) AOP(op)->type
1097 #define AOP_SIZE(op) AOP(op)->size
1098 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1099 AOP_TYPE(x) == AOP_R0))
1101 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1102 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1105 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1106 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1107 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1109 /*-----------------------------------------------------------------*/
1110 /* genNotFloat - generates not for float operations */
1111 /*-----------------------------------------------------------------*/
1112 static void genNotFloat (operand *op, operand *res)
1118 /* we will put 127 in the first byte of
1120 aopPut(AOP(res),"#127",0);
1121 size = AOP_SIZE(op) - 1;
1124 l = aopGet(op->aop,offset++,FALSE,FALSE);
1128 emitcode("orl","a,%s",
1130 offset++,FALSE,FALSE));
1132 tlbl = newiTempLabel(NULL);
1134 tlbl = newiTempLabel(NULL);
1135 aopPut(res->aop,one,1);
1136 emitcode("jz","%05d$",(tlbl->key+100));
1137 aopPut(res->aop,zero,1);
1138 emitcode("","%05d$:",(tlbl->key+100));
1140 size = res->aop->size - 2;
1142 /* put zeros in the rest */
1144 aopPut(res->aop,zero,offset++);
1147 /*-----------------------------------------------------------------*/
1148 /* opIsGptr: returns non-zero if the passed operand is */
1149 /* a generic pointer type. */
1150 /*-----------------------------------------------------------------*/
1151 static int opIsGptr(operand *op)
1153 link *type = operandType(op);
1155 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1162 /*-----------------------------------------------------------------*/
1163 /* getDataSize - get the operand data size */
1164 /*-----------------------------------------------------------------*/
1165 static int getDataSize(operand *op)
1168 size = AOP_SIZE(op);
1169 if (size == GPTRSIZE)
1171 link *type = operandType(op);
1172 if (IS_GENPTR(type))
1174 /* generic pointer; arithmetic operations
1175 * should ignore the high byte (pointer type).
1183 /*-----------------------------------------------------------------*/
1184 /* outAcc - output Acc */
1185 /*-----------------------------------------------------------------*/
1186 static void outAcc(operand *result)
1189 size = getDataSize(result);
1191 aopPut(AOP(result),"a",0);
1194 /* unsigned or positive */
1196 aopPut(AOP(result),zero,offset++);
1201 /*-----------------------------------------------------------------*/
1202 /* outBitC - output a bit C */
1203 /*-----------------------------------------------------------------*/
1204 static void outBitC(operand *result)
1206 /* if the result is bit */
1207 if (AOP_TYPE(result) == AOP_CRY)
1208 aopPut(AOP(result),"c",0);
1210 emitcode("clr","a");
1211 emitcode("rlc","a");
1216 /*-----------------------------------------------------------------*/
1217 /* toBoolean - emit code for orl a,operator(sizeop) */
1218 /*-----------------------------------------------------------------*/
1219 static void toBoolean(operand *oper)
1221 int size = AOP_SIZE(oper) - 1;
1223 MOVA(aopGet(AOP(oper),0,FALSE,FALSE));
1225 emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE));
1229 /*-----------------------------------------------------------------*/
1230 /* genNot - generate code for ! operation */
1231 /*-----------------------------------------------------------------*/
1232 static void genNot (iCode *ic)
1235 link *optype = operandType(IC_LEFT(ic));
1237 /* assign asmOps to operand & result */
1238 aopOp (IC_LEFT(ic),ic,FALSE);
1239 aopOp (IC_RESULT(ic),ic,TRUE);
1241 /* if in bit space then a special case */
1242 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1243 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1244 emitcode("cpl","c");
1245 outBitC(IC_RESULT(ic));
1249 /* if type float then do float */
1250 if (IS_FLOAT(optype)) {
1251 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1255 toBoolean(IC_LEFT(ic));
1257 tlbl = newiTempLabel(NULL);
1258 emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1259 emitcode("","%05d$:",tlbl->key+100);
1260 outBitC(IC_RESULT(ic));
1263 /* release the aops */
1264 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1265 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1269 /*-----------------------------------------------------------------*/
1270 /* genCpl - generate code for complement */
1271 /*-----------------------------------------------------------------*/
1272 static void genCpl (iCode *ic)
1278 /* assign asmOps to operand & result */
1279 aopOp (IC_LEFT(ic),ic,FALSE);
1280 aopOp (IC_RESULT(ic),ic,TRUE);
1282 /* if both are in bit space then
1284 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1285 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1287 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1288 emitcode("cpl","c");
1289 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1293 size = AOP_SIZE(IC_RESULT(ic));
1295 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1297 emitcode("cpl","a");
1298 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1303 /* release the aops */
1304 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1305 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1308 /*-----------------------------------------------------------------*/
1309 /* genUminusFloat - unary minus for floating points */
1310 /*-----------------------------------------------------------------*/
1311 static void genUminusFloat(operand *op,operand *result)
1313 int size ,offset =0 ;
1315 /* for this we just need to flip the
1316 first it then copy the rest in place */
1317 size = AOP_SIZE(op) - 1;
1318 l = aopGet(AOP(op),3,FALSE,FALSE);
1322 emitcode("cpl","acc.7");
1323 aopPut(AOP(result),"a",3);
1327 aopGet(AOP(op),offset,FALSE,FALSE),
1333 /*-----------------------------------------------------------------*/
1334 /* genUminus - unary minus code generation */
1335 /*-----------------------------------------------------------------*/
1336 static void genUminus (iCode *ic)
1339 link *optype, *rtype;
1343 aopOp(IC_LEFT(ic),ic,FALSE);
1344 aopOp(IC_RESULT(ic),ic,TRUE);
1346 /* if both in bit space then special
1348 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1349 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1351 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1352 emitcode("cpl","c");
1353 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1357 optype = operandType(IC_LEFT(ic));
1358 rtype = operandType(IC_RESULT(ic));
1360 /* if float then do float stuff */
1361 if (IS_FLOAT(optype)) {
1362 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1366 /* otherwise subtract from zero */
1367 size = AOP_SIZE(IC_LEFT(ic));
1371 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1372 if (!strcmp(l,"a")) {
1373 emitcode("cpl","a");
1374 emitcode("inc","a");
1376 emitcode("clr","a");
1377 emitcode("subb","a,%s",l);
1379 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1382 /* if any remaining bytes in the result */
1383 /* we just need to propagate the sign */
1384 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1385 emitcode("rlc","a");
1386 emitcode("subb","a,acc");
1388 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1392 /* release the aops */
1393 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1394 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1397 /*-----------------------------------------------------------------*/
1398 /* saveRegisters - will look for a call and save the registers */
1399 /*-----------------------------------------------------------------*/
1400 static void saveRegisters(iCode *lic)
1408 for (ic = lic ; ic ; ic = ic->next)
1409 if (ic->op == CALL || ic->op == PCALL)
1413 fprintf(stderr,"found parameter push with no function call\n");
1417 /* if the registers have been saved already then
1419 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1422 /* find the registers in use at this time
1423 and push them away to safety */
1424 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1428 if (options.useXstack) {
1429 if (bitVectBitValue(rsave,R0_IDX))
1430 emitcode("mov","b,r0");
1431 emitcode("mov","r0,%s",spname);
1432 for (i = 0 ; i < mcs51_nRegs ; i++) {
1433 if (bitVectBitValue(rsave,i)) {
1435 emitcode("mov","a,b");
1437 emitcode("mov","a,%s",mcs51_regWithIdx(i)->name);
1438 emitcode("movx","@r0,a");
1439 emitcode("inc","r0");
1442 emitcode("mov","%s,r0",spname);
1443 if (bitVectBitValue(rsave,R0_IDX))
1444 emitcode("mov","r0,b");
1446 for (i = 0 ; i < mcs51_nRegs ; i++) {
1447 if (bitVectBitValue(rsave,i))
1448 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
1451 detype = getSpec(operandType(IC_LEFT(ic)));
1453 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1454 IS_ISR(currFunc->etype) &&
1457 saverbank(SPEC_BANK(detype),ic,TRUE);
1460 /*-----------------------------------------------------------------*/
1461 /* unsaveRegisters - pop the pushed registers */
1462 /*-----------------------------------------------------------------*/
1463 static void unsaveRegisters (iCode *ic)
1467 /* find the registers in use at this time
1468 and push them away to safety */
1469 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1472 if (options.useXstack) {
1473 emitcode("mov","r0,%s",spname);
1474 for (i = mcs51_nRegs ; i >= 0 ; i--) {
1475 if (bitVectBitValue(rsave,i)) {
1476 emitcode("dec","r0");
1477 emitcode("movx","a,@r0");
1479 emitcode("mov","b,a");
1481 emitcode("mov","%s,a",mcs51_regWithIdx(i)->name);
1485 emitcode("mov","%s,r0",spname);
1486 if (bitVectBitValue(rsave,R0_IDX))
1487 emitcode("mov","r0,b");
1489 for (i = mcs51_nRegs ; i >= 0 ; i--) {
1490 if (bitVectBitValue(rsave,i))
1491 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
1497 /*-----------------------------------------------------------------*/
1499 /*-----------------------------------------------------------------*/
1500 static void pushSide(operand * oper, int size)
1504 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1505 if (AOP_TYPE(oper) != AOP_REG &&
1506 AOP_TYPE(oper) != AOP_DIR &&
1508 emitcode("mov","a,%s",l);
1509 emitcode("push","acc");
1511 emitcode("push","%s",l);
1515 /*-----------------------------------------------------------------*/
1516 /* assignResultValue - */
1517 /*-----------------------------------------------------------------*/
1518 static void assignResultValue(operand * oper)
1521 int size = AOP_SIZE(oper);
1523 aopPut(AOP(oper),fReturn[offset],offset);
1529 /*-----------------------------------------------------------------*/
1530 /* genXpush - pushes onto the external stack */
1531 /*-----------------------------------------------------------------*/
1532 static void genXpush (iCode *ic)
1534 asmop *aop = newAsmop(0);
1536 int size,offset = 0;
1538 aopOp(IC_LEFT(ic),ic,FALSE);
1539 r = getFreePtr(ic,&aop,FALSE);
1542 emitcode("mov","%s,_spx",r->name);
1544 size = AOP_SIZE(IC_LEFT(ic));
1547 char *l = aopGet(AOP(IC_LEFT(ic)),
1548 offset++,FALSE,FALSE);
1550 emitcode("movx","@%s,a",r->name);
1551 emitcode("inc","%s",r->name);
1556 emitcode("mov","_spx,%s",r->name);
1558 freeAsmop(NULL,aop,ic,TRUE);
1559 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1562 /*-----------------------------------------------------------------*/
1563 /* genIpush - genrate code for pushing this gets a little complex */
1564 /*-----------------------------------------------------------------*/
1565 static void genIpush (iCode *ic)
1567 int size, offset = 0 ;
1571 /* if this is not a parm push : ie. it is spill push
1572 and spill push is always done on the local stack */
1573 if (!ic->parmPush) {
1575 /* and the item is spilt then do nothing */
1576 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1579 aopOp(IC_LEFT(ic),ic,FALSE);
1580 size = AOP_SIZE(IC_LEFT(ic));
1581 /* push it on the stack */
1583 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1588 emitcode("push","%s",l);
1593 /* this is a paramter push: in this case we call
1594 the routine to find the call and save those
1595 registers that need to be saved */
1598 /* if use external stack then call the external
1599 stack pushing routine */
1600 if (options.useXstack) {
1605 /* then do the push */
1606 aopOp(IC_LEFT(ic),ic,FALSE);
1609 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1610 size = AOP_SIZE(IC_LEFT(ic));
1613 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1614 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1615 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1617 emitcode("mov","a,%s",l);
1618 emitcode("push","acc");
1620 emitcode("push","%s",l);
1623 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1626 /*-----------------------------------------------------------------*/
1627 /* genIpop - recover the registers: can happen only for spilling */
1628 /*-----------------------------------------------------------------*/
1629 static void genIpop (iCode *ic)
1634 /* if the temp was not pushed then */
1635 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1638 aopOp(IC_LEFT(ic),ic,FALSE);
1639 size = AOP_SIZE(IC_LEFT(ic));
1642 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1645 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1648 /*-----------------------------------------------------------------*/
1649 /* unsaverbank - restores the resgister bank from stack */
1650 /*-----------------------------------------------------------------*/
1651 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1658 if (options.useXstack) {
1660 r = getFreePtr(ic,&aop,FALSE);
1663 emitcode("mov","%s,_spx",r->name);
1664 emitcode("movx","a,@%s",r->name);
1665 emitcode("mov","psw,a");
1666 emitcode("dec","%s",r->name);
1669 emitcode ("pop","psw");
1672 for (i = (mcs51_nRegs - 1) ; i >= 0 ;i--) {
1673 if (options.useXstack) {
1674 emitcode("movx","a,@%s",r->name);
1675 emitcode("mov","(%s+%d),a",
1676 regs8051[i].base,8*bank+regs8051[i].offset);
1677 emitcode("dec","%s",r->name);
1680 emitcode("pop","(%s+%d)",
1681 regs8051[i].base,8*bank+regs8051[i].offset);
1684 if (options.useXstack) {
1686 emitcode("mov","_spx,%s",r->name);
1687 freeAsmop(NULL,aop,ic,TRUE);
1692 /*-----------------------------------------------------------------*/
1693 /* saverbank - saves an entire register bank on the stack */
1694 /*-----------------------------------------------------------------*/
1695 static void saverbank (int bank, iCode *ic, bool pushPsw)
1701 if (options.useXstack) {
1704 r = getFreePtr(ic,&aop,FALSE);
1705 emitcode("mov","%s,_spx",r->name);
1709 for (i = 0 ; i < mcs51_nRegs ;i++) {
1710 if (options.useXstack) {
1711 emitcode("inc","%s",r->name);
1712 emitcode("mov","a,(%s+%d)",
1713 regs8051[i].base,8*bank+regs8051[i].offset);
1714 emitcode("movx","@%s,a",r->name);
1716 emitcode("push","(%s+%d)",
1717 regs8051[i].base,8*bank+regs8051[i].offset);
1721 if (options.useXstack) {
1722 emitcode("mov","a,psw");
1723 emitcode("movx","@%s,a",r->name);
1724 emitcode("inc","%s",r->name);
1725 emitcode("mov","_spx,%s",r->name);
1726 freeAsmop (NULL,aop,ic,TRUE);
1729 emitcode("push","psw");
1731 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1737 /*-----------------------------------------------------------------*/
1738 /* genCall - generates a call statement */
1739 /*-----------------------------------------------------------------*/
1740 static void genCall (iCode *ic)
1744 /* if caller saves & we have not saved then */
1748 /* if we are calling a function that is not using
1749 the same register bank then we need to save the
1750 destination registers on the stack */
1751 detype = getSpec(operandType(IC_LEFT(ic)));
1753 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1754 IS_ISR(currFunc->etype) &&
1757 saverbank(SPEC_BANK(detype),ic,TRUE);
1759 /* if send set is not empty the assign */
1763 for (sic = setFirstItem(_G.sendSet) ; sic ;
1764 sic = setNextItem(_G.sendSet)) {
1765 int size, offset = 0;
1766 aopOp(IC_LEFT(sic),sic,FALSE);
1767 size = AOP_SIZE(IC_LEFT(sic));
1769 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1771 if (strcmp(l,fReturn[offset]))
1772 emitcode("mov","%s,%s",
1777 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1782 emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1783 OP_SYMBOL(IC_LEFT(ic))->rname :
1784 OP_SYMBOL(IC_LEFT(ic))->name));
1786 /* if we need assign a result value */
1787 if ((IS_ITEMP(IC_RESULT(ic)) &&
1788 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1789 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1790 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1793 aopOp(IC_RESULT(ic),ic,FALSE);
1796 assignResultValue(IC_RESULT(ic));
1798 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1801 /* adjust the stack for parameters if
1803 if (IC_LEFT(ic)->parmBytes) {
1805 if (IC_LEFT(ic)->parmBytes > 3) {
1806 emitcode("mov","a,%s",spname);
1807 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1808 emitcode("mov","%s,a",spname);
1810 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1811 emitcode("dec","%s",spname);
1815 /* if register bank was saved then pop them */
1817 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1819 /* if we hade saved some registers then unsave them */
1820 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1821 unsaveRegisters (ic);
1826 /*-----------------------------------------------------------------*/
1827 /* genPcall - generates a call by pointer statement */
1828 /*-----------------------------------------------------------------*/
1829 static void genPcall (iCode *ic)
1832 symbol *rlbl = newiTempLabel(NULL);
1835 /* if caller saves & we have not saved then */
1839 /* if we are calling a function that is not using
1840 the same register bank then we need to save the
1841 destination registers on the stack */
1842 detype = getSpec(operandType(IC_LEFT(ic)));
1844 IS_ISR(currFunc->etype) &&
1845 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
1846 saverbank(SPEC_BANK(detype),ic,TRUE);
1849 /* push the return address on to the stack */
1850 emitcode("mov","a,#%05d$",(rlbl->key+100));
1851 emitcode("push","acc");
1852 emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
1853 emitcode("push","acc");
1855 if (options.model == MODEL_FLAT24)
1857 emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
1858 emitcode("push","acc");
1861 /* now push the calling address */
1862 aopOp(IC_LEFT(ic),ic,FALSE);
1864 pushSide(IC_LEFT(ic), FPTRSIZE);
1866 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1868 /* if send set is not empty the assign */
1872 for (sic = setFirstItem(_G.sendSet) ; sic ;
1873 sic = setNextItem(_G.sendSet)) {
1874 int size, offset = 0;
1875 aopOp(IC_LEFT(sic),sic,FALSE);
1876 size = AOP_SIZE(IC_LEFT(sic));
1878 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1880 if (strcmp(l,fReturn[offset]))
1881 emitcode("mov","%s,%s",
1886 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1892 emitcode("","%05d$:",(rlbl->key+100));
1895 /* if we need assign a result value */
1896 if ((IS_ITEMP(IC_RESULT(ic)) &&
1897 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1898 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
1899 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1902 aopOp(IC_RESULT(ic),ic,FALSE);
1905 assignResultValue(IC_RESULT(ic));
1907 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1910 /* adjust the stack for parameters if
1912 if (IC_LEFT(ic)->parmBytes) {
1914 if (IC_LEFT(ic)->parmBytes > 3) {
1915 emitcode("mov","a,%s",spname);
1916 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1917 emitcode("mov","%s,a",spname);
1919 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1920 emitcode("dec","%s",spname);
1924 /* if register bank was saved then unsave them */
1926 (SPEC_BANK(currFunc->etype) !=
1928 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1930 /* if we hade saved some registers then
1933 unsaveRegisters (ic);
1937 /*-----------------------------------------------------------------*/
1938 /* resultRemat - result is rematerializable */
1939 /*-----------------------------------------------------------------*/
1940 static int resultRemat (iCode *ic)
1942 if (SKIP_IC(ic) || ic->op == IFX)
1945 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1946 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1947 if (sym->remat && !POINTER_SET(ic))
1955 #define STRCASECMP stricmp
1957 #define STRCASECMP strcasecmp
1960 /*-----------------------------------------------------------------*/
1961 /* inExcludeList - return 1 if the string is in exclude Reg list */
1962 /*-----------------------------------------------------------------*/
1963 static bool inExcludeList(char *s)
1967 if (options.excludeRegs[i] &&
1968 STRCASECMP(options.excludeRegs[i],"none") == 0)
1971 for ( i = 0 ; options.excludeRegs[i]; i++) {
1972 if (options.excludeRegs[i] &&
1973 STRCASECMP(s,options.excludeRegs[i]) == 0)
1979 /*-----------------------------------------------------------------*/
1980 /* genFunction - generated code for function entry */
1981 /*-----------------------------------------------------------------*/
1982 static void genFunction (iCode *ic)
1988 /* create the function header */
1989 emitcode(";","-----------------------------------------");
1990 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1991 emitcode(";","-----------------------------------------");
1993 emitcode("","%s:",sym->rname);
1994 fetype = getSpec(operandType(IC_LEFT(ic)));
1996 /* if critical function then turn interrupts off */
1997 if (SPEC_CRTCL(fetype))
1998 emitcode("clr","ea");
2000 /* here we need to generate the equates for the
2001 register bank if required */
2002 if (SPEC_BANK(fetype) != rbank) {
2005 rbank = SPEC_BANK(fetype);
2006 for ( i = 0 ; i < mcs51_nRegs ; i++ ) {
2007 if (strcmp(regs8051[i].base,"0") == 0)
2008 emitcode("","%s = 0x%02x",
2010 8*rbank+regs8051[i].offset);
2012 emitcode ("","%s = %s + 0x%02x",
2015 8*rbank+regs8051[i].offset);
2019 /* if this is an interrupt service routine then
2020 save acc, b, dpl, dph */
2021 if (IS_ISR(sym->etype)) {
2023 if (!inExcludeList("acc"))
2024 emitcode ("push","acc");
2025 if (!inExcludeList("b"))
2026 emitcode ("push","b");
2027 if (!inExcludeList("dpl"))
2028 emitcode ("push","dpl");
2029 if (!inExcludeList("dph"))
2030 emitcode ("push","dph");
2031 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2033 emitcode ("push", "dpx");
2034 /* Make sure we're using standard DPTR */
2035 emitcode ("push", "dps");
2036 emitcode ("mov", "dps, #0x00");
2037 if (options.stack10bit)
2039 /* This ISR could conceivably use DPTR2. Better save it. */
2040 emitcode ("push", "dpl1");
2041 emitcode ("push", "dph1");
2042 emitcode ("push", "dpx1");
2045 /* if this isr has no bank i.e. is going to
2046 run with bank 0 , then we need to save more
2048 if (!SPEC_BANK(sym->etype)) {
2050 /* if this function does not call any other
2051 function then we can be economical and
2052 save only those registers that are used */
2053 if (! sym->hasFcall) {
2056 /* if any registers used */
2057 if (sym->regsUsed) {
2058 /* save the registers used */
2059 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2060 if (bitVectBitValue(sym->regsUsed,i) ||
2061 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2062 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
2067 /* this function has a function call cannot
2068 determines register usage so we will have the
2070 saverbank(0,ic,FALSE);
2074 /* if callee-save to be used for this function
2075 then save the registers being used in this function */
2076 if (sym->calleeSave) {
2079 /* if any registers used */
2080 if (sym->regsUsed) {
2081 /* save the registers used */
2082 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2083 if (bitVectBitValue(sym->regsUsed,i) ||
2084 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2085 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
2093 /* set the register bank to the desired value */
2094 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2095 emitcode("push","psw");
2096 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2099 if (IS_RENT(sym->etype) || options.stackAuto) {
2101 if (options.useXstack) {
2102 emitcode("mov","r0,%s",spname);
2103 emitcode("mov","a,_bp");
2104 emitcode("movx","@r0,a");
2105 emitcode("inc","%s",spname);
2109 /* set up the stack */
2110 emitcode ("push","_bp"); /* save the callers stack */
2112 emitcode ("mov","_bp,%s",spname);
2115 /* adjust the stack for the function */
2120 werror(W_STACK_OVERFLOW,sym->name);
2122 if (i > 3 && sym->recvSize < 4) {
2124 emitcode ("mov","a,sp");
2125 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2126 emitcode ("mov","sp,a");
2131 emitcode("inc","sp");
2136 emitcode ("mov","a,_spx");
2137 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2138 emitcode ("mov","_spx,a");
2143 /*-----------------------------------------------------------------*/
2144 /* genEndFunction - generates epilogue for functions */
2145 /*-----------------------------------------------------------------*/
2146 static void genEndFunction (iCode *ic)
2148 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2150 if (IS_RENT(sym->etype) || options.stackAuto)
2152 emitcode ("mov","%s,_bp",spname);
2155 /* if use external stack but some variables were
2156 added to the local stack then decrement the
2158 if (options.useXstack && sym->stack) {
2159 emitcode("mov","a,sp");
2160 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2161 emitcode("mov","sp,a");
2165 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2166 if (options.useXstack) {
2167 emitcode("mov","r0,%s",spname);
2168 emitcode("movx","a,@r0");
2169 emitcode("mov","_bp,a");
2170 emitcode("dec","%s",spname);
2174 emitcode ("pop","_bp");
2178 /* restore the register bank */
2179 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2180 emitcode ("pop","psw");
2182 if (IS_ISR(sym->etype)) {
2184 /* now we need to restore the registers */
2185 /* if this isr has no bank i.e. is going to
2186 run with bank 0 , then we need to save more
2188 if (!SPEC_BANK(sym->etype)) {
2190 /* if this function does not call any other
2191 function then we can be economical and
2192 save only those registers that are used */
2193 if (! sym->hasFcall) {
2196 /* if any registers used */
2197 if (sym->regsUsed) {
2198 /* save the registers used */
2199 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2200 if (bitVectBitValue(sym->regsUsed,i) ||
2201 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2202 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
2207 /* this function has a function call cannot
2208 determines register usage so we will have the
2210 unsaverbank(0,ic,FALSE);
2214 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2216 if (options.stack10bit)
2218 emitcode ("pop", "dpx1");
2219 emitcode ("pop", "dph1");
2220 emitcode ("pop", "dpl1");
2222 emitcode ("pop", "dps");
2223 emitcode ("pop", "dpx");
2225 if (!inExcludeList("dph"))
2226 emitcode ("pop","dph");
2227 if (!inExcludeList("dpl"))
2228 emitcode ("pop","dpl");
2229 if (!inExcludeList("b"))
2230 emitcode ("pop","b");
2231 if (!inExcludeList("acc"))
2232 emitcode ("pop","acc");
2234 if (SPEC_CRTCL(sym->etype))
2235 emitcode("setb","ea");
2237 /* if debug then send end of function */
2238 /* if (options.debug && currFunc) { */
2241 emitcode("","C$%s$%d$%d$%d ==.",
2242 ic->filename,currFunc->lastLine,
2243 ic->level,ic->block);
2244 if (IS_STATIC(currFunc->etype))
2245 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2247 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2251 emitcode ("reti","");
2254 if (SPEC_CRTCL(sym->etype))
2255 emitcode("setb","ea");
2257 if (sym->calleeSave) {
2260 /* if any registers used */
2261 if (sym->regsUsed) {
2262 /* save the registers used */
2263 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2264 if (bitVectBitValue(sym->regsUsed,i) ||
2265 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2266 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
2272 /* if debug then send end of function */
2275 emitcode("","C$%s$%d$%d$%d ==.",
2276 ic->filename,currFunc->lastLine,
2277 ic->level,ic->block);
2278 if (IS_STATIC(currFunc->etype))
2279 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2281 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2285 emitcode ("ret","");
2290 /*-----------------------------------------------------------------*/
2291 /* genRet - generate code for return statement */
2292 /*-----------------------------------------------------------------*/
2293 static void genRet (iCode *ic)
2295 int size,offset = 0 , pushed = 0;
2297 /* if we have no return value then
2298 just generate the "ret" */
2302 /* we have something to return then
2303 move the return value into place */
2304 aopOp(IC_LEFT(ic),ic,FALSE);
2305 size = AOP_SIZE(IC_LEFT(ic));
2309 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2311 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2313 emitcode("push","%s",l);
2316 l = aopGet(AOP(IC_LEFT(ic)),offset,
2318 if (strcmp(fReturn[offset],l))
2319 emitcode("mov","%s,%s",fReturn[offset++],l);
2326 if (strcmp(fReturn[pushed],"a"))
2327 emitcode("pop",fReturn[pushed]);
2329 emitcode("pop","acc");
2332 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2335 /* generate a jump to the return label
2336 if the next is not the return statement */
2337 if (!(ic->next && ic->next->op == LABEL &&
2338 IC_LABEL(ic->next) == returnLabel))
2340 emitcode("ljmp","%05d$",(returnLabel->key+100));
2344 /*-----------------------------------------------------------------*/
2345 /* genLabel - generates a label */
2346 /*-----------------------------------------------------------------*/
2347 static void genLabel (iCode *ic)
2349 /* special case never generate */
2350 if (IC_LABEL(ic) == entryLabel)
2353 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2356 /*-----------------------------------------------------------------*/
2357 /* genGoto - generates a ljmp */
2358 /*-----------------------------------------------------------------*/
2359 static void genGoto (iCode *ic)
2361 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2364 /*-----------------------------------------------------------------*/
2365 /* findLabelBackwards: walks back through the iCode chain looking */
2366 /* for the given label. Returns number of iCode instructions */
2367 /* between that label and given ic. */
2368 /* Returns zero if label not found. */
2369 /*-----------------------------------------------------------------*/
2370 static int findLabelBackwards(iCode *ic, int key)
2379 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2381 /* printf("findLabelBackwards = %d\n", count); */
2389 /*-----------------------------------------------------------------*/
2390 /* genPlusIncr :- does addition with increment if possible */
2391 /*-----------------------------------------------------------------*/
2392 static bool genPlusIncr (iCode *ic)
2394 unsigned int icount ;
2395 unsigned int size = getDataSize(IC_RESULT(ic));
2397 /* will try to generate an increment */
2398 /* if the right side is not a literal
2400 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2403 /* if the literal value of the right hand side
2404 is greater than 4 then it is not worth it */
2405 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2408 /* if increment 16 bits in register */
2409 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2416 /* If the next instruction is a goto and the goto target
2417 * is < 10 instructions previous to this, we can generate
2418 * jumps straight to that target.
2420 if (ic->next && ic->next->op == GOTO
2421 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2422 && labelRange <= 10 )
2424 emitcode(";", "tail increment optimized");
2425 tlbl = IC_LABEL(ic->next);
2430 tlbl = newiTempLabel(NULL);
2433 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2434 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2435 IS_AOP_PREG(IC_RESULT(ic)))
2436 emitcode("cjne","%s,#0x00,%05d$"
2437 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2440 emitcode("clr","a");
2441 emitcode("cjne","a,%s,%05d$"
2442 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2446 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2449 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2450 IS_AOP_PREG(IC_RESULT(ic)))
2451 emitcode("cjne","%s,#0x00,%05d$"
2452 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2455 emitcode("cjne","a,%s,%05d$"
2456 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2459 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2463 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2464 IS_AOP_PREG(IC_RESULT(ic)))
2465 emitcode("cjne","%s,#0x00,%05d$"
2466 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2469 emitcode("cjne","a,%s,%05d$"
2470 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2473 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2478 emitcode("","%05d$:",tlbl->key+100);
2483 /* if the sizes are greater than 1 then we cannot */
2484 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2485 AOP_SIZE(IC_LEFT(ic)) > 1 )
2488 /* we can if the aops of the left & result match or
2489 if they are in registers and the registers are the
2491 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2494 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2495 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2496 aopPut(AOP(IC_RESULT(ic)),"a",0);
2500 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2509 /*-----------------------------------------------------------------*/
2510 /* outBitAcc - output a bit in acc */
2511 /*-----------------------------------------------------------------*/
2512 static void outBitAcc(operand *result)
2514 symbol *tlbl = newiTempLabel(NULL);
2515 /* if the result is a bit */
2516 if (AOP_TYPE(result) == AOP_CRY){
2517 aopPut(AOP(result),"a",0);
2520 emitcode("jz","%05d$",tlbl->key+100);
2521 emitcode("mov","a,%s",one);
2522 emitcode("","%05d$:",tlbl->key+100);
2527 /*-----------------------------------------------------------------*/
2528 /* genPlusBits - generates code for addition of two bits */
2529 /*-----------------------------------------------------------------*/
2530 static void genPlusBits (iCode *ic)
2532 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2533 symbol *lbl = newiTempLabel(NULL);
2534 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2535 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2536 emitcode("cpl","c");
2537 emitcode("","%05d$:",(lbl->key+100));
2538 outBitC(IC_RESULT(ic));
2541 emitcode("clr","a");
2542 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2543 emitcode("rlc","a");
2544 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2545 emitcode("addc","a,#0x00");
2546 outAcc(IC_RESULT(ic));
2551 /* This is the original version of this code.
2553 * This is being kept around for reference,
2554 * because I am not entirely sure I got it right...
2556 static void adjustArithmeticResult(iCode *ic)
2558 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2559 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2560 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2561 aopPut(AOP(IC_RESULT(ic)),
2562 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2565 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2566 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
2567 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2568 aopPut(AOP(IC_RESULT(ic)),
2569 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2572 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2573 AOP_SIZE(IC_LEFT(ic)) < 3 &&
2574 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
2575 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2576 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2578 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2579 aopPut(AOP(IC_RESULT(ic)),buffer,2);
2583 /* This is the pure and virtuous version of this code.
2584 * I'm pretty certain it's right, but not enough to toss the old
2587 static void adjustArithmeticResult(iCode *ic)
2589 if (opIsGptr(IC_RESULT(ic)) &&
2590 opIsGptr(IC_LEFT(ic)) &&
2591 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2593 aopPut(AOP(IC_RESULT(ic)),
2594 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
2598 if (opIsGptr(IC_RESULT(ic)) &&
2599 opIsGptr(IC_RIGHT(ic)) &&
2600 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2602 aopPut(AOP(IC_RESULT(ic)),
2603 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
2607 if (opIsGptr(IC_RESULT(ic)) &&
2608 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2609 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2610 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2611 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2613 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2614 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2619 /*-----------------------------------------------------------------*/
2620 /* genPlus - generates code for addition */
2621 /*-----------------------------------------------------------------*/
2622 static void genPlus (iCode *ic)
2624 int size, offset = 0;
2626 /* special cases :- */
2628 aopOp (IC_LEFT(ic),ic,FALSE);
2629 aopOp (IC_RIGHT(ic),ic,FALSE);
2630 aopOp (IC_RESULT(ic),ic,TRUE);
2632 /* if literal, literal on the right or
2633 if left requires ACC or right is already
2635 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2636 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2637 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2638 operand *t = IC_RIGHT(ic);
2639 IC_RIGHT(ic) = IC_LEFT(ic);
2643 /* if both left & right are in bit
2645 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2646 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2651 /* if left in bit space & right literal */
2652 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2653 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2654 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2655 /* if result in bit space */
2656 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2657 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
2658 emitcode("cpl","c");
2659 outBitC(IC_RESULT(ic));
2661 size = getDataSize(IC_RESULT(ic));
2663 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2664 emitcode("addc","a,#00");
2665 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2671 /* if I can do an increment instead
2672 of add then GOOD for ME */
2673 if (genPlusIncr (ic) == TRUE)
2676 size = getDataSize(IC_RESULT(ic));
2679 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2680 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2682 emitcode("add","a,%s",
2683 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2685 emitcode("addc","a,%s",
2686 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2688 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2690 emitcode("add","a,%s",
2691 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2693 emitcode("addc","a,%s",
2694 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2696 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2699 adjustArithmeticResult(ic);
2702 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2703 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2704 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2707 /*-----------------------------------------------------------------*/
2708 /* genMinusDec :- does subtraction with deccrement if possible */
2709 /*-----------------------------------------------------------------*/
2710 static bool genMinusDec (iCode *ic)
2712 unsigned int icount ;
2713 unsigned int size = getDataSize(IC_RESULT(ic));
2715 /* will try to generate an increment */
2716 /* if the right side is not a literal
2718 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2721 /* if the literal value of the right hand side
2722 is greater than 4 then it is not worth it */
2723 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2726 /* if decrement 16 bits in register */
2727 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2734 /* If the next instruction is a goto and the goto target
2735 * is <= 10 instructions previous to this, we can generate
2736 * jumps straight to that target.
2738 if (ic->next && ic->next->op == GOTO
2739 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2740 && labelRange <= 10 )
2742 emitcode(";", "tail decrement optimized");
2743 tlbl = IC_LABEL(ic->next);
2748 tlbl = newiTempLabel(NULL);
2752 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2753 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2754 IS_AOP_PREG(IC_RESULT(ic)))
2755 emitcode("cjne","%s,#0xff,%05d$"
2756 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2759 emitcode("mov","a,#0xff");
2760 emitcode("cjne","a,%s,%05d$"
2761 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2764 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2767 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2768 IS_AOP_PREG(IC_RESULT(ic)))
2769 emitcode("cjne","%s,#0xff,%05d$"
2770 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2773 emitcode("cjne","a,%s,%05d$"
2774 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2777 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2781 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2782 IS_AOP_PREG(IC_RESULT(ic)))
2783 emitcode("cjne","%s,#0xff,%05d$"
2784 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2787 emitcode("cjne","a,%s,%05d$"
2788 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2791 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2795 emitcode("","%05d$:",tlbl->key+100);
2800 /* if the sizes are greater than 1 then we cannot */
2801 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2802 AOP_SIZE(IC_LEFT(ic)) > 1 )
2805 /* we can if the aops of the left & result match or
2806 if they are in registers and the registers are the
2808 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2811 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2819 /*-----------------------------------------------------------------*/
2820 /* addSign - complete with sign */
2821 /*-----------------------------------------------------------------*/
2822 static void addSign(operand *result, int offset, int sign)
2824 int size = (getDataSize(result) - offset);
2827 emitcode("rlc","a");
2828 emitcode("subb","a,acc");
2830 aopPut(AOP(result),"a",offset++);
2833 aopPut(AOP(result),zero,offset++);
2837 /*-----------------------------------------------------------------*/
2838 /* genMinusBits - generates code for subtraction of two bits */
2839 /*-----------------------------------------------------------------*/
2840 static void genMinusBits (iCode *ic)
2842 symbol *lbl = newiTempLabel(NULL);
2843 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2844 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2845 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2846 emitcode("cpl","c");
2847 emitcode("","%05d$:",(lbl->key+100));
2848 outBitC(IC_RESULT(ic));
2851 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2852 emitcode("subb","a,acc");
2853 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
2854 emitcode("inc","a");
2855 emitcode("","%05d$:",(lbl->key+100));
2856 aopPut(AOP(IC_RESULT(ic)),"a",0);
2857 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
2861 /*-----------------------------------------------------------------*/
2862 /* genMinus - generates code for subtraction */
2863 /*-----------------------------------------------------------------*/
2864 static void genMinus (iCode *ic)
2866 int size, offset = 0;
2867 unsigned long lit = 0L;
2869 aopOp (IC_LEFT(ic),ic,FALSE);
2870 aopOp (IC_RIGHT(ic),ic,FALSE);
2871 aopOp (IC_RESULT(ic),ic,TRUE);
2873 /* special cases :- */
2874 /* if both left & right are in bit space */
2875 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2876 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2881 /* if I can do an decrement instead
2882 of subtract then GOOD for ME */
2883 if (genMinusDec (ic) == TRUE)
2886 size = getDataSize(IC_RESULT(ic));
2888 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
2892 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2896 /* if literal, add a,#-lit, else normal subb */
2898 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2899 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2900 emitcode("subb","a,%s",
2901 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2903 /* first add without previous c */
2905 emitcode("add","a,#0x%02x",
2906 (unsigned int)(lit & 0x0FFL));
2908 emitcode("addc","a,#0x%02x",
2909 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
2911 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2914 adjustArithmeticResult(ic);
2917 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2918 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2919 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2923 /*-----------------------------------------------------------------*/
2924 /* genMultbits :- multiplication of bits */
2925 /*-----------------------------------------------------------------*/
2926 static void genMultbits (operand *left,
2930 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2931 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
2936 /*-----------------------------------------------------------------*/
2937 /* genMultOneByte : 8 bit multiplication & division */
2938 /*-----------------------------------------------------------------*/
2939 static void genMultOneByte (operand *left,
2943 link *opetype = operandType(result);
2948 /* (if two literals, the value is computed before) */
2949 /* if one literal, literal on the right */
2950 if (AOP_TYPE(left) == AOP_LIT){
2956 size = AOP_SIZE(result);
2957 /* signed or unsigned */
2958 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2959 l = aopGet(AOP(left),0,FALSE,FALSE);
2961 emitcode("mul","ab");
2962 /* if result size = 1, mul signed = mul unsigned */
2963 aopPut(AOP(result),"a",0);
2965 if (SPEC_USIGN(opetype)){
2966 aopPut(AOP(result),"b",1);
2968 /* for filling the MSBs */
2969 emitcode("clr","a");
2972 emitcode("mov","a,b");
2974 /* adjust the MSB if left or right neg */
2976 /* if one literal */
2977 if (AOP_TYPE(right) == AOP_LIT){
2978 /* AND literal negative */
2979 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
2980 /* adjust MSB (c==0 after mul) */
2981 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2985 lbl = newiTempLabel(NULL);
2986 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2987 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
2988 emitcode("","%05d$:",(lbl->key+100));
2989 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2990 lbl = newiTempLabel(NULL);
2991 emitcode("jc","%05d$",(lbl->key+100));
2992 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2993 emitcode("","%05d$:",(lbl->key+100));
2996 lbl = newiTempLabel(NULL);
2997 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
2998 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
2999 emitcode("","%05d$:",(lbl->key+100));
3000 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3001 lbl = newiTempLabel(NULL);
3002 emitcode("jc","%05d$",(lbl->key+100));
3003 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
3004 emitcode("","%05d$:",(lbl->key+100));
3006 aopPut(AOP(result),"a",1);
3009 emitcode("rlc","a");
3010 emitcode("subb","a,acc");
3017 aopPut(AOP(result),"a",offset++);
3021 /*-----------------------------------------------------------------*/
3022 /* genMult - generates code for multiplication */
3023 /*-----------------------------------------------------------------*/
3024 static void genMult (iCode *ic)
3026 operand *left = IC_LEFT(ic);
3027 operand *right = IC_RIGHT(ic);
3028 operand *result= IC_RESULT(ic);
3030 /* assign the amsops */
3031 aopOp (left,ic,FALSE);
3032 aopOp (right,ic,FALSE);
3033 aopOp (result,ic,TRUE);
3035 /* special cases first */
3037 if (AOP_TYPE(left) == AOP_CRY &&
3038 AOP_TYPE(right)== AOP_CRY) {
3039 genMultbits(left,right,result);
3043 /* if both are of size == 1 */
3044 if (AOP_SIZE(left) == 1 &&
3045 AOP_SIZE(right) == 1 ) {
3046 genMultOneByte(left,right,result);
3050 /* should have been converted to function call */
3054 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3055 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3056 freeAsmop(result,NULL,ic,TRUE);
3059 /*-----------------------------------------------------------------*/
3060 /* genDivbits :- division of bits */
3061 /*-----------------------------------------------------------------*/
3062 static void genDivbits (operand *left,
3069 /* the result must be bit */
3070 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3071 l = aopGet(AOP(left),0,FALSE,FALSE);
3075 emitcode("div","ab");
3076 emitcode("rrc","a");
3077 aopPut(AOP(result),"c",0);
3080 /*-----------------------------------------------------------------*/
3081 /* genDivOneByte : 8 bit division */
3082 /*-----------------------------------------------------------------*/
3083 static void genDivOneByte (operand *left,
3087 link *opetype = operandType(result);
3092 size = AOP_SIZE(result) - 1;
3094 /* signed or unsigned */
3095 if (SPEC_USIGN(opetype)) {
3096 /* unsigned is easy */
3097 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3098 l = aopGet(AOP(left),0,FALSE,FALSE);
3100 emitcode("div","ab");
3101 aopPut(AOP(result),"a",0);
3103 aopPut(AOP(result),zero,offset++);
3107 /* signed is a little bit more difficult */
3109 /* save the signs of the operands */
3110 l = aopGet(AOP(left),0,FALSE,FALSE);
3112 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3113 emitcode("push","acc"); /* save it on the stack */
3115 /* now sign adjust for both left & right */
3116 l = aopGet(AOP(right),0,FALSE,FALSE);
3118 lbl = newiTempLabel(NULL);
3119 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3120 emitcode("cpl","a");
3121 emitcode("inc","a");
3122 emitcode("","%05d$:",(lbl->key+100));
3123 emitcode("mov","b,a");
3125 /* sign adjust left side */
3126 l = aopGet(AOP(left),0,FALSE,FALSE);
3129 lbl = newiTempLabel(NULL);
3130 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3131 emitcode("cpl","a");
3132 emitcode("inc","a");
3133 emitcode("","%05d$:",(lbl->key+100));
3135 /* now the division */
3136 emitcode("div","ab");
3137 /* we are interested in the lower order
3139 emitcode("mov","b,a");
3140 lbl = newiTempLabel(NULL);
3141 emitcode("pop","acc");
3142 /* if there was an over flow we don't
3143 adjust the sign of the result */
3144 emitcode("jb","ov,%05d$",(lbl->key+100));
3145 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3147 emitcode("clr","a");
3148 emitcode("subb","a,b");
3149 emitcode("mov","b,a");
3150 emitcode("","%05d$:",(lbl->key+100));
3152 /* now we are done */
3153 aopPut(AOP(result),"b",0);
3155 emitcode("mov","c,b.7");
3156 emitcode("subb","a,acc");
3159 aopPut(AOP(result),"a",offset++);
3163 /*-----------------------------------------------------------------*/
3164 /* genDiv - generates code for division */
3165 /*-----------------------------------------------------------------*/
3166 static void genDiv (iCode *ic)
3168 operand *left = IC_LEFT(ic);
3169 operand *right = IC_RIGHT(ic);
3170 operand *result= IC_RESULT(ic);
3172 /* assign the amsops */
3173 aopOp (left,ic,FALSE);
3174 aopOp (right,ic,FALSE);
3175 aopOp (result,ic,TRUE);
3177 /* special cases first */
3179 if (AOP_TYPE(left) == AOP_CRY &&
3180 AOP_TYPE(right)== AOP_CRY) {
3181 genDivbits(left,right,result);
3185 /* if both are of size == 1 */
3186 if (AOP_SIZE(left) == 1 &&
3187 AOP_SIZE(right) == 1 ) {
3188 genDivOneByte(left,right,result);
3192 /* should have been converted to function call */
3195 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3196 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3197 freeAsmop(result,NULL,ic,TRUE);
3200 /*-----------------------------------------------------------------*/
3201 /* genModbits :- modulus of bits */
3202 /*-----------------------------------------------------------------*/
3203 static void genModbits (operand *left,
3210 /* the result must be bit */
3211 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3212 l = aopGet(AOP(left),0,FALSE,FALSE);
3216 emitcode("div","ab");
3217 emitcode("mov","a,b");
3218 emitcode("rrc","a");
3219 aopPut(AOP(result),"c",0);
3222 /*-----------------------------------------------------------------*/
3223 /* genModOneByte : 8 bit modulus */
3224 /*-----------------------------------------------------------------*/
3225 static void genModOneByte (operand *left,
3229 link *opetype = operandType(result);
3233 /* signed or unsigned */
3234 if (SPEC_USIGN(opetype)) {
3235 /* unsigned is easy */
3236 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3237 l = aopGet(AOP(left),0,FALSE,FALSE);
3239 emitcode("div","ab");
3240 aopPut(AOP(result),"b",0);
3244 /* signed is a little bit more difficult */
3246 /* save the signs of the operands */
3247 l = aopGet(AOP(left),0,FALSE,FALSE);
3250 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3251 emitcode("push","acc"); /* save it on the stack */
3253 /* now sign adjust for both left & right */
3254 l = aopGet(AOP(right),0,FALSE,FALSE);
3257 lbl = newiTempLabel(NULL);
3258 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3259 emitcode("cpl","a");
3260 emitcode("inc","a");
3261 emitcode("","%05d$:",(lbl->key+100));
3262 emitcode("mov","b,a");
3264 /* sign adjust left side */
3265 l = aopGet(AOP(left),0,FALSE,FALSE);
3268 lbl = newiTempLabel(NULL);
3269 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3270 emitcode("cpl","a");
3271 emitcode("inc","a");
3272 emitcode("","%05d$:",(lbl->key+100));
3274 /* now the multiplication */
3275 emitcode("div","ab");
3276 /* we are interested in the lower order
3278 lbl = newiTempLabel(NULL);
3279 emitcode("pop","acc");
3280 /* if there was an over flow we don't
3281 adjust the sign of the result */
3282 emitcode("jb","ov,%05d$",(lbl->key+100));
3283 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3285 emitcode("clr","a");
3286 emitcode("subb","a,b");
3287 emitcode("mov","b,a");
3288 emitcode("","%05d$:",(lbl->key+100));
3290 /* now we are done */
3291 aopPut(AOP(result),"b",0);
3295 /*-----------------------------------------------------------------*/
3296 /* genMod - generates code for division */
3297 /*-----------------------------------------------------------------*/
3298 static void genMod (iCode *ic)
3300 operand *left = IC_LEFT(ic);
3301 operand *right = IC_RIGHT(ic);
3302 operand *result= IC_RESULT(ic);
3304 /* assign the amsops */
3305 aopOp (left,ic,FALSE);
3306 aopOp (right,ic,FALSE);
3307 aopOp (result,ic,TRUE);
3309 /* special cases first */
3311 if (AOP_TYPE(left) == AOP_CRY &&
3312 AOP_TYPE(right)== AOP_CRY) {
3313 genModbits(left,right,result);
3317 /* if both are of size == 1 */
3318 if (AOP_SIZE(left) == 1 &&
3319 AOP_SIZE(right) == 1 ) {
3320 genModOneByte(left,right,result);
3324 /* should have been converted to function call */
3328 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3329 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3330 freeAsmop(result,NULL,ic,TRUE);
3333 /*-----------------------------------------------------------------*/
3334 /* genIfxJump :- will create a jump depending on the ifx */
3335 /*-----------------------------------------------------------------*/
3336 static void genIfxJump (iCode *ic, char *jval)
3339 symbol *tlbl = newiTempLabel(NULL);
3342 /* if true label then we jump if condition
3344 if ( IC_TRUE(ic) ) {
3346 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3347 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3350 /* false label is present */
3351 jlbl = IC_FALSE(ic) ;
3352 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3353 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3355 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3356 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3358 emitcode(inst,"%05d$",tlbl->key+100);
3359 emitcode("ljmp","%05d$",jlbl->key+100);
3360 emitcode("","%05d$:",tlbl->key+100);
3362 /* mark the icode as generated */
3366 /*-----------------------------------------------------------------*/
3367 /* genCmp :- greater or less than comparison */
3368 /*-----------------------------------------------------------------*/
3369 static void genCmp (operand *left,operand *right,
3370 operand *result, iCode *ifx, int sign)
3372 int size, offset = 0 ;
3373 unsigned long lit = 0L;
3375 /* if left & right are bit variables */
3376 if (AOP_TYPE(left) == AOP_CRY &&
3377 AOP_TYPE(right) == AOP_CRY ) {
3378 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3379 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3381 /* subtract right from left if at the
3382 end the carry flag is set then we know that
3383 left is greater than right */
3384 size = max(AOP_SIZE(left),AOP_SIZE(right));
3386 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3387 if((size == 1) && !sign &&
3388 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3389 symbol *lbl = newiTempLabel(NULL);
3390 emitcode("cjne","%s,%s,%05d$",
3391 aopGet(AOP(left),offset,FALSE,FALSE),
3392 aopGet(AOP(right),offset,FALSE,FALSE),
3394 emitcode("","%05d$:",lbl->key+100);
3396 if(AOP_TYPE(right) == AOP_LIT){
3397 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3398 /* optimize if(x < 0) or if(x >= 0) */
3404 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE));
3405 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3406 genIfxJump (ifx,"acc.7");
3410 emitcode("rlc","a");
3417 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3418 if (sign && size == 0) {
3419 emitcode("xrl","a,#0x80");
3420 if (AOP_TYPE(right) == AOP_LIT){
3421 unsigned long lit = (unsigned long)
3422 floatFromVal(AOP(right)->aopu.aop_lit);
3423 emitcode("subb","a,#0x%02x",
3424 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3426 emitcode("mov","b,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3427 emitcode("xrl","b,#0x80");
3428 emitcode("subb","a,b");
3431 emitcode("subb","a,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3437 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3440 /* if the result is used in the next
3441 ifx conditional branch then generate
3442 code a little differently */
3444 genIfxJump (ifx,"c");
3447 /* leave the result in acc */
3451 /*-----------------------------------------------------------------*/
3452 /* genCmpGt :- greater than comparison */
3453 /*-----------------------------------------------------------------*/
3454 static void genCmpGt (iCode *ic, iCode *ifx)
3456 operand *left, *right, *result;
3457 link *letype , *retype;
3461 right= IC_RIGHT(ic);
3462 result = IC_RESULT(ic);
3464 letype = getSpec(operandType(left));
3465 retype =getSpec(operandType(right));
3466 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3467 /* assign the amsops */
3468 aopOp (left,ic,FALSE);
3469 aopOp (right,ic,FALSE);
3470 aopOp (result,ic,TRUE);
3472 genCmp(right, left, result, ifx, sign);
3474 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3475 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3476 freeAsmop(result,NULL,ic,TRUE);
3479 /*-----------------------------------------------------------------*/
3480 /* genCmpLt - less than comparisons */
3481 /*-----------------------------------------------------------------*/
3482 static void genCmpLt (iCode *ic, iCode *ifx)
3484 operand *left, *right, *result;
3485 link *letype , *retype;
3489 right= IC_RIGHT(ic);
3490 result = IC_RESULT(ic);
3492 letype = getSpec(operandType(left));
3493 retype =getSpec(operandType(right));
3494 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3496 /* assign the amsops */
3497 aopOp (left,ic,FALSE);
3498 aopOp (right,ic,FALSE);
3499 aopOp (result,ic,TRUE);
3501 genCmp(left, right, result, ifx, sign);
3503 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3504 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3505 freeAsmop(result,NULL,ic,TRUE);
3508 /*-----------------------------------------------------------------*/
3509 /* gencjneshort - compare and jump if not equal */
3510 /*-----------------------------------------------------------------*/
3511 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3513 int size = max(AOP_SIZE(left),AOP_SIZE(right));
3515 unsigned long lit = 0L;
3517 /* if the left side is a literal or
3518 if the right is in a pointer register and left
3520 if ((AOP_TYPE(left) == AOP_LIT) ||
3521 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3526 if(AOP_TYPE(right) == AOP_LIT)
3527 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3529 /* if the right side is a literal then anything goes */
3530 if (AOP_TYPE(right) == AOP_LIT &&
3531 AOP_TYPE(left) != AOP_DIR ) {
3533 emitcode("cjne","%s,%s,%05d$",
3534 aopGet(AOP(left),offset,FALSE,FALSE),
3535 aopGet(AOP(right),offset,FALSE,FALSE),
3541 /* if the right side is in a register or in direct space or
3542 if the left is a pointer register & right is not */
3543 else if (AOP_TYPE(right) == AOP_REG ||
3544 AOP_TYPE(right) == AOP_DIR ||
3545 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3546 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3548 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3549 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3550 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
3551 emitcode("jnz","%05d$",lbl->key+100);
3553 emitcode("cjne","a,%s,%05d$",
3554 aopGet(AOP(right),offset,FALSE,TRUE),
3559 /* right is a pointer reg need both a & b */
3561 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
3563 emitcode("mov","b,%s",l);
3564 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3565 emitcode("cjne","a,b,%05d$",lbl->key+100);
3571 /*-----------------------------------------------------------------*/
3572 /* gencjne - compare and jump if not equal */
3573 /*-----------------------------------------------------------------*/
3574 static void gencjne(operand *left, operand *right, symbol *lbl)
3576 symbol *tlbl = newiTempLabel(NULL);
3578 gencjneshort(left, right, lbl);
3580 emitcode("mov","a,%s",one);
3581 emitcode("sjmp","%05d$",tlbl->key+100);
3582 emitcode("","%05d$:",lbl->key+100);
3583 emitcode("clr","a");
3584 emitcode("","%05d$:",tlbl->key+100);
3587 /*-----------------------------------------------------------------*/
3588 /* genCmpEq - generates code for equal to */
3589 /*-----------------------------------------------------------------*/
3590 static void genCmpEq (iCode *ic, iCode *ifx)
3592 operand *left, *right, *result;
3594 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3595 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3596 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3598 /* if literal, literal on the right or
3599 if the right is in a pointer register and left
3601 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
3602 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3603 operand *t = IC_RIGHT(ic);
3604 IC_RIGHT(ic) = IC_LEFT(ic);
3608 if(ifx && !AOP_SIZE(result)){
3610 /* if they are both bit variables */
3611 if (AOP_TYPE(left) == AOP_CRY &&
3612 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3613 if(AOP_TYPE(right) == AOP_LIT){
3614 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3616 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3617 emitcode("cpl","c");
3618 } else if(lit == 1L) {
3619 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3621 emitcode("clr","c");
3623 /* AOP_TYPE(right) == AOP_CRY */
3625 symbol *lbl = newiTempLabel(NULL);
3626 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3627 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3628 emitcode("cpl","c");
3629 emitcode("","%05d$:",(lbl->key+100));
3631 /* if true label then we jump if condition
3633 tlbl = newiTempLabel(NULL);
3634 if ( IC_TRUE(ifx) ) {
3635 emitcode("jnc","%05d$",tlbl->key+100);
3636 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3638 emitcode("jc","%05d$",tlbl->key+100);
3639 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3641 emitcode("","%05d$:",tlbl->key+100);
3643 tlbl = newiTempLabel(NULL);
3644 gencjneshort(left, right, tlbl);
3645 if ( IC_TRUE(ifx) ) {
3646 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3647 emitcode("","%05d$:",tlbl->key+100);
3649 symbol *lbl = newiTempLabel(NULL);
3650 emitcode("sjmp","%05d$",lbl->key+100);
3651 emitcode("","%05d$:",tlbl->key+100);
3652 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3653 emitcode("","%05d$:",lbl->key+100);
3656 /* mark the icode as generated */
3661 /* if they are both bit variables */
3662 if (AOP_TYPE(left) == AOP_CRY &&
3663 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3664 if(AOP_TYPE(right) == AOP_LIT){
3665 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3667 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3668 emitcode("cpl","c");
3669 } else if(lit == 1L) {
3670 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3672 emitcode("clr","c");
3674 /* AOP_TYPE(right) == AOP_CRY */
3676 symbol *lbl = newiTempLabel(NULL);
3677 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3678 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3679 emitcode("cpl","c");
3680 emitcode("","%05d$:",(lbl->key+100));
3683 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
3688 genIfxJump (ifx,"c");
3691 /* if the result is used in an arithmetic operation
3692 then put the result in place */
3695 gencjne(left,right,newiTempLabel(NULL));
3696 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3697 aopPut(AOP(result),"a",0);
3701 genIfxJump (ifx,"a");
3704 /* if the result is used in an arithmetic operation
3705 then put the result in place */
3706 if (AOP_TYPE(result) != AOP_CRY)
3708 /* leave the result in acc */
3712 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3713 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3714 freeAsmop(result,NULL,ic,TRUE);
3717 /*-----------------------------------------------------------------*/
3718 /* ifxForOp - returns the icode containing the ifx for operand */
3719 /*-----------------------------------------------------------------*/
3720 static iCode *ifxForOp ( operand *op, iCode *ic )
3722 /* if true symbol then needs to be assigned */
3723 if (IS_TRUE_SYMOP(op))
3726 /* if this has register type condition and
3727 the next instruction is ifx with the same operand
3728 and live to of the operand is upto the ifx only then */
3730 ic->next->op == IFX &&
3731 IC_COND(ic->next)->key == op->key &&
3732 OP_SYMBOL(op)->liveTo <= ic->next->seq )
3737 /*-----------------------------------------------------------------*/
3738 /* genAndOp - for && operation */
3739 /*-----------------------------------------------------------------*/
3740 static void genAndOp (iCode *ic)
3742 operand *left,*right, *result;
3745 /* note here that && operations that are in an
3746 if statement are taken away by backPatchLabels
3747 only those used in arthmetic operations remain */
3748 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3749 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3750 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3752 /* if both are bit variables */
3753 if (AOP_TYPE(left) == AOP_CRY &&
3754 AOP_TYPE(right) == AOP_CRY ) {
3755 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3756 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3759 tlbl = newiTempLabel(NULL);
3761 emitcode("jz","%05d$",tlbl->key+100);
3763 emitcode("","%05d$:",tlbl->key+100);
3767 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3768 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3769 freeAsmop(result,NULL,ic,TRUE);
3773 /*-----------------------------------------------------------------*/
3774 /* genOrOp - for || operation */
3775 /*-----------------------------------------------------------------*/
3776 static void genOrOp (iCode *ic)
3778 operand *left,*right, *result;
3781 /* note here that || operations that are in an
3782 if statement are taken away by backPatchLabels
3783 only those used in arthmetic operations remain */
3784 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3785 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3786 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3788 /* if both are bit variables */
3789 if (AOP_TYPE(left) == AOP_CRY &&
3790 AOP_TYPE(right) == AOP_CRY ) {
3791 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3792 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
3795 tlbl = newiTempLabel(NULL);
3797 emitcode("jnz","%05d$",tlbl->key+100);
3799 emitcode("","%05d$:",tlbl->key+100);
3803 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3804 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3805 freeAsmop(result,NULL,ic,TRUE);
3808 /*-----------------------------------------------------------------*/
3809 /* isLiteralBit - test if lit == 2^n */
3810 /*-----------------------------------------------------------------*/
3811 static int isLiteralBit(unsigned long lit)
3813 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
3814 0x100L,0x200L,0x400L,0x800L,
3815 0x1000L,0x2000L,0x4000L,0x8000L,
3816 0x10000L,0x20000L,0x40000L,0x80000L,
3817 0x100000L,0x200000L,0x400000L,0x800000L,
3818 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
3819 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
3822 for(idx = 0; idx < 32; idx++)
3828 /*-----------------------------------------------------------------*/
3829 /* continueIfTrue - */
3830 /*-----------------------------------------------------------------*/
3831 static void continueIfTrue (iCode *ic)
3834 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3838 /*-----------------------------------------------------------------*/
3840 /*-----------------------------------------------------------------*/
3841 static void jumpIfTrue (iCode *ic)
3844 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3848 /*-----------------------------------------------------------------*/
3849 /* jmpTrueOrFalse - */
3850 /*-----------------------------------------------------------------*/
3851 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
3853 // ugly but optimized by peephole
3855 symbol *nlbl = newiTempLabel(NULL);
3856 emitcode("sjmp","%05d$",nlbl->key+100);
3857 emitcode("","%05d$:",tlbl->key+100);
3858 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3859 emitcode("","%05d$:",nlbl->key+100);
3862 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3863 emitcode("","%05d$:",tlbl->key+100);
3868 /*-----------------------------------------------------------------*/
3869 /* genAnd - code for and */
3870 /*-----------------------------------------------------------------*/
3871 static void genAnd (iCode *ic, iCode *ifx)
3873 operand *left, *right, *result;
3875 unsigned long lit = 0L;
3879 aopOp((left = IC_LEFT(ic)),ic,FALSE);
3880 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3881 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3884 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3886 AOP_TYPE(left), AOP_TYPE(right));
3887 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3889 AOP_SIZE(left), AOP_SIZE(right));
3892 /* if left is a literal & right is not then exchange them */
3893 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3894 AOP_NEEDSACC(left)) {
3895 operand *tmp = right ;
3900 /* if result = right then exchange them */
3901 if(sameRegs(AOP(result),AOP(right))){
3902 operand *tmp = right ;
3907 /* if right is bit then exchange them */
3908 if (AOP_TYPE(right) == AOP_CRY &&
3909 AOP_TYPE(left) != AOP_CRY){
3910 operand *tmp = right ;
3914 if(AOP_TYPE(right) == AOP_LIT)
3915 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3917 size = AOP_SIZE(result);
3920 // result = bit & yy;
3921 if (AOP_TYPE(left) == AOP_CRY){
3922 // c = bit & literal;
3923 if(AOP_TYPE(right) == AOP_LIT){
3925 if(size && sameRegs(AOP(result),AOP(left)))
3928 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3931 if(size && (AOP_TYPE(result) == AOP_CRY)){
3932 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
3935 if((AOP_TYPE(result) == AOP_CRY) && ifx){
3939 emitcode("clr","c");
3942 if (AOP_TYPE(right) == AOP_CRY){
3944 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3945 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3948 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
3950 emitcode("rrc","a");
3951 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3959 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
3960 genIfxJump(ifx, "c");
3964 // if(val & 0xZZ) - size = 0, ifx != FALSE -
3965 // bit = val & 0xZZ - size = 1, ifx = FALSE -
3966 if((AOP_TYPE(right) == AOP_LIT) &&
3967 (AOP_TYPE(result) == AOP_CRY) &&
3968 (AOP_TYPE(left) != AOP_CRY)){
3969 int posbit = isLiteralBit(lit);
3973 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
3976 emitcode("mov","c,acc.%d",posbit&0x07);
3980 sprintf(buffer,"acc.%d",posbit&0x07);
3981 genIfxJump(ifx, buffer);
3986 symbol *tlbl = newiTempLabel(NULL);
3987 int sizel = AOP_SIZE(left);
3989 emitcode("setb","c");
3991 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
3992 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
3994 if((posbit = isLiteralBit(bytelit)) != 0)
3995 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
3997 if(bytelit != 0x0FFL)
3998 emitcode("anl","a,%s",
3999 aopGet(AOP(right),offset,FALSE,TRUE));
4000 emitcode("jnz","%05d$",tlbl->key+100);
4005 // bit = left & literal
4007 emitcode("clr","c");
4008 emitcode("","%05d$:",tlbl->key+100);
4010 // if(left & literal)
4013 jmpTrueOrFalse(ifx, tlbl);
4021 /* if left is same as result */
4022 if(sameRegs(AOP(result),AOP(left))){
4023 for(;size--; offset++) {
4024 if(AOP_TYPE(right) == AOP_LIT){
4025 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4029 aopPut(AOP(result),zero,offset);
4031 if (IS_AOP_PREG(result)) {
4032 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4033 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4034 aopPut(AOP(result),"a",offset);
4036 emitcode("anl","%s,%s",
4037 aopGet(AOP(left),offset,FALSE,TRUE),
4038 aopGet(AOP(right),offset,FALSE,FALSE));
4040 if (AOP_TYPE(left) == AOP_ACC)
4041 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4043 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4044 if (IS_AOP_PREG(result)) {
4045 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4046 aopPut(AOP(result),"a",offset);
4049 emitcode("anl","%s,a",
4050 aopGet(AOP(left),offset,FALSE,TRUE));
4055 // left & result in different registers
4056 if(AOP_TYPE(result) == AOP_CRY){
4058 // if(size), result in bit
4059 // if(!size && ifx), conditional oper: if(left & right)
4060 symbol *tlbl = newiTempLabel(NULL);
4061 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4063 emitcode("setb","c");
4065 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4066 emitcode("anl","a,%s",
4067 aopGet(AOP(left),offset,FALSE,FALSE));
4068 emitcode("jnz","%05d$",tlbl->key+100);
4073 emitcode("","%05d$:",tlbl->key+100);
4076 jmpTrueOrFalse(ifx, tlbl);
4078 for(;(size--);offset++) {
4080 // result = left & right
4081 if(AOP_TYPE(right) == AOP_LIT){
4082 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
4084 aopGet(AOP(left),offset,FALSE,FALSE),
4087 } else if(bytelit == 0){
4088 aopPut(AOP(result),zero,offset);
4092 // faster than result <- left, anl result,right
4093 // and better if result is SFR
4094 if (AOP_TYPE(left) == AOP_ACC)
4095 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4097 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4098 emitcode("anl","a,%s",
4099 aopGet(AOP(left),offset,FALSE,FALSE));
4101 aopPut(AOP(result),"a",offset);
4107 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4108 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4109 freeAsmop(result,NULL,ic,TRUE);
4112 /*-----------------------------------------------------------------*/
4113 /* genOr - code for or */
4114 /*-----------------------------------------------------------------*/
4115 static void genOr (iCode *ic, iCode *ifx)
4117 operand *left, *right, *result;
4119 unsigned long lit = 0L;
4121 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4122 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4123 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4126 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4128 AOP_TYPE(left), AOP_TYPE(right));
4129 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4131 AOP_SIZE(left), AOP_SIZE(right));
4134 /* if left is a literal & right is not then exchange them */
4135 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4136 AOP_NEEDSACC(left)) {
4137 operand *tmp = right ;
4142 /* if result = right then exchange them */
4143 if(sameRegs(AOP(result),AOP(right))){
4144 operand *tmp = right ;
4149 /* if right is bit then exchange them */
4150 if (AOP_TYPE(right) == AOP_CRY &&
4151 AOP_TYPE(left) != AOP_CRY){
4152 operand *tmp = right ;
4156 if(AOP_TYPE(right) == AOP_LIT)
4157 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4159 size = AOP_SIZE(result);
4163 if (AOP_TYPE(left) == AOP_CRY){
4164 if(AOP_TYPE(right) == AOP_LIT){
4165 // c = bit & literal;
4167 // lit != 0 => result = 1
4168 if(AOP_TYPE(result) == AOP_CRY){
4170 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4172 continueIfTrue(ifx);
4175 emitcode("setb","c");
4177 // lit == 0 => result = left
4178 if(size && sameRegs(AOP(result),AOP(left)))
4180 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4183 if (AOP_TYPE(right) == AOP_CRY){
4185 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4186 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4190 symbol *tlbl = newiTempLabel(NULL);
4191 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4192 emitcode("setb","c");
4193 emitcode("jb","%s,%05d$",
4194 AOP(left)->aopu.aop_dir,tlbl->key+100);
4196 emitcode("jnz","%05d$",tlbl->key+100);
4197 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4198 jmpTrueOrFalse(ifx, tlbl);
4202 emitcode("","%05d$:",tlbl->key+100);
4211 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4212 genIfxJump(ifx, "c");
4216 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4217 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4218 if((AOP_TYPE(right) == AOP_LIT) &&
4219 (AOP_TYPE(result) == AOP_CRY) &&
4220 (AOP_TYPE(left) != AOP_CRY)){
4224 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4226 continueIfTrue(ifx);
4229 // lit = 0, result = boolean(left)
4231 emitcode("setb","c");
4234 symbol *tlbl = newiTempLabel(NULL);
4235 emitcode("jnz","%05d$",tlbl->key+100);
4237 emitcode("","%05d$:",tlbl->key+100);
4239 genIfxJump (ifx,"a");
4247 /* if left is same as result */
4248 if(sameRegs(AOP(result),AOP(left))){
4249 for(;size--; offset++) {
4250 if(AOP_TYPE(right) == AOP_LIT){
4251 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4254 if (IS_AOP_PREG(left)) {
4255 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4256 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4257 aopPut(AOP(result),"a",offset);
4259 emitcode("orl","%s,%s",
4260 aopGet(AOP(left),offset,FALSE,TRUE),
4261 aopGet(AOP(right),offset,FALSE,FALSE));
4263 if (AOP_TYPE(left) == AOP_ACC)
4264 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4266 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4267 if (IS_AOP_PREG(left)) {
4268 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4269 aopPut(AOP(result),"a",offset);
4271 emitcode("orl","%s,a",
4272 aopGet(AOP(left),offset,FALSE,TRUE));
4277 // left & result in different registers
4278 if(AOP_TYPE(result) == AOP_CRY){
4280 // if(size), result in bit
4281 // if(!size && ifx), conditional oper: if(left | right)
4282 symbol *tlbl = newiTempLabel(NULL);
4283 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4285 emitcode("setb","c");
4287 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4288 emitcode("orl","a,%s",
4289 aopGet(AOP(left),offset,FALSE,FALSE));
4290 emitcode("jnz","%05d$",tlbl->key+100);
4295 emitcode("","%05d$:",tlbl->key+100);
4298 jmpTrueOrFalse(ifx, tlbl);
4299 } else for(;(size--);offset++){
4301 // result = left & right
4302 if(AOP_TYPE(right) == AOP_LIT){
4303 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4305 aopGet(AOP(left),offset,FALSE,FALSE),
4310 // faster than result <- left, anl result,right
4311 // and better if result is SFR
4312 if (AOP_TYPE(left) == AOP_ACC)
4313 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4315 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4316 emitcode("orl","a,%s",
4317 aopGet(AOP(left),offset,FALSE,FALSE));
4319 aopPut(AOP(result),"a",offset);
4324 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4325 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4326 freeAsmop(result,NULL,ic,TRUE);
4329 /*-----------------------------------------------------------------*/
4330 /* genXor - code for xclusive or */
4331 /*-----------------------------------------------------------------*/
4332 static void genXor (iCode *ic, iCode *ifx)
4334 operand *left, *right, *result;
4336 unsigned long lit = 0L;
4338 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4339 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4340 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4343 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4345 AOP_TYPE(left), AOP_TYPE(right));
4346 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4348 AOP_SIZE(left), AOP_SIZE(right));
4351 /* if left is a literal & right is not ||
4352 if left needs acc & right does not */
4353 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4354 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4355 operand *tmp = right ;
4360 /* if result = right then exchange them */
4361 if(sameRegs(AOP(result),AOP(right))){
4362 operand *tmp = right ;
4367 /* if right is bit then exchange them */
4368 if (AOP_TYPE(right) == AOP_CRY &&
4369 AOP_TYPE(left) != AOP_CRY){
4370 operand *tmp = right ;
4374 if(AOP_TYPE(right) == AOP_LIT)
4375 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4377 size = AOP_SIZE(result);
4381 if (AOP_TYPE(left) == AOP_CRY){
4382 if(AOP_TYPE(right) == AOP_LIT){
4383 // c = bit & literal;
4385 // lit>>1 != 0 => result = 1
4386 if(AOP_TYPE(result) == AOP_CRY){
4388 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4390 continueIfTrue(ifx);
4393 emitcode("setb","c");
4397 // lit == 0, result = left
4398 if(size && sameRegs(AOP(result),AOP(left)))
4400 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4402 // lit == 1, result = not(left)
4403 if(size && sameRegs(AOP(result),AOP(left))){
4404 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4407 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4408 emitcode("cpl","c");
4415 symbol *tlbl = newiTempLabel(NULL);
4416 if (AOP_TYPE(right) == AOP_CRY){
4418 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4421 int sizer = AOP_SIZE(right);
4423 // if val>>1 != 0, result = 1
4424 emitcode("setb","c");
4426 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
4428 // test the msb of the lsb
4429 emitcode("anl","a,#0xfe");
4430 emitcode("jnz","%05d$",tlbl->key+100);
4434 emitcode("rrc","a");
4436 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4437 emitcode("cpl","c");
4438 emitcode("","%05d$:",(tlbl->key+100));
4445 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4446 genIfxJump(ifx, "c");
4450 if(sameRegs(AOP(result),AOP(left))){
4451 /* if left is same as result */
4452 for(;size--; offset++) {
4453 if(AOP_TYPE(right) == AOP_LIT){
4454 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4457 if (IS_AOP_PREG(left)) {
4458 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4459 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4460 aopPut(AOP(result),"a",offset);
4462 emitcode("xrl","%s,%s",
4463 aopGet(AOP(left),offset,FALSE,TRUE),
4464 aopGet(AOP(right),offset,FALSE,FALSE));
4466 if (AOP_TYPE(left) == AOP_ACC)
4467 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4469 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4470 if (IS_AOP_PREG(left)) {
4471 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4472 aopPut(AOP(result),"a",offset);
4474 emitcode("xrl","%s,a",
4475 aopGet(AOP(left),offset,FALSE,TRUE));
4480 // left & result in different registers
4481 if(AOP_TYPE(result) == AOP_CRY){
4483 // if(size), result in bit
4484 // if(!size && ifx), conditional oper: if(left ^ right)
4485 symbol *tlbl = newiTempLabel(NULL);
4486 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4488 emitcode("setb","c");
4490 if((AOP_TYPE(right) == AOP_LIT) &&
4491 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4492 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4494 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4495 emitcode("xrl","a,%s",
4496 aopGet(AOP(left),offset,FALSE,FALSE));
4498 emitcode("jnz","%05d$",tlbl->key+100);
4503 emitcode("","%05d$:",tlbl->key+100);
4506 jmpTrueOrFalse(ifx, tlbl);
4507 } else for(;(size--);offset++){
4509 // result = left & right
4510 if(AOP_TYPE(right) == AOP_LIT){
4511 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4513 aopGet(AOP(left),offset,FALSE,FALSE),
4518 // faster than result <- left, anl result,right
4519 // and better if result is SFR
4520 if (AOP_TYPE(left) == AOP_ACC)
4521 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4523 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4524 emitcode("xrl","a,%s",
4525 aopGet(AOP(left),offset,FALSE,TRUE));
4527 aopPut(AOP(result),"a",offset);
4532 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4533 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4534 freeAsmop(result,NULL,ic,TRUE);
4537 /*-----------------------------------------------------------------*/
4538 /* genInline - write the inline code out */
4539 /*-----------------------------------------------------------------*/
4540 static void genInline (iCode *ic)
4542 char buffer[MAX_INLINEASM];
4546 _G.inLine += (!options.asmpeep);
4547 strcpy(buffer,IC_INLINE(ic));
4549 /* emit each line as a code */
4568 /* emitcode("",buffer); */
4569 _G.inLine -= (!options.asmpeep);
4572 /*-----------------------------------------------------------------*/
4573 /* genRRC - rotate right with carry */
4574 /*-----------------------------------------------------------------*/
4575 static void genRRC (iCode *ic)
4577 operand *left , *result ;
4578 int size, offset = 0;
4581 /* rotate right with carry */
4583 result=IC_RESULT(ic);
4584 aopOp (left,ic,FALSE);
4585 aopOp (result,ic,FALSE);
4587 /* move it to the result */
4588 size = AOP_SIZE(result);
4592 l = aopGet(AOP(left),offset,FALSE,FALSE);
4594 emitcode("rrc","a");
4595 if (AOP_SIZE(result) > 1)
4596 aopPut(AOP(result),"a",offset--);
4598 /* now we need to put the carry into the
4599 highest order byte of the result */
4600 if (AOP_SIZE(result) > 1) {
4601 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
4604 emitcode("mov","acc.7,c");
4605 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
4606 freeAsmop(left,NULL,ic,TRUE);
4607 freeAsmop(result,NULL,ic,TRUE);
4610 /*-----------------------------------------------------------------*/
4611 /* genRLC - generate code for rotate left with carry */
4612 /*-----------------------------------------------------------------*/
4613 static void genRLC (iCode *ic)
4615 operand *left , *result ;
4616 int size, offset = 0;
4619 /* rotate right with carry */
4621 result=IC_RESULT(ic);
4622 aopOp (left,ic,FALSE);
4623 aopOp (result,ic,FALSE);
4625 /* move it to the result */
4626 size = AOP_SIZE(result);
4629 l = aopGet(AOP(left),offset,FALSE,FALSE);
4631 emitcode("add","a,acc");
4632 if (AOP_SIZE(result) > 1)
4633 aopPut(AOP(result),"a",offset++);
4635 l = aopGet(AOP(left),offset,FALSE,FALSE);
4637 emitcode("rlc","a");
4638 if (AOP_SIZE(result) > 1)
4639 aopPut(AOP(result),"a",offset++);
4642 /* now we need to put the carry into the
4643 highest order byte of the result */
4644 if (AOP_SIZE(result) > 1) {
4645 l = aopGet(AOP(result),0,FALSE,FALSE);
4648 emitcode("mov","acc.0,c");
4649 aopPut(AOP(result),"a",0);
4650 freeAsmop(left,NULL,ic,TRUE);
4651 freeAsmop(result,NULL,ic,TRUE);
4654 /*-----------------------------------------------------------------*/
4655 /* genGetHbit - generates code get highest order bit */
4656 /*-----------------------------------------------------------------*/
4657 static void genGetHbit (iCode *ic)
4659 operand *left, *result;
4661 result=IC_RESULT(ic);
4662 aopOp (left,ic,FALSE);
4663 aopOp (result,ic,FALSE);
4665 /* get the highest order byte into a */
4666 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
4667 if(AOP_TYPE(result) == AOP_CRY){
4668 emitcode("rlc","a");
4673 emitcode("anl","a,#0x01");
4678 freeAsmop(left,NULL,ic,TRUE);
4679 freeAsmop(result,NULL,ic,TRUE);
4682 /*-----------------------------------------------------------------*/
4683 /* AccRol - rotate left accumulator by known count */
4684 /*-----------------------------------------------------------------*/
4685 static void AccRol (int shCount)
4687 shCount &= 0x0007; // shCount : 0..7
4699 emitcode("swap","a");
4703 emitcode("swap","a");
4706 emitcode("swap","a");
4719 /*-----------------------------------------------------------------*/
4720 /* AccLsh - left shift accumulator by known count */
4721 /*-----------------------------------------------------------------*/
4722 static void AccLsh (int shCount)
4726 emitcode("add","a,acc");
4729 emitcode("add","a,acc");
4730 emitcode("add","a,acc");
4732 /* rotate left accumulator */
4734 /* and kill the lower order bits */
4735 emitcode("anl","a,#0x%02x", SLMask[shCount]);
4740 /*-----------------------------------------------------------------*/
4741 /* AccRsh - right shift accumulator by known count */
4742 /*-----------------------------------------------------------------*/
4743 static void AccRsh (int shCount)
4748 emitcode("rrc","a");
4750 /* rotate right accumulator */
4751 AccRol(8 - shCount);
4752 /* and kill the higher order bits */
4753 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4758 /*-----------------------------------------------------------------*/
4759 /* AccSRsh - signed right shift accumulator by known count */
4760 /*-----------------------------------------------------------------*/
4761 static void AccSRsh (int shCount)
4766 emitcode("mov","c,acc.7");
4767 emitcode("rrc","a");
4768 } else if(shCount == 2){
4769 emitcode("mov","c,acc.7");
4770 emitcode("rrc","a");
4771 emitcode("mov","c,acc.7");
4772 emitcode("rrc","a");
4774 tlbl = newiTempLabel(NULL);
4775 /* rotate right accumulator */
4776 AccRol(8 - shCount);
4777 /* and kill the higher order bits */
4778 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4779 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4780 emitcode("orl","a,#0x%02x",
4781 (unsigned char)~SRMask[shCount]);
4782 emitcode("","%05d$:",tlbl->key+100);
4787 /*-----------------------------------------------------------------*/
4788 /* shiftR1Left2Result - shift right one byte from left to result */
4789 /*-----------------------------------------------------------------*/
4790 static void shiftR1Left2Result (operand *left, int offl,
4791 operand *result, int offr,
4792 int shCount, int sign)
4794 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4795 /* shift right accumulator */
4800 aopPut(AOP(result),"a",offr);
4803 /*-----------------------------------------------------------------*/
4804 /* shiftL1Left2Result - shift left one byte from left to result */
4805 /*-----------------------------------------------------------------*/
4806 static void shiftL1Left2Result (operand *left, int offl,
4807 operand *result, int offr, int shCount)
4810 l = aopGet(AOP(left),offl,FALSE,FALSE);
4812 /* shift left accumulator */
4814 aopPut(AOP(result),"a",offr);
4817 /*-----------------------------------------------------------------*/
4818 /* movLeft2Result - move byte from left to result */
4819 /*-----------------------------------------------------------------*/
4820 static void movLeft2Result (operand *left, int offl,
4821 operand *result, int offr, int sign)
4824 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
4825 l = aopGet(AOP(left),offl,FALSE,FALSE);
4827 if (*l == '@' && (IS_AOP_PREG(result))) {
4828 emitcode("mov","a,%s",l);
4829 aopPut(AOP(result),"a",offr);
4832 aopPut(AOP(result),l,offr);
4834 /* MSB sign in acc.7 ! */
4835 if(getDataSize(left) == offl+1){
4836 emitcode("mov","a,%s",l);
4837 aopPut(AOP(result),"a",offr);
4844 /*-----------------------------------------------------------------*/
4845 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
4846 /*-----------------------------------------------------------------*/
4847 static void AccAXRrl1 (char *x)
4849 emitcode("rrc","a");
4850 emitcode("xch","a,%s", x);
4851 emitcode("rrc","a");
4852 emitcode("xch","a,%s", x);
4855 /*-----------------------------------------------------------------*/
4856 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
4857 /*-----------------------------------------------------------------*/
4858 static void AccAXLrl1 (char *x)
4860 emitcode("xch","a,%s",x);
4861 emitcode("rlc","a");
4862 emitcode("xch","a,%s",x);
4863 emitcode("rlc","a");
4866 /*-----------------------------------------------------------------*/
4867 /* AccAXLsh1 - left shift a:x<-0 by 1 */
4868 /*-----------------------------------------------------------------*/
4869 static void AccAXLsh1 (char *x)
4871 emitcode("xch","a,%s",x);
4872 emitcode("add","a,acc");
4873 emitcode("xch","a,%s",x);
4874 emitcode("rlc","a");
4877 /*-----------------------------------------------------------------*/
4878 /* AccAXLsh - left shift a:x by known count (0..7) */
4879 /*-----------------------------------------------------------------*/
4880 static void AccAXLsh (char *x, int shCount)
4894 case 5 : // AAAAABBB:CCCCCDDD
4895 AccRol(shCount); // BBBAAAAA:CCCCCDDD
4896 emitcode("anl","a,#0x%02x",
4897 SLMask[shCount]); // BBB00000:CCCCCDDD
4898 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
4899 AccRol(shCount); // DDDCCCCC:BBB00000
4900 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
4901 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
4902 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
4903 emitcode("anl","a,#0x%02x",
4904 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
4905 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
4906 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
4908 case 6 : // AAAAAABB:CCCCCCDD
4909 emitcode("anl","a,#0x%02x",
4910 SRMask[shCount]); // 000000BB:CCCCCCDD
4911 emitcode("mov","c,acc.0"); // c = B
4912 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
4913 AccAXRrl1(x); // BCCCCCCD:D000000B
4914 AccAXRrl1(x); // BBCCCCCC:DD000000
4916 case 7 : // a:x <<= 7
4917 emitcode("anl","a,#0x%02x",
4918 SRMask[shCount]); // 0000000B:CCCCCCCD
4919 emitcode("mov","c,acc.0"); // c = B
4920 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
4921 AccAXRrl1(x); // BCCCCCCC:D0000000
4928 /*-----------------------------------------------------------------*/
4929 /* AccAXRsh - right shift a:x known count (0..7) */
4930 /*-----------------------------------------------------------------*/
4931 static void AccAXRsh (char *x, int shCount)
4938 AccAXRrl1(x); // 0->a:x
4942 AccAXRrl1(x); // 0->a:x
4944 AccAXRrl1(x); // 0->a:x
4948 case 5 : // AAAAABBB:CCCCCDDD = a:x
4949 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
4950 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
4951 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
4952 emitcode("anl","a,#0x%02x",
4953 SRMask[shCount]); // 000CCCCC:BBBAAAAA
4954 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
4955 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
4956 emitcode("anl","a,#0x%02x",
4957 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
4958 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
4959 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
4960 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
4962 case 6 : // AABBBBBB:CCDDDDDD
4963 emitcode("mov","c,acc.7");
4964 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
4965 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
4966 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
4967 emitcode("anl","a,#0x%02x",
4968 SRMask[shCount]); // 000000AA:BBBBBBCC
4970 case 7 : // ABBBBBBB:CDDDDDDD
4971 emitcode("mov","c,acc.7"); // c = A
4972 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
4973 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
4974 emitcode("anl","a,#0x%02x",
4975 SRMask[shCount]); // 0000000A:BBBBBBBC
4982 /*-----------------------------------------------------------------*/
4983 /* AccAXRshS - right shift signed a:x known count (0..7) */
4984 /*-----------------------------------------------------------------*/
4985 static void AccAXRshS (char *x, int shCount)
4992 emitcode("mov","c,acc.7");
4993 AccAXRrl1(x); // s->a:x
4996 emitcode("mov","c,acc.7");
4997 AccAXRrl1(x); // s->a:x
4998 emitcode("mov","c,acc.7");
4999 AccAXRrl1(x); // s->a:x
5003 case 5 : // AAAAABBB:CCCCCDDD = a:x
5004 tlbl = newiTempLabel(NULL);
5005 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5006 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5007 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5008 emitcode("anl","a,#0x%02x",
5009 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5010 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5011 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5012 emitcode("anl","a,#0x%02x",
5013 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5014 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5015 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5016 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5017 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5018 emitcode("orl","a,#0x%02x",
5019 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5020 emitcode("","%05d$:",tlbl->key+100);
5021 break; // SSSSAAAA:BBBCCCCC
5022 case 6 : // AABBBBBB:CCDDDDDD
5023 tlbl = newiTempLabel(NULL);
5024 emitcode("mov","c,acc.7");
5025 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5026 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5027 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5028 emitcode("anl","a,#0x%02x",
5029 SRMask[shCount]); // 000000AA:BBBBBBCC
5030 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5031 emitcode("orl","a,#0x%02x",
5032 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5033 emitcode("","%05d$:",tlbl->key+100);
5035 case 7 : // ABBBBBBB:CDDDDDDD
5036 tlbl = newiTempLabel(NULL);
5037 emitcode("mov","c,acc.7"); // c = A
5038 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5039 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5040 emitcode("anl","a,#0x%02x",
5041 SRMask[shCount]); // 0000000A:BBBBBBBC
5042 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5043 emitcode("orl","a,#0x%02x",
5044 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5045 emitcode("","%05d$:",tlbl->key+100);
5052 /*-----------------------------------------------------------------*/
5053 /* shiftL2Left2Result - shift left two bytes from left to result */
5054 /*-----------------------------------------------------------------*/
5055 static void shiftL2Left2Result (operand *left, int offl,
5056 operand *result, int offr, int shCount)
5058 if(sameRegs(AOP(result), AOP(left)) &&
5059 ((offl + MSB16) == offr)){
5060 /* don't crash result[offr] */
5061 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5062 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5064 movLeft2Result(left,offl, result, offr, 0);
5065 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5067 /* ax << shCount (x = lsb(result))*/
5068 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5069 aopPut(AOP(result),"a",offr+MSB16);
5073 /*-----------------------------------------------------------------*/
5074 /* shiftR2Left2Result - shift right two bytes from left to result */
5075 /*-----------------------------------------------------------------*/
5076 static void shiftR2Left2Result (operand *left, int offl,
5077 operand *result, int offr,
5078 int shCount, int sign)
5080 if(sameRegs(AOP(result), AOP(left)) &&
5081 ((offl + MSB16) == offr)){
5082 /* don't crash result[offr] */
5083 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5084 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5086 movLeft2Result(left,offl, result, offr, 0);
5087 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5089 /* a:x >> shCount (x = lsb(result))*/
5091 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5093 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5094 if(getDataSize(result) > 1)
5095 aopPut(AOP(result),"a",offr+MSB16);
5098 /*-----------------------------------------------------------------*/
5099 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5100 /*-----------------------------------------------------------------*/
5101 static void shiftLLeftOrResult (operand *left, int offl,
5102 operand *result, int offr, int shCount)
5104 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5105 /* shift left accumulator */
5107 /* or with result */
5108 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5109 /* back to result */
5110 aopPut(AOP(result),"a",offr);
5113 /*-----------------------------------------------------------------*/
5114 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5115 /*-----------------------------------------------------------------*/
5116 static void shiftRLeftOrResult (operand *left, int offl,
5117 operand *result, int offr, int shCount)
5119 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5120 /* shift right accumulator */
5122 /* or with result */
5123 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5124 /* back to result */
5125 aopPut(AOP(result),"a",offr);
5128 /*-----------------------------------------------------------------*/
5129 /* genlshOne - left shift a one byte quantity by known count */
5130 /*-----------------------------------------------------------------*/
5131 static void genlshOne (operand *result, operand *left, int shCount)
5133 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5136 /*-----------------------------------------------------------------*/
5137 /* genlshTwo - left shift two bytes by known amount != 0 */
5138 /*-----------------------------------------------------------------*/
5139 static void genlshTwo (operand *result,operand *left, int shCount)
5143 size = getDataSize(result);
5145 /* if shCount >= 8 */
5151 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5153 movLeft2Result(left, LSB, result, MSB16, 0);
5155 aopPut(AOP(result),zero,LSB);
5158 /* 1 <= shCount <= 7 */
5161 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5163 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5167 /*-----------------------------------------------------------------*/
5168 /* shiftLLong - shift left one long from left to result */
5169 /* offl = LSB or MSB16 */
5170 /*-----------------------------------------------------------------*/
5171 static void shiftLLong (operand *left, operand *result, int offr )
5174 int size = AOP_SIZE(result);
5176 if(size >= LSB+offr){
5177 l = aopGet(AOP(left),LSB,FALSE,FALSE);
5179 emitcode("add","a,acc");
5180 if (sameRegs(AOP(left),AOP(result)) &&
5181 size >= MSB16+offr && offr != LSB )
5182 emitcode("xch","a,%s",
5183 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
5185 aopPut(AOP(result),"a",LSB+offr);
5188 if(size >= MSB16+offr){
5189 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5190 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
5193 emitcode("rlc","a");
5194 if (sameRegs(AOP(left),AOP(result)) &&
5195 size >= MSB24+offr && offr != LSB)
5196 emitcode("xch","a,%s",
5197 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
5199 aopPut(AOP(result),"a",MSB16+offr);
5202 if(size >= MSB24+offr){
5203 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5204 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
5207 emitcode("rlc","a");
5208 if (sameRegs(AOP(left),AOP(result)) &&
5209 size >= MSB32+offr && offr != LSB )
5210 emitcode("xch","a,%s",
5211 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
5213 aopPut(AOP(result),"a",MSB24+offr);
5216 if(size > MSB32+offr){
5217 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5218 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
5221 emitcode("rlc","a");
5222 aopPut(AOP(result),"a",MSB32+offr);
5225 aopPut(AOP(result),zero,LSB);
5228 /*-----------------------------------------------------------------*/
5229 /* genlshFour - shift four byte by a known amount != 0 */
5230 /*-----------------------------------------------------------------*/
5231 static void genlshFour (operand *result, operand *left, int shCount)
5235 size = AOP_SIZE(result);
5237 /* if shifting more that 3 bytes */
5238 if (shCount >= 24 ) {
5241 /* lowest order of left goes to the highest
5242 order of the destination */
5243 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5245 movLeft2Result(left, LSB, result, MSB32, 0);
5246 aopPut(AOP(result),zero,LSB);
5247 aopPut(AOP(result),zero,MSB16);
5248 aopPut(AOP(result),zero,MSB32);
5252 /* more than two bytes */
5253 else if ( shCount >= 16 ) {
5254 /* lower order two bytes goes to higher order two bytes */
5256 /* if some more remaining */
5258 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5260 movLeft2Result(left, MSB16, result, MSB32, 0);
5261 movLeft2Result(left, LSB, result, MSB24, 0);
5263 aopPut(AOP(result),zero,MSB16);
5264 aopPut(AOP(result),zero,LSB);
5268 /* if more than 1 byte */
5269 else if ( shCount >= 8 ) {
5270 /* lower order three bytes goes to higher order three bytes */
5274 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5276 movLeft2Result(left, LSB, result, MSB16, 0);
5278 else{ /* size = 4 */
5280 movLeft2Result(left, MSB24, result, MSB32, 0);
5281 movLeft2Result(left, MSB16, result, MSB24, 0);
5282 movLeft2Result(left, LSB, result, MSB16, 0);
5283 aopPut(AOP(result),zero,LSB);
5285 else if(shCount == 1)
5286 shiftLLong(left, result, MSB16);
5288 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5289 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5290 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5291 aopPut(AOP(result),zero,LSB);
5296 /* 1 <= shCount <= 7 */
5297 else if(shCount <= 2){
5298 shiftLLong(left, result, LSB);
5300 shiftLLong(result, result, LSB);
5302 /* 3 <= shCount <= 7, optimize */
5304 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5305 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5306 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5310 /*-----------------------------------------------------------------*/
5311 /* genLeftShiftLiteral - left shifting by known count */
5312 /*-----------------------------------------------------------------*/
5313 static void genLeftShiftLiteral (operand *left,
5318 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5321 freeAsmop(right,NULL,ic,TRUE);
5323 aopOp(left,ic,FALSE);
5324 aopOp(result,ic,FALSE);
5326 size = getSize(operandType(result));
5329 emitcode("; shift left ","result %d, left %d",size,
5333 /* I suppose that the left size >= result size */
5336 movLeft2Result(left, size, result, size, 0);
5340 else if(shCount >= (size * 8))
5342 aopPut(AOP(result),zero,size);
5346 genlshOne (result,left,shCount);
5351 genlshTwo (result,left,shCount);
5355 genlshFour (result,left,shCount);
5359 freeAsmop(left,NULL,ic,TRUE);
5360 freeAsmop(result,NULL,ic,TRUE);
5363 /*-----------------------------------------------------------------*/
5364 /* genLeftShift - generates code for left shifting */
5365 /*-----------------------------------------------------------------*/
5366 static void genLeftShift (iCode *ic)
5368 operand *left,*right, *result;
5371 symbol *tlbl , *tlbl1;
5373 right = IC_RIGHT(ic);
5375 result = IC_RESULT(ic);
5377 aopOp(right,ic,FALSE);
5379 /* if the shift count is known then do it
5380 as efficiently as possible */
5381 if (AOP_TYPE(right) == AOP_LIT) {
5382 genLeftShiftLiteral (left,right,result,ic);
5386 /* shift count is unknown then we have to form
5387 a loop get the loop count in B : Note: we take
5388 only the lower order byte since shifting
5389 more that 32 bits make no sense anyway, ( the
5390 largest size of an object can be only 32 bits ) */
5392 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5393 emitcode("inc","b");
5394 freeAsmop (right,NULL,ic,TRUE);
5395 aopOp(left,ic,FALSE);
5396 aopOp(result,ic,FALSE);
5398 /* now move the left to the result if they are not the
5400 if (!sameRegs(AOP(left),AOP(result)) &&
5401 AOP_SIZE(result) > 1) {
5403 size = AOP_SIZE(result);
5406 l = aopGet(AOP(left),offset,FALSE,TRUE);
5407 if (*l == '@' && (IS_AOP_PREG(result))) {
5409 emitcode("mov","a,%s",l);
5410 aopPut(AOP(result),"a",offset);
5412 aopPut(AOP(result),l,offset);
5417 tlbl = newiTempLabel(NULL);
5418 size = AOP_SIZE(result);
5420 tlbl1 = newiTempLabel(NULL);
5422 /* if it is only one byte then */
5424 symbol *tlbl1 = newiTempLabel(NULL);
5426 l = aopGet(AOP(left),0,FALSE,FALSE);
5428 emitcode("sjmp","%05d$",tlbl1->key+100);
5429 emitcode("","%05d$:",tlbl->key+100);
5430 emitcode("add","a,acc");
5431 emitcode("","%05d$:",tlbl1->key+100);
5432 emitcode("djnz","b,%05d$",tlbl->key+100);
5433 aopPut(AOP(result),"a",0);
5437 reAdjustPreg(AOP(result));
5439 emitcode("sjmp","%05d$",tlbl1->key+100);
5440 emitcode("","%05d$:",tlbl->key+100);
5441 l = aopGet(AOP(result),offset,FALSE,FALSE);
5443 emitcode("add","a,acc");
5444 aopPut(AOP(result),"a",offset++);
5446 l = aopGet(AOP(result),offset,FALSE,FALSE);
5448 emitcode("rlc","a");
5449 aopPut(AOP(result),"a",offset++);
5451 reAdjustPreg(AOP(result));
5453 emitcode("","%05d$:",tlbl1->key+100);
5454 emitcode("djnz","b,%05d$",tlbl->key+100);
5456 freeAsmop(left,NULL,ic,TRUE);
5457 freeAsmop(result,NULL,ic,TRUE);
5460 /*-----------------------------------------------------------------*/
5461 /* genrshOne - right shift a one byte quantity by known count */
5462 /*-----------------------------------------------------------------*/
5463 static void genrshOne (operand *result, operand *left,
5464 int shCount, int sign)
5466 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
5469 /*-----------------------------------------------------------------*/
5470 /* genrshTwo - right shift two bytes by known amount != 0 */
5471 /*-----------------------------------------------------------------*/
5472 static void genrshTwo (operand *result,operand *left,
5473 int shCount, int sign)
5475 /* if shCount >= 8 */
5479 shiftR1Left2Result(left, MSB16, result, LSB,
5482 movLeft2Result(left, MSB16, result, LSB, sign);
5483 addSign(result, MSB16, sign);
5486 /* 1 <= shCount <= 7 */
5488 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
5491 /*-----------------------------------------------------------------*/
5492 /* shiftRLong - shift right one long from left to result */
5493 /* offl = LSB or MSB16 */
5494 /*-----------------------------------------------------------------*/
5495 static void shiftRLong (operand *left, int offl,
5496 operand *result, int sign)
5499 emitcode("clr","c");
5500 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
5502 emitcode("mov","c,acc.7");
5503 emitcode("rrc","a");
5504 aopPut(AOP(result),"a",MSB32-offl);
5506 /* add sign of "a" */
5507 addSign(result, MSB32, sign);
5509 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
5510 emitcode("rrc","a");
5511 aopPut(AOP(result),"a",MSB24-offl);
5513 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
5514 emitcode("rrc","a");
5515 aopPut(AOP(result),"a",MSB16-offl);
5518 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
5519 emitcode("rrc","a");
5520 aopPut(AOP(result),"a",LSB);
5524 /*-----------------------------------------------------------------*/
5525 /* genrshFour - shift four byte by a known amount != 0 */
5526 /*-----------------------------------------------------------------*/
5527 static void genrshFour (operand *result, operand *left,
5528 int shCount, int sign)
5530 /* if shifting more that 3 bytes */
5531 if(shCount >= 24 ) {
5534 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
5536 movLeft2Result(left, MSB32, result, LSB, sign);
5537 addSign(result, MSB16, sign);
5539 else if(shCount >= 16){
5542 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
5544 movLeft2Result(left, MSB24, result, LSB, 0);
5545 movLeft2Result(left, MSB32, result, MSB16, sign);
5547 addSign(result, MSB24, sign);
5549 else if(shCount >= 8){
5552 shiftRLong(left, MSB16, result, sign);
5553 else if(shCount == 0){
5554 movLeft2Result(left, MSB16, result, LSB, 0);
5555 movLeft2Result(left, MSB24, result, MSB16, 0);
5556 movLeft2Result(left, MSB32, result, MSB24, sign);
5557 addSign(result, MSB32, sign);
5560 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
5561 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
5562 /* the last shift is signed */
5563 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
5564 addSign(result, MSB32, sign);
5567 else{ /* 1 <= shCount <= 7 */
5569 shiftRLong(left, LSB, result, sign);
5571 shiftRLong(result, LSB, result, sign);
5574 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
5575 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
5576 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
5581 /*-----------------------------------------------------------------*/
5582 /* genRightShiftLiteral - right shifting by known count */
5583 /*-----------------------------------------------------------------*/
5584 static void genRightShiftLiteral (operand *left,
5590 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5593 freeAsmop(right,NULL,ic,TRUE);
5595 aopOp(left,ic,FALSE);
5596 aopOp(result,ic,FALSE);
5599 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
5603 size = getDataSize(left);
5604 /* test the LEFT size !!! */
5606 /* I suppose that the left size >= result size */
5608 size = getDataSize(result);
5610 movLeft2Result(left, size, result, size, 0);
5613 else if(shCount >= (size * 8)){
5615 /* get sign in acc.7 */
5616 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
5617 addSign(result, LSB, sign);
5621 genrshOne (result,left,shCount,sign);
5625 genrshTwo (result,left,shCount,sign);
5629 genrshFour (result,left,shCount,sign);
5635 freeAsmop(left,NULL,ic,TRUE);
5636 freeAsmop(result,NULL,ic,TRUE);
5640 /*-----------------------------------------------------------------*/
5641 /* genSignedRightShift - right shift of signed number */
5642 /*-----------------------------------------------------------------*/
5643 static void genSignedRightShift (iCode *ic)
5645 operand *right, *left, *result;
5648 symbol *tlbl, *tlbl1 ;
5650 /* we do it the hard way put the shift count in b
5651 and loop thru preserving the sign */
5653 right = IC_RIGHT(ic);
5655 result = IC_RESULT(ic);
5657 aopOp(right,ic,FALSE);
5660 if ( AOP_TYPE(right) == AOP_LIT) {
5661 genRightShiftLiteral (left,right,result,ic,1);
5664 /* shift count is unknown then we have to form
5665 a loop get the loop count in B : Note: we take
5666 only the lower order byte since shifting
5667 more that 32 bits make no sense anyway, ( the
5668 largest size of an object can be only 32 bits ) */
5670 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5671 emitcode("inc","b");
5672 freeAsmop (right,NULL,ic,TRUE);
5673 aopOp(left,ic,FALSE);
5674 aopOp(result,ic,FALSE);
5676 /* now move the left to the result if they are not the
5678 if (!sameRegs(AOP(left),AOP(result)) &&
5679 AOP_SIZE(result) > 1) {
5681 size = AOP_SIZE(result);
5684 l = aopGet(AOP(left),offset,FALSE,TRUE);
5685 if (*l == '@' && IS_AOP_PREG(result)) {
5687 emitcode("mov","a,%s",l);
5688 aopPut(AOP(result),"a",offset);
5690 aopPut(AOP(result),l,offset);
5695 /* mov the highest order bit to OVR */
5696 tlbl = newiTempLabel(NULL);
5697 tlbl1= newiTempLabel(NULL);
5699 size = AOP_SIZE(result);
5701 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
5702 emitcode("rlc","a");
5703 emitcode("mov","ov,c");
5704 /* if it is only one byte then */
5706 l = aopGet(AOP(left),0,FALSE,FALSE);
5708 emitcode("sjmp","%05d$",tlbl1->key+100);
5709 emitcode("","%05d$:",tlbl->key+100);
5710 emitcode("mov","c,ov");
5711 emitcode("rrc","a");
5712 emitcode("","%05d$:",tlbl1->key+100);
5713 emitcode("djnz","b,%05d$",tlbl->key+100);
5714 aopPut(AOP(result),"a",0);
5718 reAdjustPreg(AOP(result));
5719 emitcode("sjmp","%05d$",tlbl1->key+100);
5720 emitcode("","%05d$:",tlbl->key+100);
5721 emitcode("mov","c,ov");
5723 l = aopGet(AOP(result),offset,FALSE,FALSE);
5725 emitcode("rrc","a");
5726 aopPut(AOP(result),"a",offset--);
5728 reAdjustPreg(AOP(result));
5729 emitcode("","%05d$:",tlbl1->key+100);
5730 emitcode("djnz","b,%05d$",tlbl->key+100);
5733 freeAsmop(left,NULL,ic,TRUE);
5734 freeAsmop(result,NULL,ic,TRUE);
5737 /*-----------------------------------------------------------------*/
5738 /* genRightShift - generate code for right shifting */
5739 /*-----------------------------------------------------------------*/
5740 static void genRightShift (iCode *ic)
5742 operand *right, *left, *result;
5746 symbol *tlbl, *tlbl1 ;
5748 /* if signed then we do it the hard way preserve the
5749 sign bit moving it inwards */
5750 retype = getSpec(operandType(IC_RESULT(ic)));
5752 if (!SPEC_USIGN(retype)) {
5753 genSignedRightShift (ic);
5757 /* signed & unsigned types are treated the same : i.e. the
5758 signed is NOT propagated inwards : quoting from the
5759 ANSI - standard : "for E1 >> E2, is equivalent to division
5760 by 2**E2 if unsigned or if it has a non-negative value,
5761 otherwise the result is implementation defined ", MY definition
5762 is that the sign does not get propagated */
5764 right = IC_RIGHT(ic);
5766 result = IC_RESULT(ic);
5768 aopOp(right,ic,FALSE);
5770 /* if the shift count is known then do it
5771 as efficiently as possible */
5772 if (AOP_TYPE(right) == AOP_LIT) {
5773 genRightShiftLiteral (left,right,result,ic, 0);
5777 /* shift count is unknown then we have to form
5778 a loop get the loop count in B : Note: we take
5779 only the lower order byte since shifting
5780 more that 32 bits make no sense anyway, ( the
5781 largest size of an object can be only 32 bits ) */
5783 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5784 emitcode("inc","b");
5785 freeAsmop (right,NULL,ic,TRUE);
5786 aopOp(left,ic,FALSE);
5787 aopOp(result,ic,FALSE);
5789 /* now move the left to the result if they are not the
5791 if (!sameRegs(AOP(left),AOP(result)) &&
5792 AOP_SIZE(result) > 1) {
5794 size = AOP_SIZE(result);
5797 l = aopGet(AOP(left),offset,FALSE,TRUE);
5798 if (*l == '@' && IS_AOP_PREG(result)) {
5800 emitcode("mov","a,%s",l);
5801 aopPut(AOP(result),"a",offset);
5803 aopPut(AOP(result),l,offset);
5808 tlbl = newiTempLabel(NULL);
5809 tlbl1= newiTempLabel(NULL);
5810 size = AOP_SIZE(result);
5813 /* if it is only one byte then */
5815 l = aopGet(AOP(left),0,FALSE,FALSE);
5817 emitcode("sjmp","%05d$",tlbl1->key+100);
5818 emitcode("","%05d$:",tlbl->key+100);
5820 emitcode("rrc","a");
5821 emitcode("","%05d$:",tlbl1->key+100);
5822 emitcode("djnz","b,%05d$",tlbl->key+100);
5823 aopPut(AOP(result),"a",0);
5827 reAdjustPreg(AOP(result));
5828 emitcode("sjmp","%05d$",tlbl1->key+100);
5829 emitcode("","%05d$:",tlbl->key+100);
5832 l = aopGet(AOP(result),offset,FALSE,FALSE);
5834 emitcode("rrc","a");
5835 aopPut(AOP(result),"a",offset--);
5837 reAdjustPreg(AOP(result));
5839 emitcode("","%05d$:",tlbl1->key+100);
5840 emitcode("djnz","b,%05d$",tlbl->key+100);
5843 freeAsmop(left,NULL,ic,TRUE);
5844 freeAsmop(result,NULL,ic,TRUE);
5847 /*-----------------------------------------------------------------*/
5848 /* genUnpackBits - generates code for unpacking bits */
5849 /*-----------------------------------------------------------------*/
5850 static void genUnpackBits (operand *result, char *rname, int ptype)
5857 etype = getSpec(operandType(result));
5859 /* read the first byte */
5864 emitcode("mov","a,@%s",rname);
5868 emitcode("movx","a,@%s",rname);
5872 emitcode("movx","a,@dptr");
5876 emitcode("clr","a");
5877 emitcode("movc","a","@a+dptr");
5881 emitcode("lcall","__gptrget");
5885 /* if we have bitdisplacement then it fits */
5886 /* into this byte completely or if length is */
5887 /* less than a byte */
5888 if ((shCnt = SPEC_BSTR(etype)) ||
5889 (SPEC_BLEN(etype) <= 8)) {
5891 /* shift right acc */
5894 emitcode("anl","a,#0x%02x",
5895 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
5896 aopPut(AOP(result),"a",offset);
5900 /* bit field did not fit in a byte */
5901 rlen = SPEC_BLEN(etype) - 8;
5902 aopPut(AOP(result),"a",offset++);
5909 emitcode("inc","%s",rname);
5910 emitcode("mov","a,@%s",rname);
5914 emitcode("inc","%s",rname);
5915 emitcode("movx","a,@%s",rname);
5919 emitcode("inc","dptr");
5920 emitcode("movx","a,@dptr");
5924 emitcode("clr","a");
5925 emitcode("inc","dptr");
5926 emitcode("movc","a","@a+dptr");
5930 emitcode("inc","dptr");
5931 emitcode("lcall","__gptrget");
5936 /* if we are done */
5940 aopPut(AOP(result),"a",offset++);
5945 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
5946 aopPut(AOP(result),"a",offset);
5953 /*-----------------------------------------------------------------*/
5954 /* genDataPointerGet - generates code when ptr offset is known */
5955 /*-----------------------------------------------------------------*/
5956 static void genDataPointerGet (operand *left,
5962 int size , offset = 0;
5963 aopOp(result,ic,TRUE);
5965 /* get the string representation of the name */
5966 l = aopGet(AOP(left),0,FALSE,TRUE);
5967 size = AOP_SIZE(result);
5970 sprintf(buffer,"(%s + %d)",l+1,offset);
5972 sprintf(buffer,"%s",l+1);
5973 aopPut(AOP(result),buffer,offset++);
5976 freeAsmop(left,NULL,ic,TRUE);
5977 freeAsmop(result,NULL,ic,TRUE);
5980 /*-----------------------------------------------------------------*/
5981 /* genNearPointerGet - emitcode for near pointer fetch */
5982 /*-----------------------------------------------------------------*/
5983 static void genNearPointerGet (operand *left,
5990 link *rtype, *retype;
5991 link *ltype = operandType(left);
5994 rtype = operandType(result);
5995 retype= getSpec(rtype);
5997 aopOp(left,ic,FALSE);
5999 /* if left is rematerialisable and
6000 result is not bit variable type and
6001 the left is pointer to data space i.e
6002 lower 128 bytes of space */
6003 if (AOP_TYPE(left) == AOP_IMMD &&
6004 !IS_BITVAR(retype) &&
6005 DCL_TYPE(ltype) == POINTER) {
6006 genDataPointerGet (left,result,ic);
6010 /* if the value is already in a pointer register
6011 then don't need anything more */
6012 if (!AOP_INPREG(AOP(left))) {
6013 /* otherwise get a free pointer register */
6015 preg = getFreePtr(ic,&aop,FALSE);
6016 emitcode("mov","%s,%s",
6018 aopGet(AOP(left),0,FALSE,TRUE));
6019 rname = preg->name ;
6021 rname = aopGet(AOP(left),0,FALSE,FALSE);
6023 freeAsmop(left,NULL,ic,TRUE);
6024 aopOp (result,ic,FALSE);
6026 /* if bitfield then unpack the bits */
6027 if (IS_BITVAR(retype))
6028 genUnpackBits (result,rname,POINTER);
6030 /* we have can just get the values */
6031 int size = AOP_SIZE(result);
6035 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6037 emitcode("mov","a,@%s",rname);
6038 aopPut(AOP(result),"a",offset);
6040 sprintf(buffer,"@%s",rname);
6041 aopPut(AOP(result),buffer,offset);
6045 emitcode("inc","%s",rname);
6049 /* now some housekeeping stuff */
6051 /* we had to allocate for this iCode */
6052 freeAsmop(NULL,aop,ic,TRUE);
6054 /* we did not allocate which means left
6055 already in a pointer register, then
6056 if size > 0 && this could be used again
6057 we have to point it back to where it
6059 if (AOP_SIZE(result) > 1 &&
6060 !OP_SYMBOL(left)->remat &&
6061 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6063 int size = AOP_SIZE(result) - 1;
6065 emitcode("dec","%s",rname);
6070 freeAsmop(result,NULL,ic,TRUE);
6074 /*-----------------------------------------------------------------*/
6075 /* genPagedPointerGet - emitcode for paged pointer fetch */
6076 /*-----------------------------------------------------------------*/
6077 static void genPagedPointerGet (operand *left,
6084 link *rtype, *retype;
6086 rtype = operandType(result);
6087 retype= getSpec(rtype);
6089 aopOp(left,ic,FALSE);
6091 /* if the value is already in a pointer register
6092 then don't need anything more */
6093 if (!AOP_INPREG(AOP(left))) {
6094 /* otherwise get a free pointer register */
6096 preg = getFreePtr(ic,&aop,FALSE);
6097 emitcode("mov","%s,%s",
6099 aopGet(AOP(left),0,FALSE,TRUE));
6100 rname = preg->name ;
6102 rname = aopGet(AOP(left),0,FALSE,FALSE);
6104 freeAsmop(left,NULL,ic,TRUE);
6105 aopOp (result,ic,FALSE);
6107 /* if bitfield then unpack the bits */
6108 if (IS_BITVAR(retype))
6109 genUnpackBits (result,rname,PPOINTER);
6111 /* we have can just get the values */
6112 int size = AOP_SIZE(result);
6117 emitcode("movx","a,@%s",rname);
6118 aopPut(AOP(result),"a",offset);
6123 emitcode("inc","%s",rname);
6127 /* now some housekeeping stuff */
6129 /* we had to allocate for this iCode */
6130 freeAsmop(NULL,aop,ic,TRUE);
6132 /* we did not allocate which means left
6133 already in a pointer register, then
6134 if size > 0 && this could be used again
6135 we have to point it back to where it
6137 if (AOP_SIZE(result) > 1 &&
6138 !OP_SYMBOL(left)->remat &&
6139 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6141 int size = AOP_SIZE(result) - 1;
6143 emitcode("dec","%s",rname);
6148 freeAsmop(result,NULL,ic,TRUE);
6153 /*-----------------------------------------------------------------*/
6154 /* genFarPointerGet - gget value from far space */
6155 /*-----------------------------------------------------------------*/
6156 static void genFarPointerGet (operand *left,
6157 operand *result, iCode *ic)
6160 link *retype = getSpec(operandType(result));
6162 aopOp(left,ic,FALSE);
6164 /* if the operand is already in dptr
6165 then we do nothing else we move the value to dptr */
6166 if (AOP_TYPE(left) != AOP_STR) {
6167 /* if this is remateriazable */
6168 if (AOP_TYPE(left) == AOP_IMMD)
6169 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6170 else { /* we need to get it byte by byte */
6171 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6172 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6173 if (options.model == MODEL_FLAT24)
6175 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6179 /* so dptr know contains the address */
6180 freeAsmop(left,NULL,ic,TRUE);
6181 aopOp(result,ic,FALSE);
6183 /* if bit then unpack */
6184 if (IS_BITVAR(retype))
6185 genUnpackBits(result,"dptr",FPOINTER);
6187 size = AOP_SIZE(result);
6191 emitcode("movx","a,@dptr");
6192 aopPut(AOP(result),"a",offset++);
6194 emitcode("inc","dptr");
6198 freeAsmop(result,NULL,ic,TRUE);
6201 /*-----------------------------------------------------------------*/
6202 /* emitcodePointerGet - gget value from code space */
6203 /*-----------------------------------------------------------------*/
6204 static void emitcodePointerGet (operand *left,
6205 operand *result, iCode *ic)
6208 link *retype = getSpec(operandType(result));
6210 aopOp(left,ic,FALSE);
6212 /* if the operand is already in dptr
6213 then we do nothing else we move the value to dptr */
6214 if (AOP_TYPE(left) != AOP_STR) {
6215 /* if this is remateriazable */
6216 if (AOP_TYPE(left) == AOP_IMMD)
6217 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6218 else { /* we need to get it byte by byte */
6219 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6220 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6221 if (options.model == MODEL_FLAT24)
6223 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6227 /* so dptr know contains the address */
6228 freeAsmop(left,NULL,ic,TRUE);
6229 aopOp(result,ic,FALSE);
6231 /* if bit then unpack */
6232 if (IS_BITVAR(retype))
6233 genUnpackBits(result,"dptr",CPOINTER);
6235 size = AOP_SIZE(result);
6239 emitcode("clr","a");
6240 emitcode("movc","a,@a+dptr");
6241 aopPut(AOP(result),"a",offset++);
6243 emitcode("inc","dptr");
6247 freeAsmop(result,NULL,ic,TRUE);
6250 /*-----------------------------------------------------------------*/
6251 /* genGenPointerGet - gget value from generic pointer space */
6252 /*-----------------------------------------------------------------*/
6253 static void genGenPointerGet (operand *left,
6254 operand *result, iCode *ic)
6257 link *retype = getSpec(operandType(result));
6259 aopOp(left,ic,FALSE);
6261 /* if the operand is already in dptr
6262 then we do nothing else we move the value to dptr */
6263 if (AOP_TYPE(left) != AOP_STR) {
6264 /* if this is remateriazable */
6265 if (AOP_TYPE(left) == AOP_IMMD) {
6266 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6267 emitcode("mov","b,#%d",pointerCode(retype));
6269 else { /* we need to get it byte by byte */
6270 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6271 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6272 if (options.model == MODEL_FLAT24)
6274 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6275 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
6279 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
6283 /* so dptr know contains the address */
6284 freeAsmop(left,NULL,ic,TRUE);
6285 aopOp(result,ic,FALSE);
6287 /* if bit then unpack */
6288 if (IS_BITVAR(retype))
6289 genUnpackBits(result,"dptr",GPOINTER);
6291 size = AOP_SIZE(result);
6295 emitcode("lcall","__gptrget");
6296 aopPut(AOP(result),"a",offset++);
6298 emitcode("inc","dptr");
6302 freeAsmop(result,NULL,ic,TRUE);
6305 /*-----------------------------------------------------------------*/
6306 /* genPointerGet - generate code for pointer get */
6307 /*-----------------------------------------------------------------*/
6308 static void genPointerGet (iCode *ic)
6310 operand *left, *result ;
6315 result = IC_RESULT(ic) ;
6317 /* depending on the type of pointer we need to
6318 move it to the correct pointer register */
6319 type = operandType(left);
6320 etype = getSpec(type);
6321 /* if left is of type of pointer then it is simple */
6322 if (IS_PTR(type) && !IS_FUNC(type->next))
6323 p_type = DCL_TYPE(type);
6325 /* we have to go by the storage class */
6326 p_type = PTR_TYPE(SPEC_OCLS(etype));
6328 /* if (SPEC_OCLS(etype)->codesp ) { */
6329 /* p_type = CPOINTER ; */
6332 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6333 /* p_type = FPOINTER ; */
6335 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6336 /* p_type = PPOINTER; */
6338 /* if (SPEC_OCLS(etype) == idata ) */
6339 /* p_type = IPOINTER; */
6341 /* p_type = POINTER ; */
6344 /* now that we have the pointer type we assign
6345 the pointer values */
6350 genNearPointerGet (left,result,ic);
6354 genPagedPointerGet(left,result,ic);
6358 genFarPointerGet (left,result,ic);
6362 emitcodePointerGet (left,result,ic);
6366 genGenPointerGet (left,result,ic);
6372 /*-----------------------------------------------------------------*/
6373 /* genPackBits - generates code for packed bit storage */
6374 /*-----------------------------------------------------------------*/
6375 static void genPackBits (link *etype ,
6377 char *rname, int p_type)
6385 blen = SPEC_BLEN(etype);
6386 bstr = SPEC_BSTR(etype);
6388 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6391 /* if the bit lenth is less than or */
6392 /* it exactly fits a byte then */
6393 if (SPEC_BLEN(etype) <= 8 ) {
6394 shCount = SPEC_BSTR(etype) ;
6396 /* shift left acc */
6399 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6404 emitcode ("mov","b,a");
6405 emitcode("mov","a,@%s",rname);
6409 emitcode ("mov","b,a");
6410 emitcode("movx","a,@dptr");
6414 emitcode ("push","b");
6415 emitcode ("push","acc");
6416 emitcode ("lcall","__gptrget");
6417 emitcode ("pop","b");
6421 emitcode ("anl","a,#0x%02x",(unsigned char)
6422 ((unsigned char)(0xFF << (blen+bstr)) |
6423 (unsigned char)(0xFF >> (8-bstr)) ) );
6424 emitcode ("orl","a,b");
6425 if (p_type == GPOINTER)
6426 emitcode("pop","b");
6432 emitcode("mov","@%s,a",rname);
6436 emitcode("movx","@dptr,a");
6440 emitcode("lcall","__gptrput");
6445 if ( SPEC_BLEN(etype) <= 8 )
6448 emitcode("inc","%s",rname);
6449 rLen = SPEC_BLEN(etype) ;
6451 /* now generate for lengths greater than one byte */
6454 l = aopGet(AOP(right),offset++,FALSE,TRUE);
6464 emitcode("mov","@%s,a",rname);
6466 emitcode("mov","@%s,%s",rname,l);
6471 emitcode("movx","@dptr,a");
6476 emitcode("lcall","__gptrput");
6479 emitcode ("inc","%s",rname);
6484 /* last last was not complete */
6486 /* save the byte & read byte */
6489 emitcode ("mov","b,a");
6490 emitcode("mov","a,@%s",rname);
6494 emitcode ("mov","b,a");
6495 emitcode("movx","a,@dptr");
6499 emitcode ("push","b");
6500 emitcode ("push","acc");
6501 emitcode ("lcall","__gptrget");
6502 emitcode ("pop","b");
6506 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
6507 emitcode ("orl","a,b");
6510 if (p_type == GPOINTER)
6511 emitcode("pop","b");
6516 emitcode("mov","@%s,a",rname);
6520 emitcode("movx","@dptr,a");
6524 emitcode("lcall","__gptrput");
6528 /*-----------------------------------------------------------------*/
6529 /* genDataPointerSet - remat pointer to data space */
6530 /*-----------------------------------------------------------------*/
6531 static void genDataPointerSet(operand *right,
6535 int size, offset = 0 ;
6536 char *l, buffer[256];
6538 aopOp(right,ic,FALSE);
6540 l = aopGet(AOP(result),0,FALSE,TRUE);
6541 size = AOP_SIZE(right);
6544 sprintf(buffer,"(%s + %d)",l+1,offset);
6546 sprintf(buffer,"%s",l+1);
6547 emitcode("mov","%s,%s",buffer,
6548 aopGet(AOP(right),offset++,FALSE,FALSE));
6551 freeAsmop(right,NULL,ic,TRUE);
6552 freeAsmop(result,NULL,ic,TRUE);
6555 /*-----------------------------------------------------------------*/
6556 /* genNearPointerSet - emitcode for near pointer put */
6557 /*-----------------------------------------------------------------*/
6558 static void genNearPointerSet (operand *right,
6566 link *ptype = operandType(result);
6568 retype= getSpec(operandType(right));
6570 aopOp(result,ic,FALSE);
6572 /* if the result is rematerializable &
6573 in data space & not a bit variable */
6574 if (AOP_TYPE(result) == AOP_IMMD &&
6575 DCL_TYPE(ptype) == POINTER &&
6576 !IS_BITVAR(retype)) {
6577 genDataPointerSet (right,result,ic);
6581 /* if the value is already in a pointer register
6582 then don't need anything more */
6583 if (!AOP_INPREG(AOP(result))) {
6584 /* otherwise get a free pointer register */
6586 preg = getFreePtr(ic,&aop,FALSE);
6587 emitcode("mov","%s,%s",
6589 aopGet(AOP(result),0,FALSE,TRUE));
6590 rname = preg->name ;
6592 rname = aopGet(AOP(result),0,FALSE,FALSE);
6594 freeAsmop(result,NULL,ic,TRUE);
6595 aopOp (right,ic,FALSE);
6597 /* if bitfield then unpack the bits */
6598 if (IS_BITVAR(retype))
6599 genPackBits (retype,right,rname,POINTER);
6601 /* we have can just get the values */
6602 int size = AOP_SIZE(right);
6606 l = aopGet(AOP(right),offset,FALSE,TRUE);
6609 emitcode("mov","@%s,a",rname);
6611 emitcode("mov","@%s,%s",rname,l);
6613 emitcode("inc","%s",rname);
6618 /* now some housekeeping stuff */
6620 /* we had to allocate for this iCode */
6621 freeAsmop(NULL,aop,ic,TRUE);
6623 /* we did not allocate which means left
6624 already in a pointer register, then
6625 if size > 0 && this could be used again
6626 we have to point it back to where it
6628 if (AOP_SIZE(right) > 1 &&
6629 !OP_SYMBOL(result)->remat &&
6630 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6632 int size = AOP_SIZE(right) - 1;
6634 emitcode("dec","%s",rname);
6639 freeAsmop(right,NULL,ic,TRUE);
6644 /*-----------------------------------------------------------------*/
6645 /* genPagedPointerSet - emitcode for Paged pointer put */
6646 /*-----------------------------------------------------------------*/
6647 static void genPagedPointerSet (operand *right,
6656 retype= getSpec(operandType(right));
6658 aopOp(result,ic,FALSE);
6660 /* if the value is already in a pointer register
6661 then don't need anything more */
6662 if (!AOP_INPREG(AOP(result))) {
6663 /* otherwise get a free pointer register */
6665 preg = getFreePtr(ic,&aop,FALSE);
6666 emitcode("mov","%s,%s",
6668 aopGet(AOP(result),0,FALSE,TRUE));
6669 rname = preg->name ;
6671 rname = aopGet(AOP(result),0,FALSE,FALSE);
6673 freeAsmop(result,NULL,ic,TRUE);
6674 aopOp (right,ic,FALSE);
6676 /* if bitfield then unpack the bits */
6677 if (IS_BITVAR(retype))
6678 genPackBits (retype,right,rname,PPOINTER);
6680 /* we have can just get the values */
6681 int size = AOP_SIZE(right);
6685 l = aopGet(AOP(right),offset,FALSE,TRUE);
6688 emitcode("movx","@%s,a",rname);
6691 emitcode("inc","%s",rname);
6697 /* now some housekeeping stuff */
6699 /* we had to allocate for this iCode */
6700 freeAsmop(NULL,aop,ic,TRUE);
6702 /* we did not allocate which means left
6703 already in a pointer register, then
6704 if size > 0 && this could be used again
6705 we have to point it back to where it
6707 if (AOP_SIZE(right) > 1 &&
6708 !OP_SYMBOL(result)->remat &&
6709 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6711 int size = AOP_SIZE(right) - 1;
6713 emitcode("dec","%s",rname);
6718 freeAsmop(right,NULL,ic,TRUE);
6723 /*-----------------------------------------------------------------*/
6724 /* genFarPointerSet - set value from far space */
6725 /*-----------------------------------------------------------------*/
6726 static void genFarPointerSet (operand *right,
6727 operand *result, iCode *ic)
6730 link *retype = getSpec(operandType(right));
6732 aopOp(result,ic,FALSE);
6734 /* if the operand is already in dptr
6735 then we do nothing else we move the value to dptr */
6736 if (AOP_TYPE(result) != AOP_STR) {
6737 /* if this is remateriazable */
6738 if (AOP_TYPE(result) == AOP_IMMD)
6739 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6740 else { /* we need to get it byte by byte */
6741 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6742 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6743 if (options.model == MODEL_FLAT24)
6745 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6749 /* so dptr know contains the address */
6750 freeAsmop(result,NULL,ic,TRUE);
6751 aopOp(right,ic,FALSE);
6753 /* if bit then unpack */
6754 if (IS_BITVAR(retype))
6755 genPackBits(retype,right,"dptr",FPOINTER);
6757 size = AOP_SIZE(right);
6761 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6763 emitcode("movx","@dptr,a");
6765 emitcode("inc","dptr");
6769 freeAsmop(right,NULL,ic,TRUE);
6772 /*-----------------------------------------------------------------*/
6773 /* genGenPointerSet - set value from generic pointer space */
6774 /*-----------------------------------------------------------------*/
6775 static void genGenPointerSet (operand *right,
6776 operand *result, iCode *ic)
6779 link *retype = getSpec(operandType(right));
6781 aopOp(result,ic,FALSE);
6783 /* if the operand is already in dptr
6784 then we do nothing else we move the value to dptr */
6785 if (AOP_TYPE(result) != AOP_STR) {
6786 /* if this is remateriazable */
6787 if (AOP_TYPE(result) == AOP_IMMD) {
6788 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6789 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
6791 else { /* we need to get it byte by byte */
6792 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6793 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6794 if (options.model == MODEL_FLAT24)
6796 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6797 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
6801 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
6805 /* so dptr know contains the address */
6806 freeAsmop(result,NULL,ic,TRUE);
6807 aopOp(right,ic,FALSE);
6809 /* if bit then unpack */
6810 if (IS_BITVAR(retype))
6811 genPackBits(retype,right,"dptr",GPOINTER);
6813 size = AOP_SIZE(right);
6817 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6819 emitcode("lcall","__gptrput");
6821 emitcode("inc","dptr");
6825 freeAsmop(right,NULL,ic,TRUE);
6828 /*-----------------------------------------------------------------*/
6829 /* genPointerSet - stores the value into a pointer location */
6830 /*-----------------------------------------------------------------*/
6831 static void genPointerSet (iCode *ic)
6833 operand *right, *result ;
6837 right = IC_RIGHT(ic);
6838 result = IC_RESULT(ic) ;
6840 /* depending on the type of pointer we need to
6841 move it to the correct pointer register */
6842 type = operandType(result);
6843 etype = getSpec(type);
6844 /* if left is of type of pointer then it is simple */
6845 if (IS_PTR(type) && !IS_FUNC(type->next)) {
6846 p_type = DCL_TYPE(type);
6849 /* we have to go by the storage class */
6850 p_type = PTR_TYPE(SPEC_OCLS(etype));
6852 /* if (SPEC_OCLS(etype)->codesp ) { */
6853 /* p_type = CPOINTER ; */
6856 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6857 /* p_type = FPOINTER ; */
6859 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6860 /* p_type = PPOINTER ; */
6862 /* if (SPEC_OCLS(etype) == idata ) */
6863 /* p_type = IPOINTER ; */
6865 /* p_type = POINTER ; */
6868 /* now that we have the pointer type we assign
6869 the pointer values */
6874 genNearPointerSet (right,result,ic);
6878 genPagedPointerSet (right,result,ic);
6882 genFarPointerSet (right,result,ic);
6886 genGenPointerSet (right,result,ic);
6892 /*-----------------------------------------------------------------*/
6893 /* genIfx - generate code for Ifx statement */
6894 /*-----------------------------------------------------------------*/
6895 static void genIfx (iCode *ic, iCode *popIc)
6897 operand *cond = IC_COND(ic);
6900 aopOp(cond,ic,FALSE);
6902 /* get the value into acc */
6903 if (AOP_TYPE(cond) != AOP_CRY)
6907 /* the result is now in the accumulator */
6908 freeAsmop(cond,NULL,ic,TRUE);
6910 /* if there was something to be popped then do it */
6914 /* if the condition is a bit variable */
6915 if (isbit && IS_ITEMP(cond) &&
6917 genIfxJump(ic,SPIL_LOC(cond)->rname);
6919 if (isbit && !IS_ITEMP(cond))
6920 genIfxJump(ic,OP_SYMBOL(cond)->rname);
6927 /*-----------------------------------------------------------------*/
6928 /* genAddrOf - generates code for address of */
6929 /*-----------------------------------------------------------------*/
6930 static void genAddrOf (iCode *ic)
6932 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
6935 aopOp(IC_RESULT(ic),ic,FALSE);
6937 /* if the operand is on the stack then we
6938 need to get the stack offset of this
6941 /* if it has an offset then we need to compute
6944 emitcode("mov","a,_bp");
6945 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
6946 aopPut(AOP(IC_RESULT(ic)),"a",0);
6948 /* we can just move _bp */
6949 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
6951 /* fill the result with zero */
6952 size = AOP_SIZE(IC_RESULT(ic)) - 1;
6955 if (options.stack10bit && size < (FPTRSIZE - 1))
6958 "*** warning: pointer to stack var truncated.\n");
6965 if (options.stack10bit && offset == 2)
6967 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
6971 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
6978 /* object not on stack then we need the name */
6979 size = AOP_SIZE(IC_RESULT(ic));
6983 char s[SDCC_NAME_MAX];
6985 sprintf(s,"#(%s >> %d)",
6989 sprintf(s,"#%s",sym->rname);
6990 aopPut(AOP(IC_RESULT(ic)),s,offset++);
6994 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
6998 /*-----------------------------------------------------------------*/
6999 /* genFarFarAssign - assignment when both are in far space */
7000 /*-----------------------------------------------------------------*/
7001 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7003 int size = AOP_SIZE(right);
7006 /* first push the right side on to the stack */
7008 l = aopGet(AOP(right),offset++,FALSE,FALSE);
7010 emitcode ("push","acc");
7013 freeAsmop(right,NULL,ic,FALSE);
7014 /* now assign DPTR to result */
7015 aopOp(result,ic,FALSE);
7016 size = AOP_SIZE(result);
7018 emitcode ("pop","acc");
7019 aopPut(AOP(result),"a",--offset);
7021 freeAsmop(result,NULL,ic,FALSE);
7025 /*-----------------------------------------------------------------*/
7026 /* genAssign - generate code for assignment */
7027 /*-----------------------------------------------------------------*/
7028 static void genAssign (iCode *ic)
7030 operand *result, *right;
7032 unsigned long lit = 0L;
7034 result = IC_RESULT(ic);
7035 right = IC_RIGHT(ic) ;
7037 /* if they are the same */
7038 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7041 aopOp(right,ic,FALSE);
7043 /* special case both in far space */
7044 if ((AOP_TYPE(right) == AOP_DPTR ||
7045 AOP_TYPE(right) == AOP_DPTR2) &&
7046 IS_TRUE_SYMOP(result) &&
7047 isOperandInFarSpace(result)) {
7049 genFarFarAssign (result,right,ic);
7053 aopOp(result,ic,TRUE);
7055 /* if they are the same registers */
7056 if (sameRegs(AOP(right),AOP(result)))
7059 /* if the result is a bit */
7060 if (AOP_TYPE(result) == AOP_CRY) {
7062 /* if the right size is a literal then
7063 we know what the value is */
7064 if (AOP_TYPE(right) == AOP_LIT) {
7065 if (((int) operandLitValue(right)))
7066 aopPut(AOP(result),one,0);
7068 aopPut(AOP(result),zero,0);
7072 /* the right is also a bit variable */
7073 if (AOP_TYPE(right) == AOP_CRY) {
7074 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7075 aopPut(AOP(result),"c",0);
7081 aopPut(AOP(result),"a",0);
7085 /* bit variables done */
7087 size = AOP_SIZE(result);
7089 if(AOP_TYPE(right) == AOP_LIT)
7090 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7092 (AOP_TYPE(result) != AOP_REG) &&
7093 (AOP_TYPE(right) == AOP_LIT) &&
7094 !IS_FLOAT(operandType(right)) &&
7096 emitcode("clr","a");
7098 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7099 aopPut(AOP(result),"a",size);
7102 aopGet(AOP(right),size,FALSE,FALSE),
7108 aopGet(AOP(right),offset,FALSE,FALSE),
7115 freeAsmop (right,NULL,ic,FALSE);
7116 freeAsmop (result,NULL,ic,TRUE);
7119 /*-----------------------------------------------------------------*/
7120 /* genJumpTab - genrates code for jump table */
7121 /*-----------------------------------------------------------------*/
7122 static void genJumpTab (iCode *ic)
7127 aopOp(IC_JTCOND(ic),ic,FALSE);
7128 /* get the condition into accumulator */
7129 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
7131 /* multiply by three */
7132 emitcode("add","a,acc");
7133 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
7134 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7136 jtab = newiTempLabel(NULL);
7137 emitcode("mov","dptr,#%05d$",jtab->key+100);
7138 emitcode("jmp","@a+dptr");
7139 emitcode("","%05d$:",jtab->key+100);
7140 /* now generate the jump labels */
7141 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
7142 jtab = setNextItem(IC_JTLABELS(ic)))
7143 emitcode("ljmp","%05d$",jtab->key+100);
7147 /*-----------------------------------------------------------------*/
7148 /* genCast - gen code for casting */
7149 /*-----------------------------------------------------------------*/
7150 static void genCast (iCode *ic)
7152 operand *result = IC_RESULT(ic);
7153 link *ctype = operandType(IC_LEFT(ic));
7154 operand *right = IC_RIGHT(ic);
7157 /* if they are equivalent then do nothing */
7158 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
7161 aopOp(right,ic,FALSE) ;
7162 aopOp(result,ic,FALSE);
7164 /* if the result is a bit */
7165 if (AOP_TYPE(result) == AOP_CRY) {
7166 /* if the right size is a literal then
7167 we know what the value is */
7168 if (AOP_TYPE(right) == AOP_LIT) {
7169 if (((int) operandLitValue(right)))
7170 aopPut(AOP(result),one,0);
7172 aopPut(AOP(result),zero,0);
7177 /* the right is also a bit variable */
7178 if (AOP_TYPE(right) == AOP_CRY) {
7179 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7180 aopPut(AOP(result),"c",0);
7186 aopPut(AOP(result),"a",0);
7190 /* if they are the same size : or less */
7191 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
7193 /* if they are in the same place */
7194 if (sameRegs(AOP(right),AOP(result)))
7197 /* if they in different places then copy */
7198 size = AOP_SIZE(result);
7202 aopGet(AOP(right),offset,FALSE,FALSE),
7210 /* if the result is of type pointer */
7211 if (IS_PTR(ctype)) {
7214 link *type = operandType(right);
7215 link *etype = getSpec(type);
7217 /* pointer to generic pointer */
7218 if (IS_GENPTR(ctype)) {
7222 p_type = DCL_TYPE(type);
7224 /* we have to go by the storage class */
7225 p_type = PTR_TYPE(SPEC_OCLS(etype));
7227 /* if (SPEC_OCLS(etype)->codesp ) */
7228 /* p_type = CPOINTER ; */
7230 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7231 /* p_type = FPOINTER ; */
7233 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7234 /* p_type = PPOINTER; */
7236 /* if (SPEC_OCLS(etype) == idata ) */
7237 /* p_type = IPOINTER ; */
7239 /* p_type = POINTER ; */
7242 /* the first two bytes are known */
7243 size = GPTRSIZE - 1;
7247 aopGet(AOP(right),offset,FALSE,FALSE),
7251 /* the last byte depending on type */
7268 /* this should never happen */
7269 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7270 "got unknown pointer type");
7273 aopPut(AOP(result),l, GPTRSIZE - 1);
7277 /* just copy the pointers */
7278 size = AOP_SIZE(result);
7282 aopGet(AOP(right),offset,FALSE,FALSE),
7289 /* so we now know that the size of destination is greater
7290 than the size of the source */
7291 /* we move to result for the size of source */
7292 size = AOP_SIZE(right);
7296 aopGet(AOP(right),offset,FALSE,FALSE),
7301 /* now depending on the sign of the destination */
7302 size = AOP_SIZE(result) - AOP_SIZE(right);
7303 /* if unsigned or not an integral type */
7304 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
7306 aopPut(AOP(result),zero,offset++);
7308 /* we need to extend the sign :{ */
7309 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
7312 emitcode("rlc","a");
7313 emitcode("subb","a,acc");
7315 aopPut(AOP(result),"a",offset++);
7318 /* we are done hurray !!!! */
7321 freeAsmop(right,NULL,ic,TRUE);
7322 freeAsmop(result,NULL,ic,TRUE);
7326 /*-----------------------------------------------------------------*/
7327 /* genDjnz - generate decrement & jump if not zero instrucion */
7328 /*-----------------------------------------------------------------*/
7329 static int genDjnz (iCode *ic, iCode *ifx)
7335 /* if the if condition has a false label
7336 then we cannot save */
7340 /* if the minus is not of the form
7342 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
7343 !IS_OP_LITERAL(IC_RIGHT(ic)))
7346 if (operandLitValue(IC_RIGHT(ic)) != 1)
7349 /* if the size of this greater than one then no
7351 if (getSize(operandType(IC_RESULT(ic))) > 1)
7354 /* otherwise we can save BIG */
7355 lbl = newiTempLabel(NULL);
7356 lbl1= newiTempLabel(NULL);
7358 aopOp(IC_RESULT(ic),ic,FALSE);
7360 if (IS_AOP_PREG(IC_RESULT(ic))) {
7361 emitcode("dec","%s",
7362 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7363 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7364 emitcode("jnz","%05d$",lbl->key+100);
7366 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
7369 emitcode ("sjmp","%05d$",lbl1->key+100);
7370 emitcode ("","%05d$:",lbl->key+100);
7371 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
7372 emitcode ("","%05d$:",lbl1->key+100);
7374 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7379 /*-----------------------------------------------------------------*/
7380 /* genReceive - generate code for a receive iCode */
7381 /*-----------------------------------------------------------------*/
7382 static void genReceive (iCode *ic)
7384 if (isOperandInFarSpace(IC_RESULT(ic)) &&
7385 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
7386 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
7388 int size = getSize(operandType(IC_RESULT(ic)));
7389 int offset = fReturnSize - size;
7391 emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
7392 fReturn[fReturnSize - offset - 1] : "acc"));
7395 aopOp(IC_RESULT(ic),ic,FALSE);
7396 size = AOP_SIZE(IC_RESULT(ic));
7399 emitcode ("pop","acc");
7400 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
7405 aopOp(IC_RESULT(ic),ic,FALSE);
7407 assignResultValue(IC_RESULT(ic));
7410 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7413 /*-----------------------------------------------------------------*/
7414 /* gen51Code - generate code for 8051 based controllers */
7415 /*-----------------------------------------------------------------*/
7416 void gen51Code (iCode *lic)
7421 lineHead = lineCurr = NULL;
7423 /* if debug information required */
7424 /* if (options.debug && currFunc) { */
7426 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
7428 if (IS_STATIC(currFunc->etype))
7429 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
7431 emitcode("","G$%s$0$0 ==.",currFunc->name);
7434 /* stack pointer name */
7435 if (options.useXstack)
7441 for (ic = lic ; ic ; ic = ic->next ) {
7443 if ( cln != ic->lineno ) {
7444 if ( options.debug ) {
7446 emitcode("","C$%s$%d$%d$%d ==.",
7447 ic->filename,ic->lineno,
7448 ic->level,ic->block);
7451 emitcode(";","%s %d",ic->filename,ic->lineno);
7454 /* if the result is marked as
7455 spilt and rematerializable or code for
7456 this has already been generated then
7458 if (resultRemat(ic) || ic->generated )
7461 /* depending on the operation */
7480 /* IPOP happens only when trying to restore a
7481 spilt live range, if there is an ifx statement
7482 following this pop then the if statement might
7483 be using some of the registers being popped which
7484 would destory the contents of the register so
7485 we need to check for this condition and handle it */
7487 ic->next->op == IFX &&
7488 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
7489 genIfx (ic->next,ic);
7507 genEndFunction (ic);
7527 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
7544 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
7548 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
7555 /* note these two are xlated by algebraic equivalence
7556 during parsing SDCC.y */
7557 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7558 "got '>=' or '<=' shouldn't have come here");
7562 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
7574 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
7578 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
7582 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
7609 case GET_VALUE_AT_ADDRESS:
7614 if (POINTER_SET(ic))
7641 addSet(&_G.sendSet,ic);
7646 /* piCode(ic,stdout); */
7652 /* now we are ready to call the
7653 peep hole optimizer */
7654 if (!options.nopeep)
7655 peepHole (&lineHead);
7657 /* now do the actual printing */
7658 printLine (lineHead,codeOutFile);