1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
35 #include "SDCCglobl.h"
37 #ifdef HAVE_SYS_ISA_DEFS_H
38 #include <sys/isa_defs.h>
44 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
45 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
51 #include "SDCCpeeph.h"
55 char *aopLiteral (value *val, int offset);
58 /* this is the down and dirty file with all kinds of
59 kludgy & hacky stuff. This is what it is all about
60 CODE GENERATION for a specific MCU . some of the
61 routines may be reusable, will have to see */
63 static char *zero = "#0x00";
64 static char *one = "#0x01";
69 unsigned fReturnSize_390 = 5; /* shared with ralloc.c */
70 static char *fReturn[] = {"dpl","dph","dpx", "b","a" };
71 static char *accUse[] = {"a","b"};
73 static short rbank = -1;
85 extern int ds390_ptrRegReq ;
86 extern int ds390_nRegs;
87 extern FILE *codeOutFile;
88 static void saverbank (int, iCode *,bool);
89 #define RESULTONSTACK(x) \
90 (IC_RESULT(x) && IC_RESULT(x)->aop && \
91 IC_RESULT(x)->aop->type == AOP_STK )
93 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
94 #define MOVA(x) { char *_mova_tmp = strdup(x); \
95 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
97 emitcode("mov","a,%s",_mova_tmp); \
101 #define CLRC emitcode("clr","c")
102 #define SETC emitcode("setb","c")
104 static lineNode *lineHead = NULL;
105 static lineNode *lineCurr = NULL;
107 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
108 0xE0, 0xC0, 0x80, 0x00};
109 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
110 0x07, 0x03, 0x01, 0x00};
117 /*-----------------------------------------------------------------*/
118 /* emitcode - writes the code into a file : for now it is simple */
119 /*-----------------------------------------------------------------*/
120 static void emitcode (char *inst,char *fmt, ...)
123 char lb[MAX_INLINEASM];
130 sprintf(lb,"%s\t",inst);
132 sprintf(lb,"%s",inst);
133 vsprintf(lb+(strlen(lb)),fmt,ap);
137 while (isspace(*lbp)) lbp++;
140 lineCurr = (lineCurr ?
141 connectLine(lineCurr,newLineNode(lb)) :
142 (lineHead = newLineNode(lb)));
143 lineCurr->isInline = _G.inLine;
144 lineCurr->isDebug = _G.debugLine;
148 /*-----------------------------------------------------------------*/
149 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
150 /*-----------------------------------------------------------------*/
151 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
153 bool r0iu = FALSE , r1iu = FALSE;
154 bool r0ou = FALSE , r1ou = FALSE;
156 /* the logic: if r0 & r1 used in the instruction
157 then we are in trouble otherwise */
159 /* first check if r0 & r1 are used by this
160 instruction, in which case we are in trouble */
161 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
162 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
167 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
168 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
170 /* if no usage of r0 then return it */
171 if (!r0iu && !r0ou) {
172 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
173 (*aopp)->type = AOP_R0;
175 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R0_IDX);
178 /* if no usage of r1 then return it */
179 if (!r1iu && !r1ou) {
180 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
181 (*aopp)->type = AOP_R1;
183 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R1_IDX);
186 /* now we know they both have usage */
187 /* if r0 not used in this instruction */
189 /* push it if not already pushed */
191 emitcode ("push","%s",
192 ds390_regWithIdx(R0_IDX)->dname);
196 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
197 (*aopp)->type = AOP_R0;
199 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R0_IDX);
202 /* if r1 not used then */
205 /* push it if not already pushed */
207 emitcode ("push","%s",
208 ds390_regWithIdx(R1_IDX)->dname);
212 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
213 (*aopp)->type = AOP_R1;
214 return ds390_regWithIdx(R1_IDX);
218 /* I said end of world but not quite end of world yet */
219 /* if this is a result then we can push it on the stack*/
221 (*aopp)->type = AOP_STK;
226 /* other wise this is true end of the world */
227 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
228 "getFreePtr should never reach here");
232 /*-----------------------------------------------------------------*/
233 /* newAsmop - creates a new asmOp */
234 /*-----------------------------------------------------------------*/
235 static asmop *newAsmop (short type)
239 ALLOC(aop,sizeof(asmop));
244 static void genSetDPTR(int n)
248 emitcode("mov", "dps, #0x00");
252 emitcode("mov", "dps, #0x01");
256 /*-----------------------------------------------------------------*/
257 /* pointerCode - returns the code for a pointer type */
258 /*-----------------------------------------------------------------*/
259 static int pointerCode (link *etype)
262 return PTR_TYPE(SPEC_OCLS(etype));
266 /*-----------------------------------------------------------------*/
267 /* aopForSym - for a true symbol */
268 /*-----------------------------------------------------------------*/
269 static asmop *aopForSym (iCode *ic,symbol *sym,bool result, bool useDP2)
272 memmap *space= SPEC_OCLS(sym->etype);
274 /* if already has one */
278 /* assign depending on the storage class */
279 /* if it is on the stack or indirectly addressable */
280 /* space we need to assign either r0 or r1 to it */
281 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
282 sym->aop = aop = newAsmop(0);
283 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
284 aop->size = getSize(sym->type);
286 /* now assign the address of the variable to
287 the pointer register */
288 if (aop->type != AOP_STK) {
292 emitcode("push","acc");
294 emitcode("mov","a,_bp");
295 emitcode("add","a,#0x%02x",
297 ((char)(sym->stack - _G.nRegsSaved )) :
298 ((char)sym->stack)) & 0xff);
299 emitcode("mov","%s,a",
300 aop->aopu.aop_ptr->name);
303 emitcode("pop","acc");
305 emitcode("mov","%s,#%s",
306 aop->aopu.aop_ptr->name,
308 aop->paged = space->paged;
310 aop->aopu.aop_stk = sym->stack;
314 if (sym->onStack && options.stack10bit)
316 /* It's on the 10 bit stack, which is located in
321 emitcode("push","acc");
323 emitcode("mov","a,_bp");
324 emitcode("add","a,#0x%02x",
326 ((char)(sym->stack - _G.nRegsSaved )) :
327 ((char)sym->stack)) & 0xff);
332 emitcode ("mov","dpx1,#0x40");
333 emitcode ("mov","dph1,#0x00");
334 emitcode ("mov","dpl1, a");
339 emitcode ("mov","dpx,#0x40");
340 emitcode ("mov","dph,#0x00");
341 emitcode ("mov","dpl, a");
345 emitcode("pop","acc");
347 sym->aop = aop = newAsmop(useDP2 ? AOP_DPTR2 : AOP_DPTR);
348 aop->size = getSize(sym->type);
352 /* if in bit space */
353 if (IN_BITSPACE(space)) {
354 sym->aop = aop = newAsmop (AOP_CRY);
355 aop->aopu.aop_dir = sym->rname ;
356 aop->size = getSize(sym->type);
359 /* if it is in direct space */
360 if (IN_DIRSPACE(space)) {
361 sym->aop = aop = newAsmop (AOP_DIR);
362 aop->aopu.aop_dir = sym->rname ;
363 aop->size = getSize(sym->type);
367 /* special case for a function */
368 if (IS_FUNC(sym->type)) {
369 sym->aop = aop = newAsmop(AOP_IMMD);
370 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
371 strcpy(aop->aopu.aop_immd,sym->rname);
372 aop->size = FPTRSIZE;
376 /* only remaining is far space */
377 /* in which case DPTR gets the address */
378 sym->aop = aop = newAsmop(useDP2 ? AOP_DPTR2 : AOP_DPTR);
382 emitcode ("mov","dptr,#%s", sym->rname);
387 emitcode ("mov","dptr,#%s", sym->rname);
389 aop->size = getSize(sym->type);
391 /* if it is in code space */
392 if (IN_CODESPACE(space))
398 /*-----------------------------------------------------------------*/
399 /* aopForRemat - rematerialzes an object */
400 /*-----------------------------------------------------------------*/
401 static asmop *aopForRemat (symbol *sym)
403 iCode *ic = sym->rematiCode;
404 asmop *aop = newAsmop(AOP_IMMD);
410 val += operandLitValue(IC_RIGHT(ic));
411 else if (ic->op == '-')
412 val -= operandLitValue(IC_RIGHT(ic));
416 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
420 sprintf(buffer,"(%s %c 0x%04x)",
421 OP_SYMBOL(IC_LEFT(ic))->rname,
422 val >= 0 ? '+' : '-',
425 strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
427 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
428 strcpy(aop->aopu.aop_immd,buffer);
432 /*-----------------------------------------------------------------*/
433 /* regsInCommon - two operands have some registers in common */
434 /*-----------------------------------------------------------------*/
435 static bool regsInCommon (operand *op1, operand *op2)
440 /* if they have registers in common */
441 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
444 sym1 = OP_SYMBOL(op1);
445 sym2 = OP_SYMBOL(op2);
447 if (sym1->nRegs == 0 || sym2->nRegs == 0)
450 for (i = 0 ; i < sym1->nRegs ; i++) {
455 for (j = 0 ; j < sym2->nRegs ;j++ ) {
459 if (sym2->regs[j] == sym1->regs[i])
467 /*-----------------------------------------------------------------*/
468 /* operandsEqu - equivalent */
469 /*-----------------------------------------------------------------*/
470 static bool operandsEqu ( operand *op1, operand *op2)
474 /* if they not symbols */
475 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
478 sym1 = OP_SYMBOL(op1);
479 sym2 = OP_SYMBOL(op2);
481 /* if both are itemps & one is spilt
482 and the other is not then false */
483 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
484 sym1->isspilt != sym2->isspilt )
487 /* if they are the same */
491 if (strcmp(sym1->rname,sym2->rname) == 0)
495 /* if left is a tmp & right is not */
499 (sym1->usl.spillLoc == sym2))
506 (sym2->usl.spillLoc == sym1))
512 /*-----------------------------------------------------------------*/
513 /* sameRegs - two asmops have the same registers */
514 /*-----------------------------------------------------------------*/
515 static bool sameRegs (asmop *aop1, asmop *aop2 )
521 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
528 if (aop1->type != AOP_REG ||
529 aop2->type != AOP_REG )
532 if (aop1->size != aop2->size )
535 for (i = 0 ; i < aop1->size ; i++ )
536 if (aop1->aopu.aop_reg[i] !=
537 aop2->aopu.aop_reg[i] )
543 /*-----------------------------------------------------------------*/
544 /* aopOp - allocates an asmop for an operand : */
545 /*-----------------------------------------------------------------*/
546 static void aopOp (operand *op, iCode *ic, bool result, bool useDP2)
555 /* if this a literal */
556 if (IS_OP_LITERAL(op)) {
557 op->aop = aop = newAsmop(AOP_LIT);
558 aop->aopu.aop_lit = op->operand.valOperand;
559 aop->size = getSize(operandType(op));
563 /* if already has a asmop then continue */
567 /* if the underlying symbol has a aop */
568 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
569 op->aop = OP_SYMBOL(op)->aop;
573 /* if this is a true symbol */
574 if (IS_TRUE_SYMOP(op)) {
575 op->aop = aopForSym(ic,OP_SYMBOL(op),result, useDP2);
579 /* this is a temporary : this has
585 e) can be a return use only */
590 /* if the type is a conditional */
591 if (sym->regType == REG_CND) {
592 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
597 /* if it is spilt then two situations
599 b) has a spill location */
600 if (sym->isspilt || sym->nRegs == 0) {
602 /* rematerialize it NOW */
604 sym->aop = op->aop = aop =
606 aop->size = getSize(sym->type);
612 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
613 aop->size = getSize(sym->type);
614 for ( i = 0 ; i < 2 ; i++ )
615 aop->aopu.aop_str[i] = accUse[i];
621 aop = op->aop = sym->aop = newAsmop(AOP_STR);
622 aop->size = getSize(sym->type);
623 for ( i = 0 ; i < fReturnSize_390 ; i++ )
624 aop->aopu.aop_str[i] = fReturn[i];
628 /* else spill location */
629 sym->aop = op->aop = aop =
630 aopForSym(ic,sym->usl.spillLoc,result, useDP2);
631 aop->size = getSize(sym->type);
635 /* must be in a register */
636 sym->aop = op->aop = aop = newAsmop(AOP_REG);
637 aop->size = sym->nRegs;
638 for ( i = 0 ; i < sym->nRegs ;i++)
639 aop->aopu.aop_reg[i] = sym->regs[i];
642 /*-----------------------------------------------------------------*/
643 /* freeAsmop - free up the asmop given to an operand */
644 /*----------------------------------------------------------------*/
645 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
662 /* depending on the asmop type only three cases need work AOP_RO
663 , AOP_R1 && AOP_STK */
668 emitcode ("pop","ar0");
672 bitVectUnSetBit(ic->rUsed,R0_IDX);
678 emitcode ("pop","ar1");
682 bitVectUnSetBit(ic->rUsed,R1_IDX);
688 int stk = aop->aopu.aop_stk + aop->size;
689 bitVectUnSetBit(ic->rUsed,R0_IDX);
690 bitVectUnSetBit(ic->rUsed,R1_IDX);
692 getFreePtr(ic,&aop,FALSE);
694 if (options.stack10bit)
696 /* I'm not sure what to do here yet... */
699 "*** Warning: probably generating bad code for "
700 "10 bit stack mode.\n");
704 emitcode ("mov","a,_bp");
705 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
706 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
708 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
712 emitcode("pop","acc");
713 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
715 emitcode("dec","%s",aop->aopu.aop_ptr->name);
718 freeAsmop(op,NULL,ic,TRUE);
720 emitcode("pop","ar0");
725 emitcode("pop","ar1");
732 /* all other cases just dealloc */
736 OP_SYMBOL(op)->aop = NULL;
737 /* if the symbol has a spill */
739 SPIL_LOC(op)->aop = NULL;
744 /*-----------------------------------------------------------------*/
745 /* aopGet - for fetching value of the aop */
747 * Set canClobberACC if you are aure it is OK to clobber the value
748 * in the accumulator. Set it FALSE otherwise; FALSE is always safe,
749 * just less efficient.
750 /*-----------------------------------------------------------------*/
752 static char *aopGet (asmop *aop,
761 /* offset is greater than
763 if (offset > (aop->size - 1) &&
764 aop->type != AOP_LIT)
767 /* depending on type */
772 /* if we need to increment it */
773 while (offset > aop->coff) {
774 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
778 while (offset < aop->coff) {
779 emitcode("dec","%s",aop->aopu.aop_ptr->name);
785 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
786 return (dname ? "acc" : "a");
788 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
789 ALLOC_ATOMIC(rs,strlen(s)+1);
796 if (aop->type == AOP_DPTR2)
800 #ifndef KEVIN_BROKE_IT
804 emitcode("xch", "a, ap");
808 while (offset > aop->coff) {
809 emitcode ("inc","dptr");
813 while (offset < aop->coff) {
814 emitcode("lcall","__decdptr");
821 emitcode("movc","a,@a+dptr");
824 emitcode("movx","a,@dptr");
827 if (aop->type == AOP_DPTR2)
831 #ifndef KEVIN_BROKE_IT
835 emitcode("xch", "a, ap");
840 return (dname ? "acc" : "a");
845 sprintf (s,"#%s",aop->aopu.aop_immd);
848 sprintf(s,"#(%s >> %d)",
854 ALLOC_ATOMIC(rs,strlen(s)+1);
860 sprintf(s,"(%s + %d)",
864 sprintf(s,"%s",aop->aopu.aop_dir);
865 ALLOC_ATOMIC(rs,strlen(s)+1);
871 return aop->aopu.aop_reg[offset]->dname;
873 return aop->aopu.aop_reg[offset]->name;
877 emitcode("mov","c,%s",aop->aopu.aop_dir);
878 emitcode("rlc","a") ;
879 return (dname ? "acc" : "a");
882 if (!offset && dname)
884 return aop->aopu.aop_str[offset];
887 return aopLiteral (aop->aopu.aop_lit,offset);
891 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
895 return aop->aopu.aop_str[offset];
899 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
900 "aopget got unsupported aop->type");
903 /*-----------------------------------------------------------------*/
904 /* aopPut - puts a string for a aop */
905 /*-----------------------------------------------------------------*/
906 static void aopPut (asmop *aop, char *s, int offset)
911 if (aop->size && offset > ( aop->size - 1)) {
912 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
913 "aopPut got offset > aop->size");
917 /* will assign value to value */
918 /* depending on where it is ofcourse */
922 sprintf(d,"(%s + %d)",
923 aop->aopu.aop_dir,offset);
925 sprintf(d,"%s",aop->aopu.aop_dir);
928 emitcode("mov","%s,%s",d,s);
933 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
934 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
936 strcmp(s,"r0") == 0 ||
937 strcmp(s,"r1") == 0 ||
938 strcmp(s,"r2") == 0 ||
939 strcmp(s,"r3") == 0 ||
940 strcmp(s,"r4") == 0 ||
941 strcmp(s,"r5") == 0 ||
942 strcmp(s,"r6") == 0 ||
943 strcmp(s,"r7") == 0 )
944 emitcode("mov","%s,%s",
945 aop->aopu.aop_reg[offset]->dname,s);
947 emitcode("mov","%s,%s",
948 aop->aopu.aop_reg[offset]->name,s);
955 if (aop->type == AOP_DPTR2)
961 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
962 "aopPut writting to code space");
966 while (offset > aop->coff) {
968 emitcode ("inc","dptr");
971 while (offset < aop->coff) {
973 emitcode("lcall","__decdptr");
978 /* if not in accumulater */
981 emitcode ("movx","@dptr,a");
983 if (aop->type == AOP_DPTR2)
991 while (offset > aop->coff) {
993 emitcode("inc","%s",aop->aopu.aop_ptr->name);
995 while (offset < aop->coff) {
997 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1003 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1008 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1010 if (strcmp(s,"r0") == 0 ||
1011 strcmp(s,"r1") == 0 ||
1012 strcmp(s,"r2") == 0 ||
1013 strcmp(s,"r3") == 0 ||
1014 strcmp(s,"r4") == 0 ||
1015 strcmp(s,"r5") == 0 ||
1016 strcmp(s,"r6") == 0 ||
1017 strcmp(s,"r7") == 0 ) {
1019 sprintf(buffer,"a%s",s);
1020 emitcode("mov","@%s,%s",
1021 aop->aopu.aop_ptr->name,buffer);
1023 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1028 if (strcmp(s,"a") == 0)
1029 emitcode("push","acc");
1031 emitcode("push","%s",s);
1036 /* if bit variable */
1037 if (!aop->aopu.aop_dir) {
1038 emitcode("clr","a");
1039 emitcode("rlc","a");
1042 emitcode("clr","%s",aop->aopu.aop_dir);
1045 emitcode("setb","%s",aop->aopu.aop_dir);
1048 emitcode("mov","%s,c",aop->aopu.aop_dir);
1050 lbl = newiTempLabel(NULL);
1052 if (strcmp(s,"a")) {
1055 emitcode("clr","c");
1056 emitcode("jz","%05d$",lbl->key+100);
1057 emitcode("cpl","c");
1058 emitcode("","%05d$:",lbl->key+100);
1059 emitcode("mov","%s,c",aop->aopu.aop_dir);
1066 if (strcmp(aop->aopu.aop_str[offset],s))
1067 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1072 if (!offset && (strcmp(s,"acc") == 0))
1075 if (strcmp(aop->aopu.aop_str[offset],s))
1076 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1080 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1081 "aopPut got unsupported aop->type");
1089 /*-----------------------------------------------------------------*/
1090 /* pointToEnd :- points to the last byte of the operand */
1091 /*-----------------------------------------------------------------*/
1092 static void pointToEnd (asmop *aop)
1098 aop->coff = count = (aop->size - 1);
1099 switch (aop->type) {
1103 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1107 emitcode("inc","dptr");
1114 /*-----------------------------------------------------------------*/
1115 /* reAdjustPreg - points a register back to where it should */
1116 /*-----------------------------------------------------------------*/
1117 static void reAdjustPreg (asmop *aop)
1122 if ((size = aop->size) <= 1)
1125 switch (aop->type) {
1129 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1133 if (aop->type == AOP_DPTR2)
1139 emitcode("lcall","__decdptr");
1142 if (aop->type == AOP_DPTR2)
1152 #define AOP(op) op->aop
1153 #define AOP_TYPE(op) AOP(op)->type
1154 #define AOP_SIZE(op) AOP(op)->size
1155 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1156 AOP_TYPE(x) == AOP_R0))
1158 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1159 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1162 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1163 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1164 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1166 /* Workaround for DS80C390 bug: div ab may return bogus results
1167 * if A is accessed in instruction immediately before the div.
1169 * Will be fixed in B4 rev of processor, Dallas claims.
1172 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1173 if (!AOP_NEEDSACC(RIGHT)) \
1175 /* We can load A first, then B, since \
1176 * B (the RIGHT operand) won't clobber A, \
1177 * thus avoiding touching A right before the div. \
1179 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1180 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1182 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1186 /* Just stuff in a nop after loading A. */ \
1187 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1188 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1190 emitcode("nop", "; workaround for DS80C390 div bug."); \
1193 /*-----------------------------------------------------------------*/
1194 /* genNotFloat - generates not for float operations */
1195 /*-----------------------------------------------------------------*/
1196 static void genNotFloat (operand *op, operand *res)
1202 D(emitcode(";", "genNotFloat "););
1204 /* we will put 127 in the first byte of
1206 aopPut(AOP(res),"#127",0);
1207 size = AOP_SIZE(op) - 1;
1210 l = aopGet(op->aop,offset++,FALSE,FALSE,TRUE);
1214 emitcode("orl","a,%s",
1216 offset++,FALSE,FALSE,FALSE));
1218 tlbl = newiTempLabel(NULL);
1220 tlbl = newiTempLabel(NULL);
1221 aopPut(res->aop,one,1);
1222 emitcode("jz","%05d$",(tlbl->key+100));
1223 aopPut(res->aop,zero,1);
1224 emitcode("","%05d$:",(tlbl->key+100));
1226 size = res->aop->size - 2;
1228 /* put zeros in the rest */
1230 aopPut(res->aop,zero,offset++);
1233 /*-----------------------------------------------------------------*/
1234 /* opIsGptr: returns non-zero if the passed operand is */
1235 /* a generic pointer type. */
1236 /*-----------------------------------------------------------------*/
1237 static int opIsGptr(operand *op)
1239 link *type = operandType(op);
1241 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1248 /*-----------------------------------------------------------------*/
1249 /* getDataSize - get the operand data size */
1250 /*-----------------------------------------------------------------*/
1251 static int getDataSize(operand *op)
1254 size = AOP_SIZE(op);
1255 if (size == GPTRSIZE)
1257 link *type = operandType(op);
1258 if (IS_GENPTR(type))
1260 /* generic pointer; arithmetic operations
1261 * should ignore the high byte (pointer type).
1269 /*-----------------------------------------------------------------*/
1270 /* outAcc - output Acc */
1271 /*-----------------------------------------------------------------*/
1272 static void outAcc(operand *result)
1275 size = getDataSize(result);
1277 aopPut(AOP(result),"a",0);
1280 /* unsigned or positive */
1282 aopPut(AOP(result),zero,offset++);
1287 /*-----------------------------------------------------------------*/
1288 /* outBitC - output a bit C */
1289 /*-----------------------------------------------------------------*/
1290 static void outBitC(operand *result)
1292 /* if the result is bit */
1293 if (AOP_TYPE(result) == AOP_CRY)
1294 aopPut(AOP(result),"c",0);
1296 emitcode("clr","a");
1297 emitcode("rlc","a");
1302 /*-----------------------------------------------------------------*/
1303 /* toBoolean - emit code for orl a,operator(sizeop) */
1304 /*-----------------------------------------------------------------*/
1305 static void toBoolean(operand *oper)
1307 int size = AOP_SIZE(oper) - 1;
1310 if (AOP_NEEDSACC(oper))
1312 emitcode("push", "b");
1313 emitcode("mov", "b, %s", aopGet(AOP(oper),0,FALSE,FALSE,FALSE));
1317 MOVA(aopGet(AOP(oper),0,FALSE,FALSE,TRUE));
1321 if (AOP_NEEDSACC(oper))
1323 emitcode("orl","b,%s",aopGet(AOP(oper),offset++,FALSE,FALSE,FALSE));
1327 emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE,FALSE));
1331 if (AOP_NEEDSACC(oper))
1333 emitcode("mov", "a,b");
1334 emitcode("pop", "b");
1339 /*-----------------------------------------------------------------*/
1340 /* genNot - generate code for ! operation */
1341 /*-----------------------------------------------------------------*/
1342 static void genNot (iCode *ic)
1345 link *optype = operandType(IC_LEFT(ic));
1347 D(emitcode(";", "genNot "););
1349 /* assign asmOps to operand & result */
1350 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1351 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1353 /* if in bit space then a special case */
1354 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1355 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1356 emitcode("cpl","c");
1357 outBitC(IC_RESULT(ic));
1361 /* if type float then do float */
1362 if (IS_FLOAT(optype)) {
1363 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1367 toBoolean(IC_LEFT(ic));
1369 tlbl = newiTempLabel(NULL);
1370 emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1371 emitcode("","%05d$:",tlbl->key+100);
1372 outBitC(IC_RESULT(ic));
1375 /* release the aops */
1376 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1377 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1381 /*-----------------------------------------------------------------*/
1382 /* genCpl - generate code for complement */
1383 /*-----------------------------------------------------------------*/
1384 static void genCpl (iCode *ic)
1389 D(emitcode(";", "genCpl "););
1392 /* assign asmOps to operand & result */
1393 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1394 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1396 /* if both are in bit space then
1398 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1399 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1401 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1402 emitcode("cpl","c");
1403 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1407 size = AOP_SIZE(IC_RESULT(ic));
1409 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE);
1411 emitcode("cpl","a");
1412 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1417 /* release the aops */
1418 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1419 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1422 /*-----------------------------------------------------------------*/
1423 /* genUminusFloat - unary minus for floating points */
1424 /*-----------------------------------------------------------------*/
1425 static void genUminusFloat(operand *op,operand *result)
1427 int size ,offset =0 ;
1429 /* for this we just need to flip the
1430 first it then copy the rest in place */
1431 D(emitcode(";", "genUminusFloat"););
1433 size = AOP_SIZE(op) - 1;
1434 l = aopGet(AOP(op),3,FALSE,FALSE,TRUE);
1437 emitcode("cpl","acc.7");
1438 aopPut(AOP(result),"a",3);
1442 aopGet(AOP(op),offset,FALSE,FALSE,FALSE),
1448 /*-----------------------------------------------------------------*/
1449 /* genUminus - unary minus code generation */
1450 /*-----------------------------------------------------------------*/
1451 static void genUminus (iCode *ic)
1454 link *optype, *rtype;
1456 D(emitcode(";", "genUminus "););
1460 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1461 aopOp(IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1463 /* if both in bit space then special
1465 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1466 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1468 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1469 emitcode("cpl","c");
1470 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1474 optype = operandType(IC_LEFT(ic));
1475 rtype = operandType(IC_RESULT(ic));
1477 /* if float then do float stuff */
1478 if (IS_FLOAT(optype)) {
1479 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1483 /* otherwise subtract from zero */
1484 size = AOP_SIZE(IC_LEFT(ic));
1488 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE);
1489 if (!strcmp(l,"a")) {
1492 emitcode("cpl","a");
1493 emitcode("addc", "a,#0");
1497 emitcode("clr","a");
1498 emitcode("subb","a,%s",l);
1500 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1503 /* if any remaining bytes in the result */
1504 /* we just need to propagate the sign */
1505 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1506 emitcode("rlc","a");
1507 emitcode("subb","a,acc");
1509 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1513 /* release the aops */
1514 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1515 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1518 /*-----------------------------------------------------------------*/
1519 /* saveRegisters - will look for a call and save the registers */
1520 /*-----------------------------------------------------------------*/
1521 static void saveRegisters(iCode *lic)
1529 for (ic = lic ; ic ; ic = ic->next)
1530 if (ic->op == CALL || ic->op == PCALL)
1534 fprintf(stderr,"found parameter push with no function call\n");
1538 /* if the registers have been saved already then
1540 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1543 /* find the registers in use at this time
1544 and push them away to safety */
1545 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1549 if (options.useXstack) {
1550 if (bitVectBitValue(rsave,R0_IDX))
1551 emitcode("mov","b,r0");
1552 emitcode("mov","r0,%s",spname);
1553 for (i = 0 ; i < ds390_nRegs ; i++) {
1554 if (bitVectBitValue(rsave,i)) {
1556 emitcode("mov","a,b");
1558 emitcode("mov","a,%s",ds390_regWithIdx(i)->name);
1559 emitcode("movx","@r0,a");
1560 emitcode("inc","r0");
1563 emitcode("mov","%s,r0",spname);
1564 if (bitVectBitValue(rsave,R0_IDX))
1565 emitcode("mov","r0,b");
1567 for (i = 0 ; i < ds390_nRegs ; i++) {
1568 if (bitVectBitValue(rsave,i))
1569 emitcode("push","%s",ds390_regWithIdx(i)->dname);
1572 detype = getSpec(operandType(IC_LEFT(ic)));
1574 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1575 IS_ISR(currFunc->etype) &&
1578 saverbank(SPEC_BANK(detype),ic,TRUE);
1581 /*-----------------------------------------------------------------*/
1582 /* unsaveRegisters - pop the pushed registers */
1583 /*-----------------------------------------------------------------*/
1584 static void unsaveRegisters (iCode *ic)
1588 /* find the registers in use at this time
1589 and push them away to safety */
1590 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1593 if (options.useXstack) {
1594 emitcode("mov","r0,%s",spname);
1595 for (i = ds390_nRegs ; i >= 0 ; i--) {
1596 if (bitVectBitValue(rsave,i)) {
1597 emitcode("dec","r0");
1598 emitcode("movx","a,@r0");
1600 emitcode("mov","b,a");
1602 emitcode("mov","%s,a",ds390_regWithIdx(i)->name);
1606 emitcode("mov","%s,r0",spname);
1607 if (bitVectBitValue(rsave,R0_IDX))
1608 emitcode("mov","r0,b");
1610 for (i = ds390_nRegs ; i >= 0 ; i--) {
1611 if (bitVectBitValue(rsave,i))
1612 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
1618 /*-----------------------------------------------------------------*/
1620 /*-----------------------------------------------------------------*/
1621 static void pushSide(operand * oper, int size)
1625 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE,FALSE);
1626 if (AOP_TYPE(oper) != AOP_REG &&
1627 AOP_TYPE(oper) != AOP_DIR &&
1629 emitcode("mov","a,%s",l);
1630 emitcode("push","acc");
1632 emitcode("push","%s",l);
1636 /*-----------------------------------------------------------------*/
1637 /* assignResultValue - */
1638 /*-----------------------------------------------------------------*/
1639 static void assignResultValue(operand * oper)
1642 int size = AOP_SIZE(oper);
1644 aopPut(AOP(oper),fReturn[offset],offset);
1650 /*-----------------------------------------------------------------*/
1651 /* genXpush - pushes onto the external stack */
1652 /*-----------------------------------------------------------------*/
1653 static void genXpush (iCode *ic)
1655 asmop *aop = newAsmop(0);
1657 int size,offset = 0;
1659 D(emitcode(";", "genXpush "););
1661 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1662 r = getFreePtr(ic,&aop,FALSE);
1665 emitcode("mov","%s,_spx",r->name);
1667 size = AOP_SIZE(IC_LEFT(ic));
1670 char *l = aopGet(AOP(IC_LEFT(ic)),
1671 offset++,FALSE,FALSE,TRUE);
1673 emitcode("movx","@%s,a",r->name);
1674 emitcode("inc","%s",r->name);
1679 emitcode("mov","_spx,%s",r->name);
1681 freeAsmop(NULL,aop,ic,TRUE);
1682 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1685 /*-----------------------------------------------------------------*/
1686 /* genIpush - genrate code for pushing this gets a little complex */
1687 /*-----------------------------------------------------------------*/
1688 static void genIpush (iCode *ic)
1690 int size, offset = 0 ;
1693 D(emitcode(";", "genIpush "););
1696 /* if this is not a parm push : ie. it is spill push
1697 and spill push is always done on the local stack */
1698 if (!ic->parmPush) {
1700 /* and the item is spilt then do nothing */
1701 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1704 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1705 size = AOP_SIZE(IC_LEFT(ic));
1706 /* push it on the stack */
1708 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE,TRUE);
1713 emitcode("push","%s",l);
1718 /* this is a paramter push: in this case we call
1719 the routine to find the call and save those
1720 registers that need to be saved */
1723 /* if use external stack then call the external
1724 stack pushing routine */
1725 if (options.useXstack) {
1730 /* then do the push */
1731 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1734 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1735 size = AOP_SIZE(IC_LEFT(ic));
1738 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE,FALSE);
1739 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1740 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1742 emitcode("mov","a,%s",l);
1743 emitcode("push","acc");
1745 emitcode("push","%s",l);
1748 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1751 /*-----------------------------------------------------------------*/
1752 /* genIpop - recover the registers: can happen only for spilling */
1753 /*-----------------------------------------------------------------*/
1754 static void genIpop (iCode *ic)
1758 D(emitcode(";", "genIpop "););
1761 /* if the temp was not pushed then */
1762 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1765 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1766 size = AOP_SIZE(IC_LEFT(ic));
1769 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1772 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1775 /*-----------------------------------------------------------------*/
1776 /* unsaverbank - restores the resgister bank from stack */
1777 /*-----------------------------------------------------------------*/
1778 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1785 if (options.useXstack) {
1787 r = getFreePtr(ic,&aop,FALSE);
1790 emitcode("mov","%s,_spx",r->name);
1791 emitcode("movx","a,@%s",r->name);
1792 emitcode("mov","psw,a");
1793 emitcode("dec","%s",r->name);
1796 emitcode ("pop","psw");
1799 for (i = (ds390_nRegs - 1) ; i >= 0 ;i--) {
1800 if (options.useXstack) {
1801 emitcode("movx","a,@%s",r->name);
1802 emitcode("mov","(%s+%d),a",
1803 regs390[i].base,8*bank+regs390[i].offset);
1804 emitcode("dec","%s",r->name);
1807 emitcode("pop","(%s+%d)",
1808 regs390[i].base,8*bank+regs390[i].offset);
1811 if (options.useXstack) {
1813 emitcode("mov","_spx,%s",r->name);
1814 freeAsmop(NULL,aop,ic,TRUE);
1819 /*-----------------------------------------------------------------*/
1820 /* saverbank - saves an entire register bank on the stack */
1821 /*-----------------------------------------------------------------*/
1822 static void saverbank (int bank, iCode *ic, bool pushPsw)
1828 if (options.useXstack) {
1831 r = getFreePtr(ic,&aop,FALSE);
1832 emitcode("mov","%s,_spx",r->name);
1836 for (i = 0 ; i < ds390_nRegs ;i++) {
1837 if (options.useXstack) {
1838 emitcode("inc","%s",r->name);
1839 emitcode("mov","a,(%s+%d)",
1840 regs390[i].base,8*bank+regs390[i].offset);
1841 emitcode("movx","@%s,a",r->name);
1843 emitcode("push","(%s+%d)",
1844 regs390[i].base,8*bank+regs390[i].offset);
1848 if (options.useXstack) {
1849 emitcode("mov","a,psw");
1850 emitcode("movx","@%s,a",r->name);
1851 emitcode("inc","%s",r->name);
1852 emitcode("mov","_spx,%s",r->name);
1853 freeAsmop (NULL,aop,ic,TRUE);
1856 emitcode("push","psw");
1858 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1864 /*-----------------------------------------------------------------*/
1865 /* genCall - generates a call statement */
1866 /*-----------------------------------------------------------------*/
1867 static void genCall (iCode *ic)
1871 D(emitcode(";", "genCall "););
1873 /* if caller saves & we have not saved then */
1877 /* if we are calling a function that is not using
1878 the same register bank then we need to save the
1879 destination registers on the stack */
1880 detype = getSpec(operandType(IC_LEFT(ic)));
1882 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1883 IS_ISR(currFunc->etype) &&
1886 saverbank(SPEC_BANK(detype),ic,TRUE);
1888 /* if send set is not empty the assign */
1892 for (sic = setFirstItem(_G.sendSet) ; sic ;
1893 sic = setNextItem(_G.sendSet)) {
1894 int size, offset = 0;
1895 aopOp(IC_LEFT(sic),sic,FALSE, TRUE);
1896 size = AOP_SIZE(IC_LEFT(sic));
1898 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1899 FALSE, FALSE, FALSE);
1900 if (strcmp(l,fReturn[offset]))
1901 emitcode("mov","%s,%s",
1906 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1911 emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1912 OP_SYMBOL(IC_LEFT(ic))->rname :
1913 OP_SYMBOL(IC_LEFT(ic))->name));
1915 /* if we need assign a result value */
1916 if ((IS_ITEMP(IC_RESULT(ic)) &&
1917 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1918 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1919 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1921 if (!isOperandInFarSpace(IC_RESULT(ic)))
1924 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
1927 assignResultValue(IC_RESULT(ic));
1929 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1933 /* Result is in far space, and requires DPTR to access
1934 * it. Push the result onto the stack and restore from
1937 int size = getSize(operandType(IC_RESULT(ic)));
1938 int offset = size - 1;
1941 emitcode(";", "Kevin function call abuse #1");
1943 /* first push the right side on to the stack */
1944 /* NB: this relies on the fact that "a" is the last
1945 * register in fReturn. If it were not, the MOVA
1946 * would potentially clobber a returned byte in A.
1949 l = fReturn[offset--];
1951 emitcode ("push","acc");
1954 /* now assign DPTR to result */
1955 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
1956 size = AOP_SIZE(IC_RESULT(ic));
1957 aopOp(IC_RESULT(ic),ic,FALSE, FALSE); /* bug? */
1959 emitcode ("pop","acc");
1960 aopPut(AOP(IC_RESULT(ic)),"a",++offset);
1962 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1966 /* adjust the stack for parameters if
1968 if (IC_LEFT(ic)->parmBytes) {
1970 if (IC_LEFT(ic)->parmBytes > 3) {
1971 emitcode("mov","a,%s",spname);
1972 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1973 emitcode("mov","%s,a",spname);
1975 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1976 emitcode("dec","%s",spname);
1980 /* if register bank was saved then pop them */
1982 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1984 /* if we hade saved some registers then unsave them */
1985 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1986 unsaveRegisters (ic);
1991 /*-----------------------------------------------------------------*/
1992 /* genPcall - generates a call by pointer statement */
1993 /*-----------------------------------------------------------------*/
1994 static void genPcall (iCode *ic)
1997 symbol *rlbl = newiTempLabel(NULL);
1999 D(emitcode(";", "genPcall "););
2002 /* if caller saves & we have not saved then */
2006 /* if we are calling a function that is not using
2007 the same register bank then we need to save the
2008 destination registers on the stack */
2009 detype = getSpec(operandType(IC_LEFT(ic)));
2011 IS_ISR(currFunc->etype) &&
2012 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
2013 saverbank(SPEC_BANK(detype),ic,TRUE);
2016 /* push the return address on to the stack */
2017 emitcode("mov","a,#%05d$",(rlbl->key+100));
2018 emitcode("push","acc");
2019 emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
2020 emitcode("push","acc");
2022 if (options.model == MODEL_FLAT24)
2024 emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
2025 emitcode("push","acc");
2028 /* now push the calling address */
2029 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
2031 pushSide(IC_LEFT(ic), FPTRSIZE);
2033 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2035 /* if send set is not empty the assign */
2039 for (sic = setFirstItem(_G.sendSet) ; sic ;
2040 sic = setNextItem(_G.sendSet)) {
2041 int size, offset = 0;
2042 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
2043 size = AOP_SIZE(IC_LEFT(sic));
2045 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2047 if (strcmp(l,fReturn[offset]))
2048 emitcode("mov","%s,%s",
2053 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2059 emitcode("","%05d$:",(rlbl->key+100));
2062 /* if we need assign a result value */
2063 if ((IS_ITEMP(IC_RESULT(ic)) &&
2064 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2065 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2066 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2069 aopOp(IC_RESULT(ic),ic,FALSE, TRUE);
2072 assignResultValue(IC_RESULT(ic));
2074 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2077 /* adjust the stack for parameters if
2079 if (IC_LEFT(ic)->parmBytes) {
2081 if (IC_LEFT(ic)->parmBytes > 3) {
2082 emitcode("mov","a,%s",spname);
2083 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2084 emitcode("mov","%s,a",spname);
2086 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2087 emitcode("dec","%s",spname);
2091 /* if register bank was saved then unsave them */
2093 (SPEC_BANK(currFunc->etype) !=
2095 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2097 /* if we hade saved some registers then
2100 unsaveRegisters (ic);
2104 /*-----------------------------------------------------------------*/
2105 /* resultRemat - result is rematerializable */
2106 /*-----------------------------------------------------------------*/
2107 static int resultRemat (iCode *ic)
2109 if (SKIP_IC(ic) || ic->op == IFX)
2112 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2113 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2114 if (sym->remat && !POINTER_SET(ic))
2122 #define STRCASECMP stricmp
2124 #define STRCASECMP strcasecmp
2127 /*-----------------------------------------------------------------*/
2128 /* inExcludeList - return 1 if the string is in exclude Reg list */
2129 /*-----------------------------------------------------------------*/
2130 static bool inExcludeList(char *s)
2134 if (options.excludeRegs[i] &&
2135 STRCASECMP(options.excludeRegs[i],"none") == 0)
2138 for ( i = 0 ; options.excludeRegs[i]; i++) {
2139 if (options.excludeRegs[i] &&
2140 STRCASECMP(s,options.excludeRegs[i]) == 0)
2146 /*-----------------------------------------------------------------*/
2147 /* genFunction - generated code for function entry */
2148 /*-----------------------------------------------------------------*/
2149 static void genFunction (iCode *ic)
2154 D(emitcode(";", "genFunction "););
2157 /* create the function header */
2158 emitcode(";","-----------------------------------------");
2159 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2160 emitcode(";","-----------------------------------------");
2162 emitcode("","%s:",sym->rname);
2163 fetype = getSpec(operandType(IC_LEFT(ic)));
2165 /* if critical function then turn interrupts off */
2166 if (SPEC_CRTCL(fetype))
2167 emitcode("clr","ea");
2169 /* here we need to generate the equates for the
2170 register bank if required */
2171 if (SPEC_BANK(fetype) != rbank) {
2174 rbank = SPEC_BANK(fetype);
2175 for ( i = 0 ; i < ds390_nRegs ; i++ ) {
2176 if (strcmp(regs390[i].base,"0") == 0)
2177 emitcode("","%s = 0x%02x",
2179 8*rbank+regs390[i].offset);
2181 emitcode ("","%s = %s + 0x%02x",
2184 8*rbank+regs390[i].offset);
2188 /* if this is an interrupt service routine then
2189 save acc, b, dpl, dph */
2190 if (IS_ISR(sym->etype)) {
2192 if (!inExcludeList("acc"))
2193 emitcode ("push","acc");
2194 if (!inExcludeList("b"))
2195 emitcode ("push","b");
2196 if (!inExcludeList("dpl"))
2197 emitcode ("push","dpl");
2198 if (!inExcludeList("dph"))
2199 emitcode ("push","dph");
2200 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2202 emitcode ("push", "dpx");
2203 /* Make sure we're using standard DPTR */
2204 emitcode ("push", "dps");
2205 emitcode ("mov", "dps, #0x00");
2206 if (options.stack10bit)
2208 /* This ISR could conceivably use DPTR2. Better save it. */
2209 emitcode ("push", "dpl1");
2210 emitcode ("push", "dph1");
2211 emitcode ("push", "dpx1");
2212 emitcode ("push", "ap");
2215 /* if this isr has no bank i.e. is going to
2216 run with bank 0 , then we need to save more
2218 if (!SPEC_BANK(sym->etype)) {
2220 /* if this function does not call any other
2221 function then we can be economical and
2222 save only those registers that are used */
2223 if (! sym->hasFcall) {
2226 /* if any registers used */
2227 if (sym->regsUsed) {
2228 /* save the registers used */
2229 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2230 if (bitVectBitValue(sym->regsUsed,i) ||
2231 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2232 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2237 /* this function has a function call cannot
2238 determines register usage so we will have the
2240 saverbank(0,ic,FALSE);
2244 /* if callee-save to be used for this function
2245 then save the registers being used in this function */
2246 if (sym->calleeSave) {
2249 /* if any registers used */
2250 if (sym->regsUsed) {
2251 /* save the registers used */
2252 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2253 if (bitVectBitValue(sym->regsUsed,i) ||
2254 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2255 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2263 /* set the register bank to the desired value */
2264 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2265 emitcode("push","psw");
2266 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2269 if (IS_RENT(sym->etype) || options.stackAuto) {
2271 if (options.useXstack) {
2272 emitcode("mov","r0,%s",spname);
2273 emitcode("mov","a,_bp");
2274 emitcode("movx","@r0,a");
2275 emitcode("inc","%s",spname);
2279 /* set up the stack */
2280 emitcode ("push","_bp"); /* save the callers stack */
2282 emitcode ("mov","_bp,%s",spname);
2285 /* adjust the stack for the function */
2290 werror(W_STACK_OVERFLOW,sym->name);
2292 if (i > 3 && sym->recvSize < 4) {
2294 emitcode ("mov","a,sp");
2295 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2296 emitcode ("mov","sp,a");
2301 emitcode("inc","sp");
2306 emitcode ("mov","a,_spx");
2307 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2308 emitcode ("mov","_spx,a");
2313 /*-----------------------------------------------------------------*/
2314 /* genEndFunction - generates epilogue for functions */
2315 /*-----------------------------------------------------------------*/
2316 static void genEndFunction (iCode *ic)
2318 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2320 D(emitcode(";", "genEndFunction "););
2322 if (IS_RENT(sym->etype) || options.stackAuto)
2324 emitcode ("mov","%s,_bp",spname);
2327 /* if use external stack but some variables were
2328 added to the local stack then decrement the
2330 if (options.useXstack && sym->stack) {
2331 emitcode("mov","a,sp");
2332 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2333 emitcode("mov","sp,a");
2337 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2338 if (options.useXstack) {
2339 emitcode("mov","r0,%s",spname);
2340 emitcode("movx","a,@r0");
2341 emitcode("mov","_bp,a");
2342 emitcode("dec","%s",spname);
2346 emitcode ("pop","_bp");
2350 /* restore the register bank */
2351 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2352 emitcode ("pop","psw");
2354 if (IS_ISR(sym->etype)) {
2356 /* now we need to restore the registers */
2357 /* if this isr has no bank i.e. is going to
2358 run with bank 0 , then we need to save more
2360 if (!SPEC_BANK(sym->etype)) {
2362 /* if this function does not call any other
2363 function then we can be economical and
2364 save only those registers that are used */
2365 if (! sym->hasFcall) {
2368 /* if any registers used */
2369 if (sym->regsUsed) {
2370 /* save the registers used */
2371 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2372 if (bitVectBitValue(sym->regsUsed,i) ||
2373 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2374 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2379 /* this function has a function call cannot
2380 determines register usage so we will have the
2382 unsaverbank(0,ic,FALSE);
2386 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2388 if (options.stack10bit)
2390 emitcode ("pop", "ap");
2391 emitcode ("pop", "dpx1");
2392 emitcode ("pop", "dph1");
2393 emitcode ("pop", "dpl1");
2395 emitcode ("pop", "dps");
2396 emitcode ("pop", "dpx");
2398 if (!inExcludeList("dph"))
2399 emitcode ("pop","dph");
2400 if (!inExcludeList("dpl"))
2401 emitcode ("pop","dpl");
2402 if (!inExcludeList("b"))
2403 emitcode ("pop","b");
2404 if (!inExcludeList("acc"))
2405 emitcode ("pop","acc");
2407 if (SPEC_CRTCL(sym->etype))
2408 emitcode("setb","ea");
2410 /* if debug then send end of function */
2411 /* if (options.debug && currFunc) { */
2414 emitcode("","C$%s$%d$%d$%d ==.",
2415 ic->filename,currFunc->lastLine,
2416 ic->level,ic->block);
2417 if (IS_STATIC(currFunc->etype))
2418 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2420 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2424 emitcode ("reti","");
2427 if (SPEC_CRTCL(sym->etype))
2428 emitcode("setb","ea");
2430 if (sym->calleeSave) {
2433 /* if any registers used */
2434 if (sym->regsUsed) {
2435 /* save the registers used */
2436 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2437 if (bitVectBitValue(sym->regsUsed,i) ||
2438 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2439 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2445 /* if debug then send end of function */
2448 emitcode("","C$%s$%d$%d$%d ==.",
2449 ic->filename,currFunc->lastLine,
2450 ic->level,ic->block);
2451 if (IS_STATIC(currFunc->etype))
2452 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2454 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2458 emitcode ("ret","");
2463 /*-----------------------------------------------------------------*/
2464 /* genRet - generate code for return statement */
2465 /*-----------------------------------------------------------------*/
2466 static void genRet (iCode *ic)
2468 int size,offset = 0 , pushed = 0;
2470 D(emitcode(";", "genRet "););
2472 /* if we have no return value then
2473 just generate the "ret" */
2477 /* we have something to return then
2478 move the return value into place */
2479 aopOp(IC_LEFT(ic),ic,FALSE, TRUE);
2480 size = AOP_SIZE(IC_LEFT(ic));
2484 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2485 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2487 emitcode("push","%s",l);
2490 l = aopGet(AOP(IC_LEFT(ic)),offset,
2492 if (strcmp(fReturn[offset],l))
2493 emitcode("mov","%s,%s",fReturn[offset++],l);
2500 if (strcmp(fReturn[pushed],"a"))
2501 emitcode("pop",fReturn[pushed]);
2503 emitcode("pop","acc");
2506 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2509 /* generate a jump to the return label
2510 if the next is not the return statement */
2511 if (!(ic->next && ic->next->op == LABEL &&
2512 IC_LABEL(ic->next) == returnLabel))
2514 emitcode("ljmp","%05d$",(returnLabel->key+100));
2518 /*-----------------------------------------------------------------*/
2519 /* genLabel - generates a label */
2520 /*-----------------------------------------------------------------*/
2521 static void genLabel (iCode *ic)
2523 /* special case never generate */
2524 if (IC_LABEL(ic) == entryLabel)
2527 D(emitcode(";", "genLabel "););
2529 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2532 /*-----------------------------------------------------------------*/
2533 /* genGoto - generates a ljmp */
2534 /*-----------------------------------------------------------------*/
2535 static void genGoto (iCode *ic)
2537 D(emitcode(";", "genGoto "););
2538 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2541 /*-----------------------------------------------------------------*/
2542 /* findLabelBackwards: walks back through the iCode chain looking */
2543 /* for the given label. Returns number of iCode instructions */
2544 /* between that label and given ic. */
2545 /* Returns zero if label not found. */
2546 /*-----------------------------------------------------------------*/
2547 static int findLabelBackwards(iCode *ic, int key)
2556 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2558 /* printf("findLabelBackwards = %d\n", count); */
2566 /*-----------------------------------------------------------------*/
2567 /* genPlusIncr :- does addition with increment if possible */
2568 /*-----------------------------------------------------------------*/
2569 static bool genPlusIncr (iCode *ic)
2571 unsigned int icount ;
2572 unsigned int size = getDataSize(IC_RESULT(ic));
2574 /* will try to generate an increment */
2575 /* if the right side is not a literal
2577 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2580 /* if the literal value of the right hand side
2581 is greater than 4 then it is not worth it */
2582 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2585 /* if increment 16 bits in register */
2587 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2588 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2589 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2596 /* If the next instruction is a goto and the goto target
2597 * is < 10 instructions previous to this, we can generate
2598 * jumps straight to that target.
2600 if (ic->next && ic->next->op == GOTO
2601 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2602 && labelRange <= 10 )
2604 emitcode(";", "tail increment optimized");
2605 tlbl = IC_LABEL(ic->next);
2610 tlbl = newiTempLabel(NULL);
2613 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
2614 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2615 IS_AOP_PREG(IC_RESULT(ic)))
2616 emitcode("cjne","%s,#0x00,%05d$"
2617 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2620 emitcode("clr","a");
2621 emitcode("cjne","a,%s,%05d$"
2622 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2626 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
2629 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2630 IS_AOP_PREG(IC_RESULT(ic)))
2631 emitcode("cjne","%s,#0x00,%05d$"
2632 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2635 emitcode("cjne","a,%s,%05d$"
2636 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2639 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
2643 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2644 IS_AOP_PREG(IC_RESULT(ic)))
2645 emitcode("cjne","%s,#0x00,%05d$"
2646 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2649 emitcode("cjne","a,%s,%05d$"
2650 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2653 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
2658 emitcode("","%05d$:",tlbl->key+100);
2663 /* if the sizes are greater than 1 then we cannot */
2664 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2665 AOP_SIZE(IC_LEFT(ic)) > 1 )
2668 /* we can if the aops of the left & result match or
2669 if they are in registers and the registers are the
2672 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2673 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2674 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2677 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE,TRUE));
2678 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2679 aopPut(AOP(IC_RESULT(ic)),"a",0);
2683 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE,FALSE));
2692 /*-----------------------------------------------------------------*/
2693 /* outBitAcc - output a bit in acc */
2694 /*-----------------------------------------------------------------*/
2695 static void outBitAcc(operand *result)
2697 symbol *tlbl = newiTempLabel(NULL);
2698 /* if the result is a bit */
2699 if (AOP_TYPE(result) == AOP_CRY){
2700 aopPut(AOP(result),"a",0);
2703 emitcode("jz","%05d$",tlbl->key+100);
2704 emitcode("mov","a,%s",one);
2705 emitcode("","%05d$:",tlbl->key+100);
2710 /*-----------------------------------------------------------------*/
2711 /* genPlusBits - generates code for addition of two bits */
2712 /*-----------------------------------------------------------------*/
2713 static void genPlusBits (iCode *ic)
2715 D(emitcode(";", "genPlusBits "););
2716 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2717 symbol *lbl = newiTempLabel(NULL);
2718 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2719 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2720 emitcode("cpl","c");
2721 emitcode("","%05d$:",(lbl->key+100));
2722 outBitC(IC_RESULT(ic));
2725 emitcode("clr","a");
2726 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2727 emitcode("rlc","a");
2728 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2729 emitcode("addc","a,#0x00");
2730 outAcc(IC_RESULT(ic));
2734 static void adjustArithmeticResult(iCode *ic)
2736 if (opIsGptr(IC_RESULT(ic)) &&
2737 opIsGptr(IC_LEFT(ic)) &&
2738 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2740 aopPut(AOP(IC_RESULT(ic)),
2741 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE,FALSE),
2745 if (opIsGptr(IC_RESULT(ic)) &&
2746 opIsGptr(IC_RIGHT(ic)) &&
2747 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2749 aopPut(AOP(IC_RESULT(ic)),
2750 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE,FALSE),
2754 if (opIsGptr(IC_RESULT(ic)) &&
2755 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2756 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2757 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2758 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2760 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2761 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2765 #define AOP_OP_3(ic) \
2766 aopOp (IC_LEFT(ic),ic,FALSE, FALSE); \
2767 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE); \
2768 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR); \
2769 if (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2 && \
2770 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
2772 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
2774 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
2777 #define AOP_SET_LOCALS(ic) \
2778 left = IC_LEFT(ic); \
2779 right = IC_RIGHT(ic); \
2780 result = IC_RESULT(ic);
2782 /*-----------------------------------------------------------------*/
2783 /* genPlus - generates code for addition */
2784 /*-----------------------------------------------------------------*/
2785 static void genPlus (iCode *ic)
2787 int size, offset = 0;
2788 bool pushResult = FALSE;
2790 D(emitcode(";", "genPlus "););
2792 /* special cases :- */
2794 aopOp (IC_LEFT(ic),ic,FALSE, TRUE);
2795 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
2796 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2) &&
2797 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR))
2803 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR);
2805 /* if literal, literal on the right or
2806 if left requires ACC or right is already
2808 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2809 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2810 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2811 operand *t = IC_RIGHT(ic);
2812 IC_RIGHT(ic) = IC_LEFT(ic);
2816 /* if both left & right are in bit
2818 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2819 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2824 /* if left in bit space & right literal */
2825 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2826 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2827 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2828 /* if result in bit space */
2829 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2830 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
2831 emitcode("cpl","c");
2832 outBitC(IC_RESULT(ic));
2834 size = getDataSize(IC_RESULT(ic));
2836 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
2837 emitcode("addc","a,#00");
2838 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2844 /* if I can do an increment instead
2845 of add then GOOD for ME */
2846 if (genPlusIncr (ic) == TRUE)
2850 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
2853 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2854 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
2856 emitcode("add","a,%s",
2857 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
2859 emitcode("addc","a,%s",
2860 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
2862 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
2864 emitcode("add","a,%s",
2865 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
2867 emitcode("addc","a,%s",
2868 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
2872 aopPut(AOP(IC_RESULT(ic)),"a",offset);
2876 emitcode("push", "acc");
2883 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
2885 size = getDataSize(IC_LEFT(ic));
2889 emitcode("pop", "acc");
2890 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
2894 adjustArithmeticResult(ic);
2897 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2898 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2899 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2902 /*-----------------------------------------------------------------*/
2903 /* genMinusDec :- does subtraction with deccrement if possible */
2904 /*-----------------------------------------------------------------*/
2905 static bool genMinusDec (iCode *ic)
2907 unsigned int icount ;
2908 unsigned int size = getDataSize(IC_RESULT(ic));
2910 /* will try to generate an increment */
2911 /* if the right side is not a literal
2913 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2916 /* if the literal value of the right hand side
2917 is greater than 4 then it is not worth it */
2918 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2921 /* if decrement 16 bits in register */
2922 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2923 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2924 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2931 /* If the next instruction is a goto and the goto target
2932 * is <= 10 instructions previous to this, we can generate
2933 * jumps straight to that target.
2935 if (ic->next && ic->next->op == GOTO
2936 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2937 && labelRange <= 10 )
2939 emitcode(";", "tail decrement optimized");
2940 tlbl = IC_LABEL(ic->next);
2945 tlbl = newiTempLabel(NULL);
2949 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
2950 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2951 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
2952 IS_AOP_PREG(IC_RESULT(ic)))
2953 emitcode("cjne","%s,#0xff,%05d$"
2954 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2957 emitcode("mov","a,#0xff");
2958 emitcode("cjne","a,%s,%05d$"
2959 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2962 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
2965 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2966 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
2967 IS_AOP_PREG(IC_RESULT(ic)))
2968 emitcode("cjne","%s,#0xff,%05d$"
2969 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2972 emitcode("cjne","a,%s,%05d$"
2973 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2976 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
2980 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2981 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
2982 IS_AOP_PREG(IC_RESULT(ic)))
2983 emitcode("cjne","%s,#0xff,%05d$"
2984 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2987 emitcode("cjne","a,%s,%05d$"
2988 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2991 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
2995 emitcode("","%05d$:",tlbl->key+100);
3000 /* if the sizes are greater than 1 then we cannot */
3001 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
3002 AOP_SIZE(IC_LEFT(ic)) > 1 )
3005 /* we can if the aops of the left & result match or
3006 if they are in registers and the registers are the
3009 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3010 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3011 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3014 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3022 /*-----------------------------------------------------------------*/
3023 /* addSign - complete with sign */
3024 /*-----------------------------------------------------------------*/
3025 static void addSign(operand *result, int offset, int sign)
3027 int size = (getDataSize(result) - offset);
3030 emitcode("rlc","a");
3031 emitcode("subb","a,acc");
3033 aopPut(AOP(result),"a",offset++);
3036 aopPut(AOP(result),zero,offset++);
3040 /*-----------------------------------------------------------------*/
3041 /* genMinusBits - generates code for subtraction of two bits */
3042 /*-----------------------------------------------------------------*/
3043 static void genMinusBits (iCode *ic)
3045 symbol *lbl = newiTempLabel(NULL);
3047 D(emitcode(";", "genMinusBits "););
3049 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3050 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3051 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3052 emitcode("cpl","c");
3053 emitcode("","%05d$:",(lbl->key+100));
3054 outBitC(IC_RESULT(ic));
3057 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3058 emitcode("subb","a,acc");
3059 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3060 emitcode("inc","a");
3061 emitcode("","%05d$:",(lbl->key+100));
3062 aopPut(AOP(IC_RESULT(ic)),"a",0);
3063 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3067 /*-----------------------------------------------------------------*/
3068 /* genMinus - generates code for subtraction */
3069 /*-----------------------------------------------------------------*/
3070 static void genMinus (iCode *ic)
3072 int size, offset = 0;
3073 unsigned long lit = 0L;
3074 bool pushResult = FALSE;
3076 D(emitcode(";", "genMinus "););
3078 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
3079 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE);
3080 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) &&
3081 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2))
3087 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
3089 /* special cases :- */
3090 /* if both left & right are in bit space */
3091 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3092 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3097 /* if I can do an decrement instead
3098 of subtract then GOOD for ME */
3099 if (genMinusDec (ic) == TRUE)
3104 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3106 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
3110 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3115 /* if literal, add a,#-lit, else normal subb */
3117 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
3118 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3119 emitcode("subb","a,%s",
3120 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3122 /* first add without previous c */
3124 emitcode("add","a,#0x%02x",
3125 (unsigned int)(lit & 0x0FFL));
3127 emitcode("addc","a,#0x%02x",
3128 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3133 emitcode("push", "acc");
3137 aopPut(AOP(IC_RESULT(ic)),"a",offset);
3144 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3146 size = getDataSize(IC_LEFT(ic));
3150 emitcode("pop", "acc");
3151 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3155 adjustArithmeticResult(ic);
3158 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3159 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3160 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3164 /*-----------------------------------------------------------------*/
3165 /* genMultbits :- multiplication of bits */
3166 /*-----------------------------------------------------------------*/
3167 static void genMultbits (operand *left,
3171 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3172 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3177 /*-----------------------------------------------------------------*/
3178 /* genMultOneByte : 8 bit multiplication & division */
3179 /*-----------------------------------------------------------------*/
3180 static void genMultOneByte (operand *left,
3184 link *opetype = operandType(result);
3189 /* (if two literals, the value is computed before) */
3190 /* if one literal, literal on the right */
3191 if (AOP_TYPE(left) == AOP_LIT){
3197 size = AOP_SIZE(result);
3198 /* signed or unsigned */
3199 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3200 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3202 emitcode("mul","ab");
3203 /* if result size = 1, mul signed = mul unsigned */
3204 aopPut(AOP(result),"a",0);
3206 if (SPEC_USIGN(opetype)){
3207 aopPut(AOP(result),"b",1);
3209 /* for filling the MSBs */
3210 emitcode("clr","a");
3213 emitcode("mov","a,b");
3215 /* adjust the MSB if left or right neg */
3217 /* if one literal */
3218 if (AOP_TYPE(right) == AOP_LIT){
3219 /* AND literal negative */
3220 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3221 /* adjust MSB (c==0 after mul) */
3222 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3226 lbl = newiTempLabel(NULL);
3227 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3228 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3229 emitcode("","%05d$:",(lbl->key+100));
3230 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3231 lbl = newiTempLabel(NULL);
3232 emitcode("jc","%05d$",(lbl->key+100));
3233 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3234 emitcode("","%05d$:",(lbl->key+100));
3237 lbl = newiTempLabel(NULL);
3238 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3239 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3240 emitcode("","%05d$:",(lbl->key+100));
3241 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3242 lbl = newiTempLabel(NULL);
3243 emitcode("jc","%05d$",(lbl->key+100));
3244 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3245 emitcode("","%05d$:",(lbl->key+100));
3247 aopPut(AOP(result),"a",1);
3250 emitcode("rlc","a");
3251 emitcode("subb","a,acc");
3258 aopPut(AOP(result),"a",offset++);
3262 /*-----------------------------------------------------------------*/
3263 /* genMult - generates code for multiplication */
3264 /*-----------------------------------------------------------------*/
3265 static void genMult (iCode *ic)
3267 operand *left = IC_LEFT(ic);
3268 operand *right = IC_RIGHT(ic);
3269 operand *result= IC_RESULT(ic);
3271 D(emitcode(";", "genMult "););
3273 /* assign the amsops */
3276 aopOp (left,ic,FALSE, FALSE);
3277 aopOp (right,ic,FALSE, TRUE);
3278 aopOp (result,ic,TRUE, FALSE);
3281 /* special cases first */
3283 if (AOP_TYPE(left) == AOP_CRY &&
3284 AOP_TYPE(right)== AOP_CRY) {
3285 genMultbits(left,right,result);
3289 /* if both are of size == 1 */
3290 if (AOP_SIZE(left) == 1 &&
3291 AOP_SIZE(right) == 1 ) {
3292 genMultOneByte(left,right,result);
3296 /* should have been converted to function call */
3300 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3301 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3302 freeAsmop(result,NULL,ic,TRUE);
3305 /*-----------------------------------------------------------------*/
3306 /* genDivbits :- division of bits */
3307 /*-----------------------------------------------------------------*/
3308 static void genDivbits (operand *left,
3315 /* the result must be bit */
3316 LOAD_AB_FOR_DIV(left, right, l);
3317 emitcode("div","ab");
3318 emitcode("rrc","a");
3319 aopPut(AOP(result),"c",0);
3322 /*-----------------------------------------------------------------*/
3323 /* genDivOneByte : 8 bit division */
3324 /*-----------------------------------------------------------------*/
3325 static void genDivOneByte (operand *left,
3329 link *opetype = operandType(result);
3334 size = AOP_SIZE(result) - 1;
3336 /* signed or unsigned */
3337 if (SPEC_USIGN(opetype)) {
3338 /* unsigned is easy */
3339 LOAD_AB_FOR_DIV(left, right, l);
3340 emitcode("div","ab");
3341 aopPut(AOP(result),"a",0);
3343 aopPut(AOP(result),zero,offset++);
3347 /* signed is a little bit more difficult */
3349 /* save the signs of the operands */
3350 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3352 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE,FALSE));
3353 emitcode("push","acc"); /* save it on the stack */
3355 /* now sign adjust for both left & right */
3356 l = aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3358 lbl = newiTempLabel(NULL);
3359 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3360 emitcode("cpl","a");
3361 emitcode("inc","a");
3362 emitcode("","%05d$:",(lbl->key+100));
3363 emitcode("mov","b,a");
3365 /* sign adjust left side */
3366 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3369 lbl = newiTempLabel(NULL);
3370 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3371 emitcode("cpl","a");
3372 emitcode("inc","a");
3373 emitcode("","%05d$:",(lbl->key+100));
3375 /* now the division */
3376 emitcode("nop", "; workaround for DS80C390 div bug.");
3377 emitcode("div","ab");
3378 /* we are interested in the lower order
3380 emitcode("mov","b,a");
3381 lbl = newiTempLabel(NULL);
3382 emitcode("pop","acc");
3383 /* if there was an over flow we don't
3384 adjust the sign of the result */
3385 emitcode("jb","ov,%05d$",(lbl->key+100));
3386 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3388 emitcode("clr","a");
3389 emitcode("subb","a,b");
3390 emitcode("mov","b,a");
3391 emitcode("","%05d$:",(lbl->key+100));
3393 /* now we are done */
3394 aopPut(AOP(result),"b",0);
3396 emitcode("mov","c,b.7");
3397 emitcode("subb","a,acc");
3400 aopPut(AOP(result),"a",offset++);
3404 /*-----------------------------------------------------------------*/
3405 /* genDiv - generates code for division */
3406 /*-----------------------------------------------------------------*/
3407 static void genDiv (iCode *ic)
3409 operand *left = IC_LEFT(ic);
3410 operand *right = IC_RIGHT(ic);
3411 operand *result= IC_RESULT(ic);
3413 D(emitcode(";", "genDiv "););
3415 /* assign the amsops */
3418 aopOp (left,ic,FALSE, FALSE);
3419 aopOp (right,ic,FALSE, TRUE);
3420 aopOp (result,ic,TRUE, FALSE);
3423 /* special cases first */
3425 if (AOP_TYPE(left) == AOP_CRY &&
3426 AOP_TYPE(right)== AOP_CRY) {
3427 genDivbits(left,right,result);
3431 /* if both are of size == 1 */
3432 if (AOP_SIZE(left) == 1 &&
3433 AOP_SIZE(right) == 1 ) {
3434 genDivOneByte(left,right,result);
3438 /* should have been converted to function call */
3441 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3442 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3443 freeAsmop(result,NULL,ic,TRUE);
3446 /*-----------------------------------------------------------------*/
3447 /* genModbits :- modulus of bits */
3448 /*-----------------------------------------------------------------*/
3449 static void genModbits (operand *left,
3456 /* the result must be bit */
3457 LOAD_AB_FOR_DIV(left, right, l);
3458 emitcode("div","ab");
3459 emitcode("mov","a,b");
3460 emitcode("rrc","a");
3461 aopPut(AOP(result),"c",0);
3464 /*-----------------------------------------------------------------*/
3465 /* genModOneByte : 8 bit modulus */
3466 /*-----------------------------------------------------------------*/
3467 static void genModOneByte (operand *left,
3471 link *opetype = operandType(result);
3475 /* signed or unsigned */
3476 if (SPEC_USIGN(opetype)) {
3477 /* unsigned is easy */
3478 LOAD_AB_FOR_DIV(left, right, l);
3479 emitcode("div","ab");
3480 aopPut(AOP(result),"b",0);
3484 /* signed is a little bit more difficult */
3486 /* save the signs of the operands */
3487 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3490 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3491 emitcode("push","acc"); /* save it on the stack */
3493 /* now sign adjust for both left & right */
3494 l = aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3497 lbl = newiTempLabel(NULL);
3498 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3499 emitcode("cpl","a");
3500 emitcode("inc","a");
3501 emitcode("","%05d$:",(lbl->key+100));
3502 emitcode("mov","b,a");
3504 /* sign adjust left side */
3505 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3508 lbl = newiTempLabel(NULL);
3509 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3510 emitcode("cpl","a");
3511 emitcode("inc","a");
3512 emitcode("","%05d$:",(lbl->key+100));
3514 /* now the multiplication */
3515 emitcode("nop", "; workaround for DS80C390 div bug.");
3516 emitcode("div","ab");
3517 /* we are interested in the lower order
3519 lbl = newiTempLabel(NULL);
3520 emitcode("pop","acc");
3521 /* if there was an over flow we don't
3522 adjust the sign of the result */
3523 emitcode("jb","ov,%05d$",(lbl->key+100));
3524 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3526 emitcode("clr","a");
3527 emitcode("subb","a,b");
3528 emitcode("mov","b,a");
3529 emitcode("","%05d$:",(lbl->key+100));
3531 /* now we are done */
3532 aopPut(AOP(result),"b",0);
3536 /*-----------------------------------------------------------------*/
3537 /* genMod - generates code for division */
3538 /*-----------------------------------------------------------------*/
3539 static void genMod (iCode *ic)
3541 operand *left = IC_LEFT(ic);
3542 operand *right = IC_RIGHT(ic);
3543 operand *result= IC_RESULT(ic);
3545 D(emitcode(";", "genMod "););
3547 /* assign the amsops */
3550 aopOp (left,ic,FALSE, FALSE);
3551 aopOp (right,ic,FALSE, TRUE);
3552 aopOp (result,ic,TRUE, FALSE);
3555 /* special cases first */
3557 if (AOP_TYPE(left) == AOP_CRY &&
3558 AOP_TYPE(right)== AOP_CRY) {
3559 genModbits(left,right,result);
3563 /* if both are of size == 1 */
3564 if (AOP_SIZE(left) == 1 &&
3565 AOP_SIZE(right) == 1 ) {
3566 genModOneByte(left,right,result);
3570 /* should have been converted to function call */
3574 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3575 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3576 freeAsmop(result,NULL,ic,TRUE);
3579 /*-----------------------------------------------------------------*/
3580 /* genIfxJump :- will create a jump depending on the ifx */
3581 /*-----------------------------------------------------------------*/
3582 static void genIfxJump (iCode *ic, char *jval)
3585 symbol *tlbl = newiTempLabel(NULL);
3588 D(emitcode(";", "genIfxJump "););
3590 /* if true label then we jump if condition
3592 if ( IC_TRUE(ic) ) {
3594 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3595 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3598 /* false label is present */
3599 jlbl = IC_FALSE(ic) ;
3600 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3601 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3603 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3604 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3606 emitcode(inst,"%05d$",tlbl->key+100);
3607 emitcode("ljmp","%05d$",jlbl->key+100);
3608 emitcode("","%05d$:",tlbl->key+100);
3610 /* mark the icode as generated */
3614 /*-----------------------------------------------------------------*/
3615 /* genCmp :- greater or less than comparison */
3616 /*-----------------------------------------------------------------*/
3617 static void genCmp (operand *left,operand *right,
3618 operand *result, iCode *ifx, int sign)
3620 int size, offset = 0 ;
3621 unsigned long lit = 0L;
3622 bool swappedOps = FALSE;
3624 D(emitcode(";", "genCmp"););
3627 /* If left if lit and right isn't, swap 'em. */
3628 if (AOP_TYPE(left) == AOP_LIT &&
3629 AOP_TYPE(right) != AOP_LIT)
3631 operand *tmp = left;
3634 D(emitcode(";", "kevin literal hack"););
3635 swappedOps = !swappedOps;
3638 if (AOP_NEEDSACC(right))
3640 if (AOP_NEEDSACC(left))
3642 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
3643 "both CMP operands need ACC!");
3648 operand *tmp = left;
3651 D(emitcode(";", "kevin ACC hack"););
3652 swappedOps = !swappedOps;
3657 /* if left & right are bit variables */
3658 if (AOP_TYPE(left) == AOP_CRY &&
3659 AOP_TYPE(right) == AOP_CRY ) {
3660 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3661 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3663 /* subtract right from left if at the
3664 end the carry flag is set then we know that
3665 left is greater than right */
3666 size = max(AOP_SIZE(left),AOP_SIZE(right));
3668 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3669 if((size == 1) && !sign &&
3670 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3671 symbol *lbl = newiTempLabel(NULL);
3672 emitcode("cjne","%s,%s,%05d$",
3673 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
3674 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
3676 emitcode("","%05d$:",lbl->key+100);
3678 if(AOP_TYPE(right) == AOP_LIT){
3679 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3680 /* optimize if(x < 0) or if(x >= 0) */
3686 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE,TRUE));
3687 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3688 genIfxJump (ifx,"acc.7");
3692 emitcode("rlc","a");
3700 emitcode(";", "genCmp #1: %d/%d/%d", size, sign, offset);
3701 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
3702 emitcode(";", "genCmp #2");
3703 if (sign && (size == 0))
3705 emitcode(";", "genCmp #3");
3706 emitcode("xrl","a,#0x80");
3707 if (AOP_TYPE(right) == AOP_LIT)
3709 unsigned long lit = (unsigned long)
3710 floatFromVal(AOP(right)->aopu.aop_lit);
3711 emitcode(";", "genCmp #3.1");
3712 emitcode("subb","a,#0x%02x",
3713 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3717 emitcode(";", "genCmp #3.2");
3718 if (AOP_NEEDSACC(right))
3720 emitcode("push", "acc");
3722 emitcode("mov","b,%s",aopGet(AOP(right),offset++,
3723 FALSE,FALSE,FALSE));
3724 emitcode("xrl","b,#0x80");
3725 if (AOP_NEEDSACC(right))
3727 emitcode("pop", "acc");
3729 emitcode("subb","a,b");
3736 emitcode(";", "genCmp #4");
3737 if (AOP_NEEDSACC(right))
3740 emitcode(";", "genCmp #4.1");
3741 emitcode("xch", "a, b");
3742 MOVA(aopGet(AOP(right),offset++,FALSE,FALSE,TRUE));
3743 emitcode("xch", "a, b");
3748 emitcode(";", "genCmp #4.2");
3749 s = aopGet(AOP(right),offset++,FALSE,FALSE,FALSE);
3752 emitcode("subb","a,%s",s);
3761 D(emitcode(";","kevHack: flip carry."););
3762 emitcode("cpl", "c");
3765 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3768 /* if the result is used in the next
3769 ifx conditional branch then generate
3770 code a little differently */
3772 genIfxJump (ifx,"c");
3775 /* leave the result in acc */
3779 /*-----------------------------------------------------------------*/
3780 /* genCmpGt :- greater than comparison */
3781 /*-----------------------------------------------------------------*/
3782 static void genCmpGt (iCode *ic, iCode *ifx)
3784 operand *left, *right, *result;
3785 link *letype , *retype;
3788 D(emitcode(";", "genCmpGt "););
3791 right= IC_RIGHT(ic);
3792 result = IC_RESULT(ic);
3794 letype = getSpec(operandType(left));
3795 retype =getSpec(operandType(right));
3796 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3797 /* assign the amsops */
3800 aopOp (left,ic,FALSE, TRUE);
3801 aopOp (right,ic,FALSE, FALSE);
3802 aopOp (result,ic,TRUE, FALSE);
3805 genCmp(right, left, result, ifx, sign);
3807 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3808 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3809 freeAsmop(result,NULL,ic,TRUE);
3812 /*-----------------------------------------------------------------*/
3813 /* genCmpLt - less than comparisons */
3814 /*-----------------------------------------------------------------*/
3815 static void genCmpLt (iCode *ic, iCode *ifx)
3817 operand *left, *right, *result;
3818 link *letype , *retype;
3821 D(emitcode(";", "genCmpLt "););
3824 right= IC_RIGHT(ic);
3825 result = IC_RESULT(ic);
3827 letype = getSpec(operandType(left));
3828 retype =getSpec(operandType(right));
3829 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3831 /* assign the amsops */
3834 aopOp (left,ic,FALSE, FALSE);
3835 aopOp (right,ic,FALSE, TRUE);
3836 aopOp (result,ic,TRUE, FALSE);
3839 genCmp(left, right, result, ifx, sign);
3841 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3842 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3843 freeAsmop(result,NULL,ic,TRUE);
3846 /*-----------------------------------------------------------------*/
3847 /* gencjneshort - compare and jump if not equal */
3848 /*-----------------------------------------------------------------*/
3849 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3851 int size = max(AOP_SIZE(left),AOP_SIZE(right));
3853 unsigned long lit = 0L;
3855 D(emitcode(";", "gencjneshort"););
3857 /* if the left side is a literal or
3858 if the right is in a pointer register and left
3860 if ((AOP_TYPE(left) == AOP_LIT) ||
3861 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3866 if(AOP_TYPE(right) == AOP_LIT)
3867 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3869 /* if the right side is a literal then anything goes */
3870 if (AOP_TYPE(right) == AOP_LIT &&
3871 AOP_TYPE(left) != AOP_DIR ) {
3873 char *l = aopGet(AOP(left), offset, FALSE, FALSE,TRUE);
3875 emitcode("cjne","a,%s,%05d$",
3876 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
3882 /* if the right side is in a register or in direct space or
3883 if the left is a pointer register & right is not */
3884 else if (AOP_TYPE(right) == AOP_REG ||
3885 AOP_TYPE(right) == AOP_DIR ||
3886 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3887 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3889 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
3890 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3891 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
3892 emitcode("jnz","%05d$",lbl->key+100);
3894 emitcode("cjne","a,%s,%05d$",
3895 aopGet(AOP(right),offset,FALSE,TRUE,FALSE),
3900 /* right is a pointer reg need both a & b */
3902 char *l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
3904 emitcode("mov","b,%s",l);
3905 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
3906 emitcode("cjne","a,b,%05d$",lbl->key+100);
3912 /*-----------------------------------------------------------------*/
3913 /* gencjne - compare and jump if not equal */
3914 /*-----------------------------------------------------------------*/
3915 static void gencjne(operand *left, operand *right, symbol *lbl)
3917 symbol *tlbl = newiTempLabel(NULL);
3919 D(emitcode(";", "gencjne"););
3921 gencjneshort(left, right, lbl);
3923 emitcode("mov","a,%s",one);
3924 emitcode("sjmp","%05d$",tlbl->key+100);
3925 emitcode("","%05d$:",lbl->key+100);
3926 emitcode("clr","a");
3927 emitcode("","%05d$:",tlbl->key+100);
3930 /*-----------------------------------------------------------------*/
3931 /* genCmpEq - generates code for equal to */
3932 /*-----------------------------------------------------------------*/
3933 static void genCmpEq (iCode *ic, iCode *ifx)
3935 operand *left, *right, *result;
3937 D(emitcode(";", "genCmpEq "););
3942 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
3943 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
3944 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
3947 /* if literal, literal on the right or
3948 if the right is in a pointer register and left
3950 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
3951 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3952 operand *t = IC_RIGHT(ic);
3953 IC_RIGHT(ic) = IC_LEFT(ic);
3957 if(ifx && !AOP_SIZE(result)){
3959 /* if they are both bit variables */
3960 if (AOP_TYPE(left) == AOP_CRY &&
3961 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3962 if(AOP_TYPE(right) == AOP_LIT){
3963 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3965 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3966 emitcode("cpl","c");
3967 } else if(lit == 1L) {
3968 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3970 emitcode("clr","c");
3972 /* AOP_TYPE(right) == AOP_CRY */
3974 symbol *lbl = newiTempLabel(NULL);
3975 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3976 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3977 emitcode("cpl","c");
3978 emitcode("","%05d$:",(lbl->key+100));
3980 /* if true label then we jump if condition
3982 tlbl = newiTempLabel(NULL);
3983 if ( IC_TRUE(ifx) ) {
3984 emitcode("jnc","%05d$",tlbl->key+100);
3985 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3987 emitcode("jc","%05d$",tlbl->key+100);
3988 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3990 emitcode("","%05d$:",tlbl->key+100);
3992 tlbl = newiTempLabel(NULL);
3993 gencjneshort(left, right, tlbl);
3994 if ( IC_TRUE(ifx) ) {
3995 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3996 emitcode("","%05d$:",tlbl->key+100);
3998 symbol *lbl = newiTempLabel(NULL);
3999 emitcode("sjmp","%05d$",lbl->key+100);
4000 emitcode("","%05d$:",tlbl->key+100);
4001 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4002 emitcode("","%05d$:",lbl->key+100);
4005 /* mark the icode as generated */
4010 /* if they are both bit variables */
4011 if (AOP_TYPE(left) == AOP_CRY &&
4012 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4013 if(AOP_TYPE(right) == AOP_LIT){
4014 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4016 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4017 emitcode("cpl","c");
4018 } else if(lit == 1L) {
4019 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4021 emitcode("clr","c");
4023 /* AOP_TYPE(right) == AOP_CRY */
4025 symbol *lbl = newiTempLabel(NULL);
4026 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4027 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4028 emitcode("cpl","c");
4029 emitcode("","%05d$:",(lbl->key+100));
4032 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4037 genIfxJump (ifx,"c");
4040 /* if the result is used in an arithmetic operation
4041 then put the result in place */
4044 gencjne(left,right,newiTempLabel(NULL));
4045 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4046 aopPut(AOP(result),"a",0);
4050 genIfxJump (ifx,"a");
4053 /* if the result is used in an arithmetic operation
4054 then put the result in place */
4055 if (AOP_TYPE(result) != AOP_CRY)
4057 /* leave the result in acc */
4061 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4062 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4063 freeAsmop(result,NULL,ic,TRUE);
4066 /*-----------------------------------------------------------------*/
4067 /* ifxForOp - returns the icode containing the ifx for operand */
4068 /*-----------------------------------------------------------------*/
4069 static iCode *ifxForOp ( operand *op, iCode *ic )
4071 /* if true symbol then needs to be assigned */
4072 if (IS_TRUE_SYMOP(op))
4075 /* if this has register type condition and
4076 the next instruction is ifx with the same operand
4077 and live to of the operand is upto the ifx only then */
4079 ic->next->op == IFX &&
4080 IC_COND(ic->next)->key == op->key &&
4081 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4086 /*-----------------------------------------------------------------*/
4087 /* genAndOp - for && operation */
4088 /*-----------------------------------------------------------------*/
4089 static void genAndOp (iCode *ic)
4091 operand *left,*right, *result;
4094 D(emitcode(";", "genAndOp "););
4096 /* note here that && operations that are in an
4097 if statement are taken away by backPatchLabels
4098 only those used in arthmetic operations remain */
4102 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4103 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4104 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4107 /* if both are bit variables */
4108 if (AOP_TYPE(left) == AOP_CRY &&
4109 AOP_TYPE(right) == AOP_CRY ) {
4110 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4111 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4114 tlbl = newiTempLabel(NULL);
4116 emitcode("jz","%05d$",tlbl->key+100);
4118 emitcode("","%05d$:",tlbl->key+100);
4122 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4123 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4124 freeAsmop(result,NULL,ic,TRUE);
4128 /*-----------------------------------------------------------------*/
4129 /* genOrOp - for || operation */
4130 /*-----------------------------------------------------------------*/
4131 static void genOrOp (iCode *ic)
4133 operand *left,*right, *result;
4136 D(emitcode(";", "genOrOp "););
4138 /* note here that || operations that are in an
4139 if statement are taken away by backPatchLabels
4140 only those used in arthmetic operations remain */
4144 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4145 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4146 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4149 /* if both are bit variables */
4150 if (AOP_TYPE(left) == AOP_CRY &&
4151 AOP_TYPE(right) == AOP_CRY ) {
4152 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4153 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
4156 tlbl = newiTempLabel(NULL);
4158 emitcode("jnz","%05d$",tlbl->key+100);
4160 emitcode("","%05d$:",tlbl->key+100);
4164 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4165 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4166 freeAsmop(result,NULL,ic,TRUE);
4169 /*-----------------------------------------------------------------*/
4170 /* isLiteralBit - test if lit == 2^n */
4171 /*-----------------------------------------------------------------*/
4172 static int isLiteralBit(unsigned long lit)
4174 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4175 0x100L,0x200L,0x400L,0x800L,
4176 0x1000L,0x2000L,0x4000L,0x8000L,
4177 0x10000L,0x20000L,0x40000L,0x80000L,
4178 0x100000L,0x200000L,0x400000L,0x800000L,
4179 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4180 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4183 for(idx = 0; idx < 32; idx++)
4189 /*-----------------------------------------------------------------*/
4190 /* continueIfTrue - */
4191 /*-----------------------------------------------------------------*/
4192 static void continueIfTrue (iCode *ic)
4195 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4199 /*-----------------------------------------------------------------*/
4201 /*-----------------------------------------------------------------*/
4202 static void jumpIfTrue (iCode *ic)
4205 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4209 /*-----------------------------------------------------------------*/
4210 /* jmpTrueOrFalse - */
4211 /*-----------------------------------------------------------------*/
4212 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4214 // ugly but optimized by peephole
4216 symbol *nlbl = newiTempLabel(NULL);
4217 emitcode("sjmp","%05d$",nlbl->key+100);
4218 emitcode("","%05d$:",tlbl->key+100);
4219 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4220 emitcode("","%05d$:",nlbl->key+100);
4223 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4224 emitcode("","%05d$:",tlbl->key+100);
4229 /*-----------------------------------------------------------------*/
4230 /* genAnd - code for and */
4231 /*-----------------------------------------------------------------*/
4232 static void genAnd (iCode *ic, iCode *ifx)
4234 operand *left, *right, *result;
4236 unsigned long lit = 0L;
4240 D(emitcode(";", "genAnd "););
4245 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4246 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4247 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4251 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4253 AOP_TYPE(left), AOP_TYPE(right));
4254 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4256 AOP_SIZE(left), AOP_SIZE(right));
4259 /* if left is a literal & right is not then exchange them */
4260 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4261 AOP_NEEDSACC(left)) {
4262 operand *tmp = right ;
4267 /* if result = right then exchange them */
4268 if(sameRegs(AOP(result),AOP(right))){
4269 operand *tmp = right ;
4274 /* if right is bit then exchange them */
4275 if (AOP_TYPE(right) == AOP_CRY &&
4276 AOP_TYPE(left) != AOP_CRY){
4277 operand *tmp = right ;
4281 if(AOP_TYPE(right) == AOP_LIT)
4282 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4284 size = AOP_SIZE(result);
4287 // result = bit & yy;
4288 if (AOP_TYPE(left) == AOP_CRY){
4289 // c = bit & literal;
4290 if(AOP_TYPE(right) == AOP_LIT){
4292 if(size && sameRegs(AOP(result),AOP(left)))
4295 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4298 if(size && (AOP_TYPE(result) == AOP_CRY)){
4299 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4302 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4306 emitcode("clr","c");
4309 if (AOP_TYPE(right) == AOP_CRY){
4311 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4312 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4315 MOVA(aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4317 emitcode("rrc","a");
4318 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4326 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4327 genIfxJump(ifx, "c");
4331 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4332 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4333 if((AOP_TYPE(right) == AOP_LIT) &&
4334 (AOP_TYPE(result) == AOP_CRY) &&
4335 (AOP_TYPE(left) != AOP_CRY)){
4336 int posbit = isLiteralBit(lit);
4340 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE,TRUE));
4343 emitcode("mov","c,acc.%d",posbit&0x07);
4347 sprintf(buffer,"acc.%d",posbit&0x07);
4348 genIfxJump(ifx, buffer);
4353 symbol *tlbl = newiTempLabel(NULL);
4354 int sizel = AOP_SIZE(left);
4356 emitcode("setb","c");
4358 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4359 MOVA( aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4361 if((posbit = isLiteralBit(bytelit)) != 0)
4362 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
4364 if(bytelit != 0x0FFL)
4365 emitcode("anl","a,%s",
4366 aopGet(AOP(right),offset,FALSE,TRUE,FALSE));
4367 emitcode("jnz","%05d$",tlbl->key+100);
4372 // bit = left & literal
4374 emitcode("clr","c");
4375 emitcode("","%05d$:",tlbl->key+100);
4377 // if(left & literal)
4380 jmpTrueOrFalse(ifx, tlbl);
4388 /* if left is same as result */
4389 if(sameRegs(AOP(result),AOP(left))){
4390 for(;size--; offset++) {
4391 if(AOP_TYPE(right) == AOP_LIT){
4392 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4396 aopPut(AOP(result),zero,offset);
4398 if (IS_AOP_PREG(result)) {
4399 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4400 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4401 aopPut(AOP(result),"a",offset);
4403 emitcode("anl","%s,%s",
4404 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4405 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4407 if (AOP_TYPE(left) == AOP_ACC)
4408 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4410 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4411 if (IS_AOP_PREG(result)) {
4412 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4413 aopPut(AOP(result),"a",offset);
4416 emitcode("anl","%s,a",
4417 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4422 // left & result in different registers
4423 if(AOP_TYPE(result) == AOP_CRY){
4425 // if(size), result in bit
4426 // if(!size && ifx), conditional oper: if(left & right)
4427 symbol *tlbl = newiTempLabel(NULL);
4428 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4430 emitcode("setb","c");
4432 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4433 emitcode("anl","a,%s",
4434 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4435 emitcode("jnz","%05d$",tlbl->key+100);
4440 emitcode("","%05d$:",tlbl->key+100);
4443 jmpTrueOrFalse(ifx, tlbl);
4445 for(;(size--);offset++) {
4447 // result = left & right
4448 if(AOP_TYPE(right) == AOP_LIT){
4449 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
4451 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4454 } else if(bytelit == 0){
4455 aopPut(AOP(result),zero,offset);
4459 // faster than result <- left, anl result,right
4460 // and better if result is SFR
4461 if (AOP_TYPE(left) == AOP_ACC)
4462 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4464 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4465 emitcode("anl","a,%s",
4466 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4468 aopPut(AOP(result),"a",offset);
4474 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4475 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4476 freeAsmop(result,NULL,ic,TRUE);
4479 /*-----------------------------------------------------------------*/
4480 /* genOr - code for or */
4481 /*-----------------------------------------------------------------*/
4482 static void genOr (iCode *ic, iCode *ifx)
4484 operand *left, *right, *result;
4486 unsigned long lit = 0L;
4488 D(emitcode(";", "genOr "););
4493 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4494 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4495 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4499 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4501 AOP_TYPE(left), AOP_TYPE(right));
4502 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4504 AOP_SIZE(left), AOP_SIZE(right));
4507 /* if left is a literal & right is not then exchange them */
4508 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4509 AOP_NEEDSACC(left)) {
4510 operand *tmp = right ;
4515 /* if result = right then exchange them */
4516 if(sameRegs(AOP(result),AOP(right))){
4517 operand *tmp = right ;
4522 /* if right is bit then exchange them */
4523 if (AOP_TYPE(right) == AOP_CRY &&
4524 AOP_TYPE(left) != AOP_CRY){
4525 operand *tmp = right ;
4529 if(AOP_TYPE(right) == AOP_LIT)
4530 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4532 size = AOP_SIZE(result);
4536 if (AOP_TYPE(left) == AOP_CRY){
4537 if(AOP_TYPE(right) == AOP_LIT){
4538 // c = bit & literal;
4540 // lit != 0 => result = 1
4541 if(AOP_TYPE(result) == AOP_CRY){
4543 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4545 continueIfTrue(ifx);
4548 emitcode("setb","c");
4550 // lit == 0 => result = left
4551 if(size && sameRegs(AOP(result),AOP(left)))
4553 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4556 if (AOP_TYPE(right) == AOP_CRY){
4558 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4559 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4563 symbol *tlbl = newiTempLabel(NULL);
4564 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4565 emitcode("setb","c");
4566 emitcode("jb","%s,%05d$",
4567 AOP(left)->aopu.aop_dir,tlbl->key+100);
4569 emitcode("jnz","%05d$",tlbl->key+100);
4570 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4571 jmpTrueOrFalse(ifx, tlbl);
4575 emitcode("","%05d$:",tlbl->key+100);
4584 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4585 genIfxJump(ifx, "c");
4589 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4590 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4591 if((AOP_TYPE(right) == AOP_LIT) &&
4592 (AOP_TYPE(result) == AOP_CRY) &&
4593 (AOP_TYPE(left) != AOP_CRY)){
4597 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4599 continueIfTrue(ifx);
4602 // lit = 0, result = boolean(left)
4604 emitcode("setb","c");
4607 symbol *tlbl = newiTempLabel(NULL);
4608 emitcode("jnz","%05d$",tlbl->key+100);
4610 emitcode("","%05d$:",tlbl->key+100);
4612 genIfxJump (ifx,"a");
4620 /* if left is same as result */
4621 if(sameRegs(AOP(result),AOP(left))){
4622 for(;size--; offset++) {
4623 if(AOP_TYPE(right) == AOP_LIT){
4624 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4627 if (IS_AOP_PREG(left)) {
4628 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4629 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4630 aopPut(AOP(result),"a",offset);
4632 emitcode("orl","%s,%s",
4633 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4634 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4636 if (AOP_TYPE(left) == AOP_ACC)
4637 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4639 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4640 if (IS_AOP_PREG(left)) {
4641 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4642 aopPut(AOP(result),"a",offset);
4644 emitcode("orl","%s,a",
4645 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4650 // left & result in different registers
4651 if(AOP_TYPE(result) == AOP_CRY){
4653 // if(size), result in bit
4654 // if(!size && ifx), conditional oper: if(left | right)
4655 symbol *tlbl = newiTempLabel(NULL);
4656 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4658 emitcode("setb","c");
4660 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4661 emitcode("orl","a,%s",
4662 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4663 emitcode("jnz","%05d$",tlbl->key+100);
4668 emitcode("","%05d$:",tlbl->key+100);
4671 jmpTrueOrFalse(ifx, tlbl);
4672 } else for(;(size--);offset++){
4674 // result = left & right
4675 if(AOP_TYPE(right) == AOP_LIT){
4676 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4678 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4683 // faster than result <- left, anl result,right
4684 // and better if result is SFR
4685 if (AOP_TYPE(left) == AOP_ACC)
4686 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4688 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4689 emitcode("orl","a,%s",
4690 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4692 aopPut(AOP(result),"a",offset);
4697 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4698 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4699 freeAsmop(result,NULL,ic,TRUE);
4702 /*-----------------------------------------------------------------*/
4703 /* genXor - code for xclusive or */
4704 /*-----------------------------------------------------------------*/
4705 static void genXor (iCode *ic, iCode *ifx)
4707 operand *left, *right, *result;
4709 unsigned long lit = 0L;
4711 D(emitcode(";", "genXor "););
4716 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4717 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4718 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4722 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4724 AOP_TYPE(left), AOP_TYPE(right));
4725 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4727 AOP_SIZE(left), AOP_SIZE(right));
4730 /* if left is a literal & right is not ||
4731 if left needs acc & right does not */
4732 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4733 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4734 operand *tmp = right ;
4739 /* if result = right then exchange them */
4740 if(sameRegs(AOP(result),AOP(right))){
4741 operand *tmp = right ;
4746 /* if right is bit then exchange them */
4747 if (AOP_TYPE(right) == AOP_CRY &&
4748 AOP_TYPE(left) != AOP_CRY){
4749 operand *tmp = right ;
4753 if(AOP_TYPE(right) == AOP_LIT)
4754 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4756 size = AOP_SIZE(result);
4760 if (AOP_TYPE(left) == AOP_CRY){
4761 if(AOP_TYPE(right) == AOP_LIT){
4762 // c = bit & literal;
4764 // lit>>1 != 0 => result = 1
4765 if(AOP_TYPE(result) == AOP_CRY){
4767 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4769 continueIfTrue(ifx);
4772 emitcode("setb","c");
4776 // lit == 0, result = left
4777 if(size && sameRegs(AOP(result),AOP(left)))
4779 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4781 // lit == 1, result = not(left)
4782 if(size && sameRegs(AOP(result),AOP(left))){
4783 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4786 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4787 emitcode("cpl","c");
4794 symbol *tlbl = newiTempLabel(NULL);
4795 if (AOP_TYPE(right) == AOP_CRY){
4797 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4800 int sizer = AOP_SIZE(right);
4802 // if val>>1 != 0, result = 1
4803 emitcode("setb","c");
4805 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE,TRUE));
4807 // test the msb of the lsb
4808 emitcode("anl","a,#0xfe");
4809 emitcode("jnz","%05d$",tlbl->key+100);
4813 emitcode("rrc","a");
4815 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4816 emitcode("cpl","c");
4817 emitcode("","%05d$:",(tlbl->key+100));
4824 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4825 genIfxJump(ifx, "c");
4829 if(sameRegs(AOP(result),AOP(left))){
4830 /* if left is same as result */
4831 for(;size--; offset++) {
4832 if(AOP_TYPE(right) == AOP_LIT){
4833 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4836 if (IS_AOP_PREG(left)) {
4837 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4838 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4839 aopPut(AOP(result),"a",offset);
4841 emitcode("xrl","%s,%s",
4842 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4843 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4845 if (AOP_TYPE(left) == AOP_ACC)
4846 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4848 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4849 if (IS_AOP_PREG(left)) {
4850 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4851 aopPut(AOP(result),"a",offset);
4853 emitcode("xrl","%s,a",
4854 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4859 // left & result in different registers
4860 if(AOP_TYPE(result) == AOP_CRY){
4862 // if(size), result in bit
4863 // if(!size && ifx), conditional oper: if(left ^ right)
4864 symbol *tlbl = newiTempLabel(NULL);
4865 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4867 emitcode("setb","c");
4869 if((AOP_TYPE(right) == AOP_LIT) &&
4870 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4871 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4873 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4874 emitcode("xrl","a,%s",
4875 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4877 emitcode("jnz","%05d$",tlbl->key+100);
4882 emitcode("","%05d$:",tlbl->key+100);
4885 jmpTrueOrFalse(ifx, tlbl);
4886 } else for(;(size--);offset++){
4888 // result = left & right
4889 if(AOP_TYPE(right) == AOP_LIT){
4890 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4892 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4897 // faster than result <- left, anl result,right
4898 // and better if result is SFR
4899 if (AOP_TYPE(left) == AOP_ACC)
4900 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4902 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4903 emitcode("xrl","a,%s",
4904 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4906 aopPut(AOP(result),"a",offset);
4911 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4912 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4913 freeAsmop(result,NULL,ic,TRUE);
4916 /*-----------------------------------------------------------------*/
4917 /* genInline - write the inline code out */
4918 /*-----------------------------------------------------------------*/
4919 static void genInline (iCode *ic)
4921 char buffer[MAX_INLINEASM];
4925 D(emitcode(";", "genInline "););
4927 _G.inLine += (!options.asmpeep);
4928 strcpy(buffer,IC_INLINE(ic));
4930 /* emit each line as a code */
4949 /* emitcode("",buffer); */
4950 _G.inLine -= (!options.asmpeep);
4953 /*-----------------------------------------------------------------*/
4954 /* genRRC - rotate right with carry */
4955 /*-----------------------------------------------------------------*/
4956 static void genRRC (iCode *ic)
4958 operand *left , *result ;
4959 int size, offset = 0;
4962 D(emitcode(";", "genRRC "););
4964 /* rotate right with carry */
4966 result=IC_RESULT(ic);
4967 aopOp (left,ic,FALSE, FALSE);
4968 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
4970 /* move it to the result */
4971 size = AOP_SIZE(result);
4975 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
4977 emitcode("rrc","a");
4978 if (AOP_SIZE(result) > 1)
4979 aopPut(AOP(result),"a",offset--);
4981 /* now we need to put the carry into the
4982 highest order byte of the result */
4983 if (AOP_SIZE(result) > 1) {
4984 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE,TRUE);
4987 emitcode("mov","acc.7,c");
4988 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
4989 freeAsmop(left,NULL,ic,TRUE);
4990 freeAsmop(result,NULL,ic,TRUE);
4993 /*-----------------------------------------------------------------*/
4994 /* genRLC - generate code for rotate left with carry */
4995 /*-----------------------------------------------------------------*/
4996 static void genRLC (iCode *ic)
4998 operand *left , *result ;
4999 int size, offset = 0;
5002 D(emitcode(";", "genRLC "););
5004 /* rotate right with carry */
5006 result=IC_RESULT(ic);
5007 aopOp (left,ic,FALSE, FALSE);
5008 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5010 /* move it to the result */
5011 size = AOP_SIZE(result);
5014 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5016 emitcode("add","a,acc");
5017 if (AOP_SIZE(result) > 1)
5018 aopPut(AOP(result),"a",offset++);
5020 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5022 emitcode("rlc","a");
5023 if (AOP_SIZE(result) > 1)
5024 aopPut(AOP(result),"a",offset++);
5027 /* now we need to put the carry into the
5028 highest order byte of the result */
5029 if (AOP_SIZE(result) > 1) {
5030 l = aopGet(AOP(result),0,FALSE,FALSE,TRUE);
5033 emitcode("mov","acc.0,c");
5034 aopPut(AOP(result),"a",0);
5035 freeAsmop(left,NULL,ic,TRUE);
5036 freeAsmop(result,NULL,ic,TRUE);
5039 /*-----------------------------------------------------------------*/
5040 /* genGetHbit - generates code get highest order bit */
5041 /*-----------------------------------------------------------------*/
5042 static void genGetHbit (iCode *ic)
5044 operand *left, *result;
5046 result=IC_RESULT(ic);
5047 aopOp (left,ic,FALSE, FALSE);
5048 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5050 D(emitcode(";", "genGetHbit "););
5052 /* get the highest order byte into a */
5053 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE,TRUE));
5054 if(AOP_TYPE(result) == AOP_CRY){
5055 emitcode("rlc","a");
5060 emitcode("anl","a,#0x01");
5065 freeAsmop(left,NULL,ic,TRUE);
5066 freeAsmop(result,NULL,ic,TRUE);
5069 /*-----------------------------------------------------------------*/
5070 /* AccRol - rotate left accumulator by known count */
5071 /*-----------------------------------------------------------------*/
5072 static void AccRol (int shCount)
5074 shCount &= 0x0007; // shCount : 0..7
5086 emitcode("swap","a");
5090 emitcode("swap","a");
5093 emitcode("swap","a");
5106 /*-----------------------------------------------------------------*/
5107 /* AccLsh - left shift accumulator by known count */
5108 /*-----------------------------------------------------------------*/
5109 static void AccLsh (int shCount)
5113 emitcode("add","a,acc");
5116 emitcode("add","a,acc");
5117 emitcode("add","a,acc");
5119 /* rotate left accumulator */
5121 /* and kill the lower order bits */
5122 emitcode("anl","a,#0x%02x", SLMask[shCount]);
5127 /*-----------------------------------------------------------------*/
5128 /* AccRsh - right shift accumulator by known count */
5129 /*-----------------------------------------------------------------*/
5130 static void AccRsh (int shCount)
5135 emitcode("rrc","a");
5137 /* rotate right accumulator */
5138 AccRol(8 - shCount);
5139 /* and kill the higher order bits */
5140 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5145 /*-----------------------------------------------------------------*/
5146 /* AccSRsh - signed right shift accumulator by known count */
5147 /*-----------------------------------------------------------------*/
5148 static void AccSRsh (int shCount)
5153 emitcode("mov","c,acc.7");
5154 emitcode("rrc","a");
5155 } else if(shCount == 2){
5156 emitcode("mov","c,acc.7");
5157 emitcode("rrc","a");
5158 emitcode("mov","c,acc.7");
5159 emitcode("rrc","a");
5161 tlbl = newiTempLabel(NULL);
5162 /* rotate right accumulator */
5163 AccRol(8 - shCount);
5164 /* and kill the higher order bits */
5165 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5166 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5167 emitcode("orl","a,#0x%02x",
5168 (unsigned char)~SRMask[shCount]);
5169 emitcode("","%05d$:",tlbl->key+100);
5174 /*-----------------------------------------------------------------*/
5175 /* shiftR1Left2Result - shift right one byte from left to result */
5176 /*-----------------------------------------------------------------*/
5177 static void shiftR1Left2Result (operand *left, int offl,
5178 operand *result, int offr,
5179 int shCount, int sign)
5181 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5182 /* shift right accumulator */
5187 aopPut(AOP(result),"a",offr);
5190 /*-----------------------------------------------------------------*/
5191 /* shiftL1Left2Result - shift left one byte from left to result */
5192 /*-----------------------------------------------------------------*/
5193 static void shiftL1Left2Result (operand *left, int offl,
5194 operand *result, int offr, int shCount)
5197 l = aopGet(AOP(left),offl,FALSE,FALSE,TRUE);
5199 /* shift left accumulator */
5201 aopPut(AOP(result),"a",offr);
5204 /*-----------------------------------------------------------------*/
5205 /* movLeft2Result - move byte from left to result */
5206 /*-----------------------------------------------------------------*/
5207 static void movLeft2Result (operand *left, int offl,
5208 operand *result, int offr, int sign)
5211 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5212 l = aopGet(AOP(left),offl,FALSE,FALSE,FALSE);
5214 if (*l == '@' && (IS_AOP_PREG(result))) {
5215 emitcode("mov","a,%s",l);
5216 aopPut(AOP(result),"a",offr);
5219 aopPut(AOP(result),l,offr);
5221 /* MSB sign in acc.7 ! */
5222 if(getDataSize(left) == offl+1){
5223 emitcode("mov","a,%s",l);
5224 aopPut(AOP(result),"a",offr);
5231 /*-----------------------------------------------------------------*/
5232 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5233 /*-----------------------------------------------------------------*/
5234 static void AccAXRrl1 (char *x)
5236 emitcode("rrc","a");
5237 emitcode("xch","a,%s", x);
5238 emitcode("rrc","a");
5239 emitcode("xch","a,%s", x);
5242 /*-----------------------------------------------------------------*/
5243 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5244 /*-----------------------------------------------------------------*/
5245 static void AccAXLrl1 (char *x)
5247 emitcode("xch","a,%s",x);
5248 emitcode("rlc","a");
5249 emitcode("xch","a,%s",x);
5250 emitcode("rlc","a");
5253 /*-----------------------------------------------------------------*/
5254 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5255 /*-----------------------------------------------------------------*/
5256 static void AccAXLsh1 (char *x)
5258 emitcode("xch","a,%s",x);
5259 emitcode("add","a,acc");
5260 emitcode("xch","a,%s",x);
5261 emitcode("rlc","a");
5264 /*-----------------------------------------------------------------*/
5265 /* AccAXLsh - left shift a:x by known count (0..7) */
5266 /*-----------------------------------------------------------------*/
5267 static void AccAXLsh (char *x, int shCount)
5281 case 5 : // AAAAABBB:CCCCCDDD
5282 AccRol(shCount); // BBBAAAAA:CCCCCDDD
5283 emitcode("anl","a,#0x%02x",
5284 SLMask[shCount]); // BBB00000:CCCCCDDD
5285 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
5286 AccRol(shCount); // DDDCCCCC:BBB00000
5287 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
5288 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
5289 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
5290 emitcode("anl","a,#0x%02x",
5291 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5292 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
5293 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
5295 case 6 : // AAAAAABB:CCCCCCDD
5296 emitcode("anl","a,#0x%02x",
5297 SRMask[shCount]); // 000000BB:CCCCCCDD
5298 emitcode("mov","c,acc.0"); // c = B
5299 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
5300 AccAXRrl1(x); // BCCCCCCD:D000000B
5301 AccAXRrl1(x); // BBCCCCCC:DD000000
5303 case 7 : // a:x <<= 7
5304 emitcode("anl","a,#0x%02x",
5305 SRMask[shCount]); // 0000000B:CCCCCCCD
5306 emitcode("mov","c,acc.0"); // c = B
5307 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
5308 AccAXRrl1(x); // BCCCCCCC:D0000000
5315 /*-----------------------------------------------------------------*/
5316 /* AccAXRsh - right shift a:x known count (0..7) */
5317 /*-----------------------------------------------------------------*/
5318 static void AccAXRsh (char *x, int shCount)
5325 AccAXRrl1(x); // 0->a:x
5329 AccAXRrl1(x); // 0->a:x
5331 AccAXRrl1(x); // 0->a:x
5335 case 5 : // AAAAABBB:CCCCCDDD = a:x
5336 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
5337 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5338 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5339 emitcode("anl","a,#0x%02x",
5340 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5341 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5342 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5343 emitcode("anl","a,#0x%02x",
5344 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5345 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5346 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5347 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
5349 case 6 : // AABBBBBB:CCDDDDDD
5350 emitcode("mov","c,acc.7");
5351 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5352 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5353 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5354 emitcode("anl","a,#0x%02x",
5355 SRMask[shCount]); // 000000AA:BBBBBBCC
5357 case 7 : // ABBBBBBB:CDDDDDDD
5358 emitcode("mov","c,acc.7"); // c = A
5359 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5360 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5361 emitcode("anl","a,#0x%02x",
5362 SRMask[shCount]); // 0000000A:BBBBBBBC
5369 /*-----------------------------------------------------------------*/
5370 /* AccAXRshS - right shift signed a:x known count (0..7) */
5371 /*-----------------------------------------------------------------*/
5372 static void AccAXRshS (char *x, int shCount)
5379 emitcode("mov","c,acc.7");
5380 AccAXRrl1(x); // s->a:x
5383 emitcode("mov","c,acc.7");
5384 AccAXRrl1(x); // s->a:x
5385 emitcode("mov","c,acc.7");
5386 AccAXRrl1(x); // s->a:x
5390 case 5 : // AAAAABBB:CCCCCDDD = a:x
5391 tlbl = newiTempLabel(NULL);
5392 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5393 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5394 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5395 emitcode("anl","a,#0x%02x",
5396 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5397 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5398 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5399 emitcode("anl","a,#0x%02x",
5400 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5401 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5402 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5403 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5404 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5405 emitcode("orl","a,#0x%02x",
5406 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5407 emitcode("","%05d$:",tlbl->key+100);
5408 break; // SSSSAAAA:BBBCCCCC
5409 case 6 : // AABBBBBB:CCDDDDDD
5410 tlbl = newiTempLabel(NULL);
5411 emitcode("mov","c,acc.7");
5412 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5413 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5414 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5415 emitcode("anl","a,#0x%02x",
5416 SRMask[shCount]); // 000000AA:BBBBBBCC
5417 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5418 emitcode("orl","a,#0x%02x",
5419 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5420 emitcode("","%05d$:",tlbl->key+100);
5422 case 7 : // ABBBBBBB:CDDDDDDD
5423 tlbl = newiTempLabel(NULL);
5424 emitcode("mov","c,acc.7"); // c = A
5425 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5426 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5427 emitcode("anl","a,#0x%02x",
5428 SRMask[shCount]); // 0000000A:BBBBBBBC
5429 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5430 emitcode("orl","a,#0x%02x",
5431 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5432 emitcode("","%05d$:",tlbl->key+100);
5439 /*-----------------------------------------------------------------*/
5440 /* shiftL2Left2Result - shift left two bytes from left to result */
5441 /*-----------------------------------------------------------------*/
5442 static void shiftL2Left2Result (operand *left, int offl,
5443 operand *result, int offr, int shCount)
5445 if(sameRegs(AOP(result), AOP(left)) &&
5446 ((offl + MSB16) == offr)){
5447 /* don't crash result[offr] */
5448 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5449 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5451 movLeft2Result(left,offl, result, offr, 0);
5452 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5454 /* ax << shCount (x = lsb(result))*/
5455 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE), shCount);
5456 aopPut(AOP(result),"a",offr+MSB16);
5460 /*-----------------------------------------------------------------*/
5461 /* shiftR2Left2Result - shift right two bytes from left to result */
5462 /*-----------------------------------------------------------------*/
5463 static void shiftR2Left2Result (operand *left, int offl,
5464 operand *result, int offr,
5465 int shCount, int sign)
5467 if(sameRegs(AOP(result), AOP(left)) &&
5468 ((offl + MSB16) == offr)){
5469 /* don't crash result[offr] */
5470 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5471 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5473 movLeft2Result(left,offl, result, offr, 0);
5474 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5476 /* a:x >> shCount (x = lsb(result))*/
5478 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5480 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5481 if(getDataSize(result) > 1)
5482 aopPut(AOP(result),"a",offr+MSB16);
5485 /*-----------------------------------------------------------------*/
5486 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5487 /*-----------------------------------------------------------------*/
5488 static void shiftLLeftOrResult (operand *left, int offl,
5489 operand *result, int offr, int shCount)
5491 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5492 /* shift left accumulator */
5494 /* or with result */
5495 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5496 /* back to result */
5497 aopPut(AOP(result),"a",offr);
5500 /*-----------------------------------------------------------------*/
5501 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5502 /*-----------------------------------------------------------------*/
5503 static void shiftRLeftOrResult (operand *left, int offl,
5504 operand *result, int offr, int shCount)
5506 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5507 /* shift right accumulator */
5509 /* or with result */
5510 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5511 /* back to result */
5512 aopPut(AOP(result),"a",offr);
5515 /*-----------------------------------------------------------------*/
5516 /* genlshOne - left shift a one byte quantity by known count */
5517 /*-----------------------------------------------------------------*/
5518 static void genlshOne (operand *result, operand *left, int shCount)
5520 D(emitcode(";", "genlshOne "););
5521 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5524 /*-----------------------------------------------------------------*/
5525 /* genlshTwo - left shift two bytes by known amount != 0 */
5526 /*-----------------------------------------------------------------*/
5527 static void genlshTwo (operand *result,operand *left, int shCount)
5531 D(emitcode(";", "genlshTwo "););
5533 size = getDataSize(result);
5535 /* if shCount >= 8 */
5541 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5543 movLeft2Result(left, LSB, result, MSB16, 0);
5545 aopPut(AOP(result),zero,LSB);
5548 /* 1 <= shCount <= 7 */
5551 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5553 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5557 /*-----------------------------------------------------------------*/
5558 /* shiftLLong - shift left one long from left to result */
5559 /* offl = LSB or MSB16 */
5560 /*-----------------------------------------------------------------*/
5561 static void shiftLLong (operand *left, operand *result, int offr )
5564 int size = AOP_SIZE(result);
5566 if(size >= LSB+offr){
5567 l = aopGet(AOP(left),LSB,FALSE,FALSE,TRUE);
5569 emitcode("add","a,acc");
5570 if (sameRegs(AOP(left),AOP(result)) &&
5571 size >= MSB16+offr && offr != LSB )
5572 emitcode("xch","a,%s",
5573 aopGet(AOP(left),LSB+offr,FALSE,FALSE,FALSE));
5575 aopPut(AOP(result),"a",LSB+offr);
5578 if(size >= MSB16+offr){
5579 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5580 l = aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE);
5583 emitcode("rlc","a");
5584 if (sameRegs(AOP(left),AOP(result)) &&
5585 size >= MSB24+offr && offr != LSB)
5586 emitcode("xch","a,%s",
5587 aopGet(AOP(left),MSB16+offr,FALSE,FALSE,FALSE));
5589 aopPut(AOP(result),"a",MSB16+offr);
5592 if(size >= MSB24+offr){
5593 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5594 l = aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE);
5597 emitcode("rlc","a");
5598 if (sameRegs(AOP(left),AOP(result)) &&
5599 size >= MSB32+offr && offr != LSB )
5600 emitcode("xch","a,%s",
5601 aopGet(AOP(left),MSB24+offr,FALSE,FALSE,FALSE));
5603 aopPut(AOP(result),"a",MSB24+offr);
5606 if(size > MSB32+offr){
5607 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5608 l = aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE);
5611 emitcode("rlc","a");
5612 aopPut(AOP(result),"a",MSB32+offr);
5615 aopPut(AOP(result),zero,LSB);
5618 /*-----------------------------------------------------------------*/
5619 /* genlshFour - shift four byte by a known amount != 0 */
5620 /*-----------------------------------------------------------------*/
5621 static void genlshFour (operand *result, operand *left, int shCount)
5625 D(emitcode(";", "genlshFour "););
5627 size = AOP_SIZE(result);
5629 /* if shifting more that 3 bytes */
5630 if (shCount >= 24 ) {
5633 /* lowest order of left goes to the highest
5634 order of the destination */
5635 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5637 movLeft2Result(left, LSB, result, MSB32, 0);
5638 aopPut(AOP(result),zero,LSB);
5639 aopPut(AOP(result),zero,MSB16);
5640 aopPut(AOP(result),zero,MSB32);
5644 /* more than two bytes */
5645 else if ( shCount >= 16 ) {
5646 /* lower order two bytes goes to higher order two bytes */
5648 /* if some more remaining */
5650 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5652 movLeft2Result(left, MSB16, result, MSB32, 0);
5653 movLeft2Result(left, LSB, result, MSB24, 0);
5655 aopPut(AOP(result),zero,MSB16);
5656 aopPut(AOP(result),zero,LSB);
5660 /* if more than 1 byte */
5661 else if ( shCount >= 8 ) {
5662 /* lower order three bytes goes to higher order three bytes */
5666 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5668 movLeft2Result(left, LSB, result, MSB16, 0);
5670 else{ /* size = 4 */
5672 movLeft2Result(left, MSB24, result, MSB32, 0);
5673 movLeft2Result(left, MSB16, result, MSB24, 0);
5674 movLeft2Result(left, LSB, result, MSB16, 0);
5675 aopPut(AOP(result),zero,LSB);
5677 else if(shCount == 1)
5678 shiftLLong(left, result, MSB16);
5680 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5681 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5682 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5683 aopPut(AOP(result),zero,LSB);
5688 /* 1 <= shCount <= 7 */
5689 else if(shCount <= 2){
5690 shiftLLong(left, result, LSB);
5692 shiftLLong(result, result, LSB);
5694 /* 3 <= shCount <= 7, optimize */
5696 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5697 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5698 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5702 /*-----------------------------------------------------------------*/
5703 /* genLeftShiftLiteral - left shifting by known count */
5704 /*-----------------------------------------------------------------*/
5705 static void genLeftShiftLiteral (operand *left,
5710 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5713 D(emitcode(";","genLeftShiftLiteral (%d)", shCount););
5715 freeAsmop(right,NULL,ic,TRUE);
5717 aopOp(left,ic,FALSE, FALSE);
5718 aopOp(result,ic,FALSE, TRUE);
5720 size = getSize(operandType(result));
5723 emitcode("; shift left ","result %d, left %d",size,
5727 /* I suppose that the left size >= result size */
5730 movLeft2Result(left, size, result, size, 0);
5734 else if(shCount >= (size * 8))
5736 aopPut(AOP(result),zero,size);
5740 genlshOne (result,left,shCount);
5744 case 3: /* bug: this is for generic pointers, I bet. */
5745 genlshTwo (result,left,shCount);
5749 genlshFour (result,left,shCount);
5753 freeAsmop(left,NULL,ic,TRUE);
5754 freeAsmop(result,NULL,ic,TRUE);
5757 /*-----------------------------------------------------------------*/
5758 /* genLeftShift - generates code for left shifting */
5759 /*-----------------------------------------------------------------*/
5760 static void genLeftShift (iCode *ic)
5762 operand *left,*right, *result;
5765 symbol *tlbl , *tlbl1;
5767 D(emitcode(";", "genLeftShift "););
5769 right = IC_RIGHT(ic);
5771 result = IC_RESULT(ic);
5773 aopOp(right,ic,FALSE, FALSE);
5776 /* if the shift count is known then do it
5777 as efficiently as possible */
5778 if (AOP_TYPE(right) == AOP_LIT) {
5779 genLeftShiftLiteral (left,right,result,ic);
5784 /* shift count is unknown then we have to form
5785 a loop get the loop count in B : Note: we take
5786 only the lower order byte since shifting
5787 more that 32 bits make no sense anyway, ( the
5788 largest size of an object can be only 32 bits ) */
5790 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
5791 emitcode("inc","b");
5792 freeAsmop (right,NULL,ic,TRUE);
5793 aopOp(left,ic,FALSE, FALSE);
5794 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5796 /* now move the left to the result if they are not the
5798 if (!sameRegs(AOP(left),AOP(result)) &&
5799 AOP_SIZE(result) > 1) {
5801 size = AOP_SIZE(result);
5804 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
5805 if (*l == '@' && (IS_AOP_PREG(result))) {
5807 emitcode("mov","a,%s",l);
5808 aopPut(AOP(result),"a",offset);
5810 aopPut(AOP(result),l,offset);
5815 tlbl = newiTempLabel(NULL);
5816 size = AOP_SIZE(result);
5818 tlbl1 = newiTempLabel(NULL);
5820 /* if it is only one byte then */
5822 symbol *tlbl1 = newiTempLabel(NULL);
5824 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
5826 emitcode("sjmp","%05d$",tlbl1->key+100);
5827 emitcode("","%05d$:",tlbl->key+100);
5828 emitcode("add","a,acc");
5829 emitcode("","%05d$:",tlbl1->key+100);
5830 emitcode("djnz","b,%05d$",tlbl->key+100);
5831 aopPut(AOP(result),"a",0);
5835 reAdjustPreg(AOP(result));
5837 emitcode("sjmp","%05d$",tlbl1->key+100);
5838 emitcode("","%05d$:",tlbl->key+100);
5839 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
5841 emitcode("add","a,acc");
5842 aopPut(AOP(result),"a",offset++);
5844 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
5846 emitcode("rlc","a");
5847 aopPut(AOP(result),"a",offset++);
5849 reAdjustPreg(AOP(result));
5851 emitcode("","%05d$:",tlbl1->key+100);
5852 emitcode("djnz","b,%05d$",tlbl->key+100);
5854 freeAsmop(left,NULL,ic,TRUE);
5855 freeAsmop(result,NULL,ic,TRUE);
5858 /*-----------------------------------------------------------------*/
5859 /* genrshOne - right shift a one byte quantity by known count */
5860 /*-----------------------------------------------------------------*/
5861 static void genrshOne (operand *result, operand *left,
5862 int shCount, int sign)
5864 D(emitcode(";", "genrshOne"););
5865 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
5868 /*-----------------------------------------------------------------*/
5869 /* genrshTwo - right shift two bytes by known amount != 0 */
5870 /*-----------------------------------------------------------------*/
5871 static void genrshTwo (operand *result,operand *left,
5872 int shCount, int sign)
5874 D(emitcode(";", "genrshTwo"););
5876 /* if shCount >= 8 */
5880 shiftR1Left2Result(left, MSB16, result, LSB,
5883 movLeft2Result(left, MSB16, result, LSB, sign);
5884 addSign(result, MSB16, sign);
5887 /* 1 <= shCount <= 7 */
5889 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
5892 /*-----------------------------------------------------------------*/
5893 /* shiftRLong - shift right one long from left to result */
5894 /* offl = LSB or MSB16 */
5895 /*-----------------------------------------------------------------*/
5896 static void shiftRLong (operand *left, int offl,
5897 operand *result, int sign)
5900 emitcode("clr","c");
5901 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE));
5903 emitcode("mov","c,acc.7");
5904 emitcode("rrc","a");
5905 aopPut(AOP(result),"a",MSB32-offl);
5907 /* add sign of "a" */
5908 addSign(result, MSB32, sign);
5910 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE));
5911 emitcode("rrc","a");
5912 aopPut(AOP(result),"a",MSB24-offl);
5914 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE));
5915 emitcode("rrc","a");
5916 aopPut(AOP(result),"a",MSB16-offl);
5919 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE,TRUE));
5920 emitcode("rrc","a");
5921 aopPut(AOP(result),"a",LSB);
5925 /*-----------------------------------------------------------------*/
5926 /* genrshFour - shift four byte by a known amount != 0 */
5927 /*-----------------------------------------------------------------*/
5928 static void genrshFour (operand *result, operand *left,
5929 int shCount, int sign)
5931 D(emitcode(";", "genrshFour"););
5933 /* if shifting more that 3 bytes */
5934 if(shCount >= 24 ) {
5937 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
5939 movLeft2Result(left, MSB32, result, LSB, sign);
5940 addSign(result, MSB16, sign);
5942 else if(shCount >= 16){
5945 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
5947 movLeft2Result(left, MSB24, result, LSB, 0);
5948 movLeft2Result(left, MSB32, result, MSB16, sign);
5950 addSign(result, MSB24, sign);
5952 else if(shCount >= 8){
5955 shiftRLong(left, MSB16, result, sign);
5956 else if(shCount == 0){
5957 movLeft2Result(left, MSB16, result, LSB, 0);
5958 movLeft2Result(left, MSB24, result, MSB16, 0);
5959 movLeft2Result(left, MSB32, result, MSB24, sign);
5960 addSign(result, MSB32, sign);
5963 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
5964 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
5965 /* the last shift is signed */
5966 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
5967 addSign(result, MSB32, sign);
5970 else{ /* 1 <= shCount <= 7 */
5972 shiftRLong(left, LSB, result, sign);
5974 shiftRLong(result, LSB, result, sign);
5977 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
5978 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
5979 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
5984 /*-----------------------------------------------------------------*/
5985 /* genRightShiftLiteral - right shifting by known count */
5986 /*-----------------------------------------------------------------*/
5987 static void genRightShiftLiteral (operand *left,
5993 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5996 D(emitcode(";", "genRightShiftLiteral"););
5998 freeAsmop(right,NULL,ic,TRUE);
6000 aopOp(left,ic,FALSE, FALSE);
6001 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6004 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6008 size = getDataSize(left);
6009 /* test the LEFT size !!! */
6011 /* I suppose that the left size >= result size */
6013 size = getDataSize(result);
6015 movLeft2Result(left, size, result, size, 0);
6018 else if(shCount >= (size * 8)){
6020 /* get sign in acc.7 */
6021 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE,TRUE));
6022 addSign(result, LSB, sign);
6026 genrshOne (result,left,shCount,sign);
6030 genrshTwo (result,left,shCount,sign);
6034 genrshFour (result,left,shCount,sign);
6040 freeAsmop(left,NULL,ic,TRUE);
6041 freeAsmop(result,NULL,ic,TRUE);
6045 /*-----------------------------------------------------------------*/
6046 /* genSignedRightShift - right shift of signed number */
6047 /*-----------------------------------------------------------------*/
6048 static void genSignedRightShift (iCode *ic)
6050 operand *right, *left, *result;
6053 symbol *tlbl, *tlbl1 ;
6055 D(emitcode(";", "genSignedRightShift "););
6057 /* we do it the hard way put the shift count in b
6058 and loop thru preserving the sign */
6060 right = IC_RIGHT(ic);
6062 result = IC_RESULT(ic);
6064 aopOp(right,ic,FALSE, FALSE);
6067 if ( AOP_TYPE(right) == AOP_LIT) {
6068 genRightShiftLiteral (left,right,result,ic,1);
6072 /* shift count is unknown then we have to form
6073 a loop get the loop count in B : Note: we take
6074 only the lower order byte since shifting
6075 more that 32 bits make no sense anyway, ( the
6076 largest size of an object can be only 32 bits ) */
6078 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6079 emitcode("inc","b");
6080 freeAsmop (right,NULL,ic,TRUE);
6081 aopOp(left,ic,FALSE, FALSE);
6082 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6084 /* now move the left to the result if they are not the
6086 if (!sameRegs(AOP(left),AOP(result)) &&
6087 AOP_SIZE(result) > 1) {
6089 size = AOP_SIZE(result);
6092 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6093 if (*l == '@' && IS_AOP_PREG(result)) {
6095 emitcode("mov","a,%s",l);
6096 aopPut(AOP(result),"a",offset);
6098 aopPut(AOP(result),l,offset);
6103 /* mov the highest order bit to OVR */
6104 tlbl = newiTempLabel(NULL);
6105 tlbl1= newiTempLabel(NULL);
6107 size = AOP_SIZE(result);
6109 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
6110 emitcode("rlc","a");
6111 emitcode("mov","ov,c");
6112 /* if it is only one byte then */
6114 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6116 emitcode("sjmp","%05d$",tlbl1->key+100);
6117 emitcode("","%05d$:",tlbl->key+100);
6118 emitcode("mov","c,ov");
6119 emitcode("rrc","a");
6120 emitcode("","%05d$:",tlbl1->key+100);
6121 emitcode("djnz","b,%05d$",tlbl->key+100);
6122 aopPut(AOP(result),"a",0);
6126 reAdjustPreg(AOP(result));
6127 emitcode("sjmp","%05d$",tlbl1->key+100);
6128 emitcode("","%05d$:",tlbl->key+100);
6129 emitcode("mov","c,ov");
6131 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6133 emitcode("rrc","a");
6134 aopPut(AOP(result),"a",offset--);
6136 reAdjustPreg(AOP(result));
6137 emitcode("","%05d$:",tlbl1->key+100);
6138 emitcode("djnz","b,%05d$",tlbl->key+100);
6141 freeAsmop(left,NULL,ic,TRUE);
6142 freeAsmop(result,NULL,ic,TRUE);
6145 /*-----------------------------------------------------------------*/
6146 /* genRightShift - generate code for right shifting */
6147 /*-----------------------------------------------------------------*/
6148 static void genRightShift (iCode *ic)
6150 operand *right, *left, *result;
6154 symbol *tlbl, *tlbl1 ;
6156 D(emitcode(";", "genRightShift "););
6158 /* if signed then we do it the hard way preserve the
6159 sign bit moving it inwards */
6160 retype = getSpec(operandType(IC_RESULT(ic)));
6162 if (!SPEC_USIGN(retype)) {
6163 genSignedRightShift (ic);
6167 /* signed & unsigned types are treated the same : i.e. the
6168 signed is NOT propagated inwards : quoting from the
6169 ANSI - standard : "for E1 >> E2, is equivalent to division
6170 by 2**E2 if unsigned or if it has a non-negative value,
6171 otherwise the result is implementation defined ", MY definition
6172 is that the sign does not get propagated */
6174 right = IC_RIGHT(ic);
6176 result = IC_RESULT(ic);
6178 aopOp(right,ic,FALSE, FALSE);
6181 /* if the shift count is known then do it
6182 as efficiently as possible */
6183 if (AOP_TYPE(right) == AOP_LIT) {
6184 genRightShiftLiteral (left,right,result,ic, 0);
6189 /* shift count is unknown then we have to form
6190 a loop get the loop count in B : Note: we take
6191 only the lower order byte since shifting
6192 more that 32 bits make no sense anyway, ( the
6193 largest size of an object can be only 32 bits ) */
6195 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6196 emitcode("inc","b");
6197 freeAsmop (right,NULL,ic,TRUE);
6198 aopOp(left,ic,FALSE, FALSE);
6199 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6201 /* now move the left to the result if they are not the
6203 if (!sameRegs(AOP(left),AOP(result)) &&
6204 AOP_SIZE(result) > 1) {
6206 size = AOP_SIZE(result);
6209 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6210 if (*l == '@' && IS_AOP_PREG(result)) {
6212 emitcode("mov","a,%s",l);
6213 aopPut(AOP(result),"a",offset);
6215 aopPut(AOP(result),l,offset);
6220 tlbl = newiTempLabel(NULL);
6221 tlbl1= newiTempLabel(NULL);
6222 size = AOP_SIZE(result);
6225 /* if it is only one byte then */
6227 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6229 emitcode("sjmp","%05d$",tlbl1->key+100);
6230 emitcode("","%05d$:",tlbl->key+100);
6232 emitcode("rrc","a");
6233 emitcode("","%05d$:",tlbl1->key+100);
6234 emitcode("djnz","b,%05d$",tlbl->key+100);
6235 aopPut(AOP(result),"a",0);
6239 reAdjustPreg(AOP(result));
6240 emitcode("sjmp","%05d$",tlbl1->key+100);
6241 emitcode("","%05d$:",tlbl->key+100);
6244 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6246 emitcode("rrc","a");
6247 aopPut(AOP(result),"a",offset--);
6249 reAdjustPreg(AOP(result));
6251 emitcode("","%05d$:",tlbl1->key+100);
6252 emitcode("djnz","b,%05d$",tlbl->key+100);
6255 freeAsmop(left,NULL,ic,TRUE);
6256 freeAsmop(result,NULL,ic,TRUE);
6259 /*-----------------------------------------------------------------*/
6260 /* genUnpackBits - generates code for unpacking bits */
6261 /*-----------------------------------------------------------------*/
6262 static void genUnpackBits (operand *result, char *rname, int ptype)
6269 D(emitcode(";", "genUnpackBits "););
6271 etype = getSpec(operandType(result));
6273 /* read the first byte */
6278 emitcode("mov","a,@%s",rname);
6282 emitcode("movx","a,@%s",rname);
6286 emitcode("movx","a,@dptr");
6290 emitcode("clr","a");
6291 emitcode("movc","a","@a+dptr");
6295 emitcode("lcall","__gptrget");
6299 /* if we have bitdisplacement then it fits */
6300 /* into this byte completely or if length is */
6301 /* less than a byte */
6302 if ((shCnt = SPEC_BSTR(etype)) ||
6303 (SPEC_BLEN(etype) <= 8)) {
6305 /* shift right acc */
6308 emitcode("anl","a,#0x%02x",
6309 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6310 aopPut(AOP(result),"a",offset);
6314 /* bit field did not fit in a byte */
6315 rlen = SPEC_BLEN(etype) - 8;
6316 aopPut(AOP(result),"a",offset++);
6323 emitcode("inc","%s",rname);
6324 emitcode("mov","a,@%s",rname);
6328 emitcode("inc","%s",rname);
6329 emitcode("movx","a,@%s",rname);
6333 emitcode("inc","dptr");
6334 emitcode("movx","a,@dptr");
6338 emitcode("clr","a");
6339 emitcode("inc","dptr");
6340 emitcode("movc","a","@a+dptr");
6344 emitcode("inc","dptr");
6345 emitcode("lcall","__gptrget");
6350 /* if we are done */
6354 aopPut(AOP(result),"a",offset++);
6359 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
6360 aopPut(AOP(result),"a",offset);
6367 /*-----------------------------------------------------------------*/
6368 /* genDataPointerGet - generates code when ptr offset is known */
6369 /*-----------------------------------------------------------------*/
6370 static void genDataPointerGet (operand *left,
6376 int size , offset = 0;
6377 aopOp(result,ic,TRUE, FALSE);
6379 /* get the string representation of the name */
6380 l = aopGet(AOP(left),0,FALSE,TRUE,FALSE);
6381 size = AOP_SIZE(result);
6384 sprintf(buffer,"(%s + %d)",l+1,offset);
6386 sprintf(buffer,"%s",l+1);
6387 aopPut(AOP(result),buffer,offset++);
6390 freeAsmop(left,NULL,ic,TRUE);
6391 freeAsmop(result,NULL,ic,TRUE);
6394 /*-----------------------------------------------------------------*/
6395 /* genNearPointerGet - emitcode for near pointer fetch */
6396 /*-----------------------------------------------------------------*/
6397 static void genNearPointerGet (operand *left,
6404 link *rtype, *retype;
6405 link *ltype = operandType(left);
6408 rtype = operandType(result);
6409 retype= getSpec(rtype);
6411 aopOp(left,ic,FALSE, FALSE);
6413 /* if left is rematerialisable and
6414 result is not bit variable type and
6415 the left is pointer to data space i.e
6416 lower 128 bytes of space */
6417 if (AOP_TYPE(left) == AOP_IMMD &&
6418 !IS_BITVAR(retype) &&
6419 DCL_TYPE(ltype) == POINTER) {
6420 genDataPointerGet (left,result,ic);
6424 /* if the value is already in a pointer register
6425 then don't need anything more */
6426 if (!AOP_INPREG(AOP(left))) {
6427 /* otherwise get a free pointer register */
6429 preg = getFreePtr(ic,&aop,FALSE);
6430 emitcode("mov","%s,%s",
6432 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6433 rname = preg->name ;
6435 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6437 freeAsmop(left,NULL,ic,TRUE);
6438 aopOp (result,ic,FALSE, FALSE);
6440 /* if bitfield then unpack the bits */
6441 if (IS_BITVAR(retype))
6442 genUnpackBits (result,rname,POINTER);
6444 /* we have can just get the values */
6445 int size = AOP_SIZE(result);
6449 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6451 emitcode("mov","a,@%s",rname);
6452 aopPut(AOP(result),"a",offset);
6454 sprintf(buffer,"@%s",rname);
6455 aopPut(AOP(result),buffer,offset);
6459 emitcode("inc","%s",rname);
6463 /* now some housekeeping stuff */
6465 /* we had to allocate for this iCode */
6466 freeAsmop(NULL,aop,ic,TRUE);
6468 /* we did not allocate which means left
6469 already in a pointer register, then
6470 if size > 0 && this could be used again
6471 we have to point it back to where it
6473 if (AOP_SIZE(result) > 1 &&
6474 !OP_SYMBOL(left)->remat &&
6475 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6477 int size = AOP_SIZE(result) - 1;
6479 emitcode("dec","%s",rname);
6484 freeAsmop(result,NULL,ic,TRUE);
6488 /*-----------------------------------------------------------------*/
6489 /* genPagedPointerGet - emitcode for paged pointer fetch */
6490 /*-----------------------------------------------------------------*/
6491 static void genPagedPointerGet (operand *left,
6498 link *rtype, *retype;
6500 rtype = operandType(result);
6501 retype= getSpec(rtype);
6503 aopOp(left,ic,FALSE, FALSE);
6505 /* if the value is already in a pointer register
6506 then don't need anything more */
6507 if (!AOP_INPREG(AOP(left))) {
6508 /* otherwise get a free pointer register */
6510 preg = getFreePtr(ic,&aop,FALSE);
6511 emitcode("mov","%s,%s",
6513 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6514 rname = preg->name ;
6516 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6518 freeAsmop(left,NULL,ic,TRUE);
6519 aopOp (result,ic,FALSE, FALSE);
6521 /* if bitfield then unpack the bits */
6522 if (IS_BITVAR(retype))
6523 genUnpackBits (result,rname,PPOINTER);
6525 /* we have can just get the values */
6526 int size = AOP_SIZE(result);
6531 emitcode("movx","a,@%s",rname);
6532 aopPut(AOP(result),"a",offset);
6537 emitcode("inc","%s",rname);
6541 /* now some housekeeping stuff */
6543 /* we had to allocate for this iCode */
6544 freeAsmop(NULL,aop,ic,TRUE);
6546 /* we did not allocate which means left
6547 already in a pointer register, then
6548 if size > 0 && this could be used again
6549 we have to point it back to where it
6551 if (AOP_SIZE(result) > 1 &&
6552 !OP_SYMBOL(left)->remat &&
6553 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6555 int size = AOP_SIZE(result) - 1;
6557 emitcode("dec","%s",rname);
6562 freeAsmop(result,NULL,ic,TRUE);
6567 /*-----------------------------------------------------------------*/
6568 /* genFarPointerGet - gget value from far space */
6569 /*-----------------------------------------------------------------*/
6570 static void genFarPointerGet (operand *left,
6571 operand *result, iCode *ic)
6574 link *retype = getSpec(operandType(result));
6576 D(emitcode(";", "genFarPointerGet"););
6578 aopOp(left,ic,FALSE, FALSE);
6580 /* if the operand is already in dptr
6581 then we do nothing else we move the value to dptr */
6582 if (AOP_TYPE(left) != AOP_STR) {
6583 /* if this is remateriazable */
6584 if (AOP_TYPE(left) == AOP_IMMD)
6586 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6590 /* we need to get it byte by byte */
6591 if (AOP_TYPE(left) != AOP_DPTR)
6593 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6594 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6595 if (options.model == MODEL_FLAT24)
6597 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6602 /* We need to generate a load to DPTR indirect through DPTR. */
6603 D(emitcode(";", "genFarPointerGet -- indirection special case."););
6604 emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE,TRUE));
6605 emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE,TRUE));
6606 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6607 emitcode("pop", "dph");
6608 emitcode("pop", "dpl");
6612 /* so dptr know contains the address */
6613 freeAsmop(left,NULL,ic,TRUE);
6614 aopOp(result,ic,FALSE, TRUE);
6616 /* if bit then unpack */
6617 if (IS_BITVAR(retype))
6618 genUnpackBits(result,"dptr",FPOINTER);
6620 size = AOP_SIZE(result);
6624 emitcode("movx","a,@dptr");
6625 aopPut(AOP(result),"a",offset++);
6627 emitcode("inc","dptr");
6631 freeAsmop(result,NULL,ic,TRUE);
6634 /*-----------------------------------------------------------------*/
6635 /* emitcodePointerGet - gget value from code space */
6636 /*-----------------------------------------------------------------*/
6637 static void emitcodePointerGet (operand *left,
6638 operand *result, iCode *ic)
6641 link *retype = getSpec(operandType(result));
6643 aopOp(left,ic,FALSE, FALSE);
6645 /* if the operand is already in dptr
6646 then we do nothing else we move the value to dptr */
6647 if (AOP_TYPE(left) != AOP_STR) {
6648 /* if this is remateriazable */
6649 if (AOP_TYPE(left) == AOP_IMMD)
6650 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6651 else { /* we need to get it byte by byte */
6652 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6653 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6654 if (options.model == MODEL_FLAT24)
6656 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6660 /* so dptr know contains the address */
6661 freeAsmop(left,NULL,ic,TRUE);
6662 aopOp(result,ic,FALSE, FALSE);
6664 /* if bit then unpack */
6665 if (IS_BITVAR(retype))
6666 genUnpackBits(result,"dptr",CPOINTER);
6668 size = AOP_SIZE(result);
6672 emitcode("clr","a");
6673 emitcode("movc","a,@a+dptr");
6674 aopPut(AOP(result),"a",offset++);
6676 emitcode("inc","dptr");
6680 freeAsmop(result,NULL,ic,TRUE);
6683 /*-----------------------------------------------------------------*/
6684 /* genGenPointerGet - gget value from generic pointer space */
6685 /*-----------------------------------------------------------------*/
6686 static void genGenPointerGet (operand *left,
6687 operand *result, iCode *ic)
6690 link *retype = getSpec(operandType(result));
6692 aopOp(left,ic,FALSE, TRUE);
6694 /* if the operand is already in dptr
6695 then we do nothing else we move the value to dptr */
6696 if (AOP_TYPE(left) != AOP_STR) {
6697 /* if this is remateriazable */
6698 if (AOP_TYPE(left) == AOP_IMMD) {
6699 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6700 emitcode("mov","b,#%d",pointerCode(retype));
6702 else { /* we need to get it byte by byte */
6703 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6704 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6705 if (options.model == MODEL_FLAT24)
6707 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6708 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE,TRUE));
6712 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6716 /* so dptr know contains the address */
6717 freeAsmop(left,NULL,ic,TRUE);
6718 aopOp(result,ic,FALSE, TRUE);
6720 /* if bit then unpack */
6721 if (IS_BITVAR(retype))
6722 genUnpackBits(result,"dptr",GPOINTER);
6724 size = AOP_SIZE(result);
6728 emitcode("lcall","__gptrget");
6729 aopPut(AOP(result),"a",offset++);
6731 emitcode("inc","dptr");
6735 freeAsmop(result,NULL,ic,TRUE);
6738 /*-----------------------------------------------------------------*/
6739 /* genPointerGet - generate code for pointer get */
6740 /*-----------------------------------------------------------------*/
6741 static void genPointerGet (iCode *ic)
6743 operand *left, *result ;
6747 D(emitcode(";", "genPointerGet "););
6750 result = IC_RESULT(ic) ;
6752 /* depending on the type of pointer we need to
6753 move it to the correct pointer register */
6754 type = operandType(left);
6755 etype = getSpec(type);
6756 /* if left is of type of pointer then it is simple */
6757 if (IS_PTR(type) && !IS_FUNC(type->next))
6758 p_type = DCL_TYPE(type);
6760 /* we have to go by the storage class */
6761 p_type = PTR_TYPE(SPEC_OCLS(etype));
6763 /* if (SPEC_OCLS(etype)->codesp ) { */
6764 /* p_type = CPOINTER ; */
6767 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6768 /* p_type = FPOINTER ; */
6770 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6771 /* p_type = PPOINTER; */
6773 /* if (SPEC_OCLS(etype) == idata ) */
6774 /* p_type = IPOINTER; */
6776 /* p_type = POINTER ; */
6779 /* now that we have the pointer type we assign
6780 the pointer values */
6785 genNearPointerGet (left,result,ic);
6789 genPagedPointerGet(left,result,ic);
6793 genFarPointerGet (left,result,ic);
6797 emitcodePointerGet (left,result,ic);
6801 genGenPointerGet (left,result,ic);
6807 /*-----------------------------------------------------------------*/
6808 /* genPackBits - generates code for packed bit storage */
6809 /*-----------------------------------------------------------------*/
6810 static void genPackBits (link *etype ,
6812 char *rname, int p_type)
6820 blen = SPEC_BLEN(etype);
6821 bstr = SPEC_BSTR(etype);
6823 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
6826 /* if the bit lenth is less than or */
6827 /* it exactly fits a byte then */
6828 if (SPEC_BLEN(etype) <= 8 ) {
6829 shCount = SPEC_BSTR(etype) ;
6831 /* shift left acc */
6834 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6839 emitcode ("mov","b,a");
6840 emitcode("mov","a,@%s",rname);
6844 emitcode ("mov","b,a");
6845 emitcode("movx","a,@dptr");
6849 emitcode ("push","b");
6850 emitcode ("push","acc");
6851 emitcode ("lcall","__gptrget");
6852 emitcode ("pop","b");
6856 emitcode ("anl","a,#0x%02x",(unsigned char)
6857 ((unsigned char)(0xFF << (blen+bstr)) |
6858 (unsigned char)(0xFF >> (8-bstr)) ) );
6859 emitcode ("orl","a,b");
6860 if (p_type == GPOINTER)
6861 emitcode("pop","b");
6867 emitcode("mov","@%s,a",rname);
6871 emitcode("movx","@dptr,a");
6875 emitcode("lcall","__gptrput");
6880 if ( SPEC_BLEN(etype) <= 8 )
6883 emitcode("inc","%s",rname);
6884 rLen = SPEC_BLEN(etype) ;
6886 /* now generate for lengths greater than one byte */
6889 l = aopGet(AOP(right),offset++,FALSE,TRUE,FALSE);
6899 emitcode("mov","@%s,a",rname);
6901 emitcode("mov","@%s,%s",rname,l);
6906 emitcode("movx","@dptr,a");
6911 emitcode("lcall","__gptrput");
6914 emitcode ("inc","%s",rname);
6919 /* last last was not complete */
6921 /* save the byte & read byte */
6924 emitcode ("mov","b,a");
6925 emitcode("mov","a,@%s",rname);
6929 emitcode ("mov","b,a");
6930 emitcode("movx","a,@dptr");
6934 emitcode ("push","b");
6935 emitcode ("push","acc");
6936 emitcode ("lcall","__gptrget");
6937 emitcode ("pop","b");
6941 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
6942 emitcode ("orl","a,b");
6945 if (p_type == GPOINTER)
6946 emitcode("pop","b");
6951 emitcode("mov","@%s,a",rname);
6955 emitcode("movx","@dptr,a");
6959 emitcode("lcall","__gptrput");
6963 /*-----------------------------------------------------------------*/
6964 /* genDataPointerSet - remat pointer to data space */
6965 /*-----------------------------------------------------------------*/
6966 static void genDataPointerSet(operand *right,
6970 int size, offset = 0 ;
6971 char *l, buffer[256];
6973 aopOp(right,ic,FALSE, FALSE);
6975 l = aopGet(AOP(result),0,FALSE,TRUE,FALSE);
6976 size = AOP_SIZE(right);
6979 sprintf(buffer,"(%s + %d)",l+1,offset);
6981 sprintf(buffer,"%s",l+1);
6982 emitcode("mov","%s,%s",buffer,
6983 aopGet(AOP(right),offset++,FALSE,FALSE,FALSE));
6986 freeAsmop(right,NULL,ic,TRUE);
6987 freeAsmop(result,NULL,ic,TRUE);
6990 /*-----------------------------------------------------------------*/
6991 /* genNearPointerSet - emitcode for near pointer put */
6992 /*-----------------------------------------------------------------*/
6993 static void genNearPointerSet (operand *right,
7001 link *ptype = operandType(result);
7003 retype= getSpec(operandType(right));
7005 aopOp(result,ic,FALSE, FALSE);
7007 /* if the result is rematerializable &
7008 in data space & not a bit variable */
7009 if (AOP_TYPE(result) == AOP_IMMD &&
7010 DCL_TYPE(ptype) == POINTER &&
7011 !IS_BITVAR(retype)) {
7012 genDataPointerSet (right,result,ic);
7016 /* if the value is already in a pointer register
7017 then don't need anything more */
7018 if (!AOP_INPREG(AOP(result))) {
7019 /* otherwise get a free pointer register */
7021 preg = getFreePtr(ic,&aop,FALSE);
7022 emitcode("mov","%s,%s",
7024 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7025 rname = preg->name ;
7027 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7029 freeAsmop(result,NULL,ic,TRUE);
7030 aopOp (right,ic,FALSE, FALSE);
7032 /* if bitfield then unpack the bits */
7033 if (IS_BITVAR(retype))
7034 genPackBits (retype,right,rname,POINTER);
7036 /* we have can just get the values */
7037 int size = AOP_SIZE(right);
7041 l = aopGet(AOP(right),offset,FALSE,TRUE,FALSE);
7044 emitcode("mov","@%s,a",rname);
7046 emitcode("mov","@%s,%s",rname,l);
7048 emitcode("inc","%s",rname);
7053 /* now some housekeeping stuff */
7055 /* we had to allocate for this iCode */
7056 freeAsmop(NULL,aop,ic,TRUE);
7058 /* we did not allocate which means left
7059 already in a pointer register, then
7060 if size > 0 && this could be used again
7061 we have to point it back to where it
7063 if (AOP_SIZE(right) > 1 &&
7064 !OP_SYMBOL(result)->remat &&
7065 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7067 int size = AOP_SIZE(right) - 1;
7069 emitcode("dec","%s",rname);
7074 freeAsmop(right,NULL,ic,TRUE);
7079 /*-----------------------------------------------------------------*/
7080 /* genPagedPointerSet - emitcode for Paged pointer put */
7081 /*-----------------------------------------------------------------*/
7082 static void genPagedPointerSet (operand *right,
7091 retype= getSpec(operandType(right));
7093 aopOp(result,ic,FALSE, FALSE);
7095 /* if the value is already in a pointer register
7096 then don't need anything more */
7097 if (!AOP_INPREG(AOP(result))) {
7098 /* otherwise get a free pointer register */
7100 preg = getFreePtr(ic,&aop,FALSE);
7101 emitcode("mov","%s,%s",
7103 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7104 rname = preg->name ;
7106 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7108 freeAsmop(result,NULL,ic,TRUE);
7109 aopOp (right,ic,FALSE, FALSE);
7111 /* if bitfield then unpack the bits */
7112 if (IS_BITVAR(retype))
7113 genPackBits (retype,right,rname,PPOINTER);
7115 /* we have can just get the values */
7116 int size = AOP_SIZE(right);
7120 l = aopGet(AOP(right),offset,FALSE,TRUE,TRUE);
7123 emitcode("movx","@%s,a",rname);
7126 emitcode("inc","%s",rname);
7132 /* now some housekeeping stuff */
7134 /* we had to allocate for this iCode */
7135 freeAsmop(NULL,aop,ic,TRUE);
7137 /* we did not allocate which means left
7138 already in a pointer register, then
7139 if size > 0 && this could be used again
7140 we have to point it back to where it
7142 if (AOP_SIZE(right) > 1 &&
7143 !OP_SYMBOL(result)->remat &&
7144 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7146 int size = AOP_SIZE(right) - 1;
7148 emitcode("dec","%s",rname);
7153 freeAsmop(right,NULL,ic,TRUE);
7158 /*-----------------------------------------------------------------*/
7159 /* genFarPointerSet - set value from far space */
7160 /*-----------------------------------------------------------------*/
7161 static void genFarPointerSet (operand *right,
7162 operand *result, iCode *ic)
7165 link *retype = getSpec(operandType(right));
7167 aopOp(result,ic,FALSE, FALSE);
7169 /* if the operand is already in dptr
7170 then we do nothing else we move the value to dptr */
7171 if (AOP_TYPE(result) != AOP_STR) {
7172 /* if this is remateriazable */
7173 if (AOP_TYPE(result) == AOP_IMMD)
7174 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7177 /* we need to get it byte by byte */
7178 if (AOP_TYPE(result) != AOP_DPTR)
7180 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7181 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7182 if (options.model == MODEL_FLAT24)
7184 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7189 /* We need to generate a load to DPTR indirect through DPTR. */
7190 D(emitcode(";", "genFarPointerSet -- indirection special case."););
7191 emitcode("push", "%s", aopGet(AOP(result),0,FALSE,TRUE,TRUE));
7192 emitcode("push", "%s", aopGet(AOP(result),1,FALSE,TRUE,TRUE));
7193 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7194 emitcode("pop", "dph");
7195 emitcode("pop", "dpl");
7199 /* so dptr know contains the address */
7200 freeAsmop(result,NULL,ic,TRUE);
7201 aopOp(right,ic,FALSE, TRUE);
7203 /* if bit then unpack */
7204 if (IS_BITVAR(retype))
7205 genPackBits(retype,right,"dptr",FPOINTER);
7207 size = AOP_SIZE(right);
7211 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7213 emitcode("movx","@dptr,a");
7215 emitcode("inc","dptr");
7219 freeAsmop(right,NULL,ic,TRUE);
7222 /*-----------------------------------------------------------------*/
7223 /* genGenPointerSet - set value from generic pointer space */
7224 /*-----------------------------------------------------------------*/
7225 static void genGenPointerSet (operand *right,
7226 operand *result, iCode *ic)
7229 link *retype = getSpec(operandType(right));
7231 aopOp(result,ic,FALSE, TRUE);
7233 /* if the operand is already in dptr
7234 then we do nothing else we move the value to dptr */
7235 if (AOP_TYPE(result) != AOP_STR) {
7236 /* if this is remateriazable */
7237 if (AOP_TYPE(result) == AOP_IMMD) {
7238 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7239 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7241 else { /* we need to get it byte by byte */
7242 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7243 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7244 if (options.model == MODEL_FLAT24)
7246 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7247 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE,TRUE));
7251 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7255 /* so dptr know contains the address */
7256 freeAsmop(result,NULL,ic,TRUE);
7257 aopOp(right,ic,FALSE, TRUE);
7259 /* if bit then unpack */
7260 if (IS_BITVAR(retype))
7261 genPackBits(retype,right,"dptr",GPOINTER);
7263 size = AOP_SIZE(right);
7267 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7269 emitcode("lcall","__gptrput");
7271 emitcode("inc","dptr");
7275 freeAsmop(right,NULL,ic,TRUE);
7278 /*-----------------------------------------------------------------*/
7279 /* genPointerSet - stores the value into a pointer location */
7280 /*-----------------------------------------------------------------*/
7281 static void genPointerSet (iCode *ic)
7283 operand *right, *result ;
7287 D(emitcode(";", "genPointerSet "););
7289 right = IC_RIGHT(ic);
7290 result = IC_RESULT(ic) ;
7292 /* depending on the type of pointer we need to
7293 move it to the correct pointer register */
7294 type = operandType(result);
7295 etype = getSpec(type);
7296 /* if left is of type of pointer then it is simple */
7297 if (IS_PTR(type) && !IS_FUNC(type->next)) {
7298 p_type = DCL_TYPE(type);
7301 /* we have to go by the storage class */
7302 p_type = PTR_TYPE(SPEC_OCLS(etype));
7304 /* if (SPEC_OCLS(etype)->codesp ) { */
7305 /* p_type = CPOINTER ; */
7308 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7309 /* p_type = FPOINTER ; */
7311 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7312 /* p_type = PPOINTER ; */
7314 /* if (SPEC_OCLS(etype) == idata ) */
7315 /* p_type = IPOINTER ; */
7317 /* p_type = POINTER ; */
7320 /* now that we have the pointer type we assign
7321 the pointer values */
7326 genNearPointerSet (right,result,ic);
7330 genPagedPointerSet (right,result,ic);
7334 genFarPointerSet (right,result,ic);
7338 genGenPointerSet (right,result,ic);
7344 /*-----------------------------------------------------------------*/
7345 /* genIfx - generate code for Ifx statement */
7346 /*-----------------------------------------------------------------*/
7347 static void genIfx (iCode *ic, iCode *popIc)
7349 operand *cond = IC_COND(ic);
7352 D(emitcode(";", "genIfx "););
7354 aopOp(cond,ic,FALSE, FALSE);
7356 /* get the value into acc */
7357 if (AOP_TYPE(cond) != AOP_CRY)
7361 /* the result is now in the accumulator */
7362 freeAsmop(cond,NULL,ic,TRUE);
7364 /* if there was something to be popped then do it */
7368 /* if the condition is a bit variable */
7369 if (isbit && IS_ITEMP(cond) &&
7371 genIfxJump(ic,SPIL_LOC(cond)->rname);
7373 if (isbit && !IS_ITEMP(cond))
7374 genIfxJump(ic,OP_SYMBOL(cond)->rname);
7381 /*-----------------------------------------------------------------*/
7382 /* genAddrOf - generates code for address of */
7383 /*-----------------------------------------------------------------*/
7384 static void genAddrOf (iCode *ic)
7386 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7389 D(emitcode(";", "genAddrOf "););
7391 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7393 /* if the operand is on the stack then we
7394 need to get the stack offset of this
7397 /* if it has an offset then we need to compute
7400 emitcode("mov","a,_bp");
7401 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7402 aopPut(AOP(IC_RESULT(ic)),"a",0);
7404 /* we can just move _bp */
7405 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7407 /* fill the result with zero */
7408 size = AOP_SIZE(IC_RESULT(ic)) - 1;
7411 if (options.stack10bit && size < (FPTRSIZE - 1))
7414 "*** warning: pointer to stack var truncated.\n");
7421 if (options.stack10bit && offset == 2)
7423 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7427 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7434 /* object not on stack then we need the name */
7435 size = AOP_SIZE(IC_RESULT(ic));
7439 char s[SDCC_NAME_MAX];
7441 sprintf(s,"#(%s >> %d)",
7445 sprintf(s,"#%s",sym->rname);
7446 aopPut(AOP(IC_RESULT(ic)),s,offset++);
7450 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7454 /*-----------------------------------------------------------------*/
7455 /* genFarFarAssign - assignment when both are in far space */
7456 /*-----------------------------------------------------------------*/
7457 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7459 int size = AOP_SIZE(right);
7462 /* first push the right side on to the stack */
7464 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7466 emitcode ("push","acc");
7469 D(emitcode(";", "genFarFarAssign "););
7471 freeAsmop(right,NULL,ic,FALSE);
7472 /* now assign DPTR to result */
7473 aopOp(result,ic,FALSE, FALSE);
7474 size = AOP_SIZE(result);
7476 emitcode ("pop","acc");
7477 aopPut(AOP(result),"a",--offset);
7479 freeAsmop(result,NULL,ic,FALSE);
7483 /*-----------------------------------------------------------------*/
7484 /* genAssign - generate code for assignment */
7485 /*-----------------------------------------------------------------*/
7486 static void genAssign (iCode *ic)
7488 operand *result, *right;
7490 unsigned long lit = 0L;
7492 D(emitcode(";", "genAssign "););
7494 result = IC_RESULT(ic);
7495 right = IC_RIGHT(ic) ;
7497 /* if they are the same */
7498 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7501 aopOp(right,ic,FALSE, FALSE);
7503 emitcode(";", "genAssign: resultIsFar = %s",
7504 isOperandInFarSpace(result) ?
7507 /* special case both in far space */
7508 if ((AOP_TYPE(right) == AOP_DPTR ||
7509 AOP_TYPE(right) == AOP_DPTR2) &&
7510 /* IS_TRUE_SYMOP(result) && */
7511 isOperandInFarSpace(result)) {
7513 genFarFarAssign (result,right,ic);
7517 aopOp(result,ic,TRUE, FALSE);
7519 /* if they are the same registers */
7520 if (sameRegs(AOP(right),AOP(result)))
7523 /* if the result is a bit */
7524 if (AOP_TYPE(result) == AOP_CRY) {
7526 /* if the right size is a literal then
7527 we know what the value is */
7528 if (AOP_TYPE(right) == AOP_LIT) {
7529 if (((int) operandLitValue(right)))
7530 aopPut(AOP(result),one,0);
7532 aopPut(AOP(result),zero,0);
7536 /* the right is also a bit variable */
7537 if (AOP_TYPE(right) == AOP_CRY) {
7538 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7539 aopPut(AOP(result),"c",0);
7545 aopPut(AOP(result),"a",0);
7549 /* bit variables done */
7551 size = AOP_SIZE(result);
7553 if(AOP_TYPE(right) == AOP_LIT)
7554 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7556 (AOP_TYPE(result) != AOP_REG) &&
7557 (AOP_TYPE(right) == AOP_LIT) &&
7558 !IS_FLOAT(operandType(right)) &&
7560 emitcode("clr","a");
7562 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7563 aopPut(AOP(result),"a",size);
7566 aopGet(AOP(right),size,FALSE,FALSE,FALSE),
7572 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7579 freeAsmop (right,NULL,ic,FALSE);
7580 freeAsmop (result,NULL,ic,TRUE);
7583 /*-----------------------------------------------------------------*/
7584 /* genJumpTab - genrates code for jump table */
7585 /*-----------------------------------------------------------------*/
7586 static void genJumpTab (iCode *ic)
7591 D(emitcode(";", "genJumpTab "););
7593 aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
7594 /* get the condition into accumulator */
7595 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE,TRUE);
7597 /* multiply by four! */
7598 emitcode("add","a,acc");
7599 emitcode("add","a,acc");
7600 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7602 jtab = newiTempLabel(NULL);
7603 emitcode("mov","dptr,#%05d$",jtab->key+100);
7604 emitcode("jmp","@a+dptr");
7605 emitcode("","%05d$:",jtab->key+100);
7606 /* now generate the jump labels */
7607 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
7608 jtab = setNextItem(IC_JTLABELS(ic)))
7609 emitcode("ljmp","%05d$",jtab->key+100);
7613 /*-----------------------------------------------------------------*/
7614 /* genCast - gen code for casting */
7615 /*-----------------------------------------------------------------*/
7616 static void genCast (iCode *ic)
7618 operand *result = IC_RESULT(ic);
7619 link *ctype = operandType(IC_LEFT(ic));
7620 link *rtype = operandType(IC_RIGHT(ic));
7621 operand *right = IC_RIGHT(ic);
7624 D(emitcode(";", "genCast "););
7626 /* if they are equivalent then do nothing */
7627 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
7630 aopOp(right,ic,FALSE, FALSE) ;
7631 aopOp(result,ic,FALSE, AOP_TYPE(right) == AOP_DPTR);
7633 /* if the result is a bit */
7634 if (AOP_TYPE(result) == AOP_CRY) {
7635 /* if the right size is a literal then
7636 we know what the value is */
7637 if (AOP_TYPE(right) == AOP_LIT) {
7638 if (((int) operandLitValue(right)))
7639 aopPut(AOP(result),one,0);
7641 aopPut(AOP(result),zero,0);
7646 /* the right is also a bit variable */
7647 if (AOP_TYPE(right) == AOP_CRY) {
7648 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7649 aopPut(AOP(result),"c",0);
7655 aopPut(AOP(result),"a",0);
7659 /* if they are the same size : or less */
7660 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
7662 /* if they are in the same place */
7663 if (sameRegs(AOP(right),AOP(result)))
7666 /* if they in different places then copy */
7667 size = AOP_SIZE(result);
7671 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7679 /* if the result is of type pointer */
7680 if (IS_PTR(ctype)) {
7683 link *type = operandType(right);
7684 link *etype = getSpec(type);
7686 /* pointer to generic pointer */
7687 if (IS_GENPTR(ctype)) {
7691 p_type = DCL_TYPE(type);
7693 /* we have to go by the storage class */
7694 p_type = PTR_TYPE(SPEC_OCLS(etype));
7697 /* the first two bytes are known */
7698 size = GPTRSIZE - 1;
7702 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7706 /* the last byte depending on type */
7723 /* this should never happen */
7724 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7725 "got unknown pointer type");
7728 aopPut(AOP(result),l, GPTRSIZE - 1);
7732 /* just copy the pointers */
7733 size = AOP_SIZE(result);
7737 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7744 /* so we now know that the size of destination is greater
7745 than the size of the source */
7746 /* we move to result for the size of source */
7747 size = AOP_SIZE(right);
7751 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7756 /* now depending on the sign of the source && destination */
7757 size = AOP_SIZE(result) - AOP_SIZE(right);
7758 /* if unsigned or not an integral type */
7759 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
7761 aopPut(AOP(result),zero,offset++);
7763 /* we need to extend the sign :{ */
7764 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
7767 emitcode("rlc","a");
7768 emitcode("subb","a,acc");
7770 aopPut(AOP(result),"a",offset++);
7773 /* we are done hurray !!!! */
7776 freeAsmop(right,NULL,ic,TRUE);
7777 freeAsmop(result,NULL,ic,TRUE);
7781 /*-----------------------------------------------------------------*/
7782 /* genDjnz - generate decrement & jump if not zero instrucion */
7783 /*-----------------------------------------------------------------*/
7784 static int genDjnz (iCode *ic, iCode *ifx)
7790 /* if the if condition has a false label
7791 then we cannot save */
7795 /* if the minus is not of the form
7797 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
7798 !IS_OP_LITERAL(IC_RIGHT(ic)))
7801 if (operandLitValue(IC_RIGHT(ic)) != 1)
7804 /* if the size of this greater than one then no
7806 if (getSize(operandType(IC_RESULT(ic))) > 1)
7809 /* otherwise we can save BIG */
7810 lbl = newiTempLabel(NULL);
7811 lbl1= newiTempLabel(NULL);
7813 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7815 if (IS_AOP_PREG(IC_RESULT(ic))) {
7816 emitcode("dec","%s",
7817 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
7818 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
7819 emitcode("jnz","%05d$",lbl->key+100);
7821 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE),
7824 emitcode ("sjmp","%05d$",lbl1->key+100);
7825 emitcode ("","%05d$:",lbl->key+100);
7826 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
7827 emitcode ("","%05d$:",lbl1->key+100);
7829 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7834 /*-----------------------------------------------------------------*/
7835 /* genReceive - generate code for a receive iCode */
7836 /*-----------------------------------------------------------------*/
7837 static void genReceive (iCode *ic)
7840 D(emitcode(";", "genReceive "););
7842 if (isOperandInFarSpace(IC_RESULT(ic)) &&
7843 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
7844 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
7845 int size = getSize(operandType(IC_RESULT(ic)));
7846 int offset = fReturnSize_390 - size;
7848 emitcode ("push","%s", (strcmp(fReturn[fReturnSize_390 - offset - 1],"a") ?
7849 fReturn[fReturnSize_390 - offset - 1] : "acc"));
7852 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7853 size = AOP_SIZE(IC_RESULT(ic));
7856 emitcode ("pop","acc");
7857 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
7862 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7864 assignResultValue(IC_RESULT(ic));
7867 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7870 /*-----------------------------------------------------------------*/
7871 /* gen390Code - generate code for 8051 based controllers */
7872 /*-----------------------------------------------------------------*/
7873 void gen390Code (iCode *lic)
7878 lineHead = lineCurr = NULL;
7880 /* print the allocation information */
7882 printAllocInfo( currFunc, codeOutFile);
7883 /* if debug information required */
7884 /* if (options.debug && currFunc) { */
7886 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
7888 if (IS_STATIC(currFunc->etype))
7889 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
7891 emitcode("","G$%s$0$0 ==.",currFunc->name);
7894 /* stack pointer name */
7895 if (options.useXstack)
7901 for (ic = lic ; ic ; ic = ic->next ) {
7903 if ( cln != ic->lineno ) {
7904 if ( options.debug ) {
7906 emitcode("","C$%s$%d$%d$%d ==.",
7907 ic->filename,ic->lineno,
7908 ic->level,ic->block);
7911 emitcode(";","%s %d",ic->filename,ic->lineno);
7914 /* if the result is marked as
7915 spilt and rematerializable or code for
7916 this has already been generated then
7918 if (resultRemat(ic) || ic->generated )
7921 /* depending on the operation */
7940 /* IPOP happens only when trying to restore a
7941 spilt live range, if there is an ifx statement
7942 following this pop then the if statement might
7943 be using some of the registers being popped which
7944 would destory the contents of the register so
7945 we need to check for this condition and handle it */
7947 ic->next->op == IFX &&
7948 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
7949 genIfx (ic->next,ic);
7967 genEndFunction (ic);
7987 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8004 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
8008 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8015 /* note these two are xlated by algebraic equivalence
8016 during parsing SDCC.y */
8017 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8018 "got '>=' or '<=' shouldn't have come here");
8022 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8034 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8038 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8042 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8069 case GET_VALUE_AT_ADDRESS:
8074 if (POINTER_SET(ic))
8101 addSet(&_G.sendSet,ic);
8106 /* piCode(ic,stdout); */
8112 /* now we are ready to call the
8113 peep hole optimizer */
8114 if (!options.nopeep)
8115 peepHole (&lineHead);
8117 /* now do the actual printing */
8118 printLine (lineHead,codeOutFile);