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"
38 #ifdef HAVE_SYS_ISA_DEFS_H
39 #include <sys/isa_defs.h>
44 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
45 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
46 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
52 #include "SDCCpeeph.h"
56 char *aopLiteral (value *val, int offset);
59 /* this is the down and dirty file with all kinds of
60 kludgy & hacky stuff. This is what it is all about
61 CODE GENERATION for a specific MCU . some of the
62 routines may be reusable, will have to see */
64 static char *zero = "#0x00";
65 static char *one = "#0x01";
68 char *fReturn8051[] = {"dpl","dph","b","a" };
69 char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
70 unsigned fReturnSize = 4; /* shared with ralloc.c */
71 char **fReturn = fReturn8051;
72 static char *accUse[] = {"a","b"};
74 static short rbank = -1;
86 extern int mcs51_ptrRegReq ;
87 extern int mcs51_nRegs;
88 extern FILE *codeOutFile;
89 static void saverbank (int, iCode *,bool);
90 #define RESULTONSTACK(x) \
91 (IC_RESULT(x) && IC_RESULT(x)->aop && \
92 IC_RESULT(x)->aop->type == AOP_STK )
94 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x);
95 #define CLRC emitcode("clr","c")
96 #define SETC emitcode("setb","c")
98 static lineNode *lineHead = NULL;
99 static lineNode *lineCurr = NULL;
101 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
102 0xE0, 0xC0, 0x80, 0x00};
103 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
104 0x07, 0x03, 0x01, 0x00};
111 /*-----------------------------------------------------------------*/
112 /* emitcode - writes the code into a file : for now it is simple */
113 /*-----------------------------------------------------------------*/
114 static void emitcode (char *inst,char *fmt, ...)
117 char lb[MAX_INLINEASM];
124 sprintf(lb,"%s\t",inst);
126 sprintf(lb,"%s",inst);
127 vsprintf(lb+(strlen(lb)),fmt,ap);
131 while (isspace(*lbp)) lbp++;
134 lineCurr = (lineCurr ?
135 connectLine(lineCurr,newLineNode(lb)) :
136 (lineHead = newLineNode(lb)));
137 lineCurr->isInline = _G.inLine;
138 lineCurr->isDebug = _G.debugLine;
142 /*-----------------------------------------------------------------*/
143 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
144 /*-----------------------------------------------------------------*/
145 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
147 bool r0iu = FALSE , r1iu = FALSE;
148 bool r0ou = FALSE , r1ou = FALSE;
150 /* the logic: if r0 & r1 used in the instruction
151 then we are in trouble otherwise */
153 /* first check if r0 & r1 are used by this
154 instruction, in which case we are in trouble */
155 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
156 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
161 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
162 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
164 /* if no usage of r0 then return it */
165 if (!r0iu && !r0ou) {
166 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
167 (*aopp)->type = AOP_R0;
169 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R0_IDX);
172 /* if no usage of r1 then return it */
173 if (!r1iu && !r1ou) {
174 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
175 (*aopp)->type = AOP_R1;
177 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R1_IDX);
180 /* now we know they both have usage */
181 /* if r0 not used in this instruction */
183 /* push it if not already pushed */
185 emitcode ("push","%s",
186 mcs51_regWithIdx(R0_IDX)->dname);
190 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
191 (*aopp)->type = AOP_R0;
193 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R0_IDX);
196 /* if r1 not used then */
199 /* push it if not already pushed */
201 emitcode ("push","%s",
202 mcs51_regWithIdx(R1_IDX)->dname);
206 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
207 (*aopp)->type = AOP_R1;
208 return mcs51_regWithIdx(R1_IDX);
212 /* I said end of world but not quite end of world yet */
213 /* if this is a result then we can push it on the stack*/
215 (*aopp)->type = AOP_STK;
220 /* other wise this is true end of the world */
221 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
222 "getFreePtr should never reach here");
226 /*-----------------------------------------------------------------*/
227 /* newAsmop - creates a new asmOp */
228 /*-----------------------------------------------------------------*/
229 static asmop *newAsmop (short type)
233 aop = Safe_calloc(1,sizeof(asmop));
238 static void genSetDPTR(int n)
242 emitcode(";", "Select standard DPTR");
243 emitcode("mov", "dps, #0x00");
247 emitcode(";", "Select alternate DPTR");
248 emitcode("mov", "dps, #0x01");
252 /*-----------------------------------------------------------------*/
253 /* pointerCode - returns the code for a pointer type */
254 /*-----------------------------------------------------------------*/
255 static int pointerCode (sym_link *etype)
258 return PTR_TYPE(SPEC_OCLS(etype));
262 /*-----------------------------------------------------------------*/
263 /* aopForSym - for a true symbol */
264 /*-----------------------------------------------------------------*/
265 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
268 memmap *space= SPEC_OCLS(sym->etype);
270 /* if already has one */
274 /* assign depending on the storage class */
275 /* if it is on the stack or indirectly addressable */
276 /* space we need to assign either r0 or r1 to it */
277 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
278 sym->aop = aop = newAsmop(0);
279 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
280 aop->size = getSize(sym->type);
282 /* now assign the address of the variable to
283 the pointer register */
284 if (aop->type != AOP_STK) {
288 emitcode("push","acc");
290 emitcode("mov","a,_bp");
291 emitcode("add","a,#0x%02x",
293 ((char)(sym->stack - _G.nRegsSaved )) :
294 ((char)sym->stack)) & 0xff);
295 emitcode("mov","%s,a",
296 aop->aopu.aop_ptr->name);
299 emitcode("pop","acc");
301 emitcode("mov","%s,#%s",
302 aop->aopu.aop_ptr->name,
304 aop->paged = space->paged;
306 aop->aopu.aop_stk = sym->stack;
310 if (sym->onStack && options.stack10bit)
312 /* It's on the 10 bit stack, which is located in
317 emitcode("push","acc");
319 emitcode("mov","a,_bp");
320 emitcode("add","a,#0x%02x",
322 ((char)(sym->stack - _G.nRegsSaved )) :
323 ((char)sym->stack)) & 0xff);
326 emitcode ("mov","dpx1,#0x40");
327 emitcode ("mov","dph1,#0x00");
328 emitcode ("mov","dpl1, a");
332 emitcode("pop","acc");
334 sym->aop = aop = newAsmop(AOP_DPTR2);
335 aop->size = getSize(sym->type);
339 /* if in bit space */
340 if (IN_BITSPACE(space)) {
341 sym->aop = aop = newAsmop (AOP_CRY);
342 aop->aopu.aop_dir = sym->rname ;
343 aop->size = getSize(sym->type);
346 /* if it is in direct space */
347 if (IN_DIRSPACE(space)) {
348 sym->aop = aop = newAsmop (AOP_DIR);
349 aop->aopu.aop_dir = sym->rname ;
350 aop->size = getSize(sym->type);
354 /* special case for a function */
355 if (IS_FUNC(sym->type)) {
356 sym->aop = aop = newAsmop(AOP_IMMD);
357 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
358 strcpy(aop->aopu.aop_immd,sym->rname);
359 aop->size = FPTRSIZE;
363 /* only remaining is far space */
364 /* in which case DPTR gets the address */
365 sym->aop = aop = newAsmop(AOP_DPTR);
366 emitcode ("mov","dptr,#%s", sym->rname);
367 aop->size = getSize(sym->type);
369 /* if it is in code space */
370 if (IN_CODESPACE(space))
376 /*-----------------------------------------------------------------*/
377 /* aopForRemat - rematerialzes an object */
378 /*-----------------------------------------------------------------*/
379 static asmop *aopForRemat (symbol *sym)
381 iCode *ic = sym->rematiCode;
382 asmop *aop = newAsmop(AOP_IMMD);
387 val += operandLitValue(IC_RIGHT(ic));
388 else if (ic->op == '-')
389 val -= operandLitValue(IC_RIGHT(ic));
393 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
397 sprintf(buffer,"(%s %c 0x%04x)",
398 OP_SYMBOL(IC_LEFT(ic))->rname,
399 val >= 0 ? '+' : '-',
402 strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
404 aop->aopu.aop_immd = Safe_calloc(1,strlen(buffer)+1);
405 strcpy(aop->aopu.aop_immd,buffer);
409 /*-----------------------------------------------------------------*/
410 /* regsInCommon - two operands have some registers in common */
411 /*-----------------------------------------------------------------*/
412 static bool regsInCommon (operand *op1, operand *op2)
417 /* if they have registers in common */
418 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
421 sym1 = OP_SYMBOL(op1);
422 sym2 = OP_SYMBOL(op2);
424 if (sym1->nRegs == 0 || sym2->nRegs == 0)
427 for (i = 0 ; i < sym1->nRegs ; i++) {
432 for (j = 0 ; j < sym2->nRegs ;j++ ) {
436 if (sym2->regs[j] == sym1->regs[i])
444 /*-----------------------------------------------------------------*/
445 /* operandsEqu - equivalent */
446 /*-----------------------------------------------------------------*/
447 static bool operandsEqu ( operand *op1, operand *op2)
451 /* if they not symbols */
452 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
455 sym1 = OP_SYMBOL(op1);
456 sym2 = OP_SYMBOL(op2);
458 /* if both are itemps & one is spilt
459 and the other is not then false */
460 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
461 sym1->isspilt != sym2->isspilt )
464 /* if they are the same */
468 if (strcmp(sym1->rname,sym2->rname) == 0)
472 /* if left is a tmp & right is not */
476 (sym1->usl.spillLoc == sym2))
483 (sym2->usl.spillLoc == sym1))
489 /*-----------------------------------------------------------------*/
490 /* sameRegs - two asmops have the same registers */
491 /*-----------------------------------------------------------------*/
492 static bool sameRegs (asmop *aop1, asmop *aop2 )
499 if (aop1->type != AOP_REG ||
500 aop2->type != AOP_REG )
503 if (aop1->size != aop2->size )
506 for (i = 0 ; i < aop1->size ; i++ )
507 if (aop1->aopu.aop_reg[i] !=
508 aop2->aopu.aop_reg[i] )
514 /*-----------------------------------------------------------------*/
515 /* aopOp - allocates an asmop for an operand : */
516 /*-----------------------------------------------------------------*/
517 static void aopOp (operand *op, iCode *ic, bool result)
526 /* if this a literal */
527 if (IS_OP_LITERAL(op)) {
528 op->aop = aop = newAsmop(AOP_LIT);
529 aop->aopu.aop_lit = op->operand.valOperand;
530 aop->size = getSize(operandType(op));
534 /* if already has a asmop then continue */
538 /* if the underlying symbol has a aop */
539 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
540 op->aop = OP_SYMBOL(op)->aop;
544 /* if this is a true symbol */
545 if (IS_TRUE_SYMOP(op)) {
546 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
550 /* this is a temporary : this has
556 e) can be a return use only */
561 /* if the type is a conditional */
562 if (sym->regType == REG_CND) {
563 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
568 /* if it is spilt then two situations
570 b) has a spill location */
571 if (sym->isspilt || sym->nRegs == 0) {
573 /* rematerialize it NOW */
575 sym->aop = op->aop = aop =
577 aop->size = getSize(sym->type);
583 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
584 aop->size = getSize(sym->type);
585 for ( i = 0 ; i < 2 ; i++ )
586 aop->aopu.aop_str[i] = accUse[i];
592 aop = op->aop = sym->aop = newAsmop(AOP_STR);
593 aop->size = getSize(sym->type);
594 for ( i = 0 ; i < fReturnSize ; i++ )
595 aop->aopu.aop_str[i] = fReturn[i];
599 /* else spill location */
600 sym->aop = op->aop = aop =
601 aopForSym(ic,sym->usl.spillLoc,result);
602 aop->size = getSize(sym->type);
606 /* must be in a register */
607 sym->aop = op->aop = aop = newAsmop(AOP_REG);
608 aop->size = sym->nRegs;
609 for ( i = 0 ; i < sym->nRegs ;i++)
610 aop->aopu.aop_reg[i] = sym->regs[i];
613 /*-----------------------------------------------------------------*/
614 /* freeAsmop - free up the asmop given to an operand */
615 /*----------------------------------------------------------------*/
616 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
633 /* depending on the asmop type only three cases need work AOP_RO
634 , AOP_R1 && AOP_STK */
639 emitcode ("pop","ar0");
643 bitVectUnSetBit(ic->rUsed,R0_IDX);
649 emitcode ("pop","ar1");
653 bitVectUnSetBit(ic->rUsed,R1_IDX);
659 int stk = aop->aopu.aop_stk + aop->size;
660 bitVectUnSetBit(ic->rUsed,R0_IDX);
661 bitVectUnSetBit(ic->rUsed,R1_IDX);
663 getFreePtr(ic,&aop,FALSE);
665 if (options.stack10bit)
667 /* I'm not sure what to do here yet... */
670 "*** Warning: probably generating bad code for "
671 "10 bit stack mode.\n");
675 emitcode ("mov","a,_bp");
676 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
677 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
679 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
683 emitcode("pop","acc");
684 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
686 emitcode("dec","%s",aop->aopu.aop_ptr->name);
689 freeAsmop(op,NULL,ic,TRUE);
691 emitcode("pop","ar0");
696 emitcode("pop","ar1");
703 /* all other cases just dealloc */
707 OP_SYMBOL(op)->aop = NULL;
708 /* if the symbol has a spill */
710 SPIL_LOC(op)->aop = NULL;
715 /*-----------------------------------------------------------------*/
716 /* aopGet - for fetching value of the aop */
717 /*-----------------------------------------------------------------*/
718 static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
723 /* offset is greater than
725 if (offset > (aop->size - 1) &&
726 aop->type != AOP_LIT)
729 /* depending on type */
734 /* if we need to increment it */
735 while (offset > aop->coff) {
736 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
740 while (offset < aop->coff) {
741 emitcode("dec","%s",aop->aopu.aop_ptr->name);
747 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
748 return (dname ? "acc" : "a");
750 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
751 rs = Safe_calloc(1,strlen(s)+1);
758 if (aop->type == AOP_DPTR2)
763 while (offset > aop->coff) {
764 emitcode ("inc","dptr");
768 while (offset < aop->coff) {
769 emitcode("lcall","__decdptr");
776 emitcode("movc","a,@a+dptr");
779 emitcode("movx","a,@dptr");
782 if (aop->type == AOP_DPTR2)
787 return (dname ? "acc" : "a");
792 sprintf (s,"#%s",aop->aopu.aop_immd);
795 sprintf(s,"#(%s >> %d)",
801 rs = Safe_calloc(1,strlen(s)+1);
807 sprintf(s,"(%s + %d)",
811 sprintf(s,"%s",aop->aopu.aop_dir);
812 rs = Safe_calloc(1,strlen(s)+1);
818 return aop->aopu.aop_reg[offset]->dname;
820 return aop->aopu.aop_reg[offset]->name;
824 emitcode("mov","c,%s",aop->aopu.aop_dir);
825 emitcode("rlc","a") ;
826 return (dname ? "acc" : "a");
829 if (!offset && dname)
831 return aop->aopu.aop_str[offset];
834 return aopLiteral (aop->aopu.aop_lit,offset);
838 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
842 return aop->aopu.aop_str[offset];
846 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
847 "aopget got unsupported aop->type");
850 /*-----------------------------------------------------------------*/
851 /* aopPut - puts a string for a aop */
852 /*-----------------------------------------------------------------*/
853 static void aopPut (asmop *aop, char *s, int offset)
858 if (aop->size && offset > ( aop->size - 1)) {
859 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
860 "aopPut got offset > aop->size");
864 /* will assign value to value */
865 /* depending on where it is ofcourse */
869 sprintf(d,"(%s + %d)",
870 aop->aopu.aop_dir,offset);
872 sprintf(d,"%s",aop->aopu.aop_dir);
875 emitcode("mov","%s,%s",d,s);
880 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
881 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
883 strcmp(s,"r0") == 0 ||
884 strcmp(s,"r1") == 0 ||
885 strcmp(s,"r2") == 0 ||
886 strcmp(s,"r3") == 0 ||
887 strcmp(s,"r4") == 0 ||
888 strcmp(s,"r5") == 0 ||
889 strcmp(s,"r6") == 0 ||
890 strcmp(s,"r7") == 0 )
891 emitcode("mov","%s,%s",
892 aop->aopu.aop_reg[offset]->dname,s);
894 emitcode("mov","%s,%s",
895 aop->aopu.aop_reg[offset]->name,s);
902 if (aop->type == AOP_DPTR2)
908 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
909 "aopPut writting to code space");
913 while (offset > aop->coff) {
915 emitcode ("inc","dptr");
918 while (offset < aop->coff) {
920 emitcode("lcall","__decdptr");
925 /* if not in accumulater */
928 emitcode ("movx","@dptr,a");
930 if (aop->type == AOP_DPTR2)
938 while (offset > aop->coff) {
940 emitcode("inc","%s",aop->aopu.aop_ptr->name);
942 while (offset < aop->coff) {
944 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
950 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
955 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
957 if (strcmp(s,"r0") == 0 ||
958 strcmp(s,"r1") == 0 ||
959 strcmp(s,"r2") == 0 ||
960 strcmp(s,"r3") == 0 ||
961 strcmp(s,"r4") == 0 ||
962 strcmp(s,"r5") == 0 ||
963 strcmp(s,"r6") == 0 ||
964 strcmp(s,"r7") == 0 ) {
966 sprintf(buffer,"a%s",s);
967 emitcode("mov","@%s,%s",
968 aop->aopu.aop_ptr->name,buffer);
970 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
975 if (strcmp(s,"a") == 0)
976 emitcode("push","acc");
978 emitcode("push","%s",s);
983 /* if bit variable */
984 if (!aop->aopu.aop_dir) {
989 emitcode("clr","%s",aop->aopu.aop_dir);
992 emitcode("setb","%s",aop->aopu.aop_dir);
995 emitcode("mov","%s,c",aop->aopu.aop_dir);
997 lbl = newiTempLabel(NULL);
1002 emitcode("clr","c");
1003 emitcode("jz","%05d$",lbl->key+100);
1004 emitcode("cpl","c");
1005 emitcode("","%05d$:",lbl->key+100);
1006 emitcode("mov","%s,c",aop->aopu.aop_dir);
1013 if (strcmp(aop->aopu.aop_str[offset],s))
1014 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1019 if (!offset && (strcmp(s,"acc") == 0))
1022 if (strcmp(aop->aopu.aop_str[offset],s))
1023 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1027 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1028 "aopPut got unsupported aop->type");
1036 /*-----------------------------------------------------------------*/
1037 /* pointToEnd :- points to the last byte of the operand */
1038 /*-----------------------------------------------------------------*/
1039 static void pointToEnd (asmop *aop)
1045 aop->coff = count = (aop->size - 1);
1046 switch (aop->type) {
1050 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1054 emitcode("inc","dptr");
1061 /*-----------------------------------------------------------------*/
1062 /* reAdjustPreg - points a register back to where it should */
1063 /*-----------------------------------------------------------------*/
1064 static void reAdjustPreg (asmop *aop)
1069 if ((size = aop->size) <= 1)
1072 switch (aop->type) {
1076 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1080 if (aop->type == AOP_DPTR2)
1086 emitcode("lcall","__decdptr");
1089 if (aop->type == AOP_DPTR2)
1099 #define AOP(op) op->aop
1100 #define AOP_TYPE(op) AOP(op)->type
1101 #define AOP_SIZE(op) AOP(op)->size
1102 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1103 AOP_TYPE(x) == AOP_R0))
1105 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1106 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1109 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1110 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1111 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1113 /*-----------------------------------------------------------------*/
1114 /* genNotFloat - generates not for float operations */
1115 /*-----------------------------------------------------------------*/
1116 static void genNotFloat (operand *op, operand *res)
1122 /* we will put 127 in the first byte of
1124 aopPut(AOP(res),"#127",0);
1125 size = AOP_SIZE(op) - 1;
1128 l = aopGet(op->aop,offset++,FALSE,FALSE);
1132 emitcode("orl","a,%s",
1134 offset++,FALSE,FALSE));
1136 tlbl = newiTempLabel(NULL);
1138 tlbl = newiTempLabel(NULL);
1139 aopPut(res->aop,one,1);
1140 emitcode("jz","%05d$",(tlbl->key+100));
1141 aopPut(res->aop,zero,1);
1142 emitcode("","%05d$:",(tlbl->key+100));
1144 size = res->aop->size - 2;
1146 /* put zeros in the rest */
1148 aopPut(res->aop,zero,offset++);
1151 /*-----------------------------------------------------------------*/
1152 /* opIsGptr: returns non-zero if the passed operand is */
1153 /* a generic pointer type. */
1154 /*-----------------------------------------------------------------*/
1155 static int opIsGptr(operand *op)
1157 sym_link *type = operandType(op);
1159 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1166 /*-----------------------------------------------------------------*/
1167 /* getDataSize - get the operand data size */
1168 /*-----------------------------------------------------------------*/
1169 static int getDataSize(operand *op)
1172 size = AOP_SIZE(op);
1173 if (size == GPTRSIZE)
1175 sym_link *type = operandType(op);
1176 if (IS_GENPTR(type))
1178 /* generic pointer; arithmetic operations
1179 * should ignore the high byte (pointer type).
1187 /*-----------------------------------------------------------------*/
1188 /* outAcc - output Acc */
1189 /*-----------------------------------------------------------------*/
1190 static void outAcc(operand *result)
1193 size = getDataSize(result);
1195 aopPut(AOP(result),"a",0);
1198 /* unsigned or positive */
1200 aopPut(AOP(result),zero,offset++);
1205 /*-----------------------------------------------------------------*/
1206 /* outBitC - output a bit C */
1207 /*-----------------------------------------------------------------*/
1208 static void outBitC(operand *result)
1210 /* if the result is bit */
1211 if (AOP_TYPE(result) == AOP_CRY)
1212 aopPut(AOP(result),"c",0);
1214 emitcode("clr","a");
1215 emitcode("rlc","a");
1220 /*-----------------------------------------------------------------*/
1221 /* toBoolean - emit code for orl a,operator(sizeop) */
1222 /*-----------------------------------------------------------------*/
1223 static void toBoolean(operand *oper)
1225 int size = AOP_SIZE(oper) - 1;
1227 MOVA(aopGet(AOP(oper),0,FALSE,FALSE));
1229 emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE));
1233 /*-----------------------------------------------------------------*/
1234 /* genNot - generate code for ! operation */
1235 /*-----------------------------------------------------------------*/
1236 static void genNot (iCode *ic)
1239 sym_link *optype = operandType(IC_LEFT(ic));
1241 /* assign asmOps to operand & result */
1242 aopOp (IC_LEFT(ic),ic,FALSE);
1243 aopOp (IC_RESULT(ic),ic,TRUE);
1245 /* if in bit space then a special case */
1246 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1247 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1248 emitcode("cpl","c");
1249 outBitC(IC_RESULT(ic));
1253 /* if type float then do float */
1254 if (IS_FLOAT(optype)) {
1255 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1259 toBoolean(IC_LEFT(ic));
1261 tlbl = newiTempLabel(NULL);
1262 emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1263 emitcode("","%05d$:",tlbl->key+100);
1264 outBitC(IC_RESULT(ic));
1267 /* release the aops */
1268 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1269 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1273 /*-----------------------------------------------------------------*/
1274 /* genCpl - generate code for complement */
1275 /*-----------------------------------------------------------------*/
1276 static void genCpl (iCode *ic)
1282 /* assign asmOps to operand & result */
1283 aopOp (IC_LEFT(ic),ic,FALSE);
1284 aopOp (IC_RESULT(ic),ic,TRUE);
1286 /* if both are in bit space then
1288 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1289 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1291 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1292 emitcode("cpl","c");
1293 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1297 size = AOP_SIZE(IC_RESULT(ic));
1299 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1301 emitcode("cpl","a");
1302 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1307 /* release the aops */
1308 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1309 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1312 /*-----------------------------------------------------------------*/
1313 /* genUminusFloat - unary minus for floating points */
1314 /*-----------------------------------------------------------------*/
1315 static void genUminusFloat(operand *op,operand *result)
1317 int size ,offset =0 ;
1319 /* for this we just need to flip the
1320 first it then copy the rest in place */
1321 size = AOP_SIZE(op) - 1;
1322 l = aopGet(AOP(op),3,FALSE,FALSE);
1326 emitcode("cpl","acc.7");
1327 aopPut(AOP(result),"a",3);
1331 aopGet(AOP(op),offset,FALSE,FALSE),
1337 /*-----------------------------------------------------------------*/
1338 /* genUminus - unary minus code generation */
1339 /*-----------------------------------------------------------------*/
1340 static void genUminus (iCode *ic)
1343 sym_link *optype, *rtype;
1347 aopOp(IC_LEFT(ic),ic,FALSE);
1348 aopOp(IC_RESULT(ic),ic,TRUE);
1350 /* if both in bit space then special
1352 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1353 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1355 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1356 emitcode("cpl","c");
1357 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1361 optype = operandType(IC_LEFT(ic));
1362 rtype = operandType(IC_RESULT(ic));
1364 /* if float then do float stuff */
1365 if (IS_FLOAT(optype)) {
1366 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1370 /* otherwise subtract from zero */
1371 size = AOP_SIZE(IC_LEFT(ic));
1375 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1376 if (!strcmp(l,"a")) {
1379 emitcode("cpl","a");
1380 emitcode("addc","a,#0");
1384 emitcode("clr","a");
1385 emitcode("subb","a,%s",l);
1387 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1390 /* if any remaining bytes in the result */
1391 /* we just need to propagate the sign */
1392 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1393 emitcode("rlc","a");
1394 emitcode("subb","a,acc");
1396 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1400 /* release the aops */
1401 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1402 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1405 /*-----------------------------------------------------------------*/
1406 /* saveRegisters - will look for a call and save the registers */
1407 /*-----------------------------------------------------------------*/
1408 static void saveRegisters(iCode *lic)
1416 for (ic = lic ; ic ; ic = ic->next)
1417 if (ic->op == CALL || ic->op == PCALL)
1421 fprintf(stderr,"found parameter push with no function call\n");
1425 /* if the registers have been saved already then
1427 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1430 /* find the registers in use at this time
1431 and push them away to safety */
1432 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1436 if (options.useXstack) {
1437 if (bitVectBitValue(rsave,R0_IDX))
1438 emitcode("mov","b,r0");
1439 emitcode("mov","r0,%s",spname);
1440 for (i = 0 ; i < mcs51_nRegs ; i++) {
1441 if (bitVectBitValue(rsave,i)) {
1443 emitcode("mov","a,b");
1445 emitcode("mov","a,%s",mcs51_regWithIdx(i)->name);
1446 emitcode("movx","@r0,a");
1447 emitcode("inc","r0");
1450 emitcode("mov","%s,r0",spname);
1451 if (bitVectBitValue(rsave,R0_IDX))
1452 emitcode("mov","r0,b");
1454 for (i = 0 ; i < mcs51_nRegs ; i++) {
1455 if (bitVectBitValue(rsave,i))
1456 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
1459 detype = getSpec(operandType(IC_LEFT(ic)));
1461 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1462 IS_ISR(currFunc->etype) &&
1465 saverbank(SPEC_BANK(detype),ic,TRUE);
1468 /*-----------------------------------------------------------------*/
1469 /* unsaveRegisters - pop the pushed registers */
1470 /*-----------------------------------------------------------------*/
1471 static void unsaveRegisters (iCode *ic)
1475 /* find the registers in use at this time
1476 and push them away to safety */
1477 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1480 if (options.useXstack) {
1481 emitcode("mov","r0,%s",spname);
1482 for (i = mcs51_nRegs ; i >= 0 ; i--) {
1483 if (bitVectBitValue(rsave,i)) {
1484 emitcode("dec","r0");
1485 emitcode("movx","a,@r0");
1487 emitcode("mov","b,a");
1489 emitcode("mov","%s,a",mcs51_regWithIdx(i)->name);
1493 emitcode("mov","%s,r0",spname);
1494 if (bitVectBitValue(rsave,R0_IDX))
1495 emitcode("mov","r0,b");
1497 for (i = mcs51_nRegs ; i >= 0 ; i--) {
1498 if (bitVectBitValue(rsave,i))
1499 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
1505 /*-----------------------------------------------------------------*/
1507 /*-----------------------------------------------------------------*/
1508 static void pushSide(operand * oper, int size)
1512 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1513 if (AOP_TYPE(oper) != AOP_REG &&
1514 AOP_TYPE(oper) != AOP_DIR &&
1516 emitcode("mov","a,%s",l);
1517 emitcode("push","acc");
1519 emitcode("push","%s",l);
1523 /*-----------------------------------------------------------------*/
1524 /* assignResultValue - */
1525 /*-----------------------------------------------------------------*/
1526 static void assignResultValue(operand * oper)
1529 int size = AOP_SIZE(oper);
1531 aopPut(AOP(oper),fReturn[offset],offset);
1537 /*-----------------------------------------------------------------*/
1538 /* genXpush - pushes onto the external stack */
1539 /*-----------------------------------------------------------------*/
1540 static void genXpush (iCode *ic)
1542 asmop *aop = newAsmop(0);
1544 int size,offset = 0;
1546 aopOp(IC_LEFT(ic),ic,FALSE);
1547 r = getFreePtr(ic,&aop,FALSE);
1550 emitcode("mov","%s,_spx",r->name);
1552 size = AOP_SIZE(IC_LEFT(ic));
1555 char *l = aopGet(AOP(IC_LEFT(ic)),
1556 offset++,FALSE,FALSE);
1558 emitcode("movx","@%s,a",r->name);
1559 emitcode("inc","%s",r->name);
1564 emitcode("mov","_spx,%s",r->name);
1566 freeAsmop(NULL,aop,ic,TRUE);
1567 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1570 /*-----------------------------------------------------------------*/
1571 /* genIpush - genrate code for pushing this gets a little complex */
1572 /*-----------------------------------------------------------------*/
1573 static void genIpush (iCode *ic)
1575 int size, offset = 0 ;
1579 /* if this is not a parm push : ie. it is spill push
1580 and spill push is always done on the local stack */
1581 if (!ic->parmPush) {
1583 /* and the item is spilt then do nothing */
1584 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1587 aopOp(IC_LEFT(ic),ic,FALSE);
1588 size = AOP_SIZE(IC_LEFT(ic));
1589 /* push it on the stack */
1591 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1596 emitcode("push","%s",l);
1601 /* this is a paramter push: in this case we call
1602 the routine to find the call and save those
1603 registers that need to be saved */
1606 /* if use external stack then call the external
1607 stack pushing routine */
1608 if (options.useXstack) {
1613 /* then do the push */
1614 aopOp(IC_LEFT(ic),ic,FALSE);
1617 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1618 size = AOP_SIZE(IC_LEFT(ic));
1621 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1622 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1623 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1625 emitcode("mov","a,%s",l);
1626 emitcode("push","acc");
1628 emitcode("push","%s",l);
1631 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1634 /*-----------------------------------------------------------------*/
1635 /* genIpop - recover the registers: can happen only for spilling */
1636 /*-----------------------------------------------------------------*/
1637 static void genIpop (iCode *ic)
1642 /* if the temp was not pushed then */
1643 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1646 aopOp(IC_LEFT(ic),ic,FALSE);
1647 size = AOP_SIZE(IC_LEFT(ic));
1650 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1653 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1656 /*-----------------------------------------------------------------*/
1657 /* unsaverbank - restores the resgister bank from stack */
1658 /*-----------------------------------------------------------------*/
1659 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1666 if (options.useXstack) {
1668 r = getFreePtr(ic,&aop,FALSE);
1671 emitcode("mov","%s,_spx",r->name);
1672 emitcode("movx","a,@%s",r->name);
1673 emitcode("mov","psw,a");
1674 emitcode("dec","%s",r->name);
1677 emitcode ("pop","psw");
1680 for (i = (mcs51_nRegs - 1) ; i >= 0 ;i--) {
1681 if (options.useXstack) {
1682 emitcode("movx","a,@%s",r->name);
1683 emitcode("mov","(%s+%d),a",
1684 regs8051[i].base,8*bank+regs8051[i].offset);
1685 emitcode("dec","%s",r->name);
1688 emitcode("pop","(%s+%d)",
1689 regs8051[i].base,8*bank+regs8051[i].offset);
1692 if (options.useXstack) {
1694 emitcode("mov","_spx,%s",r->name);
1695 freeAsmop(NULL,aop,ic,TRUE);
1700 /*-----------------------------------------------------------------*/
1701 /* saverbank - saves an entire register bank on the stack */
1702 /*-----------------------------------------------------------------*/
1703 static void saverbank (int bank, iCode *ic, bool pushPsw)
1709 if (options.useXstack) {
1712 r = getFreePtr(ic,&aop,FALSE);
1713 emitcode("mov","%s,_spx",r->name);
1717 for (i = 0 ; i < mcs51_nRegs ;i++) {
1718 if (options.useXstack) {
1719 emitcode("inc","%s",r->name);
1720 emitcode("mov","a,(%s+%d)",
1721 regs8051[i].base,8*bank+regs8051[i].offset);
1722 emitcode("movx","@%s,a",r->name);
1724 emitcode("push","(%s+%d)",
1725 regs8051[i].base,8*bank+regs8051[i].offset);
1729 if (options.useXstack) {
1730 emitcode("mov","a,psw");
1731 emitcode("movx","@%s,a",r->name);
1732 emitcode("inc","%s",r->name);
1733 emitcode("mov","_spx,%s",r->name);
1734 freeAsmop (NULL,aop,ic,TRUE);
1737 emitcode("push","psw");
1739 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1745 /*-----------------------------------------------------------------*/
1746 /* genCall - generates a call statement */
1747 /*-----------------------------------------------------------------*/
1748 static void genCall (iCode *ic)
1752 /* if caller saves & we have not saved then */
1756 /* if we are calling a function that is not using
1757 the same register bank then we need to save the
1758 destination registers on the stack */
1759 detype = getSpec(operandType(IC_LEFT(ic)));
1761 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1762 IS_ISR(currFunc->etype) &&
1765 saverbank(SPEC_BANK(detype),ic,TRUE);
1767 /* if send set is not empty the assign */
1771 for (sic = setFirstItem(_G.sendSet) ; sic ;
1772 sic = setNextItem(_G.sendSet)) {
1773 int size, offset = 0;
1774 aopOp(IC_LEFT(sic),sic,FALSE);
1775 size = AOP_SIZE(IC_LEFT(sic));
1777 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1779 if (strcmp(l,fReturn[offset]))
1780 emitcode("mov","%s,%s",
1785 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1790 emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1791 OP_SYMBOL(IC_LEFT(ic))->rname :
1792 OP_SYMBOL(IC_LEFT(ic))->name));
1794 /* if we need assign a result value */
1795 if ((IS_ITEMP(IC_RESULT(ic)) &&
1796 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1797 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1798 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1801 aopOp(IC_RESULT(ic),ic,FALSE);
1804 assignResultValue(IC_RESULT(ic));
1806 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1809 /* adjust the stack for parameters if
1811 if (IC_LEFT(ic)->parmBytes) {
1813 if (IC_LEFT(ic)->parmBytes > 3) {
1814 emitcode("mov","a,%s",spname);
1815 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1816 emitcode("mov","%s,a",spname);
1818 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1819 emitcode("dec","%s",spname);
1823 /* if register bank was saved then pop them */
1825 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1827 /* if we hade saved some registers then unsave them */
1828 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1829 unsaveRegisters (ic);
1834 /*-----------------------------------------------------------------*/
1835 /* genPcall - generates a call by pointer statement */
1836 /*-----------------------------------------------------------------*/
1837 static void genPcall (iCode *ic)
1840 symbol *rlbl = newiTempLabel(NULL);
1843 /* if caller saves & we have not saved then */
1847 /* if we are calling a function that is not using
1848 the same register bank then we need to save the
1849 destination registers on the stack */
1850 detype = getSpec(operandType(IC_LEFT(ic)));
1852 IS_ISR(currFunc->etype) &&
1853 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
1854 saverbank(SPEC_BANK(detype),ic,TRUE);
1857 /* push the return address on to the stack */
1858 emitcode("mov","a,#%05d$",(rlbl->key+100));
1859 emitcode("push","acc");
1860 emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
1861 emitcode("push","acc");
1863 if (options.model == MODEL_FLAT24)
1865 emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
1866 emitcode("push","acc");
1869 /* now push the calling address */
1870 aopOp(IC_LEFT(ic),ic,FALSE);
1872 pushSide(IC_LEFT(ic), FPTRSIZE);
1874 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1876 /* if send set is not empty the assign */
1880 for (sic = setFirstItem(_G.sendSet) ; sic ;
1881 sic = setNextItem(_G.sendSet)) {
1882 int size, offset = 0;
1883 aopOp(IC_LEFT(sic),sic,FALSE);
1884 size = AOP_SIZE(IC_LEFT(sic));
1886 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1888 if (strcmp(l,fReturn[offset]))
1889 emitcode("mov","%s,%s",
1894 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1900 emitcode("","%05d$:",(rlbl->key+100));
1903 /* if we need assign a result value */
1904 if ((IS_ITEMP(IC_RESULT(ic)) &&
1905 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1906 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
1907 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1910 aopOp(IC_RESULT(ic),ic,FALSE);
1913 assignResultValue(IC_RESULT(ic));
1915 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1918 /* adjust the stack for parameters if
1920 if (IC_LEFT(ic)->parmBytes) {
1922 if (IC_LEFT(ic)->parmBytes > 3) {
1923 emitcode("mov","a,%s",spname);
1924 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1925 emitcode("mov","%s,a",spname);
1927 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1928 emitcode("dec","%s",spname);
1932 /* if register bank was saved then unsave them */
1934 (SPEC_BANK(currFunc->etype) !=
1936 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1938 /* if we hade saved some registers then
1941 unsaveRegisters (ic);
1945 /*-----------------------------------------------------------------*/
1946 /* resultRemat - result is rematerializable */
1947 /*-----------------------------------------------------------------*/
1948 static int resultRemat (iCode *ic)
1950 if (SKIP_IC(ic) || ic->op == IFX)
1953 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1954 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1955 if (sym->remat && !POINTER_SET(ic))
1962 #if defined(__BORLANDC__) || defined(_MSC_VER)
1963 #define STRCASECMP stricmp
1965 #define STRCASECMP strcasecmp
1968 /*-----------------------------------------------------------------*/
1969 /* inExcludeList - return 1 if the string is in exclude Reg list */
1970 /*-----------------------------------------------------------------*/
1971 static bool inExcludeList(char *s)
1975 if (options.excludeRegs[i] &&
1976 STRCASECMP(options.excludeRegs[i],"none") == 0)
1979 for ( i = 0 ; options.excludeRegs[i]; i++) {
1980 if (options.excludeRegs[i] &&
1981 STRCASECMP(s,options.excludeRegs[i]) == 0)
1987 /*-----------------------------------------------------------------*/
1988 /* genFunction - generated code for function entry */
1989 /*-----------------------------------------------------------------*/
1990 static void genFunction (iCode *ic)
1996 /* create the function header */
1997 emitcode(";","-----------------------------------------");
1998 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1999 emitcode(";","-----------------------------------------");
2001 emitcode("","%s:",sym->rname);
2002 fetype = getSpec(operandType(IC_LEFT(ic)));
2004 /* if critical function then turn interrupts off */
2005 if (SPEC_CRTCL(fetype))
2006 emitcode("clr","ea");
2008 /* here we need to generate the equates for the
2009 register bank if required */
2010 if (SPEC_BANK(fetype) != rbank) {
2013 rbank = SPEC_BANK(fetype);
2014 for ( i = 0 ; i < mcs51_nRegs ; i++ ) {
2015 if (strcmp(regs8051[i].base,"0") == 0)
2016 emitcode("","%s = 0x%02x",
2018 8*rbank+regs8051[i].offset);
2020 emitcode ("","%s = %s + 0x%02x",
2023 8*rbank+regs8051[i].offset);
2027 /* if this is an interrupt service routine then
2028 save acc, b, dpl, dph */
2029 if (IS_ISR(sym->etype)) {
2031 if (!inExcludeList("acc"))
2032 emitcode ("push","acc");
2033 if (!inExcludeList("b"))
2034 emitcode ("push","b");
2035 if (!inExcludeList("dpl"))
2036 emitcode ("push","dpl");
2037 if (!inExcludeList("dph"))
2038 emitcode ("push","dph");
2039 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2041 emitcode ("push", "dpx");
2042 /* Make sure we're using standard DPTR */
2043 emitcode ("push", "dps");
2044 emitcode ("mov", "dps, #0x00");
2045 if (options.stack10bit)
2047 /* This ISR could conceivably use DPTR2. Better save it. */
2048 emitcode ("push", "dpl1");
2049 emitcode ("push", "dph1");
2050 emitcode ("push", "dpx1");
2053 /* if this isr has no bank i.e. is going to
2054 run with bank 0 , then we need to save more
2056 if (!SPEC_BANK(sym->etype)) {
2058 /* if this function does not call any other
2059 function then we can be economical and
2060 save only those registers that are used */
2061 if (! sym->hasFcall) {
2064 /* if any registers used */
2065 if (sym->regsUsed) {
2066 /* save the registers used */
2067 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2068 if (bitVectBitValue(sym->regsUsed,i) ||
2069 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2070 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
2075 /* this function has a function call cannot
2076 determines register usage so we will have the
2078 saverbank(0,ic,FALSE);
2082 /* if callee-save to be used for this function
2083 then save the registers being used in this function */
2084 if (sym->calleeSave) {
2087 /* if any registers used */
2088 if (sym->regsUsed) {
2089 /* save the registers used */
2090 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2091 if (bitVectBitValue(sym->regsUsed,i) ||
2092 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2093 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
2101 /* set the register bank to the desired value */
2102 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2103 emitcode("push","psw");
2104 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2107 if (IS_RENT(sym->etype) || options.stackAuto) {
2109 if (options.useXstack) {
2110 emitcode("mov","r0,%s",spname);
2111 emitcode("mov","a,_bp");
2112 emitcode("movx","@r0,a");
2113 emitcode("inc","%s",spname);
2117 /* set up the stack */
2118 emitcode ("push","_bp"); /* save the callers stack */
2120 emitcode ("mov","_bp,%s",spname);
2123 /* adjust the stack for the function */
2128 werror(W_STACK_OVERFLOW,sym->name);
2130 if (i > 3 && sym->recvSize < 4) {
2132 emitcode ("mov","a,sp");
2133 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2134 emitcode ("mov","sp,a");
2139 emitcode("inc","sp");
2144 emitcode ("mov","a,_spx");
2145 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2146 emitcode ("mov","_spx,a");
2151 /*-----------------------------------------------------------------*/
2152 /* genEndFunction - generates epilogue for functions */
2153 /*-----------------------------------------------------------------*/
2154 static void genEndFunction (iCode *ic)
2156 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2158 if (IS_RENT(sym->etype) || options.stackAuto)
2160 emitcode ("mov","%s,_bp",spname);
2163 /* if use external stack but some variables were
2164 added to the local stack then decrement the
2166 if (options.useXstack && sym->stack) {
2167 emitcode("mov","a,sp");
2168 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2169 emitcode("mov","sp,a");
2173 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2174 if (options.useXstack) {
2175 emitcode("mov","r0,%s",spname);
2176 emitcode("movx","a,@r0");
2177 emitcode("mov","_bp,a");
2178 emitcode("dec","%s",spname);
2182 emitcode ("pop","_bp");
2186 /* restore the register bank */
2187 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2188 emitcode ("pop","psw");
2190 if (IS_ISR(sym->etype)) {
2192 /* now we need to restore the registers */
2193 /* if this isr has no bank i.e. is going to
2194 run with bank 0 , then we need to save more
2196 if (!SPEC_BANK(sym->etype)) {
2198 /* if this function does not call any other
2199 function then we can be economical and
2200 save only those registers that are used */
2201 if (! sym->hasFcall) {
2204 /* if any registers used */
2205 if (sym->regsUsed) {
2206 /* save the registers used */
2207 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2208 if (bitVectBitValue(sym->regsUsed,i) ||
2209 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2210 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
2215 /* this function has a function call cannot
2216 determines register usage so we will have the
2218 unsaverbank(0,ic,FALSE);
2222 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2224 if (options.stack10bit)
2226 emitcode ("pop", "dpx1");
2227 emitcode ("pop", "dph1");
2228 emitcode ("pop", "dpl1");
2230 emitcode ("pop", "dps");
2231 emitcode ("pop", "dpx");
2233 if (!inExcludeList("dph"))
2234 emitcode ("pop","dph");
2235 if (!inExcludeList("dpl"))
2236 emitcode ("pop","dpl");
2237 if (!inExcludeList("b"))
2238 emitcode ("pop","b");
2239 if (!inExcludeList("acc"))
2240 emitcode ("pop","acc");
2242 if (SPEC_CRTCL(sym->etype))
2243 emitcode("setb","ea");
2245 /* if debug then send end of function */
2246 /* if (options.debug && currFunc) { */
2249 emitcode("","C$%s$%d$%d$%d ==.",
2250 ic->filename,currFunc->lastLine,
2251 ic->level,ic->block);
2252 if (IS_STATIC(currFunc->etype))
2253 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2255 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2259 emitcode ("reti","");
2262 if (SPEC_CRTCL(sym->etype))
2263 emitcode("setb","ea");
2265 if (sym->calleeSave) {
2268 /* if any registers used */
2269 if (sym->regsUsed) {
2270 /* save the registers used */
2271 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2272 if (bitVectBitValue(sym->regsUsed,i) ||
2273 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2274 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
2280 /* if debug then send end of function */
2283 emitcode("","C$%s$%d$%d$%d ==.",
2284 ic->filename,currFunc->lastLine,
2285 ic->level,ic->block);
2286 if (IS_STATIC(currFunc->etype))
2287 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2289 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2293 emitcode ("ret","");
2298 /*-----------------------------------------------------------------*/
2299 /* genRet - generate code for return statement */
2300 /*-----------------------------------------------------------------*/
2301 static void genRet (iCode *ic)
2303 int size,offset = 0 , pushed = 0;
2305 /* if we have no return value then
2306 just generate the "ret" */
2310 /* we have something to return then
2311 move the return value into place */
2312 aopOp(IC_LEFT(ic),ic,FALSE);
2313 size = AOP_SIZE(IC_LEFT(ic));
2317 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2319 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2321 emitcode("push","%s",l);
2324 l = aopGet(AOP(IC_LEFT(ic)),offset,
2326 if (strcmp(fReturn[offset],l))
2327 emitcode("mov","%s,%s",fReturn[offset++],l);
2334 if (strcmp(fReturn[pushed],"a"))
2335 emitcode("pop",fReturn[pushed]);
2337 emitcode("pop","acc");
2340 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2343 /* generate a jump to the return label
2344 if the next is not the return statement */
2345 if (!(ic->next && ic->next->op == LABEL &&
2346 IC_LABEL(ic->next) == returnLabel))
2348 emitcode("ljmp","%05d$",(returnLabel->key+100));
2352 /*-----------------------------------------------------------------*/
2353 /* genLabel - generates a label */
2354 /*-----------------------------------------------------------------*/
2355 static void genLabel (iCode *ic)
2357 /* special case never generate */
2358 if (IC_LABEL(ic) == entryLabel)
2361 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2364 /*-----------------------------------------------------------------*/
2365 /* genGoto - generates a ljmp */
2366 /*-----------------------------------------------------------------*/
2367 static void genGoto (iCode *ic)
2369 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2372 /*-----------------------------------------------------------------*/
2373 /* findLabelBackwards: walks back through the iCode chain looking */
2374 /* for the given label. Returns number of iCode instructions */
2375 /* between that label and given ic. */
2376 /* Returns zero if label not found. */
2377 /*-----------------------------------------------------------------*/
2378 static int findLabelBackwards(iCode *ic, int key)
2387 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2389 /* printf("findLabelBackwards = %d\n", count); */
2397 /*-----------------------------------------------------------------*/
2398 /* genPlusIncr :- does addition with increment if possible */
2399 /*-----------------------------------------------------------------*/
2400 static bool genPlusIncr (iCode *ic)
2402 unsigned int icount ;
2403 unsigned int size = getDataSize(IC_RESULT(ic));
2405 /* will try to generate an increment */
2406 /* if the right side is not a literal
2408 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2411 /* if the literal value of the right hand side
2412 is greater than 4 then it is not worth it */
2413 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2416 /* if increment 16 bits in register */
2417 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2424 /* If the next instruction is a goto and the goto target
2425 * is < 10 instructions previous to this, we can generate
2426 * jumps straight to that target.
2428 if (ic->next && ic->next->op == GOTO
2429 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2430 && labelRange <= 10 )
2432 emitcode(";", "tail increment optimized");
2433 tlbl = IC_LABEL(ic->next);
2438 tlbl = newiTempLabel(NULL);
2441 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2442 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2443 IS_AOP_PREG(IC_RESULT(ic)))
2444 emitcode("cjne","%s,#0x00,%05d$"
2445 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2448 emitcode("clr","a");
2449 emitcode("cjne","a,%s,%05d$"
2450 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2454 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2457 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2458 IS_AOP_PREG(IC_RESULT(ic)))
2459 emitcode("cjne","%s,#0x00,%05d$"
2460 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2463 emitcode("cjne","a,%s,%05d$"
2464 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2467 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2471 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2472 IS_AOP_PREG(IC_RESULT(ic)))
2473 emitcode("cjne","%s,#0x00,%05d$"
2474 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2477 emitcode("cjne","a,%s,%05d$"
2478 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2481 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2486 emitcode("","%05d$:",tlbl->key+100);
2491 /* if the sizes are greater than 1 then we cannot */
2492 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2493 AOP_SIZE(IC_LEFT(ic)) > 1 )
2496 /* we can if the aops of the left & result match or
2497 if they are in registers and the registers are the
2499 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2502 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2503 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2504 aopPut(AOP(IC_RESULT(ic)),"a",0);
2508 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2517 /*-----------------------------------------------------------------*/
2518 /* outBitAcc - output a bit in acc */
2519 /*-----------------------------------------------------------------*/
2520 static void outBitAcc(operand *result)
2522 symbol *tlbl = newiTempLabel(NULL);
2523 /* if the result is a bit */
2524 if (AOP_TYPE(result) == AOP_CRY){
2525 aopPut(AOP(result),"a",0);
2528 emitcode("jz","%05d$",tlbl->key+100);
2529 emitcode("mov","a,%s",one);
2530 emitcode("","%05d$:",tlbl->key+100);
2535 /*-----------------------------------------------------------------*/
2536 /* genPlusBits - generates code for addition of two bits */
2537 /*-----------------------------------------------------------------*/
2538 static void genPlusBits (iCode *ic)
2540 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2541 symbol *lbl = newiTempLabel(NULL);
2542 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2543 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2544 emitcode("cpl","c");
2545 emitcode("","%05d$:",(lbl->key+100));
2546 outBitC(IC_RESULT(ic));
2549 emitcode("clr","a");
2550 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2551 emitcode("rlc","a");
2552 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2553 emitcode("addc","a,#0x00");
2554 outAcc(IC_RESULT(ic));
2559 /* This is the original version of this code.
2561 * This is being kept around for reference,
2562 * because I am not entirely sure I got it right...
2564 static void adjustArithmeticResult(iCode *ic)
2566 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2567 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2568 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2569 aopPut(AOP(IC_RESULT(ic)),
2570 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2573 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2574 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
2575 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2576 aopPut(AOP(IC_RESULT(ic)),
2577 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2580 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2581 AOP_SIZE(IC_LEFT(ic)) < 3 &&
2582 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
2583 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2584 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2586 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2587 aopPut(AOP(IC_RESULT(ic)),buffer,2);
2591 /* This is the pure and virtuous version of this code.
2592 * I'm pretty certain it's right, but not enough to toss the old
2595 static void adjustArithmeticResult(iCode *ic)
2597 if (opIsGptr(IC_RESULT(ic)) &&
2598 opIsGptr(IC_LEFT(ic)) &&
2599 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2601 aopPut(AOP(IC_RESULT(ic)),
2602 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
2606 if (opIsGptr(IC_RESULT(ic)) &&
2607 opIsGptr(IC_RIGHT(ic)) &&
2608 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2610 aopPut(AOP(IC_RESULT(ic)),
2611 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
2615 if (opIsGptr(IC_RESULT(ic)) &&
2616 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2617 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2618 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2619 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2621 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2622 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2627 /*-----------------------------------------------------------------*/
2628 /* genPlus - generates code for addition */
2629 /*-----------------------------------------------------------------*/
2630 static void genPlus (iCode *ic)
2632 int size, offset = 0;
2634 /* special cases :- */
2636 aopOp (IC_LEFT(ic),ic,FALSE);
2637 aopOp (IC_RIGHT(ic),ic,FALSE);
2638 aopOp (IC_RESULT(ic),ic,TRUE);
2640 /* if literal, literal on the right or
2641 if left requires ACC or right is already
2643 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2644 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2645 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2646 operand *t = IC_RIGHT(ic);
2647 IC_RIGHT(ic) = IC_LEFT(ic);
2651 /* if both left & right are in bit
2653 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2654 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2659 /* if left in bit space & right literal */
2660 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2661 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2662 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2663 /* if result in bit space */
2664 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2665 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
2666 emitcode("cpl","c");
2667 outBitC(IC_RESULT(ic));
2669 size = getDataSize(IC_RESULT(ic));
2671 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2672 emitcode("addc","a,#00");
2673 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2679 /* if I can do an increment instead
2680 of add then GOOD for ME */
2681 if (genPlusIncr (ic) == TRUE)
2684 size = getDataSize(IC_RESULT(ic));
2687 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2688 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2690 emitcode("add","a,%s",
2691 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2693 emitcode("addc","a,%s",
2694 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2696 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2698 emitcode("add","a,%s",
2699 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2701 emitcode("addc","a,%s",
2702 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2704 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2707 adjustArithmeticResult(ic);
2710 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2711 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2712 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2715 /*-----------------------------------------------------------------*/
2716 /* genMinusDec :- does subtraction with deccrement if possible */
2717 /*-----------------------------------------------------------------*/
2718 static bool genMinusDec (iCode *ic)
2720 unsigned int icount ;
2721 unsigned int size = getDataSize(IC_RESULT(ic));
2723 /* will try to generate an increment */
2724 /* if the right side is not a literal
2726 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2729 /* if the literal value of the right hand side
2730 is greater than 4 then it is not worth it */
2731 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2734 /* if decrement 16 bits in register */
2735 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2742 /* If the next instruction is a goto and the goto target
2743 * is <= 10 instructions previous to this, we can generate
2744 * jumps straight to that target.
2746 if (ic->next && ic->next->op == GOTO
2747 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2748 && labelRange <= 10 )
2750 emitcode(";", "tail decrement optimized");
2751 tlbl = IC_LABEL(ic->next);
2756 tlbl = newiTempLabel(NULL);
2760 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2761 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2762 IS_AOP_PREG(IC_RESULT(ic)))
2763 emitcode("cjne","%s,#0xff,%05d$"
2764 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2767 emitcode("mov","a,#0xff");
2768 emitcode("cjne","a,%s,%05d$"
2769 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2772 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2775 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2776 IS_AOP_PREG(IC_RESULT(ic)))
2777 emitcode("cjne","%s,#0xff,%05d$"
2778 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2781 emitcode("cjne","a,%s,%05d$"
2782 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2785 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2789 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2790 IS_AOP_PREG(IC_RESULT(ic)))
2791 emitcode("cjne","%s,#0xff,%05d$"
2792 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2795 emitcode("cjne","a,%s,%05d$"
2796 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2799 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2803 emitcode("","%05d$:",tlbl->key+100);
2808 /* if the sizes are greater than 1 then we cannot */
2809 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2810 AOP_SIZE(IC_LEFT(ic)) > 1 )
2813 /* we can if the aops of the left & result match or
2814 if they are in registers and the registers are the
2816 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2819 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2827 /*-----------------------------------------------------------------*/
2828 /* addSign - complete with sign */
2829 /*-----------------------------------------------------------------*/
2830 static void addSign(operand *result, int offset, int sign)
2832 int size = (getDataSize(result) - offset);
2835 emitcode("rlc","a");
2836 emitcode("subb","a,acc");
2838 aopPut(AOP(result),"a",offset++);
2841 aopPut(AOP(result),zero,offset++);
2845 /*-----------------------------------------------------------------*/
2846 /* genMinusBits - generates code for subtraction of two bits */
2847 /*-----------------------------------------------------------------*/
2848 static void genMinusBits (iCode *ic)
2850 symbol *lbl = newiTempLabel(NULL);
2851 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2852 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2853 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2854 emitcode("cpl","c");
2855 emitcode("","%05d$:",(lbl->key+100));
2856 outBitC(IC_RESULT(ic));
2859 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2860 emitcode("subb","a,acc");
2861 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
2862 emitcode("inc","a");
2863 emitcode("","%05d$:",(lbl->key+100));
2864 aopPut(AOP(IC_RESULT(ic)),"a",0);
2865 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
2869 /*-----------------------------------------------------------------*/
2870 /* genMinus - generates code for subtraction */
2871 /*-----------------------------------------------------------------*/
2872 static void genMinus (iCode *ic)
2874 int size, offset = 0;
2875 unsigned long lit = 0L;
2877 aopOp (IC_LEFT(ic),ic,FALSE);
2878 aopOp (IC_RIGHT(ic),ic,FALSE);
2879 aopOp (IC_RESULT(ic),ic,TRUE);
2881 /* special cases :- */
2882 /* if both left & right are in bit space */
2883 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2884 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2889 /* if I can do an decrement instead
2890 of subtract then GOOD for ME */
2891 if (genMinusDec (ic) == TRUE)
2894 size = getDataSize(IC_RESULT(ic));
2896 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
2900 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2904 /* if literal, add a,#-lit, else normal subb */
2906 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2907 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2908 emitcode("subb","a,%s",
2909 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2911 /* first add without previous c */
2913 emitcode("add","a,#0x%02x",
2914 (unsigned int)(lit & 0x0FFL));
2916 emitcode("addc","a,#0x%02x",
2917 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
2919 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2922 adjustArithmeticResult(ic);
2925 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2926 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2927 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2931 /*-----------------------------------------------------------------*/
2932 /* genMultbits :- multiplication of bits */
2933 /*-----------------------------------------------------------------*/
2934 static void genMultbits (operand *left,
2938 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2939 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
2944 /*-----------------------------------------------------------------*/
2945 /* genMultOneByte : 8 bit multiplication & division */
2946 /*-----------------------------------------------------------------*/
2947 static void genMultOneByte (operand *left,
2951 sym_link *opetype = operandType(result);
2956 /* (if two literals, the value is computed before) */
2957 /* if one literal, literal on the right */
2958 if (AOP_TYPE(left) == AOP_LIT){
2964 size = AOP_SIZE(result);
2965 /* signed or unsigned */
2966 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2967 l = aopGet(AOP(left),0,FALSE,FALSE);
2969 emitcode("mul","ab");
2970 /* if result size = 1, mul signed = mul unsigned */
2971 aopPut(AOP(result),"a",0);
2973 if (SPEC_USIGN(opetype)){
2974 aopPut(AOP(result),"b",1);
2976 /* for filling the MSBs */
2977 emitcode("clr","a");
2980 emitcode("mov","a,b");
2982 /* adjust the MSB if left or right neg */
2984 /* if one literal */
2985 if (AOP_TYPE(right) == AOP_LIT){
2986 /* AND literal negative */
2987 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
2988 /* adjust MSB (c==0 after mul) */
2989 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2993 lbl = newiTempLabel(NULL);
2994 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2995 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
2996 emitcode("","%05d$:",(lbl->key+100));
2997 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2998 lbl = newiTempLabel(NULL);
2999 emitcode("jc","%05d$",(lbl->key+100));
3000 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3001 emitcode("","%05d$:",(lbl->key+100));
3004 lbl = newiTempLabel(NULL);
3005 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3006 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3007 emitcode("","%05d$:",(lbl->key+100));
3008 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3009 lbl = newiTempLabel(NULL);
3010 emitcode("jc","%05d$",(lbl->key+100));
3011 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
3012 emitcode("","%05d$:",(lbl->key+100));
3014 aopPut(AOP(result),"a",1);
3017 emitcode("rlc","a");
3018 emitcode("subb","a,acc");
3025 aopPut(AOP(result),"a",offset++);
3029 /*-----------------------------------------------------------------*/
3030 /* genMult - generates code for multiplication */
3031 /*-----------------------------------------------------------------*/
3032 static void genMult (iCode *ic)
3034 operand *left = IC_LEFT(ic);
3035 operand *right = IC_RIGHT(ic);
3036 operand *result= IC_RESULT(ic);
3038 /* assign the amsops */
3039 aopOp (left,ic,FALSE);
3040 aopOp (right,ic,FALSE);
3041 aopOp (result,ic,TRUE);
3043 /* special cases first */
3045 if (AOP_TYPE(left) == AOP_CRY &&
3046 AOP_TYPE(right)== AOP_CRY) {
3047 genMultbits(left,right,result);
3051 /* if both are of size == 1 */
3052 if (AOP_SIZE(left) == 1 &&
3053 AOP_SIZE(right) == 1 ) {
3054 genMultOneByte(left,right,result);
3058 /* should have been converted to function call */
3062 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3063 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3064 freeAsmop(result,NULL,ic,TRUE);
3067 /*-----------------------------------------------------------------*/
3068 /* genDivbits :- division of bits */
3069 /*-----------------------------------------------------------------*/
3070 static void genDivbits (operand *left,
3077 /* the result must be bit */
3078 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3079 l = aopGet(AOP(left),0,FALSE,FALSE);
3083 emitcode("div","ab");
3084 emitcode("rrc","a");
3085 aopPut(AOP(result),"c",0);
3088 /*-----------------------------------------------------------------*/
3089 /* genDivOneByte : 8 bit division */
3090 /*-----------------------------------------------------------------*/
3091 static void genDivOneByte (operand *left,
3095 sym_link *opetype = operandType(result);
3100 size = AOP_SIZE(result) - 1;
3102 /* signed or unsigned */
3103 if (SPEC_USIGN(opetype)) {
3104 /* unsigned is easy */
3105 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3106 l = aopGet(AOP(left),0,FALSE,FALSE);
3108 emitcode("div","ab");
3109 aopPut(AOP(result),"a",0);
3111 aopPut(AOP(result),zero,offset++);
3115 /* signed is a little bit more difficult */
3117 /* save the signs of the operands */
3118 l = aopGet(AOP(left),0,FALSE,FALSE);
3120 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3121 emitcode("push","acc"); /* save it on the stack */
3123 /* now sign adjust for both left & right */
3124 l = aopGet(AOP(right),0,FALSE,FALSE);
3126 lbl = newiTempLabel(NULL);
3127 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3128 emitcode("cpl","a");
3129 emitcode("inc","a");
3130 emitcode("","%05d$:",(lbl->key+100));
3131 emitcode("mov","b,a");
3133 /* sign adjust left side */
3134 l = aopGet(AOP(left),0,FALSE,FALSE);
3137 lbl = newiTempLabel(NULL);
3138 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3139 emitcode("cpl","a");
3140 emitcode("inc","a");
3141 emitcode("","%05d$:",(lbl->key+100));
3143 /* now the division */
3144 emitcode("div","ab");
3145 /* we are interested in the lower order
3147 emitcode("mov","b,a");
3148 lbl = newiTempLabel(NULL);
3149 emitcode("pop","acc");
3150 /* if there was an over flow we don't
3151 adjust the sign of the result */
3152 emitcode("jb","ov,%05d$",(lbl->key+100));
3153 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3155 emitcode("clr","a");
3156 emitcode("subb","a,b");
3157 emitcode("mov","b,a");
3158 emitcode("","%05d$:",(lbl->key+100));
3160 /* now we are done */
3161 aopPut(AOP(result),"b",0);
3163 emitcode("mov","c,b.7");
3164 emitcode("subb","a,acc");
3167 aopPut(AOP(result),"a",offset++);
3171 /*-----------------------------------------------------------------*/
3172 /* genDiv - generates code for division */
3173 /*-----------------------------------------------------------------*/
3174 static void genDiv (iCode *ic)
3176 operand *left = IC_LEFT(ic);
3177 operand *right = IC_RIGHT(ic);
3178 operand *result= IC_RESULT(ic);
3180 /* assign the amsops */
3181 aopOp (left,ic,FALSE);
3182 aopOp (right,ic,FALSE);
3183 aopOp (result,ic,TRUE);
3185 /* special cases first */
3187 if (AOP_TYPE(left) == AOP_CRY &&
3188 AOP_TYPE(right)== AOP_CRY) {
3189 genDivbits(left,right,result);
3193 /* if both are of size == 1 */
3194 if (AOP_SIZE(left) == 1 &&
3195 AOP_SIZE(right) == 1 ) {
3196 genDivOneByte(left,right,result);
3200 /* should have been converted to function call */
3203 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3204 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3205 freeAsmop(result,NULL,ic,TRUE);
3208 /*-----------------------------------------------------------------*/
3209 /* genModbits :- modulus of bits */
3210 /*-----------------------------------------------------------------*/
3211 static void genModbits (operand *left,
3218 /* the result must be bit */
3219 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3220 l = aopGet(AOP(left),0,FALSE,FALSE);
3224 emitcode("div","ab");
3225 emitcode("mov","a,b");
3226 emitcode("rrc","a");
3227 aopPut(AOP(result),"c",0);
3230 /*-----------------------------------------------------------------*/
3231 /* genModOneByte : 8 bit modulus */
3232 /*-----------------------------------------------------------------*/
3233 static void genModOneByte (operand *left,
3237 sym_link *opetype = operandType(result);
3241 /* signed or unsigned */
3242 if (SPEC_USIGN(opetype)) {
3243 /* unsigned is easy */
3244 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3245 l = aopGet(AOP(left),0,FALSE,FALSE);
3247 emitcode("div","ab");
3248 aopPut(AOP(result),"b",0);
3252 /* signed is a little bit more difficult */
3254 /* save the signs of the operands */
3255 l = aopGet(AOP(left),0,FALSE,FALSE);
3258 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3259 emitcode("push","acc"); /* save it on the stack */
3261 /* now sign adjust for both left & right */
3262 l = aopGet(AOP(right),0,FALSE,FALSE);
3265 lbl = newiTempLabel(NULL);
3266 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3267 emitcode("cpl","a");
3268 emitcode("inc","a");
3269 emitcode("","%05d$:",(lbl->key+100));
3270 emitcode("mov","b,a");
3272 /* sign adjust left side */
3273 l = aopGet(AOP(left),0,FALSE,FALSE);
3276 lbl = newiTempLabel(NULL);
3277 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3278 emitcode("cpl","a");
3279 emitcode("inc","a");
3280 emitcode("","%05d$:",(lbl->key+100));
3282 /* now the multiplication */
3283 emitcode("div","ab");
3284 /* we are interested in the lower order
3286 lbl = newiTempLabel(NULL);
3287 emitcode("pop","acc");
3288 /* if there was an over flow we don't
3289 adjust the sign of the result */
3290 emitcode("jb","ov,%05d$",(lbl->key+100));
3291 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3293 emitcode("clr","a");
3294 emitcode("subb","a,b");
3295 emitcode("mov","b,a");
3296 emitcode("","%05d$:",(lbl->key+100));
3298 /* now we are done */
3299 aopPut(AOP(result),"b",0);
3303 /*-----------------------------------------------------------------*/
3304 /* genMod - generates code for division */
3305 /*-----------------------------------------------------------------*/
3306 static void genMod (iCode *ic)
3308 operand *left = IC_LEFT(ic);
3309 operand *right = IC_RIGHT(ic);
3310 operand *result= IC_RESULT(ic);
3312 /* assign the amsops */
3313 aopOp (left,ic,FALSE);
3314 aopOp (right,ic,FALSE);
3315 aopOp (result,ic,TRUE);
3317 /* special cases first */
3319 if (AOP_TYPE(left) == AOP_CRY &&
3320 AOP_TYPE(right)== AOP_CRY) {
3321 genModbits(left,right,result);
3325 /* if both are of size == 1 */
3326 if (AOP_SIZE(left) == 1 &&
3327 AOP_SIZE(right) == 1 ) {
3328 genModOneByte(left,right,result);
3332 /* should have been converted to function call */
3336 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3337 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3338 freeAsmop(result,NULL,ic,TRUE);
3341 /*-----------------------------------------------------------------*/
3342 /* genIfxJump :- will create a jump depending on the ifx */
3343 /*-----------------------------------------------------------------*/
3344 static void genIfxJump (iCode *ic, char *jval)
3347 symbol *tlbl = newiTempLabel(NULL);
3350 /* if true label then we jump if condition
3352 if ( IC_TRUE(ic) ) {
3354 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3355 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3358 /* false label is present */
3359 jlbl = IC_FALSE(ic) ;
3360 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3361 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3363 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3364 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3366 emitcode(inst,"%05d$",tlbl->key+100);
3367 emitcode("ljmp","%05d$",jlbl->key+100);
3368 emitcode("","%05d$:",tlbl->key+100);
3370 /* mark the icode as generated */
3374 /*-----------------------------------------------------------------*/
3375 /* genCmp :- greater or less than comparison */
3376 /*-----------------------------------------------------------------*/
3377 static void genCmp (operand *left,operand *right,
3378 operand *result, iCode *ifx, int sign)
3380 int size, offset = 0 ;
3381 unsigned long lit = 0L;
3383 /* if left & right are bit variables */
3384 if (AOP_TYPE(left) == AOP_CRY &&
3385 AOP_TYPE(right) == AOP_CRY ) {
3386 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3387 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3389 /* subtract right from left if at the
3390 end the carry flag is set then we know that
3391 left is greater than right */
3392 size = max(AOP_SIZE(left),AOP_SIZE(right));
3394 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3395 if((size == 1) && !sign &&
3396 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3397 symbol *lbl = newiTempLabel(NULL);
3398 emitcode("cjne","%s,%s,%05d$",
3399 aopGet(AOP(left),offset,FALSE,FALSE),
3400 aopGet(AOP(right),offset,FALSE,FALSE),
3402 emitcode("","%05d$:",lbl->key+100);
3404 if(AOP_TYPE(right) == AOP_LIT){
3405 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3406 /* optimize if(x < 0) or if(x >= 0) */
3412 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE));
3413 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3414 genIfxJump (ifx,"acc.7");
3418 emitcode("rlc","a");
3425 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3426 if (sign && size == 0) {
3427 emitcode("xrl","a,#0x80");
3428 if (AOP_TYPE(right) == AOP_LIT){
3429 unsigned long lit = (unsigned long)
3430 floatFromVal(AOP(right)->aopu.aop_lit);
3431 emitcode("subb","a,#0x%02x",
3432 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3434 emitcode("mov","b,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3435 emitcode("xrl","b,#0x80");
3436 emitcode("subb","a,b");
3439 emitcode("subb","a,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3445 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3448 /* if the result is used in the next
3449 ifx conditional branch then generate
3450 code a little differently */
3452 genIfxJump (ifx,"c");
3455 /* leave the result in acc */
3459 /*-----------------------------------------------------------------*/
3460 /* genCmpGt :- greater than comparison */
3461 /*-----------------------------------------------------------------*/
3462 static void genCmpGt (iCode *ic, iCode *ifx)
3464 operand *left, *right, *result;
3465 sym_link *letype , *retype;
3469 right= IC_RIGHT(ic);
3470 result = IC_RESULT(ic);
3472 letype = getSpec(operandType(left));
3473 retype =getSpec(operandType(right));
3474 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3475 /* assign the amsops */
3476 aopOp (left,ic,FALSE);
3477 aopOp (right,ic,FALSE);
3478 aopOp (result,ic,TRUE);
3480 genCmp(right, left, result, ifx, sign);
3482 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3483 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3484 freeAsmop(result,NULL,ic,TRUE);
3487 /*-----------------------------------------------------------------*/
3488 /* genCmpLt - less than comparisons */
3489 /*-----------------------------------------------------------------*/
3490 static void genCmpLt (iCode *ic, iCode *ifx)
3492 operand *left, *right, *result;
3493 sym_link *letype , *retype;
3497 right= IC_RIGHT(ic);
3498 result = IC_RESULT(ic);
3500 letype = getSpec(operandType(left));
3501 retype =getSpec(operandType(right));
3502 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3504 /* assign the amsops */
3505 aopOp (left,ic,FALSE);
3506 aopOp (right,ic,FALSE);
3507 aopOp (result,ic,TRUE);
3509 genCmp(left, right, result, ifx, sign);
3511 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3512 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3513 freeAsmop(result,NULL,ic,TRUE);
3516 /*-----------------------------------------------------------------*/
3517 /* gencjneshort - compare and jump if not equal */
3518 /*-----------------------------------------------------------------*/
3519 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3521 int size = max(AOP_SIZE(left),AOP_SIZE(right));
3523 unsigned long lit = 0L;
3525 /* if the left side is a literal or
3526 if the right is in a pointer register and left
3528 if ((AOP_TYPE(left) == AOP_LIT) ||
3529 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3534 if(AOP_TYPE(right) == AOP_LIT)
3535 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3537 /* if the right side is a literal then anything goes */
3538 if (AOP_TYPE(right) == AOP_LIT &&
3539 AOP_TYPE(left) != AOP_DIR ) {
3541 emitcode("cjne","%s,%s,%05d$",
3542 aopGet(AOP(left),offset,FALSE,FALSE),
3543 aopGet(AOP(right),offset,FALSE,FALSE),
3549 /* if the right side is in a register or in direct space or
3550 if the left is a pointer register & right is not */
3551 else if (AOP_TYPE(right) == AOP_REG ||
3552 AOP_TYPE(right) == AOP_DIR ||
3553 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3554 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3556 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3557 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3558 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
3559 emitcode("jnz","%05d$",lbl->key+100);
3561 emitcode("cjne","a,%s,%05d$",
3562 aopGet(AOP(right),offset,FALSE,TRUE),
3567 /* right is a pointer reg need both a & b */
3569 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
3571 emitcode("mov","b,%s",l);
3572 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3573 emitcode("cjne","a,b,%05d$",lbl->key+100);
3579 /*-----------------------------------------------------------------*/
3580 /* gencjne - compare and jump if not equal */
3581 /*-----------------------------------------------------------------*/
3582 static void gencjne(operand *left, operand *right, symbol *lbl)
3584 symbol *tlbl = newiTempLabel(NULL);
3586 gencjneshort(left, right, lbl);
3588 emitcode("mov","a,%s",one);
3589 emitcode("sjmp","%05d$",tlbl->key+100);
3590 emitcode("","%05d$:",lbl->key+100);
3591 emitcode("clr","a");
3592 emitcode("","%05d$:",tlbl->key+100);
3595 /*-----------------------------------------------------------------*/
3596 /* genCmpEq - generates code for equal to */
3597 /*-----------------------------------------------------------------*/
3598 static void genCmpEq (iCode *ic, iCode *ifx)
3600 operand *left, *right, *result;
3602 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3603 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3604 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3606 /* if literal, literal on the right or
3607 if the right is in a pointer register and left
3609 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
3610 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3611 operand *t = IC_RIGHT(ic);
3612 IC_RIGHT(ic) = IC_LEFT(ic);
3616 if(ifx && !AOP_SIZE(result)){
3618 /* if they are both bit variables */
3619 if (AOP_TYPE(left) == AOP_CRY &&
3620 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3621 if(AOP_TYPE(right) == AOP_LIT){
3622 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3624 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3625 emitcode("cpl","c");
3626 } else if(lit == 1L) {
3627 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3629 emitcode("clr","c");
3631 /* AOP_TYPE(right) == AOP_CRY */
3633 symbol *lbl = newiTempLabel(NULL);
3634 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3635 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3636 emitcode("cpl","c");
3637 emitcode("","%05d$:",(lbl->key+100));
3639 /* if true label then we jump if condition
3641 tlbl = newiTempLabel(NULL);
3642 if ( IC_TRUE(ifx) ) {
3643 emitcode("jnc","%05d$",tlbl->key+100);
3644 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3646 emitcode("jc","%05d$",tlbl->key+100);
3647 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3649 emitcode("","%05d$:",tlbl->key+100);
3651 tlbl = newiTempLabel(NULL);
3652 gencjneshort(left, right, tlbl);
3653 if ( IC_TRUE(ifx) ) {
3654 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3655 emitcode("","%05d$:",tlbl->key+100);
3657 symbol *lbl = newiTempLabel(NULL);
3658 emitcode("sjmp","%05d$",lbl->key+100);
3659 emitcode("","%05d$:",tlbl->key+100);
3660 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3661 emitcode("","%05d$:",lbl->key+100);
3664 /* mark the icode as generated */
3669 /* if they are both bit variables */
3670 if (AOP_TYPE(left) == AOP_CRY &&
3671 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3672 if(AOP_TYPE(right) == AOP_LIT){
3673 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3675 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3676 emitcode("cpl","c");
3677 } else if(lit == 1L) {
3678 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3680 emitcode("clr","c");
3682 /* AOP_TYPE(right) == AOP_CRY */
3684 symbol *lbl = newiTempLabel(NULL);
3685 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3686 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3687 emitcode("cpl","c");
3688 emitcode("","%05d$:",(lbl->key+100));
3691 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
3696 genIfxJump (ifx,"c");
3699 /* if the result is used in an arithmetic operation
3700 then put the result in place */
3703 gencjne(left,right,newiTempLabel(NULL));
3704 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3705 aopPut(AOP(result),"a",0);
3709 genIfxJump (ifx,"a");
3712 /* if the result is used in an arithmetic operation
3713 then put the result in place */
3714 if (AOP_TYPE(result) != AOP_CRY)
3716 /* leave the result in acc */
3720 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3721 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3722 freeAsmop(result,NULL,ic,TRUE);
3725 /*-----------------------------------------------------------------*/
3726 /* ifxForOp - returns the icode containing the ifx for operand */
3727 /*-----------------------------------------------------------------*/
3728 static iCode *ifxForOp ( operand *op, iCode *ic )
3730 /* if true symbol then needs to be assigned */
3731 if (IS_TRUE_SYMOP(op))
3734 /* if this has register type condition and
3735 the next instruction is ifx with the same operand
3736 and live to of the operand is upto the ifx only then */
3738 ic->next->op == IFX &&
3739 IC_COND(ic->next)->key == op->key &&
3740 OP_SYMBOL(op)->liveTo <= ic->next->seq )
3745 /*-----------------------------------------------------------------*/
3746 /* genAndOp - for && operation */
3747 /*-----------------------------------------------------------------*/
3748 static void genAndOp (iCode *ic)
3750 operand *left,*right, *result;
3753 /* note here that && operations that are in an
3754 if statement are taken away by backPatchLabels
3755 only those used in arthmetic operations remain */
3756 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3757 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3758 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3760 /* if both are bit variables */
3761 if (AOP_TYPE(left) == AOP_CRY &&
3762 AOP_TYPE(right) == AOP_CRY ) {
3763 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3764 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3767 tlbl = newiTempLabel(NULL);
3769 emitcode("jz","%05d$",tlbl->key+100);
3771 emitcode("","%05d$:",tlbl->key+100);
3775 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3776 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3777 freeAsmop(result,NULL,ic,TRUE);
3781 /*-----------------------------------------------------------------*/
3782 /* genOrOp - for || operation */
3783 /*-----------------------------------------------------------------*/
3784 static void genOrOp (iCode *ic)
3786 operand *left,*right, *result;
3789 /* note here that || operations that are in an
3790 if statement are taken away by backPatchLabels
3791 only those used in arthmetic operations remain */
3792 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3793 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3794 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3796 /* if both are bit variables */
3797 if (AOP_TYPE(left) == AOP_CRY &&
3798 AOP_TYPE(right) == AOP_CRY ) {
3799 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3800 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
3803 tlbl = newiTempLabel(NULL);
3805 emitcode("jnz","%05d$",tlbl->key+100);
3807 emitcode("","%05d$:",tlbl->key+100);
3811 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3812 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3813 freeAsmop(result,NULL,ic,TRUE);
3816 /*-----------------------------------------------------------------*/
3817 /* isLiteralBit - test if lit == 2^n */
3818 /*-----------------------------------------------------------------*/
3819 static int isLiteralBit(unsigned long lit)
3821 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
3822 0x100L,0x200L,0x400L,0x800L,
3823 0x1000L,0x2000L,0x4000L,0x8000L,
3824 0x10000L,0x20000L,0x40000L,0x80000L,
3825 0x100000L,0x200000L,0x400000L,0x800000L,
3826 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
3827 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
3830 for(idx = 0; idx < 32; idx++)
3836 /*-----------------------------------------------------------------*/
3837 /* continueIfTrue - */
3838 /*-----------------------------------------------------------------*/
3839 static void continueIfTrue (iCode *ic)
3842 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3846 /*-----------------------------------------------------------------*/
3848 /*-----------------------------------------------------------------*/
3849 static void jumpIfTrue (iCode *ic)
3852 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3856 /*-----------------------------------------------------------------*/
3857 /* jmpTrueOrFalse - */
3858 /*-----------------------------------------------------------------*/
3859 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
3861 // ugly but optimized by peephole
3863 symbol *nlbl = newiTempLabel(NULL);
3864 emitcode("sjmp","%05d$",nlbl->key+100);
3865 emitcode("","%05d$:",tlbl->key+100);
3866 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3867 emitcode("","%05d$:",nlbl->key+100);
3870 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3871 emitcode("","%05d$:",tlbl->key+100);
3876 /*-----------------------------------------------------------------*/
3877 /* genAnd - code for and */
3878 /*-----------------------------------------------------------------*/
3879 static void genAnd (iCode *ic, iCode *ifx)
3881 operand *left, *right, *result;
3883 unsigned long lit = 0L;
3887 aopOp((left = IC_LEFT(ic)),ic,FALSE);
3888 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3889 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3892 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3894 AOP_TYPE(left), AOP_TYPE(right));
3895 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3897 AOP_SIZE(left), AOP_SIZE(right));
3900 /* if left is a literal & right is not then exchange them */
3901 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3902 AOP_NEEDSACC(left)) {
3903 operand *tmp = right ;
3908 /* if result = right then exchange them */
3909 if(sameRegs(AOP(result),AOP(right))){
3910 operand *tmp = right ;
3915 /* if right is bit then exchange them */
3916 if (AOP_TYPE(right) == AOP_CRY &&
3917 AOP_TYPE(left) != AOP_CRY){
3918 operand *tmp = right ;
3922 if(AOP_TYPE(right) == AOP_LIT)
3923 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3925 size = AOP_SIZE(result);
3928 // result = bit & yy;
3929 if (AOP_TYPE(left) == AOP_CRY){
3930 // c = bit & literal;
3931 if(AOP_TYPE(right) == AOP_LIT){
3933 if(size && sameRegs(AOP(result),AOP(left)))
3936 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3939 if(size && (AOP_TYPE(result) == AOP_CRY)){
3940 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
3943 if((AOP_TYPE(result) == AOP_CRY) && ifx){
3947 emitcode("clr","c");
3950 if (AOP_TYPE(right) == AOP_CRY){
3952 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3953 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3956 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
3958 emitcode("rrc","a");
3959 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3967 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
3968 genIfxJump(ifx, "c");
3972 // if(val & 0xZZ) - size = 0, ifx != FALSE -
3973 // bit = val & 0xZZ - size = 1, ifx = FALSE -
3974 if((AOP_TYPE(right) == AOP_LIT) &&
3975 (AOP_TYPE(result) == AOP_CRY) &&
3976 (AOP_TYPE(left) != AOP_CRY)){
3977 int posbit = isLiteralBit(lit);
3981 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
3984 emitcode("mov","c,acc.%d",posbit&0x07);
3988 sprintf(buffer,"acc.%d",posbit&0x07);
3989 genIfxJump(ifx, buffer);
3994 symbol *tlbl = newiTempLabel(NULL);
3995 int sizel = AOP_SIZE(left);
3997 emitcode("setb","c");
3999 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4000 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
4002 if((posbit = isLiteralBit(bytelit)) != 0)
4003 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
4005 if(bytelit != 0x0FFL)
4006 emitcode("anl","a,%s",
4007 aopGet(AOP(right),offset,FALSE,TRUE));
4008 emitcode("jnz","%05d$",tlbl->key+100);
4013 // bit = left & literal
4015 emitcode("clr","c");
4016 emitcode("","%05d$:",tlbl->key+100);
4018 // if(left & literal)
4021 jmpTrueOrFalse(ifx, tlbl);
4029 /* if left is same as result */
4030 if(sameRegs(AOP(result),AOP(left))){
4031 for(;size--; offset++) {
4032 if(AOP_TYPE(right) == AOP_LIT){
4033 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4037 aopPut(AOP(result),zero,offset);
4039 if (IS_AOP_PREG(result)) {
4040 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4041 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4042 aopPut(AOP(result),"a",offset);
4044 emitcode("anl","%s,%s",
4045 aopGet(AOP(left),offset,FALSE,TRUE),
4046 aopGet(AOP(right),offset,FALSE,FALSE));
4048 if (AOP_TYPE(left) == AOP_ACC)
4049 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4051 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4052 if (IS_AOP_PREG(result)) {
4053 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4054 aopPut(AOP(result),"a",offset);
4057 emitcode("anl","%s,a",
4058 aopGet(AOP(left),offset,FALSE,TRUE));
4063 // left & result in different registers
4064 if(AOP_TYPE(result) == AOP_CRY){
4066 // if(size), result in bit
4067 // if(!size && ifx), conditional oper: if(left & right)
4068 symbol *tlbl = newiTempLabel(NULL);
4069 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4071 emitcode("setb","c");
4073 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4074 emitcode("anl","a,%s",
4075 aopGet(AOP(left),offset,FALSE,FALSE));
4076 emitcode("jnz","%05d$",tlbl->key+100);
4081 emitcode("","%05d$:",tlbl->key+100);
4084 jmpTrueOrFalse(ifx, tlbl);
4086 for(;(size--);offset++) {
4088 // result = left & right
4089 if(AOP_TYPE(right) == AOP_LIT){
4090 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
4092 aopGet(AOP(left),offset,FALSE,FALSE),
4095 } else if(bytelit == 0){
4096 aopPut(AOP(result),zero,offset);
4100 // faster than result <- left, anl result,right
4101 // and better if result is SFR
4102 if (AOP_TYPE(left) == AOP_ACC)
4103 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4105 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4106 emitcode("anl","a,%s",
4107 aopGet(AOP(left),offset,FALSE,FALSE));
4109 aopPut(AOP(result),"a",offset);
4115 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4116 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4117 freeAsmop(result,NULL,ic,TRUE);
4120 /*-----------------------------------------------------------------*/
4121 /* genOr - code for or */
4122 /*-----------------------------------------------------------------*/
4123 static void genOr (iCode *ic, iCode *ifx)
4125 operand *left, *right, *result;
4127 unsigned long lit = 0L;
4129 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4130 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4131 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4134 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4136 AOP_TYPE(left), AOP_TYPE(right));
4137 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4139 AOP_SIZE(left), AOP_SIZE(right));
4142 /* if left is a literal & right is not then exchange them */
4143 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4144 AOP_NEEDSACC(left)) {
4145 operand *tmp = right ;
4150 /* if result = right then exchange them */
4151 if(sameRegs(AOP(result),AOP(right))){
4152 operand *tmp = right ;
4157 /* if right is bit then exchange them */
4158 if (AOP_TYPE(right) == AOP_CRY &&
4159 AOP_TYPE(left) != AOP_CRY){
4160 operand *tmp = right ;
4164 if(AOP_TYPE(right) == AOP_LIT)
4165 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4167 size = AOP_SIZE(result);
4171 if (AOP_TYPE(left) == AOP_CRY){
4172 if(AOP_TYPE(right) == AOP_LIT){
4173 // c = bit & literal;
4175 // lit != 0 => result = 1
4176 if(AOP_TYPE(result) == AOP_CRY){
4178 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4180 continueIfTrue(ifx);
4183 emitcode("setb","c");
4185 // lit == 0 => result = left
4186 if(size && sameRegs(AOP(result),AOP(left)))
4188 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4191 if (AOP_TYPE(right) == AOP_CRY){
4193 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4194 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4198 symbol *tlbl = newiTempLabel(NULL);
4199 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4200 emitcode("setb","c");
4201 emitcode("jb","%s,%05d$",
4202 AOP(left)->aopu.aop_dir,tlbl->key+100);
4204 emitcode("jnz","%05d$",tlbl->key+100);
4205 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4206 jmpTrueOrFalse(ifx, tlbl);
4210 emitcode("","%05d$:",tlbl->key+100);
4219 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4220 genIfxJump(ifx, "c");
4224 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4225 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4226 if((AOP_TYPE(right) == AOP_LIT) &&
4227 (AOP_TYPE(result) == AOP_CRY) &&
4228 (AOP_TYPE(left) != AOP_CRY)){
4232 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4234 continueIfTrue(ifx);
4237 // lit = 0, result = boolean(left)
4239 emitcode("setb","c");
4242 symbol *tlbl = newiTempLabel(NULL);
4243 emitcode("jnz","%05d$",tlbl->key+100);
4245 emitcode("","%05d$:",tlbl->key+100);
4247 genIfxJump (ifx,"a");
4255 /* if left is same as result */
4256 if(sameRegs(AOP(result),AOP(left))){
4257 for(;size--; offset++) {
4258 if(AOP_TYPE(right) == AOP_LIT){
4259 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4262 if (IS_AOP_PREG(left)) {
4263 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4264 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4265 aopPut(AOP(result),"a",offset);
4267 emitcode("orl","%s,%s",
4268 aopGet(AOP(left),offset,FALSE,TRUE),
4269 aopGet(AOP(right),offset,FALSE,FALSE));
4271 if (AOP_TYPE(left) == AOP_ACC)
4272 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4274 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4275 if (IS_AOP_PREG(left)) {
4276 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4277 aopPut(AOP(result),"a",offset);
4279 emitcode("orl","%s,a",
4280 aopGet(AOP(left),offset,FALSE,TRUE));
4285 // left & result in different registers
4286 if(AOP_TYPE(result) == AOP_CRY){
4288 // if(size), result in bit
4289 // if(!size && ifx), conditional oper: if(left | right)
4290 symbol *tlbl = newiTempLabel(NULL);
4291 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4293 emitcode("setb","c");
4295 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4296 emitcode("orl","a,%s",
4297 aopGet(AOP(left),offset,FALSE,FALSE));
4298 emitcode("jnz","%05d$",tlbl->key+100);
4303 emitcode("","%05d$:",tlbl->key+100);
4306 jmpTrueOrFalse(ifx, tlbl);
4307 } else for(;(size--);offset++){
4309 // result = left & right
4310 if(AOP_TYPE(right) == AOP_LIT){
4311 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4313 aopGet(AOP(left),offset,FALSE,FALSE),
4318 // faster than result <- left, anl result,right
4319 // and better if result is SFR
4320 if (AOP_TYPE(left) == AOP_ACC)
4321 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4323 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4324 emitcode("orl","a,%s",
4325 aopGet(AOP(left),offset,FALSE,FALSE));
4327 aopPut(AOP(result),"a",offset);
4332 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4333 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4334 freeAsmop(result,NULL,ic,TRUE);
4337 /*-----------------------------------------------------------------*/
4338 /* genXor - code for xclusive or */
4339 /*-----------------------------------------------------------------*/
4340 static void genXor (iCode *ic, iCode *ifx)
4342 operand *left, *right, *result;
4344 unsigned long lit = 0L;
4346 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4347 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4348 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4351 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4353 AOP_TYPE(left), AOP_TYPE(right));
4354 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4356 AOP_SIZE(left), AOP_SIZE(right));
4359 /* if left is a literal & right is not ||
4360 if left needs acc & right does not */
4361 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4362 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4363 operand *tmp = right ;
4368 /* if result = right then exchange them */
4369 if(sameRegs(AOP(result),AOP(right))){
4370 operand *tmp = right ;
4375 /* if right is bit then exchange them */
4376 if (AOP_TYPE(right) == AOP_CRY &&
4377 AOP_TYPE(left) != AOP_CRY){
4378 operand *tmp = right ;
4382 if(AOP_TYPE(right) == AOP_LIT)
4383 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4385 size = AOP_SIZE(result);
4389 if (AOP_TYPE(left) == AOP_CRY){
4390 if(AOP_TYPE(right) == AOP_LIT){
4391 // c = bit & literal;
4393 // lit>>1 != 0 => result = 1
4394 if(AOP_TYPE(result) == AOP_CRY){
4396 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4398 continueIfTrue(ifx);
4401 emitcode("setb","c");
4405 // lit == 0, result = left
4406 if(size && sameRegs(AOP(result),AOP(left)))
4408 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4410 // lit == 1, result = not(left)
4411 if(size && sameRegs(AOP(result),AOP(left))){
4412 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4415 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4416 emitcode("cpl","c");
4423 symbol *tlbl = newiTempLabel(NULL);
4424 if (AOP_TYPE(right) == AOP_CRY){
4426 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4429 int sizer = AOP_SIZE(right);
4431 // if val>>1 != 0, result = 1
4432 emitcode("setb","c");
4434 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
4436 // test the msb of the lsb
4437 emitcode("anl","a,#0xfe");
4438 emitcode("jnz","%05d$",tlbl->key+100);
4442 emitcode("rrc","a");
4444 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4445 emitcode("cpl","c");
4446 emitcode("","%05d$:",(tlbl->key+100));
4453 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4454 genIfxJump(ifx, "c");
4458 if(sameRegs(AOP(result),AOP(left))){
4459 /* if left is same as result */
4460 for(;size--; offset++) {
4461 if(AOP_TYPE(right) == AOP_LIT){
4462 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4465 if (IS_AOP_PREG(left)) {
4466 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4467 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4468 aopPut(AOP(result),"a",offset);
4470 emitcode("xrl","%s,%s",
4471 aopGet(AOP(left),offset,FALSE,TRUE),
4472 aopGet(AOP(right),offset,FALSE,FALSE));
4474 if (AOP_TYPE(left) == AOP_ACC)
4475 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4477 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4478 if (IS_AOP_PREG(left)) {
4479 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4480 aopPut(AOP(result),"a",offset);
4482 emitcode("xrl","%s,a",
4483 aopGet(AOP(left),offset,FALSE,TRUE));
4488 // left & result in different registers
4489 if(AOP_TYPE(result) == AOP_CRY){
4491 // if(size), result in bit
4492 // if(!size && ifx), conditional oper: if(left ^ right)
4493 symbol *tlbl = newiTempLabel(NULL);
4494 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4496 emitcode("setb","c");
4498 if((AOP_TYPE(right) == AOP_LIT) &&
4499 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4500 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4502 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4503 emitcode("xrl","a,%s",
4504 aopGet(AOP(left),offset,FALSE,FALSE));
4506 emitcode("jnz","%05d$",tlbl->key+100);
4511 emitcode("","%05d$:",tlbl->key+100);
4514 jmpTrueOrFalse(ifx, tlbl);
4515 } else for(;(size--);offset++){
4517 // result = left & right
4518 if(AOP_TYPE(right) == AOP_LIT){
4519 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4521 aopGet(AOP(left),offset,FALSE,FALSE),
4526 // faster than result <- left, anl result,right
4527 // and better if result is SFR
4528 if (AOP_TYPE(left) == AOP_ACC)
4529 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4531 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4532 emitcode("xrl","a,%s",
4533 aopGet(AOP(left),offset,FALSE,TRUE));
4535 aopPut(AOP(result),"a",offset);
4540 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4541 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4542 freeAsmop(result,NULL,ic,TRUE);
4545 /*-----------------------------------------------------------------*/
4546 /* genInline - write the inline code out */
4547 /*-----------------------------------------------------------------*/
4548 static void genInline (iCode *ic)
4550 char buffer[MAX_INLINEASM];
4554 _G.inLine += (!options.asmpeep);
4555 strcpy(buffer,IC_INLINE(ic));
4557 /* emit each line as a code */
4576 /* emitcode("",buffer); */
4577 _G.inLine -= (!options.asmpeep);
4580 /*-----------------------------------------------------------------*/
4581 /* genRRC - rotate right with carry */
4582 /*-----------------------------------------------------------------*/
4583 static void genRRC (iCode *ic)
4585 operand *left , *result ;
4586 int size, offset = 0;
4589 /* rotate right with carry */
4591 result=IC_RESULT(ic);
4592 aopOp (left,ic,FALSE);
4593 aopOp (result,ic,FALSE);
4595 /* move it to the result */
4596 size = AOP_SIZE(result);
4600 l = aopGet(AOP(left),offset,FALSE,FALSE);
4602 emitcode("rrc","a");
4603 if (AOP_SIZE(result) > 1)
4604 aopPut(AOP(result),"a",offset--);
4606 /* now we need to put the carry into the
4607 highest order byte of the result */
4608 if (AOP_SIZE(result) > 1) {
4609 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
4612 emitcode("mov","acc.7,c");
4613 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
4614 freeAsmop(left,NULL,ic,TRUE);
4615 freeAsmop(result,NULL,ic,TRUE);
4618 /*-----------------------------------------------------------------*/
4619 /* genRLC - generate code for rotate left with carry */
4620 /*-----------------------------------------------------------------*/
4621 static void genRLC (iCode *ic)
4623 operand *left , *result ;
4624 int size, offset = 0;
4627 /* rotate right with carry */
4629 result=IC_RESULT(ic);
4630 aopOp (left,ic,FALSE);
4631 aopOp (result,ic,FALSE);
4633 /* move it to the result */
4634 size = AOP_SIZE(result);
4637 l = aopGet(AOP(left),offset,FALSE,FALSE);
4639 emitcode("add","a,acc");
4640 if (AOP_SIZE(result) > 1)
4641 aopPut(AOP(result),"a",offset++);
4643 l = aopGet(AOP(left),offset,FALSE,FALSE);
4645 emitcode("rlc","a");
4646 if (AOP_SIZE(result) > 1)
4647 aopPut(AOP(result),"a",offset++);
4650 /* now we need to put the carry into the
4651 highest order byte of the result */
4652 if (AOP_SIZE(result) > 1) {
4653 l = aopGet(AOP(result),0,FALSE,FALSE);
4656 emitcode("mov","acc.0,c");
4657 aopPut(AOP(result),"a",0);
4658 freeAsmop(left,NULL,ic,TRUE);
4659 freeAsmop(result,NULL,ic,TRUE);
4662 /*-----------------------------------------------------------------*/
4663 /* genGetHbit - generates code get highest order bit */
4664 /*-----------------------------------------------------------------*/
4665 static void genGetHbit (iCode *ic)
4667 operand *left, *result;
4669 result=IC_RESULT(ic);
4670 aopOp (left,ic,FALSE);
4671 aopOp (result,ic,FALSE);
4673 /* get the highest order byte into a */
4674 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
4675 if(AOP_TYPE(result) == AOP_CRY){
4676 emitcode("rlc","a");
4681 emitcode("anl","a,#0x01");
4686 freeAsmop(left,NULL,ic,TRUE);
4687 freeAsmop(result,NULL,ic,TRUE);
4690 /*-----------------------------------------------------------------*/
4691 /* AccRol - rotate left accumulator by known count */
4692 /*-----------------------------------------------------------------*/
4693 static void AccRol (int shCount)
4695 shCount &= 0x0007; // shCount : 0..7
4707 emitcode("swap","a");
4711 emitcode("swap","a");
4714 emitcode("swap","a");
4727 /*-----------------------------------------------------------------*/
4728 /* AccLsh - left shift accumulator by known count */
4729 /*-----------------------------------------------------------------*/
4730 static void AccLsh (int shCount)
4734 emitcode("add","a,acc");
4737 emitcode("add","a,acc");
4738 emitcode("add","a,acc");
4740 /* rotate left accumulator */
4742 /* and kill the lower order bits */
4743 emitcode("anl","a,#0x%02x", SLMask[shCount]);
4748 /*-----------------------------------------------------------------*/
4749 /* AccRsh - right shift accumulator by known count */
4750 /*-----------------------------------------------------------------*/
4751 static void AccRsh (int shCount)
4756 emitcode("rrc","a");
4758 /* rotate right accumulator */
4759 AccRol(8 - shCount);
4760 /* and kill the higher order bits */
4761 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4766 /*-----------------------------------------------------------------*/
4767 /* AccSRsh - signed right shift accumulator by known count */
4768 /*-----------------------------------------------------------------*/
4769 static void AccSRsh (int shCount)
4774 emitcode("mov","c,acc.7");
4775 emitcode("rrc","a");
4776 } else if(shCount == 2){
4777 emitcode("mov","c,acc.7");
4778 emitcode("rrc","a");
4779 emitcode("mov","c,acc.7");
4780 emitcode("rrc","a");
4782 tlbl = newiTempLabel(NULL);
4783 /* rotate right accumulator */
4784 AccRol(8 - shCount);
4785 /* and kill the higher order bits */
4786 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4787 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4788 emitcode("orl","a,#0x%02x",
4789 (unsigned char)~SRMask[shCount]);
4790 emitcode("","%05d$:",tlbl->key+100);
4795 /*-----------------------------------------------------------------*/
4796 /* shiftR1Left2Result - shift right one byte from left to result */
4797 /*-----------------------------------------------------------------*/
4798 static void shiftR1Left2Result (operand *left, int offl,
4799 operand *result, int offr,
4800 int shCount, int sign)
4802 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4803 /* shift right accumulator */
4808 aopPut(AOP(result),"a",offr);
4811 /*-----------------------------------------------------------------*/
4812 /* shiftL1Left2Result - shift left one byte from left to result */
4813 /*-----------------------------------------------------------------*/
4814 static void shiftL1Left2Result (operand *left, int offl,
4815 operand *result, int offr, int shCount)
4818 l = aopGet(AOP(left),offl,FALSE,FALSE);
4820 /* shift left accumulator */
4822 aopPut(AOP(result),"a",offr);
4825 /*-----------------------------------------------------------------*/
4826 /* movLeft2Result - move byte from left to result */
4827 /*-----------------------------------------------------------------*/
4828 static void movLeft2Result (operand *left, int offl,
4829 operand *result, int offr, int sign)
4832 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
4833 l = aopGet(AOP(left),offl,FALSE,FALSE);
4835 if (*l == '@' && (IS_AOP_PREG(result))) {
4836 emitcode("mov","a,%s",l);
4837 aopPut(AOP(result),"a",offr);
4840 aopPut(AOP(result),l,offr);
4842 /* MSB sign in acc.7 ! */
4843 if(getDataSize(left) == offl+1){
4844 emitcode("mov","a,%s",l);
4845 aopPut(AOP(result),"a",offr);
4852 /*-----------------------------------------------------------------*/
4853 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
4854 /*-----------------------------------------------------------------*/
4855 static void AccAXRrl1 (char *x)
4857 emitcode("rrc","a");
4858 emitcode("xch","a,%s", x);
4859 emitcode("rrc","a");
4860 emitcode("xch","a,%s", x);
4863 /*-----------------------------------------------------------------*/
4864 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
4865 /*-----------------------------------------------------------------*/
4866 static void AccAXLrl1 (char *x)
4868 emitcode("xch","a,%s",x);
4869 emitcode("rlc","a");
4870 emitcode("xch","a,%s",x);
4871 emitcode("rlc","a");
4874 /*-----------------------------------------------------------------*/
4875 /* AccAXLsh1 - left shift a:x<-0 by 1 */
4876 /*-----------------------------------------------------------------*/
4877 static void AccAXLsh1 (char *x)
4879 emitcode("xch","a,%s",x);
4880 emitcode("add","a,acc");
4881 emitcode("xch","a,%s",x);
4882 emitcode("rlc","a");
4885 /*-----------------------------------------------------------------*/
4886 /* AccAXLsh - left shift a:x by known count (0..7) */
4887 /*-----------------------------------------------------------------*/
4888 static void AccAXLsh (char *x, int shCount)
4902 case 5 : // AAAAABBB:CCCCCDDD
4903 AccRol(shCount); // BBBAAAAA:CCCCCDDD
4904 emitcode("anl","a,#0x%02x",
4905 SLMask[shCount]); // BBB00000:CCCCCDDD
4906 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
4907 AccRol(shCount); // DDDCCCCC:BBB00000
4908 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
4909 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
4910 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
4911 emitcode("anl","a,#0x%02x",
4912 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
4913 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
4914 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
4916 case 6 : // AAAAAABB:CCCCCCDD
4917 emitcode("anl","a,#0x%02x",
4918 SRMask[shCount]); // 000000BB:CCCCCCDD
4919 emitcode("mov","c,acc.0"); // c = B
4920 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
4921 AccAXRrl1(x); // BCCCCCCD:D000000B
4922 AccAXRrl1(x); // BBCCCCCC:DD000000
4924 case 7 : // a:x <<= 7
4925 emitcode("anl","a,#0x%02x",
4926 SRMask[shCount]); // 0000000B:CCCCCCCD
4927 emitcode("mov","c,acc.0"); // c = B
4928 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
4929 AccAXRrl1(x); // BCCCCCCC:D0000000
4936 /*-----------------------------------------------------------------*/
4937 /* AccAXRsh - right shift a:x known count (0..7) */
4938 /*-----------------------------------------------------------------*/
4939 static void AccAXRsh (char *x, int shCount)
4946 AccAXRrl1(x); // 0->a:x
4950 AccAXRrl1(x); // 0->a:x
4952 AccAXRrl1(x); // 0->a:x
4956 case 5 : // AAAAABBB:CCCCCDDD = a:x
4957 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
4958 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
4959 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
4960 emitcode("anl","a,#0x%02x",
4961 SRMask[shCount]); // 000CCCCC:BBBAAAAA
4962 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
4963 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
4964 emitcode("anl","a,#0x%02x",
4965 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
4966 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
4967 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
4968 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
4970 case 6 : // AABBBBBB:CCDDDDDD
4971 emitcode("mov","c,acc.7");
4972 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
4973 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
4974 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
4975 emitcode("anl","a,#0x%02x",
4976 SRMask[shCount]); // 000000AA:BBBBBBCC
4978 case 7 : // ABBBBBBB:CDDDDDDD
4979 emitcode("mov","c,acc.7"); // c = A
4980 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
4981 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
4982 emitcode("anl","a,#0x%02x",
4983 SRMask[shCount]); // 0000000A:BBBBBBBC
4990 /*-----------------------------------------------------------------*/
4991 /* AccAXRshS - right shift signed a:x known count (0..7) */
4992 /*-----------------------------------------------------------------*/
4993 static void AccAXRshS (char *x, int shCount)
5000 emitcode("mov","c,acc.7");
5001 AccAXRrl1(x); // s->a:x
5004 emitcode("mov","c,acc.7");
5005 AccAXRrl1(x); // s->a:x
5006 emitcode("mov","c,acc.7");
5007 AccAXRrl1(x); // s->a:x
5011 case 5 : // AAAAABBB:CCCCCDDD = a:x
5012 tlbl = newiTempLabel(NULL);
5013 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5014 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5015 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5016 emitcode("anl","a,#0x%02x",
5017 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5018 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5019 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5020 emitcode("anl","a,#0x%02x",
5021 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5022 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5023 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5024 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5025 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5026 emitcode("orl","a,#0x%02x",
5027 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5028 emitcode("","%05d$:",tlbl->key+100);
5029 break; // SSSSAAAA:BBBCCCCC
5030 case 6 : // AABBBBBB:CCDDDDDD
5031 tlbl = newiTempLabel(NULL);
5032 emitcode("mov","c,acc.7");
5033 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5034 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5035 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5036 emitcode("anl","a,#0x%02x",
5037 SRMask[shCount]); // 000000AA:BBBBBBCC
5038 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5039 emitcode("orl","a,#0x%02x",
5040 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5041 emitcode("","%05d$:",tlbl->key+100);
5043 case 7 : // ABBBBBBB:CDDDDDDD
5044 tlbl = newiTempLabel(NULL);
5045 emitcode("mov","c,acc.7"); // c = A
5046 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5047 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5048 emitcode("anl","a,#0x%02x",
5049 SRMask[shCount]); // 0000000A:BBBBBBBC
5050 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5051 emitcode("orl","a,#0x%02x",
5052 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5053 emitcode("","%05d$:",tlbl->key+100);
5060 /*-----------------------------------------------------------------*/
5061 /* shiftL2Left2Result - shift left two bytes from left to result */
5062 /*-----------------------------------------------------------------*/
5063 static void shiftL2Left2Result (operand *left, int offl,
5064 operand *result, int offr, int shCount)
5066 if(sameRegs(AOP(result), AOP(left)) &&
5067 ((offl + MSB16) == offr)){
5068 /* don't crash result[offr] */
5069 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5070 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5072 movLeft2Result(left,offl, result, offr, 0);
5073 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5075 /* ax << shCount (x = lsb(result))*/
5076 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5077 aopPut(AOP(result),"a",offr+MSB16);
5081 /*-----------------------------------------------------------------*/
5082 /* shiftR2Left2Result - shift right two bytes from left to result */
5083 /*-----------------------------------------------------------------*/
5084 static void shiftR2Left2Result (operand *left, int offl,
5085 operand *result, int offr,
5086 int shCount, int sign)
5088 if(sameRegs(AOP(result), AOP(left)) &&
5089 ((offl + MSB16) == offr)){
5090 /* don't crash result[offr] */
5091 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5092 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5094 movLeft2Result(left,offl, result, offr, 0);
5095 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5097 /* a:x >> shCount (x = lsb(result))*/
5099 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5101 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5102 if(getDataSize(result) > 1)
5103 aopPut(AOP(result),"a",offr+MSB16);
5106 /*-----------------------------------------------------------------*/
5107 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5108 /*-----------------------------------------------------------------*/
5109 static void shiftLLeftOrResult (operand *left, int offl,
5110 operand *result, int offr, int shCount)
5112 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5113 /* shift left accumulator */
5115 /* or with result */
5116 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5117 /* back to result */
5118 aopPut(AOP(result),"a",offr);
5121 /*-----------------------------------------------------------------*/
5122 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5123 /*-----------------------------------------------------------------*/
5124 static void shiftRLeftOrResult (operand *left, int offl,
5125 operand *result, int offr, int shCount)
5127 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5128 /* shift right accumulator */
5130 /* or with result */
5131 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5132 /* back to result */
5133 aopPut(AOP(result),"a",offr);
5136 /*-----------------------------------------------------------------*/
5137 /* genlshOne - left shift a one byte quantity by known count */
5138 /*-----------------------------------------------------------------*/
5139 static void genlshOne (operand *result, operand *left, int shCount)
5141 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5144 /*-----------------------------------------------------------------*/
5145 /* genlshTwo - left shift two bytes by known amount != 0 */
5146 /*-----------------------------------------------------------------*/
5147 static void genlshTwo (operand *result,operand *left, int shCount)
5151 size = getDataSize(result);
5153 /* if shCount >= 8 */
5159 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5161 movLeft2Result(left, LSB, result, MSB16, 0);
5163 aopPut(AOP(result),zero,LSB);
5166 /* 1 <= shCount <= 7 */
5169 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5171 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5175 /*-----------------------------------------------------------------*/
5176 /* shiftLLong - shift left one long from left to result */
5177 /* offl = LSB or MSB16 */
5178 /*-----------------------------------------------------------------*/
5179 static void shiftLLong (operand *left, operand *result, int offr )
5182 int size = AOP_SIZE(result);
5184 if(size >= LSB+offr){
5185 l = aopGet(AOP(left),LSB,FALSE,FALSE);
5187 emitcode("add","a,acc");
5188 if (sameRegs(AOP(left),AOP(result)) &&
5189 size >= MSB16+offr && offr != LSB )
5190 emitcode("xch","a,%s",
5191 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
5193 aopPut(AOP(result),"a",LSB+offr);
5196 if(size >= MSB16+offr){
5197 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5198 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
5201 emitcode("rlc","a");
5202 if (sameRegs(AOP(left),AOP(result)) &&
5203 size >= MSB24+offr && offr != LSB)
5204 emitcode("xch","a,%s",
5205 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
5207 aopPut(AOP(result),"a",MSB16+offr);
5210 if(size >= MSB24+offr){
5211 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5212 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
5215 emitcode("rlc","a");
5216 if (sameRegs(AOP(left),AOP(result)) &&
5217 size >= MSB32+offr && offr != LSB )
5218 emitcode("xch","a,%s",
5219 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
5221 aopPut(AOP(result),"a",MSB24+offr);
5224 if(size > MSB32+offr){
5225 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5226 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
5229 emitcode("rlc","a");
5230 aopPut(AOP(result),"a",MSB32+offr);
5233 aopPut(AOP(result),zero,LSB);
5236 /*-----------------------------------------------------------------*/
5237 /* genlshFour - shift four byte by a known amount != 0 */
5238 /*-----------------------------------------------------------------*/
5239 static void genlshFour (operand *result, operand *left, int shCount)
5243 size = AOP_SIZE(result);
5245 /* if shifting more that 3 bytes */
5246 if (shCount >= 24 ) {
5249 /* lowest order of left goes to the highest
5250 order of the destination */
5251 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5253 movLeft2Result(left, LSB, result, MSB32, 0);
5254 aopPut(AOP(result),zero,LSB);
5255 aopPut(AOP(result),zero,MSB16);
5256 aopPut(AOP(result),zero,MSB32);
5260 /* more than two bytes */
5261 else if ( shCount >= 16 ) {
5262 /* lower order two bytes goes to higher order two bytes */
5264 /* if some more remaining */
5266 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5268 movLeft2Result(left, MSB16, result, MSB32, 0);
5269 movLeft2Result(left, LSB, result, MSB24, 0);
5271 aopPut(AOP(result),zero,MSB16);
5272 aopPut(AOP(result),zero,LSB);
5276 /* if more than 1 byte */
5277 else if ( shCount >= 8 ) {
5278 /* lower order three bytes goes to higher order three bytes */
5282 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5284 movLeft2Result(left, LSB, result, MSB16, 0);
5286 else{ /* size = 4 */
5288 movLeft2Result(left, MSB24, result, MSB32, 0);
5289 movLeft2Result(left, MSB16, result, MSB24, 0);
5290 movLeft2Result(left, LSB, result, MSB16, 0);
5291 aopPut(AOP(result),zero,LSB);
5293 else if(shCount == 1)
5294 shiftLLong(left, result, MSB16);
5296 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5297 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5298 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5299 aopPut(AOP(result),zero,LSB);
5304 /* 1 <= shCount <= 7 */
5305 else if(shCount <= 2){
5306 shiftLLong(left, result, LSB);
5308 shiftLLong(result, result, LSB);
5310 /* 3 <= shCount <= 7, optimize */
5312 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5313 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5314 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5318 /*-----------------------------------------------------------------*/
5319 /* genLeftShiftLiteral - left shifting by known count */
5320 /*-----------------------------------------------------------------*/
5321 static void genLeftShiftLiteral (operand *left,
5326 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5329 freeAsmop(right,NULL,ic,TRUE);
5331 aopOp(left,ic,FALSE);
5332 aopOp(result,ic,FALSE);
5334 size = getSize(operandType(result));
5337 emitcode("; shift left ","result %d, left %d",size,
5341 /* I suppose that the left size >= result size */
5344 movLeft2Result(left, size, result, size, 0);
5348 else if(shCount >= (size * 8))
5350 aopPut(AOP(result),zero,size);
5354 genlshOne (result,left,shCount);
5359 genlshTwo (result,left,shCount);
5363 genlshFour (result,left,shCount);
5367 freeAsmop(left,NULL,ic,TRUE);
5368 freeAsmop(result,NULL,ic,TRUE);
5371 /*-----------------------------------------------------------------*/
5372 /* genLeftShift - generates code for left shifting */
5373 /*-----------------------------------------------------------------*/
5374 static void genLeftShift (iCode *ic)
5376 operand *left,*right, *result;
5379 symbol *tlbl , *tlbl1;
5381 right = IC_RIGHT(ic);
5383 result = IC_RESULT(ic);
5385 aopOp(right,ic,FALSE);
5387 /* if the shift count is known then do it
5388 as efficiently as possible */
5389 if (AOP_TYPE(right) == AOP_LIT) {
5390 genLeftShiftLiteral (left,right,result,ic);
5394 /* shift count is unknown then we have to form
5395 a loop get the loop count in B : Note: we take
5396 only the lower order byte since shifting
5397 more that 32 bits make no sense anyway, ( the
5398 largest size of an object can be only 32 bits ) */
5400 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5401 emitcode("inc","b");
5402 freeAsmop (right,NULL,ic,TRUE);
5403 aopOp(left,ic,FALSE);
5404 aopOp(result,ic,FALSE);
5406 /* now move the left to the result if they are not the
5408 if (!sameRegs(AOP(left),AOP(result)) &&
5409 AOP_SIZE(result) > 1) {
5411 size = AOP_SIZE(result);
5414 l = aopGet(AOP(left),offset,FALSE,TRUE);
5415 if (*l == '@' && (IS_AOP_PREG(result))) {
5417 emitcode("mov","a,%s",l);
5418 aopPut(AOP(result),"a",offset);
5420 aopPut(AOP(result),l,offset);
5425 tlbl = newiTempLabel(NULL);
5426 size = AOP_SIZE(result);
5428 tlbl1 = newiTempLabel(NULL);
5430 /* if it is only one byte then */
5432 symbol *tlbl1 = newiTempLabel(NULL);
5434 l = aopGet(AOP(left),0,FALSE,FALSE);
5436 emitcode("sjmp","%05d$",tlbl1->key+100);
5437 emitcode("","%05d$:",tlbl->key+100);
5438 emitcode("add","a,acc");
5439 emitcode("","%05d$:",tlbl1->key+100);
5440 emitcode("djnz","b,%05d$",tlbl->key+100);
5441 aopPut(AOP(result),"a",0);
5445 reAdjustPreg(AOP(result));
5447 emitcode("sjmp","%05d$",tlbl1->key+100);
5448 emitcode("","%05d$:",tlbl->key+100);
5449 l = aopGet(AOP(result),offset,FALSE,FALSE);
5451 emitcode("add","a,acc");
5452 aopPut(AOP(result),"a",offset++);
5454 l = aopGet(AOP(result),offset,FALSE,FALSE);
5456 emitcode("rlc","a");
5457 aopPut(AOP(result),"a",offset++);
5459 reAdjustPreg(AOP(result));
5461 emitcode("","%05d$:",tlbl1->key+100);
5462 emitcode("djnz","b,%05d$",tlbl->key+100);
5464 freeAsmop(left,NULL,ic,TRUE);
5465 freeAsmop(result,NULL,ic,TRUE);
5468 /*-----------------------------------------------------------------*/
5469 /* genrshOne - right shift a one byte quantity by known count */
5470 /*-----------------------------------------------------------------*/
5471 static void genrshOne (operand *result, operand *left,
5472 int shCount, int sign)
5474 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
5477 /*-----------------------------------------------------------------*/
5478 /* genrshTwo - right shift two bytes by known amount != 0 */
5479 /*-----------------------------------------------------------------*/
5480 static void genrshTwo (operand *result,operand *left,
5481 int shCount, int sign)
5483 /* if shCount >= 8 */
5487 shiftR1Left2Result(left, MSB16, result, LSB,
5490 movLeft2Result(left, MSB16, result, LSB, sign);
5491 addSign(result, MSB16, sign);
5494 /* 1 <= shCount <= 7 */
5496 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
5499 /*-----------------------------------------------------------------*/
5500 /* shiftRLong - shift right one long from left to result */
5501 /* offl = LSB or MSB16 */
5502 /*-----------------------------------------------------------------*/
5503 static void shiftRLong (operand *left, int offl,
5504 operand *result, int sign)
5507 emitcode("clr","c");
5508 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
5510 emitcode("mov","c,acc.7");
5511 emitcode("rrc","a");
5512 aopPut(AOP(result),"a",MSB32-offl);
5514 /* add sign of "a" */
5515 addSign(result, MSB32, sign);
5517 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
5518 emitcode("rrc","a");
5519 aopPut(AOP(result),"a",MSB24-offl);
5521 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
5522 emitcode("rrc","a");
5523 aopPut(AOP(result),"a",MSB16-offl);
5526 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
5527 emitcode("rrc","a");
5528 aopPut(AOP(result),"a",LSB);
5532 /*-----------------------------------------------------------------*/
5533 /* genrshFour - shift four byte by a known amount != 0 */
5534 /*-----------------------------------------------------------------*/
5535 static void genrshFour (operand *result, operand *left,
5536 int shCount, int sign)
5538 /* if shifting more that 3 bytes */
5539 if(shCount >= 24 ) {
5542 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
5544 movLeft2Result(left, MSB32, result, LSB, sign);
5545 addSign(result, MSB16, sign);
5547 else if(shCount >= 16){
5550 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
5552 movLeft2Result(left, MSB24, result, LSB, 0);
5553 movLeft2Result(left, MSB32, result, MSB16, sign);
5555 addSign(result, MSB24, sign);
5557 else if(shCount >= 8){
5560 shiftRLong(left, MSB16, result, sign);
5561 else if(shCount == 0){
5562 movLeft2Result(left, MSB16, result, LSB, 0);
5563 movLeft2Result(left, MSB24, result, MSB16, 0);
5564 movLeft2Result(left, MSB32, result, MSB24, sign);
5565 addSign(result, MSB32, sign);
5568 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
5569 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
5570 /* the last shift is signed */
5571 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
5572 addSign(result, MSB32, sign);
5575 else{ /* 1 <= shCount <= 7 */
5577 shiftRLong(left, LSB, result, sign);
5579 shiftRLong(result, LSB, result, sign);
5582 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
5583 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
5584 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
5589 /*-----------------------------------------------------------------*/
5590 /* genRightShiftLiteral - right shifting by known count */
5591 /*-----------------------------------------------------------------*/
5592 static void genRightShiftLiteral (operand *left,
5598 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5601 freeAsmop(right,NULL,ic,TRUE);
5603 aopOp(left,ic,FALSE);
5604 aopOp(result,ic,FALSE);
5607 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
5611 size = getDataSize(left);
5612 /* test the LEFT size !!! */
5614 /* I suppose that the left size >= result size */
5616 size = getDataSize(result);
5618 movLeft2Result(left, size, result, size, 0);
5621 else if(shCount >= (size * 8)){
5623 /* get sign in acc.7 */
5624 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
5625 addSign(result, LSB, sign);
5629 genrshOne (result,left,shCount,sign);
5633 genrshTwo (result,left,shCount,sign);
5637 genrshFour (result,left,shCount,sign);
5643 freeAsmop(left,NULL,ic,TRUE);
5644 freeAsmop(result,NULL,ic,TRUE);
5648 /*-----------------------------------------------------------------*/
5649 /* genSignedRightShift - right shift of signed number */
5650 /*-----------------------------------------------------------------*/
5651 static void genSignedRightShift (iCode *ic)
5653 operand *right, *left, *result;
5656 symbol *tlbl, *tlbl1 ;
5658 /* we do it the hard way put the shift count in b
5659 and loop thru preserving the sign */
5661 right = IC_RIGHT(ic);
5663 result = IC_RESULT(ic);
5665 aopOp(right,ic,FALSE);
5668 if ( AOP_TYPE(right) == AOP_LIT) {
5669 genRightShiftLiteral (left,right,result,ic,1);
5672 /* shift count is unknown then we have to form
5673 a loop get the loop count in B : Note: we take
5674 only the lower order byte since shifting
5675 more that 32 bits make no sense anyway, ( the
5676 largest size of an object can be only 32 bits ) */
5678 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5679 emitcode("inc","b");
5680 freeAsmop (right,NULL,ic,TRUE);
5681 aopOp(left,ic,FALSE);
5682 aopOp(result,ic,FALSE);
5684 /* now move the left to the result if they are not the
5686 if (!sameRegs(AOP(left),AOP(result)) &&
5687 AOP_SIZE(result) > 1) {
5689 size = AOP_SIZE(result);
5692 l = aopGet(AOP(left),offset,FALSE,TRUE);
5693 if (*l == '@' && IS_AOP_PREG(result)) {
5695 emitcode("mov","a,%s",l);
5696 aopPut(AOP(result),"a",offset);
5698 aopPut(AOP(result),l,offset);
5703 /* mov the highest order bit to OVR */
5704 tlbl = newiTempLabel(NULL);
5705 tlbl1= newiTempLabel(NULL);
5707 size = AOP_SIZE(result);
5709 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
5710 emitcode("rlc","a");
5711 emitcode("mov","ov,c");
5712 /* if it is only one byte then */
5714 l = aopGet(AOP(left),0,FALSE,FALSE);
5716 emitcode("sjmp","%05d$",tlbl1->key+100);
5717 emitcode("","%05d$:",tlbl->key+100);
5718 emitcode("mov","c,ov");
5719 emitcode("rrc","a");
5720 emitcode("","%05d$:",tlbl1->key+100);
5721 emitcode("djnz","b,%05d$",tlbl->key+100);
5722 aopPut(AOP(result),"a",0);
5726 reAdjustPreg(AOP(result));
5727 emitcode("sjmp","%05d$",tlbl1->key+100);
5728 emitcode("","%05d$:",tlbl->key+100);
5729 emitcode("mov","c,ov");
5731 l = aopGet(AOP(result),offset,FALSE,FALSE);
5733 emitcode("rrc","a");
5734 aopPut(AOP(result),"a",offset--);
5736 reAdjustPreg(AOP(result));
5737 emitcode("","%05d$:",tlbl1->key+100);
5738 emitcode("djnz","b,%05d$",tlbl->key+100);
5741 freeAsmop(left,NULL,ic,TRUE);
5742 freeAsmop(result,NULL,ic,TRUE);
5745 /*-----------------------------------------------------------------*/
5746 /* genRightShift - generate code for right shifting */
5747 /*-----------------------------------------------------------------*/
5748 static void genRightShift (iCode *ic)
5750 operand *right, *left, *result;
5754 symbol *tlbl, *tlbl1 ;
5756 /* if signed then we do it the hard way preserve the
5757 sign bit moving it inwards */
5758 retype = getSpec(operandType(IC_RESULT(ic)));
5760 if (!SPEC_USIGN(retype)) {
5761 genSignedRightShift (ic);
5765 /* signed & unsigned types are treated the same : i.e. the
5766 signed is NOT propagated inwards : quoting from the
5767 ANSI - standard : "for E1 >> E2, is equivalent to division
5768 by 2**E2 if unsigned or if it has a non-negative value,
5769 otherwise the result is implementation defined ", MY definition
5770 is that the sign does not get propagated */
5772 right = IC_RIGHT(ic);
5774 result = IC_RESULT(ic);
5776 aopOp(right,ic,FALSE);
5778 /* if the shift count is known then do it
5779 as efficiently as possible */
5780 if (AOP_TYPE(right) == AOP_LIT) {
5781 genRightShiftLiteral (left,right,result,ic, 0);
5785 /* shift count is unknown then we have to form
5786 a loop get the loop count in B : Note: we take
5787 only the lower order byte since shifting
5788 more that 32 bits make no sense anyway, ( the
5789 largest size of an object can be only 32 bits ) */
5791 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5792 emitcode("inc","b");
5793 freeAsmop (right,NULL,ic,TRUE);
5794 aopOp(left,ic,FALSE);
5795 aopOp(result,ic,FALSE);
5797 /* now move the left to the result if they are not the
5799 if (!sameRegs(AOP(left),AOP(result)) &&
5800 AOP_SIZE(result) > 1) {
5802 size = AOP_SIZE(result);
5805 l = aopGet(AOP(left),offset,FALSE,TRUE);
5806 if (*l == '@' && IS_AOP_PREG(result)) {
5808 emitcode("mov","a,%s",l);
5809 aopPut(AOP(result),"a",offset);
5811 aopPut(AOP(result),l,offset);
5816 tlbl = newiTempLabel(NULL);
5817 tlbl1= newiTempLabel(NULL);
5818 size = AOP_SIZE(result);
5821 /* if it is only one byte then */
5823 l = aopGet(AOP(left),0,FALSE,FALSE);
5825 emitcode("sjmp","%05d$",tlbl1->key+100);
5826 emitcode("","%05d$:",tlbl->key+100);
5828 emitcode("rrc","a");
5829 emitcode("","%05d$:",tlbl1->key+100);
5830 emitcode("djnz","b,%05d$",tlbl->key+100);
5831 aopPut(AOP(result),"a",0);
5835 reAdjustPreg(AOP(result));
5836 emitcode("sjmp","%05d$",tlbl1->key+100);
5837 emitcode("","%05d$:",tlbl->key+100);
5840 l = aopGet(AOP(result),offset,FALSE,FALSE);
5842 emitcode("rrc","a");
5843 aopPut(AOP(result),"a",offset--);
5845 reAdjustPreg(AOP(result));
5847 emitcode("","%05d$:",tlbl1->key+100);
5848 emitcode("djnz","b,%05d$",tlbl->key+100);
5851 freeAsmop(left,NULL,ic,TRUE);
5852 freeAsmop(result,NULL,ic,TRUE);
5855 /*-----------------------------------------------------------------*/
5856 /* genUnpackBits - generates code for unpacking bits */
5857 /*-----------------------------------------------------------------*/
5858 static void genUnpackBits (operand *result, char *rname, int ptype)
5866 etype = getSpec(operandType(result));
5867 rsize = getSize(operandType(result));
5868 /* read the first byte */
5873 emitcode("mov","a,@%s",rname);
5877 emitcode("movx","a,@%s",rname);
5881 emitcode("movx","a,@dptr");
5885 emitcode("clr","a");
5886 emitcode("movc","a","@a+dptr");
5890 emitcode("lcall","__gptrget");
5894 rlen = SPEC_BLEN(etype) ;
5896 /* if we have bitdisplacement then it fits */
5897 /* into this byte completely or if length is */
5898 /* less than a byte */
5899 if ((shCnt = SPEC_BSTR(etype)) ||
5900 (SPEC_BLEN(etype) <= 8)) {
5902 /* shift right acc */
5905 emitcode("anl","a,#0x%02x",
5906 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
5907 aopPut(AOP(result),"a",offset++);
5911 /* bit field did not fit in a byte */
5912 aopPut(AOP(result),"a",offset++);
5919 emitcode("inc","%s",rname);
5920 emitcode("mov","a,@%s",rname);
5924 emitcode("inc","%s",rname);
5925 emitcode("movx","a,@%s",rname);
5929 emitcode("inc","dptr");
5930 emitcode("movx","a,@dptr");
5934 emitcode("clr","a");
5935 emitcode("inc","dptr");
5936 emitcode("movc","a","@a+dptr");
5940 emitcode("inc","dptr");
5941 emitcode("lcall","__gptrget");
5946 /* if we are done */
5950 aopPut(AOP(result),"a",offset++);
5955 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
5957 aopPut(AOP(result),"a",offset++);
5961 if (offset < rsize) {
5963 while (rsize--) aopPut(AOP(result),zero,offset++);
5969 /*-----------------------------------------------------------------*/
5970 /* genDataPointerGet - generates code when ptr offset is known */
5971 /*-----------------------------------------------------------------*/
5972 static void genDataPointerGet (operand *left,
5978 int size , offset = 0;
5979 aopOp(result,ic,TRUE);
5981 /* get the string representation of the name */
5982 l = aopGet(AOP(left),0,FALSE,TRUE);
5983 size = AOP_SIZE(result);
5986 sprintf(buffer,"(%s + %d)",l+1,offset);
5988 sprintf(buffer,"%s",l+1);
5989 aopPut(AOP(result),buffer,offset++);
5992 freeAsmop(left,NULL,ic,TRUE);
5993 freeAsmop(result,NULL,ic,TRUE);
5996 /*-----------------------------------------------------------------*/
5997 /* genNearPointerGet - emitcode for near pointer fetch */
5998 /*-----------------------------------------------------------------*/
5999 static void genNearPointerGet (operand *left,
6006 sym_link *rtype, *retype;
6007 sym_link *ltype = operandType(left);
6010 rtype = operandType(result);
6011 retype= getSpec(rtype);
6013 aopOp(left,ic,FALSE);
6015 /* if left is rematerialisable and
6016 result is not bit variable type and
6017 the left is pointer to data space i.e
6018 lower 128 bytes of space */
6019 if (AOP_TYPE(left) == AOP_IMMD &&
6020 !IS_BITVAR(retype) &&
6021 DCL_TYPE(ltype) == POINTER) {
6022 genDataPointerGet (left,result,ic);
6026 /* if the value is already in a pointer register
6027 then don't need anything more */
6028 if (!AOP_INPREG(AOP(left))) {
6029 /* otherwise get a free pointer register */
6031 preg = getFreePtr(ic,&aop,FALSE);
6032 emitcode("mov","%s,%s",
6034 aopGet(AOP(left),0,FALSE,TRUE));
6035 rname = preg->name ;
6037 rname = aopGet(AOP(left),0,FALSE,FALSE);
6039 freeAsmop(left,NULL,ic,TRUE);
6040 aopOp (result,ic,FALSE);
6042 /* if bitfield then unpack the bits */
6043 if (IS_BITVAR(retype))
6044 genUnpackBits (result,rname,POINTER);
6046 /* we have can just get the values */
6047 int size = AOP_SIZE(result);
6051 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6053 emitcode("mov","a,@%s",rname);
6054 aopPut(AOP(result),"a",offset);
6056 sprintf(buffer,"@%s",rname);
6057 aopPut(AOP(result),buffer,offset);
6061 emitcode("inc","%s",rname);
6065 /* now some housekeeping stuff */
6067 /* we had to allocate for this iCode */
6068 freeAsmop(NULL,aop,ic,TRUE);
6070 /* we did not allocate which means left
6071 already in a pointer register, then
6072 if size > 0 && this could be used again
6073 we have to point it back to where it
6075 if (AOP_SIZE(result) > 1 &&
6076 !OP_SYMBOL(left)->remat &&
6077 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6079 int size = AOP_SIZE(result) - 1;
6081 emitcode("dec","%s",rname);
6086 freeAsmop(result,NULL,ic,TRUE);
6090 /*-----------------------------------------------------------------*/
6091 /* genPagedPointerGet - emitcode for paged pointer fetch */
6092 /*-----------------------------------------------------------------*/
6093 static void genPagedPointerGet (operand *left,
6100 sym_link *rtype, *retype;
6102 rtype = operandType(result);
6103 retype= getSpec(rtype);
6105 aopOp(left,ic,FALSE);
6107 /* if the value is already in a pointer register
6108 then don't need anything more */
6109 if (!AOP_INPREG(AOP(left))) {
6110 /* otherwise get a free pointer register */
6112 preg = getFreePtr(ic,&aop,FALSE);
6113 emitcode("mov","%s,%s",
6115 aopGet(AOP(left),0,FALSE,TRUE));
6116 rname = preg->name ;
6118 rname = aopGet(AOP(left),0,FALSE,FALSE);
6120 freeAsmop(left,NULL,ic,TRUE);
6121 aopOp (result,ic,FALSE);
6123 /* if bitfield then unpack the bits */
6124 if (IS_BITVAR(retype))
6125 genUnpackBits (result,rname,PPOINTER);
6127 /* we have can just get the values */
6128 int size = AOP_SIZE(result);
6133 emitcode("movx","a,@%s",rname);
6134 aopPut(AOP(result),"a",offset);
6139 emitcode("inc","%s",rname);
6143 /* now some housekeeping stuff */
6145 /* we had to allocate for this iCode */
6146 freeAsmop(NULL,aop,ic,TRUE);
6148 /* we did not allocate which means left
6149 already in a pointer register, then
6150 if size > 0 && this could be used again
6151 we have to point it back to where it
6153 if (AOP_SIZE(result) > 1 &&
6154 !OP_SYMBOL(left)->remat &&
6155 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6157 int size = AOP_SIZE(result) - 1;
6159 emitcode("dec","%s",rname);
6164 freeAsmop(result,NULL,ic,TRUE);
6169 /*-----------------------------------------------------------------*/
6170 /* genFarPointerGet - gget value from far space */
6171 /*-----------------------------------------------------------------*/
6172 static void genFarPointerGet (operand *left,
6173 operand *result, iCode *ic)
6176 sym_link *retype = getSpec(operandType(result));
6178 aopOp(left,ic,FALSE);
6180 /* if the operand is already in dptr
6181 then we do nothing else we move the value to dptr */
6182 if (AOP_TYPE(left) != AOP_STR) {
6183 /* if this is remateriazable */
6184 if (AOP_TYPE(left) == AOP_IMMD)
6185 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6186 else { /* we need to get it byte by byte */
6187 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6188 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6189 if (options.model == MODEL_FLAT24)
6191 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6195 /* so dptr know contains the address */
6196 freeAsmop(left,NULL,ic,TRUE);
6197 aopOp(result,ic,FALSE);
6199 /* if bit then unpack */
6200 if (IS_BITVAR(retype))
6201 genUnpackBits(result,"dptr",FPOINTER);
6203 size = AOP_SIZE(result);
6207 emitcode("movx","a,@dptr");
6208 aopPut(AOP(result),"a",offset++);
6210 emitcode("inc","dptr");
6214 freeAsmop(result,NULL,ic,TRUE);
6217 /*-----------------------------------------------------------------*/
6218 /* emitcodePointerGet - gget value from code space */
6219 /*-----------------------------------------------------------------*/
6220 static void emitcodePointerGet (operand *left,
6221 operand *result, iCode *ic)
6224 sym_link *retype = getSpec(operandType(result));
6226 aopOp(left,ic,FALSE);
6228 /* if the operand is already in dptr
6229 then we do nothing else we move the value to dptr */
6230 if (AOP_TYPE(left) != AOP_STR) {
6231 /* if this is remateriazable */
6232 if (AOP_TYPE(left) == AOP_IMMD)
6233 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6234 else { /* we need to get it byte by byte */
6235 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6236 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6237 if (options.model == MODEL_FLAT24)
6239 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6243 /* so dptr know contains the address */
6244 freeAsmop(left,NULL,ic,TRUE);
6245 aopOp(result,ic,FALSE);
6247 /* if bit then unpack */
6248 if (IS_BITVAR(retype))
6249 genUnpackBits(result,"dptr",CPOINTER);
6251 size = AOP_SIZE(result);
6255 emitcode("clr","a");
6256 emitcode("movc","a,@a+dptr");
6257 aopPut(AOP(result),"a",offset++);
6259 emitcode("inc","dptr");
6263 freeAsmop(result,NULL,ic,TRUE);
6266 /*-----------------------------------------------------------------*/
6267 /* genGenPointerGet - gget value from generic pointer space */
6268 /*-----------------------------------------------------------------*/
6269 static void genGenPointerGet (operand *left,
6270 operand *result, iCode *ic)
6273 sym_link *retype = getSpec(operandType(result));
6275 aopOp(left,ic,FALSE);
6277 /* if the operand is already in dptr
6278 then we do nothing else we move the value to dptr */
6279 if (AOP_TYPE(left) != AOP_STR) {
6280 /* if this is remateriazable */
6281 if (AOP_TYPE(left) == AOP_IMMD) {
6282 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6283 emitcode("mov","b,#%d",pointerCode(retype));
6285 else { /* we need to get it byte by byte */
6286 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6287 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6288 if (options.model == MODEL_FLAT24)
6290 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6291 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
6295 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
6299 /* so dptr know contains the address */
6300 freeAsmop(left,NULL,ic,TRUE);
6301 aopOp(result,ic,FALSE);
6303 /* if bit then unpack */
6304 if (IS_BITVAR(retype))
6305 genUnpackBits(result,"dptr",GPOINTER);
6307 size = AOP_SIZE(result);
6311 emitcode("lcall","__gptrget");
6312 aopPut(AOP(result),"a",offset++);
6314 emitcode("inc","dptr");
6318 freeAsmop(result,NULL,ic,TRUE);
6321 /*-----------------------------------------------------------------*/
6322 /* genPointerGet - generate code for pointer get */
6323 /*-----------------------------------------------------------------*/
6324 static void genPointerGet (iCode *ic)
6326 operand *left, *result ;
6327 sym_link *type, *etype;
6331 result = IC_RESULT(ic) ;
6333 /* depending on the type of pointer we need to
6334 move it to the correct pointer register */
6335 type = operandType(left);
6336 etype = getSpec(type);
6337 /* if left is of type of pointer then it is simple */
6338 if (IS_PTR(type) && !IS_FUNC(type->next))
6339 p_type = DCL_TYPE(type);
6341 /* we have to go by the storage class */
6342 p_type = PTR_TYPE(SPEC_OCLS(etype));
6344 /* if (SPEC_OCLS(etype)->codesp ) { */
6345 /* p_type = CPOINTER ; */
6348 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6349 /* p_type = FPOINTER ; */
6351 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6352 /* p_type = PPOINTER; */
6354 /* if (SPEC_OCLS(etype) == idata ) */
6355 /* p_type = IPOINTER; */
6357 /* p_type = POINTER ; */
6360 /* now that we have the pointer type we assign
6361 the pointer values */
6366 genNearPointerGet (left,result,ic);
6370 genPagedPointerGet(left,result,ic);
6374 genFarPointerGet (left,result,ic);
6378 emitcodePointerGet (left,result,ic);
6382 genGenPointerGet (left,result,ic);
6388 /*-----------------------------------------------------------------*/
6389 /* genPackBits - generates code for packed bit storage */
6390 /*-----------------------------------------------------------------*/
6391 static void genPackBits (sym_link *etype ,
6393 char *rname, int p_type)
6401 blen = SPEC_BLEN(etype);
6402 bstr = SPEC_BSTR(etype);
6404 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6407 /* if the bit lenth is less than or */
6408 /* it exactly fits a byte then */
6409 if (SPEC_BLEN(etype) <= 8 ) {
6410 shCount = SPEC_BSTR(etype) ;
6412 /* shift left acc */
6415 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6420 emitcode ("mov","b,a");
6421 emitcode("mov","a,@%s",rname);
6425 emitcode ("mov","b,a");
6426 emitcode("movx","a,@dptr");
6430 emitcode ("push","b");
6431 emitcode ("push","acc");
6432 emitcode ("lcall","__gptrget");
6433 emitcode ("pop","b");
6437 emitcode ("anl","a,#0x%02x",(unsigned char)
6438 ((unsigned char)(0xFF << (blen+bstr)) |
6439 (unsigned char)(0xFF >> (8-bstr)) ) );
6440 emitcode ("orl","a,b");
6441 if (p_type == GPOINTER)
6442 emitcode("pop","b");
6448 emitcode("mov","@%s,a",rname);
6452 emitcode("movx","@dptr,a");
6456 emitcode("lcall","__gptrput");
6461 if ( SPEC_BLEN(etype) <= 8 )
6464 emitcode("inc","%s",rname);
6465 rLen = SPEC_BLEN(etype) ;
6467 /* now generate for lengths greater than one byte */
6470 l = aopGet(AOP(right),offset++,FALSE,TRUE);
6480 emitcode("mov","@%s,a",rname);
6482 emitcode("mov","@%s,%s",rname,l);
6487 emitcode("movx","@dptr,a");
6492 emitcode("lcall","__gptrput");
6495 emitcode ("inc","%s",rname);
6500 /* last last was not complete */
6502 /* save the byte & read byte */
6505 emitcode ("mov","b,a");
6506 emitcode("mov","a,@%s",rname);
6510 emitcode ("mov","b,a");
6511 emitcode("movx","a,@dptr");
6515 emitcode ("push","b");
6516 emitcode ("push","acc");
6517 emitcode ("lcall","__gptrget");
6518 emitcode ("pop","b");
6522 emitcode ("anl","a,#0x%02x",(((unsigned char)-1 << rLen) & 0xff) );
6523 emitcode ("orl","a,b");
6526 if (p_type == GPOINTER)
6527 emitcode("pop","b");
6532 emitcode("mov","@%s,a",rname);
6536 emitcode("movx","@dptr,a");
6540 emitcode("lcall","__gptrput");
6544 /*-----------------------------------------------------------------*/
6545 /* genDataPointerSet - remat pointer to data space */
6546 /*-----------------------------------------------------------------*/
6547 static void genDataPointerSet(operand *right,
6551 int size, offset = 0 ;
6552 char *l, buffer[256];
6554 aopOp(right,ic,FALSE);
6556 l = aopGet(AOP(result),0,FALSE,TRUE);
6557 size = AOP_SIZE(right);
6560 sprintf(buffer,"(%s + %d)",l+1,offset);
6562 sprintf(buffer,"%s",l+1);
6563 emitcode("mov","%s,%s",buffer,
6564 aopGet(AOP(right),offset++,FALSE,FALSE));
6567 freeAsmop(right,NULL,ic,TRUE);
6568 freeAsmop(result,NULL,ic,TRUE);
6571 /*-----------------------------------------------------------------*/
6572 /* genNearPointerSet - emitcode for near pointer put */
6573 /*-----------------------------------------------------------------*/
6574 static void genNearPointerSet (operand *right,
6581 sym_link *retype, *letype;
6582 sym_link *ptype = operandType(result);
6584 retype= getSpec(operandType(right));
6585 letype= getSpec(ptype);
6586 aopOp(result,ic,FALSE);
6588 /* if the result is rematerializable &
6589 in data space & not a bit variable */
6590 if (AOP_TYPE(result) == AOP_IMMD &&
6591 DCL_TYPE(ptype) == POINTER &&
6592 !IS_BITVAR(retype) &&
6593 !IS_BITVAR(letype)) {
6594 genDataPointerSet (right,result,ic);
6598 /* if the value is already in a pointer register
6599 then don't need anything more */
6600 if (!AOP_INPREG(AOP(result))) {
6601 /* otherwise get a free pointer register */
6603 preg = getFreePtr(ic,&aop,FALSE);
6604 emitcode("mov","%s,%s",
6606 aopGet(AOP(result),0,FALSE,TRUE));
6607 rname = preg->name ;
6609 rname = aopGet(AOP(result),0,FALSE,FALSE);
6611 freeAsmop(result,NULL,ic,TRUE);
6612 aopOp (right,ic,FALSE);
6614 /* if bitfield then unpack the bits */
6615 if (IS_BITVAR(retype) || IS_BITVAR(letype))
6616 genPackBits ((IS_BITVAR(retype) ? retype : letype),right,rname,POINTER);
6618 /* we have can just get the values */
6619 int size = AOP_SIZE(right);
6623 l = aopGet(AOP(right),offset,FALSE,TRUE);
6626 emitcode("mov","@%s,a",rname);
6628 emitcode("mov","@%s,%s",rname,l);
6630 emitcode("inc","%s",rname);
6635 /* now some housekeeping stuff */
6637 /* we had to allocate for this iCode */
6638 freeAsmop(NULL,aop,ic,TRUE);
6640 /* we did not allocate which means left
6641 already in a pointer register, then
6642 if size > 0 && this could be used again
6643 we have to point it back to where it
6645 if (AOP_SIZE(right) > 1 &&
6646 !OP_SYMBOL(result)->remat &&
6647 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6649 int size = AOP_SIZE(right) - 1;
6651 emitcode("dec","%s",rname);
6656 freeAsmop(right,NULL,ic,TRUE);
6661 /*-----------------------------------------------------------------*/
6662 /* genPagedPointerSet - emitcode for Paged pointer put */
6663 /*-----------------------------------------------------------------*/
6664 static void genPagedPointerSet (operand *right,
6671 sym_link *retype, *letype;
6673 retype= getSpec(operandType(right));
6674 letype= getSpec(operandType(result));
6676 aopOp(result,ic,FALSE);
6678 /* if the value is already in a pointer register
6679 then don't need anything more */
6680 if (!AOP_INPREG(AOP(result))) {
6681 /* otherwise get a free pointer register */
6683 preg = getFreePtr(ic,&aop,FALSE);
6684 emitcode("mov","%s,%s",
6686 aopGet(AOP(result),0,FALSE,TRUE));
6687 rname = preg->name ;
6689 rname = aopGet(AOP(result),0,FALSE,FALSE);
6691 freeAsmop(result,NULL,ic,TRUE);
6692 aopOp (right,ic,FALSE);
6694 /* if bitfield then unpack the bits */
6695 if (IS_BITVAR(retype) || IS_BITVAR(letype))
6696 genPackBits ((IS_BITVAR(retype) ? retype : letype),right,rname,PPOINTER);
6698 /* we have can just get the values */
6699 int size = AOP_SIZE(right);
6703 l = aopGet(AOP(right),offset,FALSE,TRUE);
6706 emitcode("movx","@%s,a",rname);
6709 emitcode("inc","%s",rname);
6715 /* now some housekeeping stuff */
6717 /* we had to allocate for this iCode */
6718 freeAsmop(NULL,aop,ic,TRUE);
6720 /* we did not allocate which means left
6721 already in a pointer register, then
6722 if size > 0 && this could be used again
6723 we have to point it back to where it
6725 if (AOP_SIZE(right) > 1 &&
6726 !OP_SYMBOL(result)->remat &&
6727 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6729 int size = AOP_SIZE(right) - 1;
6731 emitcode("dec","%s",rname);
6736 freeAsmop(right,NULL,ic,TRUE);
6741 /*-----------------------------------------------------------------*/
6742 /* genFarPointerSet - set value from far space */
6743 /*-----------------------------------------------------------------*/
6744 static void genFarPointerSet (operand *right,
6745 operand *result, iCode *ic)
6748 sym_link *retype = getSpec(operandType(right));
6749 sym_link *letype = getSpec(operandType(result));
6750 aopOp(result,ic,FALSE);
6752 /* if the operand is already in dptr
6753 then we do nothing else we move the value to dptr */
6754 if (AOP_TYPE(result) != AOP_STR) {
6755 /* if this is remateriazable */
6756 if (AOP_TYPE(result) == AOP_IMMD)
6757 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6758 else { /* we need to get it byte by byte */
6759 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6760 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6761 if (options.model == MODEL_FLAT24)
6763 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6767 /* so dptr know contains the address */
6768 freeAsmop(result,NULL,ic,TRUE);
6769 aopOp(right,ic,FALSE);
6771 /* if bit then unpack */
6772 if (IS_BITVAR(retype) || IS_BITVAR(letype))
6773 genPackBits((IS_BITVAR(retype) ? retype : letype),right,"dptr",FPOINTER);
6775 size = AOP_SIZE(right);
6779 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6781 emitcode("movx","@dptr,a");
6783 emitcode("inc","dptr");
6787 freeAsmop(right,NULL,ic,TRUE);
6790 /*-----------------------------------------------------------------*/
6791 /* genGenPointerSet - set value from generic pointer space */
6792 /*-----------------------------------------------------------------*/
6793 static void genGenPointerSet (operand *right,
6794 operand *result, iCode *ic)
6797 sym_link *retype = getSpec(operandType(right));
6798 sym_link *letype = getSpec(operandType(result));
6800 aopOp(result,ic,FALSE);
6802 /* if the operand is already in dptr
6803 then we do nothing else we move the value to dptr */
6804 if (AOP_TYPE(result) != AOP_STR) {
6805 /* if this is remateriazable */
6806 if (AOP_TYPE(result) == AOP_IMMD) {
6807 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6808 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
6810 else { /* we need to get it byte by byte */
6811 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6812 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6813 if (options.model == MODEL_FLAT24)
6815 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6816 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
6820 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
6824 /* so dptr know contains the address */
6825 freeAsmop(result,NULL,ic,TRUE);
6826 aopOp(right,ic,FALSE);
6828 /* if bit then unpack */
6829 if (IS_BITVAR(retype) || IS_BITVAR(letype))
6830 genPackBits((IS_BITVAR(retype) ? retype : letype),right,"dptr",GPOINTER);
6832 size = AOP_SIZE(right);
6836 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6838 emitcode("lcall","__gptrput");
6840 emitcode("inc","dptr");
6844 freeAsmop(right,NULL,ic,TRUE);
6847 /*-----------------------------------------------------------------*/
6848 /* genPointerSet - stores the value into a pointer location */
6849 /*-----------------------------------------------------------------*/
6850 static void genPointerSet (iCode *ic)
6852 operand *right, *result ;
6853 sym_link *type, *etype;
6856 right = IC_RIGHT(ic);
6857 result = IC_RESULT(ic) ;
6859 /* depending on the type of pointer we need to
6860 move it to the correct pointer register */
6861 type = operandType(result);
6862 etype = getSpec(type);
6863 /* if left is of type of pointer then it is simple */
6864 if (IS_PTR(type) && !IS_FUNC(type->next)) {
6865 p_type = DCL_TYPE(type);
6868 /* we have to go by the storage class */
6869 p_type = PTR_TYPE(SPEC_OCLS(etype));
6872 /* now that we have the pointer type we assign
6873 the pointer values */
6878 genNearPointerSet (right,result,ic);
6882 genPagedPointerSet (right,result,ic);
6886 genFarPointerSet (right,result,ic);
6890 genGenPointerSet (right,result,ic);
6896 /*-----------------------------------------------------------------*/
6897 /* genIfx - generate code for Ifx statement */
6898 /*-----------------------------------------------------------------*/
6899 static void genIfx (iCode *ic, iCode *popIc)
6901 operand *cond = IC_COND(ic);
6904 aopOp(cond,ic,FALSE);
6906 /* get the value into acc */
6907 if (AOP_TYPE(cond) != AOP_CRY)
6911 /* the result is now in the accumulator */
6912 freeAsmop(cond,NULL,ic,TRUE);
6914 /* if there was something to be popped then do it */
6918 /* if the condition is a bit variable */
6919 if (isbit && IS_ITEMP(cond) &&
6921 genIfxJump(ic,SPIL_LOC(cond)->rname);
6923 if (isbit && !IS_ITEMP(cond))
6924 genIfxJump(ic,OP_SYMBOL(cond)->rname);
6931 /*-----------------------------------------------------------------*/
6932 /* genAddrOf - generates code for address of */
6933 /*-----------------------------------------------------------------*/
6934 static void genAddrOf (iCode *ic)
6936 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
6939 aopOp(IC_RESULT(ic),ic,FALSE);
6941 /* if the operand is on the stack then we
6942 need to get the stack offset of this
6945 /* if it has an offset then we need to compute
6948 emitcode("mov","a,_bp");
6949 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
6950 aopPut(AOP(IC_RESULT(ic)),"a",0);
6952 /* we can just move _bp */
6953 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
6955 /* fill the result with zero */
6956 size = AOP_SIZE(IC_RESULT(ic)) - 1;
6959 if (options.stack10bit && size < (FPTRSIZE - 1))
6962 "*** warning: pointer to stack var truncated.\n");
6969 if (options.stack10bit && offset == 2)
6971 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
6975 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
6982 /* object not on stack then we need the name */
6983 size = AOP_SIZE(IC_RESULT(ic));
6987 char s[SDCC_NAME_MAX];
6989 sprintf(s,"#(%s >> %d)",
6993 sprintf(s,"#%s",sym->rname);
6994 aopPut(AOP(IC_RESULT(ic)),s,offset++);
6998 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7002 /*-----------------------------------------------------------------*/
7003 /* genFarFarAssign - assignment when both are in far space */
7004 /*-----------------------------------------------------------------*/
7005 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7007 int size = AOP_SIZE(right);
7010 /* first push the right side on to the stack */
7012 l = aopGet(AOP(right),offset++,FALSE,FALSE);
7014 emitcode ("push","acc");
7017 freeAsmop(right,NULL,ic,FALSE);
7018 /* now assign DPTR to result */
7019 aopOp(result,ic,FALSE);
7020 size = AOP_SIZE(result);
7022 emitcode ("pop","acc");
7023 aopPut(AOP(result),"a",--offset);
7025 freeAsmop(result,NULL,ic,FALSE);
7029 /*-----------------------------------------------------------------*/
7030 /* genAssign - generate code for assignment */
7031 /*-----------------------------------------------------------------*/
7032 static void genAssign (iCode *ic)
7034 operand *result, *right;
7036 unsigned long lit = 0L;
7038 result = IC_RESULT(ic);
7039 right = IC_RIGHT(ic) ;
7041 /* if they are the same */
7042 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7045 aopOp(right,ic,FALSE);
7047 /* special case both in far space */
7048 if ((AOP_TYPE(right) == AOP_DPTR ||
7049 AOP_TYPE(right) == AOP_DPTR2) &&
7050 IS_TRUE_SYMOP(result) &&
7051 isOperandInFarSpace(result)) {
7053 genFarFarAssign (result,right,ic);
7057 aopOp(result,ic,TRUE);
7059 /* if they are the same registers */
7060 if (sameRegs(AOP(right),AOP(result)))
7063 /* if the result is a bit */
7064 if (AOP_TYPE(result) == AOP_CRY) {
7066 /* if the right size is a literal then
7067 we know what the value is */
7068 if (AOP_TYPE(right) == AOP_LIT) {
7069 if (((int) operandLitValue(right)))
7070 aopPut(AOP(result),one,0);
7072 aopPut(AOP(result),zero,0);
7076 /* the right is also a bit variable */
7077 if (AOP_TYPE(right) == AOP_CRY) {
7078 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7079 aopPut(AOP(result),"c",0);
7085 aopPut(AOP(result),"a",0);
7089 /* bit variables done */
7091 size = AOP_SIZE(result);
7093 if(AOP_TYPE(right) == AOP_LIT)
7094 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7096 (AOP_TYPE(result) != AOP_REG) &&
7097 (AOP_TYPE(right) == AOP_LIT) &&
7098 !IS_FLOAT(operandType(right)) &&
7100 emitcode("clr","a");
7102 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7103 aopPut(AOP(result),"a",size);
7106 aopGet(AOP(right),size,FALSE,FALSE),
7112 aopGet(AOP(right),offset,FALSE,FALSE),
7119 freeAsmop (right,NULL,ic,TRUE);
7120 freeAsmop (result,NULL,ic,TRUE);
7123 /*-----------------------------------------------------------------*/
7124 /* genJumpTab - genrates code for jump table */
7125 /*-----------------------------------------------------------------*/
7126 static void genJumpTab (iCode *ic)
7131 aopOp(IC_JTCOND(ic),ic,FALSE);
7132 /* get the condition into accumulator */
7133 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
7135 /* multiply by three */
7136 emitcode("add","a,acc");
7137 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
7138 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7140 jtab = newiTempLabel(NULL);
7141 emitcode("mov","dptr,#%05d$",jtab->key+100);
7142 emitcode("jmp","@a+dptr");
7143 emitcode("","%05d$:",jtab->key+100);
7144 /* now generate the jump labels */
7145 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
7146 jtab = setNextItem(IC_JTLABELS(ic)))
7147 emitcode("ljmp","%05d$",jtab->key+100);
7151 /*-----------------------------------------------------------------*/
7152 /* genCast - gen code for casting */
7153 /*-----------------------------------------------------------------*/
7154 static void genCast (iCode *ic)
7156 operand *result = IC_RESULT(ic);
7157 sym_link *ctype = operandType(IC_LEFT(ic));
7158 sym_link *rtype = operandType(IC_RIGHT(ic));
7159 operand *right = IC_RIGHT(ic);
7162 /* if they are equivalent then do nothing */
7163 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
7166 aopOp(right,ic,FALSE) ;
7167 aopOp(result,ic,FALSE);
7169 /* if the result is a bit */
7170 if (AOP_TYPE(result) == AOP_CRY) {
7171 /* if the right size is a literal then
7172 we know what the value is */
7173 if (AOP_TYPE(right) == AOP_LIT) {
7174 if (((int) operandLitValue(right)))
7175 aopPut(AOP(result),one,0);
7177 aopPut(AOP(result),zero,0);
7182 /* the right is also a bit variable */
7183 if (AOP_TYPE(right) == AOP_CRY) {
7184 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7185 aopPut(AOP(result),"c",0);
7191 aopPut(AOP(result),"a",0);
7195 /* if they are the same size : or less */
7196 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
7198 /* if they are in the same place */
7199 if (sameRegs(AOP(right),AOP(result)))
7202 /* if they in different places then copy */
7203 size = AOP_SIZE(result);
7207 aopGet(AOP(right),offset,FALSE,FALSE),
7215 /* if the result is of type pointer */
7216 if (IS_PTR(ctype)) {
7219 sym_link *type = operandType(right);
7220 sym_link *etype = getSpec(type);
7222 /* pointer to generic pointer */
7223 if (IS_GENPTR(ctype)) {
7227 p_type = DCL_TYPE(type);
7229 /* we have to go by the storage class */
7230 p_type = PTR_TYPE(SPEC_OCLS(etype));
7233 /* the first two bytes are known */
7234 size = GPTRSIZE - 1;
7238 aopGet(AOP(right),offset,FALSE,FALSE),
7242 /* the last byte depending on type */
7259 /* this should never happen */
7260 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7261 "got unknown pointer type");
7264 aopPut(AOP(result),l, GPTRSIZE - 1);
7268 /* just copy the pointers */
7269 size = AOP_SIZE(result);
7273 aopGet(AOP(right),offset,FALSE,FALSE),
7280 /* so we now know that the size of destination is greater
7281 than the size of the source */
7282 /* we move to result for the size of source */
7283 size = AOP_SIZE(right);
7287 aopGet(AOP(right),offset,FALSE,FALSE),
7292 /* now depending on the sign of the source && destination */
7293 size = AOP_SIZE(result) - AOP_SIZE(right);
7294 /* if unsigned or not an integral type */
7295 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
7297 aopPut(AOP(result),zero,offset++);
7299 /* we need to extend the sign :{ */
7300 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
7303 emitcode("rlc","a");
7304 emitcode("subb","a,acc");
7306 aopPut(AOP(result),"a",offset++);
7309 /* we are done hurray !!!! */
7312 freeAsmop(right,NULL,ic,TRUE);
7313 freeAsmop(result,NULL,ic,TRUE);
7317 /*-----------------------------------------------------------------*/
7318 /* genDjnz - generate decrement & jump if not zero instrucion */
7319 /*-----------------------------------------------------------------*/
7320 static int genDjnz (iCode *ic, iCode *ifx)
7326 /* if the if condition has a false label
7327 then we cannot save */
7331 /* if the minus is not of the form
7333 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
7334 !IS_OP_LITERAL(IC_RIGHT(ic)))
7337 if (operandLitValue(IC_RIGHT(ic)) != 1)
7340 /* if the size of this greater than one then no
7342 if (getSize(operandType(IC_RESULT(ic))) > 1)
7345 /* otherwise we can save BIG */
7346 lbl = newiTempLabel(NULL);
7347 lbl1= newiTempLabel(NULL);
7349 aopOp(IC_RESULT(ic),ic,FALSE);
7351 if (IS_AOP_PREG(IC_RESULT(ic))) {
7352 emitcode("dec","%s",
7353 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7354 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7355 emitcode("jnz","%05d$",lbl->key+100);
7357 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
7360 emitcode ("sjmp","%05d$",lbl1->key+100);
7361 emitcode ("","%05d$:",lbl->key+100);
7362 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
7363 emitcode ("","%05d$:",lbl1->key+100);
7365 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7370 /*-----------------------------------------------------------------*/
7371 /* genReceive - generate code for a receive iCode */
7372 /*-----------------------------------------------------------------*/
7373 static void genReceive (iCode *ic)
7375 if (isOperandInFarSpace(IC_RESULT(ic)) &&
7376 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
7377 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
7379 int size = getSize(operandType(IC_RESULT(ic)));
7380 int offset = fReturnSize - size;
7382 emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
7383 fReturn[fReturnSize - offset - 1] : "acc"));
7386 aopOp(IC_RESULT(ic),ic,FALSE);
7387 size = AOP_SIZE(IC_RESULT(ic));
7390 emitcode ("pop","acc");
7391 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
7396 aopOp(IC_RESULT(ic),ic,FALSE);
7398 assignResultValue(IC_RESULT(ic));
7401 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7404 /*-----------------------------------------------------------------*/
7405 /* gen51Code - generate code for 8051 based controllers */
7406 /*-----------------------------------------------------------------*/
7407 void gen51Code (iCode *lic)
7412 lineHead = lineCurr = NULL;
7414 /* print the allocation information */
7416 printAllocInfo( currFunc, codeOutFile);
7417 /* if debug information required */
7418 /* if (options.debug && currFunc) { */
7420 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
7422 if (IS_STATIC(currFunc->etype))
7423 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
7425 emitcode("","G$%s$0$0 ==.",currFunc->name);
7428 /* stack pointer name */
7429 if (options.useXstack)
7435 for (ic = lic ; ic ; ic = ic->next ) {
7437 if ( cln != ic->lineno ) {
7438 if ( options.debug ) {
7440 emitcode("","C$%s$%d$%d$%d ==.",
7441 ic->filename,ic->lineno,
7442 ic->level,ic->block);
7445 emitcode(";","%s %d",ic->filename,ic->lineno);
7448 /* if the result is marked as
7449 spilt and rematerializable or code for
7450 this has already been generated then
7452 if (resultRemat(ic) || ic->generated )
7455 /* depending on the operation */
7474 /* IPOP happens only when trying to restore a
7475 spilt live range, if there is an ifx statement
7476 following this pop then the if statement might
7477 be using some of the registers being popped which
7478 would destory the contents of the register so
7479 we need to check for this condition and handle it */
7481 ic->next->op == IFX &&
7482 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
7483 genIfx (ic->next,ic);
7501 genEndFunction (ic);
7521 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
7538 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
7542 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
7549 /* note these two are xlated by algebraic equivalence
7550 during parsing SDCC.y */
7551 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7552 "got '>=' or '<=' shouldn't have come here");
7556 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
7568 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
7572 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
7576 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
7603 case GET_VALUE_AT_ADDRESS:
7608 if (POINTER_SET(ic))
7635 addSet(&_G.sendSet,ic);
7640 /* piCode(ic,stdout); */
7646 /* now we are ready to call the
7647 peep hole optimizer */
7648 if (!options.nopeep)
7649 peepHole (&lineHead);
7651 /* now do the actual printing */
7652 printLine (lineHead,codeOutFile);