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 <= 5 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 <= 5 )
2604 emitcode(";", "tail increment optimized (range %d)", labelRange);
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 <= 5 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 <= 5 )
2939 emitcode(";", "tail decrement optimized (range %d)", labelRange);
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));
3148 /* If the pushed data is bigger than the result,
3149 * simply discard unused bytes. Icky, but works.
3151 * Should we throw a warning here? We're losing data...
3153 while (size > getDataSize(IC_RESULT(ic)))
3155 emitcode(";", "discarding unused result byte.");
3156 emitcode("pop", "acc");
3163 emitcode("pop", "acc");
3164 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3168 adjustArithmeticResult(ic);
3171 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3172 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3173 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3177 /*-----------------------------------------------------------------*/
3178 /* genMultbits :- multiplication of bits */
3179 /*-----------------------------------------------------------------*/
3180 static void genMultbits (operand *left,
3184 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3185 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3190 /*-----------------------------------------------------------------*/
3191 /* genMultOneByte : 8 bit multiplication & division */
3192 /*-----------------------------------------------------------------*/
3193 static void genMultOneByte (operand *left,
3197 link *opetype = operandType(result);
3202 /* (if two literals, the value is computed before) */
3203 /* if one literal, literal on the right */
3204 if (AOP_TYPE(left) == AOP_LIT){
3210 size = AOP_SIZE(result);
3211 /* signed or unsigned */
3212 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3213 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3215 emitcode("mul","ab");
3216 /* if result size = 1, mul signed = mul unsigned */
3217 aopPut(AOP(result),"a",0);
3219 if (SPEC_USIGN(opetype)){
3220 aopPut(AOP(result),"b",1);
3222 /* for filling the MSBs */
3223 emitcode("clr","a");
3226 emitcode("mov","a,b");
3228 /* adjust the MSB if left or right neg */
3230 /* if one literal */
3231 if (AOP_TYPE(right) == AOP_LIT){
3232 /* AND literal negative */
3233 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3234 /* adjust MSB (c==0 after mul) */
3235 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3239 lbl = newiTempLabel(NULL);
3240 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3241 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3242 emitcode("","%05d$:",(lbl->key+100));
3243 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3244 lbl = newiTempLabel(NULL);
3245 emitcode("jc","%05d$",(lbl->key+100));
3246 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3247 emitcode("","%05d$:",(lbl->key+100));
3250 lbl = newiTempLabel(NULL);
3251 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3252 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3253 emitcode("","%05d$:",(lbl->key+100));
3254 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3255 lbl = newiTempLabel(NULL);
3256 emitcode("jc","%05d$",(lbl->key+100));
3257 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3258 emitcode("","%05d$:",(lbl->key+100));
3260 aopPut(AOP(result),"a",1);
3263 emitcode("rlc","a");
3264 emitcode("subb","a,acc");
3271 aopPut(AOP(result),"a",offset++);
3275 /*-----------------------------------------------------------------*/
3276 /* genMult - generates code for multiplication */
3277 /*-----------------------------------------------------------------*/
3278 static void genMult (iCode *ic)
3280 operand *left = IC_LEFT(ic);
3281 operand *right = IC_RIGHT(ic);
3282 operand *result= IC_RESULT(ic);
3284 D(emitcode(";", "genMult "););
3286 /* assign the amsops */
3289 aopOp (left,ic,FALSE, FALSE);
3290 aopOp (right,ic,FALSE, TRUE);
3291 aopOp (result,ic,TRUE, FALSE);
3294 /* special cases first */
3296 if (AOP_TYPE(left) == AOP_CRY &&
3297 AOP_TYPE(right)== AOP_CRY) {
3298 genMultbits(left,right,result);
3302 /* if both are of size == 1 */
3303 if (AOP_SIZE(left) == 1 &&
3304 AOP_SIZE(right) == 1 ) {
3305 genMultOneByte(left,right,result);
3309 /* should have been converted to function call */
3313 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3314 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3315 freeAsmop(result,NULL,ic,TRUE);
3318 /*-----------------------------------------------------------------*/
3319 /* genDivbits :- division of bits */
3320 /*-----------------------------------------------------------------*/
3321 static void genDivbits (operand *left,
3328 /* the result must be bit */
3329 LOAD_AB_FOR_DIV(left, right, l);
3330 emitcode("div","ab");
3331 emitcode("rrc","a");
3332 aopPut(AOP(result),"c",0);
3335 /*-----------------------------------------------------------------*/
3336 /* genDivOneByte : 8 bit division */
3337 /*-----------------------------------------------------------------*/
3338 static void genDivOneByte (operand *left,
3342 link *opetype = operandType(result);
3347 size = AOP_SIZE(result) - 1;
3349 /* signed or unsigned */
3350 if (SPEC_USIGN(opetype)) {
3351 /* unsigned is easy */
3352 LOAD_AB_FOR_DIV(left, right, l);
3353 emitcode("div","ab");
3354 aopPut(AOP(result),"a",0);
3356 aopPut(AOP(result),zero,offset++);
3360 /* signed is a little bit more difficult */
3362 /* save the signs of the operands */
3363 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3365 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE,FALSE));
3366 emitcode("push","acc"); /* save it on the stack */
3368 /* now sign adjust for both left & right */
3369 l = aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3371 lbl = newiTempLabel(NULL);
3372 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3373 emitcode("cpl","a");
3374 emitcode("inc","a");
3375 emitcode("","%05d$:",(lbl->key+100));
3376 emitcode("mov","b,a");
3378 /* sign adjust left side */
3379 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3382 lbl = newiTempLabel(NULL);
3383 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3384 emitcode("cpl","a");
3385 emitcode("inc","a");
3386 emitcode("","%05d$:",(lbl->key+100));
3388 /* now the division */
3389 emitcode("nop", "; workaround for DS80C390 div bug.");
3390 emitcode("div","ab");
3391 /* we are interested in the lower order
3393 emitcode("mov","b,a");
3394 lbl = newiTempLabel(NULL);
3395 emitcode("pop","acc");
3396 /* if there was an over flow we don't
3397 adjust the sign of the result */
3398 emitcode("jb","ov,%05d$",(lbl->key+100));
3399 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3401 emitcode("clr","a");
3402 emitcode("subb","a,b");
3403 emitcode("mov","b,a");
3404 emitcode("","%05d$:",(lbl->key+100));
3406 /* now we are done */
3407 aopPut(AOP(result),"b",0);
3409 emitcode("mov","c,b.7");
3410 emitcode("subb","a,acc");
3413 aopPut(AOP(result),"a",offset++);
3417 /*-----------------------------------------------------------------*/
3418 /* genDiv - generates code for division */
3419 /*-----------------------------------------------------------------*/
3420 static void genDiv (iCode *ic)
3422 operand *left = IC_LEFT(ic);
3423 operand *right = IC_RIGHT(ic);
3424 operand *result= IC_RESULT(ic);
3426 D(emitcode(";", "genDiv "););
3428 /* assign the amsops */
3431 aopOp (left,ic,FALSE, FALSE);
3432 aopOp (right,ic,FALSE, TRUE);
3433 aopOp (result,ic,TRUE, FALSE);
3436 /* special cases first */
3438 if (AOP_TYPE(left) == AOP_CRY &&
3439 AOP_TYPE(right)== AOP_CRY) {
3440 genDivbits(left,right,result);
3444 /* if both are of size == 1 */
3445 if (AOP_SIZE(left) == 1 &&
3446 AOP_SIZE(right) == 1 ) {
3447 genDivOneByte(left,right,result);
3451 /* should have been converted to function call */
3454 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3455 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3456 freeAsmop(result,NULL,ic,TRUE);
3459 /*-----------------------------------------------------------------*/
3460 /* genModbits :- modulus of bits */
3461 /*-----------------------------------------------------------------*/
3462 static void genModbits (operand *left,
3469 /* the result must be bit */
3470 LOAD_AB_FOR_DIV(left, right, l);
3471 emitcode("div","ab");
3472 emitcode("mov","a,b");
3473 emitcode("rrc","a");
3474 aopPut(AOP(result),"c",0);
3477 /*-----------------------------------------------------------------*/
3478 /* genModOneByte : 8 bit modulus */
3479 /*-----------------------------------------------------------------*/
3480 static void genModOneByte (operand *left,
3484 link *opetype = operandType(result);
3488 /* signed or unsigned */
3489 if (SPEC_USIGN(opetype)) {
3490 /* unsigned is easy */
3491 LOAD_AB_FOR_DIV(left, right, l);
3492 emitcode("div","ab");
3493 aopPut(AOP(result),"b",0);
3497 /* signed is a little bit more difficult */
3499 /* save the signs of the operands */
3500 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3503 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3504 emitcode("push","acc"); /* save it on the stack */
3506 /* now sign adjust for both left & right */
3507 l = aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3510 lbl = newiTempLabel(NULL);
3511 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3512 emitcode("cpl","a");
3513 emitcode("inc","a");
3514 emitcode("","%05d$:",(lbl->key+100));
3515 emitcode("mov","b,a");
3517 /* sign adjust left side */
3518 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3521 lbl = newiTempLabel(NULL);
3522 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3523 emitcode("cpl","a");
3524 emitcode("inc","a");
3525 emitcode("","%05d$:",(lbl->key+100));
3527 /* now the multiplication */
3528 emitcode("nop", "; workaround for DS80C390 div bug.");
3529 emitcode("div","ab");
3530 /* we are interested in the lower order
3532 lbl = newiTempLabel(NULL);
3533 emitcode("pop","acc");
3534 /* if there was an over flow we don't
3535 adjust the sign of the result */
3536 emitcode("jb","ov,%05d$",(lbl->key+100));
3537 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3539 emitcode("clr","a");
3540 emitcode("subb","a,b");
3541 emitcode("mov","b,a");
3542 emitcode("","%05d$:",(lbl->key+100));
3544 /* now we are done */
3545 aopPut(AOP(result),"b",0);
3549 /*-----------------------------------------------------------------*/
3550 /* genMod - generates code for division */
3551 /*-----------------------------------------------------------------*/
3552 static void genMod (iCode *ic)
3554 operand *left = IC_LEFT(ic);
3555 operand *right = IC_RIGHT(ic);
3556 operand *result= IC_RESULT(ic);
3558 D(emitcode(";", "genMod "););
3560 /* assign the amsops */
3563 aopOp (left,ic,FALSE, FALSE);
3564 aopOp (right,ic,FALSE, TRUE);
3565 aopOp (result,ic,TRUE, FALSE);
3568 /* special cases first */
3570 if (AOP_TYPE(left) == AOP_CRY &&
3571 AOP_TYPE(right)== AOP_CRY) {
3572 genModbits(left,right,result);
3576 /* if both are of size == 1 */
3577 if (AOP_SIZE(left) == 1 &&
3578 AOP_SIZE(right) == 1 ) {
3579 genModOneByte(left,right,result);
3583 /* should have been converted to function call */
3587 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3588 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3589 freeAsmop(result,NULL,ic,TRUE);
3592 /*-----------------------------------------------------------------*/
3593 /* genIfxJump :- will create a jump depending on the ifx */
3594 /*-----------------------------------------------------------------*/
3595 static void genIfxJump (iCode *ic, char *jval)
3598 symbol *tlbl = newiTempLabel(NULL);
3601 D(emitcode(";", "genIfxJump "););
3603 /* if true label then we jump if condition
3605 if ( IC_TRUE(ic) ) {
3607 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3608 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3611 /* false label is present */
3612 jlbl = IC_FALSE(ic) ;
3613 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3614 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3616 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3617 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3619 emitcode(inst,"%05d$",tlbl->key+100);
3620 emitcode("ljmp","%05d$",jlbl->key+100);
3621 emitcode("","%05d$:",tlbl->key+100);
3623 /* mark the icode as generated */
3627 /*-----------------------------------------------------------------*/
3628 /* genCmp :- greater or less than comparison */
3629 /*-----------------------------------------------------------------*/
3630 static void genCmp (operand *left,operand *right,
3631 operand *result, iCode *ifx, int sign)
3633 int size, offset = 0 ;
3634 unsigned long lit = 0L;
3635 bool swappedOps = FALSE;
3637 D(emitcode(";", "genCmp"););
3640 /* If left if lit and right isn't, swap 'em. */
3641 if (AOP_TYPE(left) == AOP_LIT &&
3642 AOP_TYPE(right) != AOP_LIT)
3644 operand *tmp = left;
3647 D(emitcode(";", "kevin literal hack"););
3648 swappedOps = !swappedOps;
3651 if (AOP_NEEDSACC(right))
3653 if (AOP_NEEDSACC(left))
3655 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
3656 "both CMP operands need ACC!");
3661 operand *tmp = left;
3664 D(emitcode(";", "kevin ACC hack"););
3665 swappedOps = !swappedOps;
3670 /* if left & right are bit variables */
3671 if (AOP_TYPE(left) == AOP_CRY &&
3672 AOP_TYPE(right) == AOP_CRY ) {
3673 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3674 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3676 /* subtract right from left if at the
3677 end the carry flag is set then we know that
3678 left is greater than right */
3679 size = max(AOP_SIZE(left),AOP_SIZE(right));
3681 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3682 if((size == 1) && !sign &&
3683 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3684 symbol *lbl = newiTempLabel(NULL);
3685 emitcode("cjne","%s,%s,%05d$",
3686 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
3687 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
3689 emitcode("","%05d$:",lbl->key+100);
3691 if(AOP_TYPE(right) == AOP_LIT){
3692 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3693 /* optimize if(x < 0) or if(x >= 0) */
3699 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE,TRUE));
3700 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3701 genIfxJump (ifx,"acc.7");
3705 emitcode("rlc","a");
3713 emitcode(";", "genCmp #1: %d/%d/%d", size, sign, offset);
3714 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
3715 emitcode(";", "genCmp #2");
3716 if (sign && (size == 0))
3718 emitcode(";", "genCmp #3");
3719 emitcode("xrl","a,#0x80");
3720 if (AOP_TYPE(right) == AOP_LIT)
3722 unsigned long lit = (unsigned long)
3723 floatFromVal(AOP(right)->aopu.aop_lit);
3724 emitcode(";", "genCmp #3.1");
3725 emitcode("subb","a,#0x%02x",
3726 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3730 emitcode(";", "genCmp #3.2");
3731 if (AOP_NEEDSACC(right))
3733 emitcode("push", "acc");
3735 emitcode("mov","b,%s",aopGet(AOP(right),offset++,
3736 FALSE,FALSE,FALSE));
3737 emitcode("xrl","b,#0x80");
3738 if (AOP_NEEDSACC(right))
3740 emitcode("pop", "acc");
3742 emitcode("subb","a,b");
3749 emitcode(";", "genCmp #4");
3750 if (AOP_NEEDSACC(right))
3753 emitcode(";", "genCmp #4.1");
3754 emitcode("xch", "a, b");
3755 MOVA(aopGet(AOP(right),offset++,FALSE,FALSE,TRUE));
3756 emitcode("xch", "a, b");
3761 emitcode(";", "genCmp #4.2");
3762 s = aopGet(AOP(right),offset++,FALSE,FALSE,FALSE);
3765 emitcode("subb","a,%s",s);
3774 D(emitcode(";","kevHack: flip carry."););
3775 emitcode("cpl", "c");
3778 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3781 /* if the result is used in the next
3782 ifx conditional branch then generate
3783 code a little differently */
3785 genIfxJump (ifx,"c");
3788 /* leave the result in acc */
3792 /*-----------------------------------------------------------------*/
3793 /* genCmpGt :- greater than comparison */
3794 /*-----------------------------------------------------------------*/
3795 static void genCmpGt (iCode *ic, iCode *ifx)
3797 operand *left, *right, *result;
3798 link *letype , *retype;
3801 D(emitcode(";", "genCmpGt "););
3804 right= IC_RIGHT(ic);
3805 result = IC_RESULT(ic);
3807 letype = getSpec(operandType(left));
3808 retype =getSpec(operandType(right));
3809 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3810 /* assign the amsops */
3813 aopOp (left,ic,FALSE, TRUE);
3814 aopOp (right,ic,FALSE, FALSE);
3815 aopOp (result,ic,TRUE, FALSE);
3818 genCmp(right, left, result, ifx, sign);
3820 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3821 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3822 freeAsmop(result,NULL,ic,TRUE);
3825 /*-----------------------------------------------------------------*/
3826 /* genCmpLt - less than comparisons */
3827 /*-----------------------------------------------------------------*/
3828 static void genCmpLt (iCode *ic, iCode *ifx)
3830 operand *left, *right, *result;
3831 link *letype , *retype;
3834 D(emitcode(";", "genCmpLt "););
3837 right= IC_RIGHT(ic);
3838 result = IC_RESULT(ic);
3840 letype = getSpec(operandType(left));
3841 retype =getSpec(operandType(right));
3842 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3844 /* assign the amsops */
3847 aopOp (left,ic,FALSE, FALSE);
3848 aopOp (right,ic,FALSE, TRUE);
3849 aopOp (result,ic,TRUE, FALSE);
3852 genCmp(left, right, result, ifx, sign);
3854 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3855 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3856 freeAsmop(result,NULL,ic,TRUE);
3859 /*-----------------------------------------------------------------*/
3860 /* gencjneshort - compare and jump if not equal */
3861 /*-----------------------------------------------------------------*/
3862 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3864 int size = max(AOP_SIZE(left),AOP_SIZE(right));
3866 unsigned long lit = 0L;
3868 D(emitcode(";", "gencjneshort"););
3870 /* if the left side is a literal or
3871 if the right is in a pointer register and left
3873 if ((AOP_TYPE(left) == AOP_LIT) ||
3874 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3879 if(AOP_TYPE(right) == AOP_LIT)
3880 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3882 /* if the right side is a literal then anything goes */
3883 if (AOP_TYPE(right) == AOP_LIT &&
3884 AOP_TYPE(left) != AOP_DIR ) {
3886 char *l = aopGet(AOP(left), offset, FALSE, FALSE,TRUE);
3888 emitcode("cjne","a,%s,%05d$",
3889 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
3895 /* if the right side is in a register or in direct space or
3896 if the left is a pointer register & right is not */
3897 else if (AOP_TYPE(right) == AOP_REG ||
3898 AOP_TYPE(right) == AOP_DIR ||
3899 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3900 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3902 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
3903 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3904 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
3905 emitcode("jnz","%05d$",lbl->key+100);
3907 emitcode("cjne","a,%s,%05d$",
3908 aopGet(AOP(right),offset,FALSE,TRUE,FALSE),
3913 /* right is a pointer reg need both a & b */
3915 char *l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
3917 emitcode("mov","b,%s",l);
3918 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
3919 emitcode("cjne","a,b,%05d$",lbl->key+100);
3925 /*-----------------------------------------------------------------*/
3926 /* gencjne - compare and jump if not equal */
3927 /*-----------------------------------------------------------------*/
3928 static void gencjne(operand *left, operand *right, symbol *lbl)
3930 symbol *tlbl = newiTempLabel(NULL);
3932 D(emitcode(";", "gencjne"););
3934 gencjneshort(left, right, lbl);
3936 emitcode("mov","a,%s",one);
3937 emitcode("sjmp","%05d$",tlbl->key+100);
3938 emitcode("","%05d$:",lbl->key+100);
3939 emitcode("clr","a");
3940 emitcode("","%05d$:",tlbl->key+100);
3943 /*-----------------------------------------------------------------*/
3944 /* genCmpEq - generates code for equal to */
3945 /*-----------------------------------------------------------------*/
3946 static void genCmpEq (iCode *ic, iCode *ifx)
3948 operand *left, *right, *result;
3950 D(emitcode(";", "genCmpEq "););
3955 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
3956 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
3957 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
3960 /* if literal, literal on the right or
3961 if the right is in a pointer register and left
3963 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
3964 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3965 operand *t = IC_RIGHT(ic);
3966 IC_RIGHT(ic) = IC_LEFT(ic);
3970 if(ifx && !AOP_SIZE(result)){
3972 /* if they are both bit variables */
3973 if (AOP_TYPE(left) == AOP_CRY &&
3974 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3975 if(AOP_TYPE(right) == AOP_LIT){
3976 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3978 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3979 emitcode("cpl","c");
3980 } else if(lit == 1L) {
3981 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3983 emitcode("clr","c");
3985 /* AOP_TYPE(right) == AOP_CRY */
3987 symbol *lbl = newiTempLabel(NULL);
3988 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3989 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3990 emitcode("cpl","c");
3991 emitcode("","%05d$:",(lbl->key+100));
3993 /* if true label then we jump if condition
3995 tlbl = newiTempLabel(NULL);
3996 if ( IC_TRUE(ifx) ) {
3997 emitcode("jnc","%05d$",tlbl->key+100);
3998 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4000 emitcode("jc","%05d$",tlbl->key+100);
4001 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4003 emitcode("","%05d$:",tlbl->key+100);
4005 tlbl = newiTempLabel(NULL);
4006 gencjneshort(left, right, tlbl);
4007 if ( IC_TRUE(ifx) ) {
4008 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4009 emitcode("","%05d$:",tlbl->key+100);
4011 symbol *lbl = newiTempLabel(NULL);
4012 emitcode("sjmp","%05d$",lbl->key+100);
4013 emitcode("","%05d$:",tlbl->key+100);
4014 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4015 emitcode("","%05d$:",lbl->key+100);
4018 /* mark the icode as generated */
4023 /* if they are both bit variables */
4024 if (AOP_TYPE(left) == AOP_CRY &&
4025 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4026 if(AOP_TYPE(right) == AOP_LIT){
4027 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4029 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4030 emitcode("cpl","c");
4031 } else if(lit == 1L) {
4032 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4034 emitcode("clr","c");
4036 /* AOP_TYPE(right) == AOP_CRY */
4038 symbol *lbl = newiTempLabel(NULL);
4039 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4040 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4041 emitcode("cpl","c");
4042 emitcode("","%05d$:",(lbl->key+100));
4045 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4050 genIfxJump (ifx,"c");
4053 /* if the result is used in an arithmetic operation
4054 then put the result in place */
4057 gencjne(left,right,newiTempLabel(NULL));
4058 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4059 aopPut(AOP(result),"a",0);
4063 genIfxJump (ifx,"a");
4066 /* if the result is used in an arithmetic operation
4067 then put the result in place */
4068 if (AOP_TYPE(result) != AOP_CRY)
4070 /* leave the result in acc */
4074 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4075 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4076 freeAsmop(result,NULL,ic,TRUE);
4079 /*-----------------------------------------------------------------*/
4080 /* ifxForOp - returns the icode containing the ifx for operand */
4081 /*-----------------------------------------------------------------*/
4082 static iCode *ifxForOp ( operand *op, iCode *ic )
4084 /* if true symbol then needs to be assigned */
4085 if (IS_TRUE_SYMOP(op))
4088 /* if this has register type condition and
4089 the next instruction is ifx with the same operand
4090 and live to of the operand is upto the ifx only then */
4092 ic->next->op == IFX &&
4093 IC_COND(ic->next)->key == op->key &&
4094 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4099 /*-----------------------------------------------------------------*/
4100 /* genAndOp - for && operation */
4101 /*-----------------------------------------------------------------*/
4102 static void genAndOp (iCode *ic)
4104 operand *left,*right, *result;
4107 D(emitcode(";", "genAndOp "););
4109 /* note here that && operations that are in an
4110 if statement are taken away by backPatchLabels
4111 only those used in arthmetic operations remain */
4115 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4116 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4117 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4120 /* if both are bit variables */
4121 if (AOP_TYPE(left) == AOP_CRY &&
4122 AOP_TYPE(right) == AOP_CRY ) {
4123 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4124 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4127 tlbl = newiTempLabel(NULL);
4129 emitcode("jz","%05d$",tlbl->key+100);
4131 emitcode("","%05d$:",tlbl->key+100);
4135 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4136 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4137 freeAsmop(result,NULL,ic,TRUE);
4141 /*-----------------------------------------------------------------*/
4142 /* genOrOp - for || operation */
4143 /*-----------------------------------------------------------------*/
4144 static void genOrOp (iCode *ic)
4146 operand *left,*right, *result;
4149 D(emitcode(";", "genOrOp "););
4151 /* note here that || operations that are in an
4152 if statement are taken away by backPatchLabels
4153 only those used in arthmetic operations remain */
4157 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4158 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4159 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4162 /* if both are bit variables */
4163 if (AOP_TYPE(left) == AOP_CRY &&
4164 AOP_TYPE(right) == AOP_CRY ) {
4165 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4166 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
4169 tlbl = newiTempLabel(NULL);
4171 emitcode("jnz","%05d$",tlbl->key+100);
4173 emitcode("","%05d$:",tlbl->key+100);
4177 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4178 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4179 freeAsmop(result,NULL,ic,TRUE);
4182 /*-----------------------------------------------------------------*/
4183 /* isLiteralBit - test if lit == 2^n */
4184 /*-----------------------------------------------------------------*/
4185 static int isLiteralBit(unsigned long lit)
4187 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4188 0x100L,0x200L,0x400L,0x800L,
4189 0x1000L,0x2000L,0x4000L,0x8000L,
4190 0x10000L,0x20000L,0x40000L,0x80000L,
4191 0x100000L,0x200000L,0x400000L,0x800000L,
4192 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4193 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4196 for(idx = 0; idx < 32; idx++)
4202 /*-----------------------------------------------------------------*/
4203 /* continueIfTrue - */
4204 /*-----------------------------------------------------------------*/
4205 static void continueIfTrue (iCode *ic)
4208 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4212 /*-----------------------------------------------------------------*/
4214 /*-----------------------------------------------------------------*/
4215 static void jumpIfTrue (iCode *ic)
4218 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4222 /*-----------------------------------------------------------------*/
4223 /* jmpTrueOrFalse - */
4224 /*-----------------------------------------------------------------*/
4225 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4227 // ugly but optimized by peephole
4229 symbol *nlbl = newiTempLabel(NULL);
4230 emitcode("sjmp","%05d$",nlbl->key+100);
4231 emitcode("","%05d$:",tlbl->key+100);
4232 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4233 emitcode("","%05d$:",nlbl->key+100);
4236 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4237 emitcode("","%05d$:",tlbl->key+100);
4242 /*-----------------------------------------------------------------*/
4243 /* genAnd - code for and */
4244 /*-----------------------------------------------------------------*/
4245 static void genAnd (iCode *ic, iCode *ifx)
4247 operand *left, *right, *result;
4249 unsigned long lit = 0L;
4253 D(emitcode(";", "genAnd "););
4258 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4259 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4260 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4264 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4266 AOP_TYPE(left), AOP_TYPE(right));
4267 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4269 AOP_SIZE(left), AOP_SIZE(right));
4272 /* if left is a literal & right is not then exchange them */
4273 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4274 AOP_NEEDSACC(left)) {
4275 operand *tmp = right ;
4280 /* if result = right then exchange them */
4281 if(sameRegs(AOP(result),AOP(right))){
4282 operand *tmp = right ;
4287 /* if right is bit then exchange them */
4288 if (AOP_TYPE(right) == AOP_CRY &&
4289 AOP_TYPE(left) != AOP_CRY){
4290 operand *tmp = right ;
4294 if(AOP_TYPE(right) == AOP_LIT)
4295 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4297 size = AOP_SIZE(result);
4300 // result = bit & yy;
4301 if (AOP_TYPE(left) == AOP_CRY){
4302 // c = bit & literal;
4303 if(AOP_TYPE(right) == AOP_LIT){
4305 if(size && sameRegs(AOP(result),AOP(left)))
4308 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4311 if(size && (AOP_TYPE(result) == AOP_CRY)){
4312 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4315 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4319 emitcode("clr","c");
4322 if (AOP_TYPE(right) == AOP_CRY){
4324 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4325 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4328 MOVA(aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4330 emitcode("rrc","a");
4331 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4339 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4340 genIfxJump(ifx, "c");
4344 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4345 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4346 if((AOP_TYPE(right) == AOP_LIT) &&
4347 (AOP_TYPE(result) == AOP_CRY) &&
4348 (AOP_TYPE(left) != AOP_CRY)){
4349 int posbit = isLiteralBit(lit);
4353 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE,TRUE));
4356 emitcode("mov","c,acc.%d",posbit&0x07);
4360 sprintf(buffer,"acc.%d",posbit&0x07);
4361 genIfxJump(ifx, buffer);
4366 symbol *tlbl = newiTempLabel(NULL);
4367 int sizel = AOP_SIZE(left);
4369 emitcode("setb","c");
4371 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4372 MOVA( aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4374 if((posbit = isLiteralBit(bytelit)) != 0)
4375 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
4377 if(bytelit != 0x0FFL)
4378 emitcode("anl","a,%s",
4379 aopGet(AOP(right),offset,FALSE,TRUE,FALSE));
4380 emitcode("jnz","%05d$",tlbl->key+100);
4385 // bit = left & literal
4387 emitcode("clr","c");
4388 emitcode("","%05d$:",tlbl->key+100);
4390 // if(left & literal)
4393 jmpTrueOrFalse(ifx, tlbl);
4401 /* if left is same as result */
4402 if(sameRegs(AOP(result),AOP(left))){
4403 for(;size--; offset++) {
4404 if(AOP_TYPE(right) == AOP_LIT){
4405 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4409 aopPut(AOP(result),zero,offset);
4411 if (IS_AOP_PREG(result)) {
4412 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4413 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4414 aopPut(AOP(result),"a",offset);
4416 emitcode("anl","%s,%s",
4417 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4418 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4420 if (AOP_TYPE(left) == AOP_ACC)
4421 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4423 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4424 if (IS_AOP_PREG(result)) {
4425 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4426 aopPut(AOP(result),"a",offset);
4429 emitcode("anl","%s,a",
4430 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4435 // left & result in different registers
4436 if(AOP_TYPE(result) == AOP_CRY){
4438 // if(size), result in bit
4439 // if(!size && ifx), conditional oper: if(left & right)
4440 symbol *tlbl = newiTempLabel(NULL);
4441 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4443 emitcode("setb","c");
4445 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4446 emitcode("anl","a,%s",
4447 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4448 emitcode("jnz","%05d$",tlbl->key+100);
4453 emitcode("","%05d$:",tlbl->key+100);
4456 jmpTrueOrFalse(ifx, tlbl);
4458 for(;(size--);offset++) {
4460 // result = left & right
4461 if(AOP_TYPE(right) == AOP_LIT){
4462 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
4464 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4467 } else if(bytelit == 0){
4468 aopPut(AOP(result),zero,offset);
4472 // faster than result <- left, anl result,right
4473 // and better if result is SFR
4474 if (AOP_TYPE(left) == AOP_ACC)
4475 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4477 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4478 emitcode("anl","a,%s",
4479 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4481 aopPut(AOP(result),"a",offset);
4487 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4488 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4489 freeAsmop(result,NULL,ic,TRUE);
4492 /*-----------------------------------------------------------------*/
4493 /* genOr - code for or */
4494 /*-----------------------------------------------------------------*/
4495 static void genOr (iCode *ic, iCode *ifx)
4497 operand *left, *right, *result;
4499 unsigned long lit = 0L;
4501 D(emitcode(";", "genOr "););
4506 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4507 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4508 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4512 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4514 AOP_TYPE(left), AOP_TYPE(right));
4515 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4517 AOP_SIZE(left), AOP_SIZE(right));
4520 /* if left is a literal & right is not then exchange them */
4521 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4522 AOP_NEEDSACC(left)) {
4523 operand *tmp = right ;
4528 /* if result = right then exchange them */
4529 if(sameRegs(AOP(result),AOP(right))){
4530 operand *tmp = right ;
4535 /* if right is bit then exchange them */
4536 if (AOP_TYPE(right) == AOP_CRY &&
4537 AOP_TYPE(left) != AOP_CRY){
4538 operand *tmp = right ;
4542 if(AOP_TYPE(right) == AOP_LIT)
4543 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4545 size = AOP_SIZE(result);
4549 if (AOP_TYPE(left) == AOP_CRY){
4550 if(AOP_TYPE(right) == AOP_LIT){
4551 // c = bit & literal;
4553 // lit != 0 => result = 1
4554 if(AOP_TYPE(result) == AOP_CRY){
4556 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4558 continueIfTrue(ifx);
4561 emitcode("setb","c");
4563 // lit == 0 => result = left
4564 if(size && sameRegs(AOP(result),AOP(left)))
4566 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4569 if (AOP_TYPE(right) == AOP_CRY){
4571 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4572 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4576 symbol *tlbl = newiTempLabel(NULL);
4577 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4578 emitcode("setb","c");
4579 emitcode("jb","%s,%05d$",
4580 AOP(left)->aopu.aop_dir,tlbl->key+100);
4582 emitcode("jnz","%05d$",tlbl->key+100);
4583 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4584 jmpTrueOrFalse(ifx, tlbl);
4588 emitcode("","%05d$:",tlbl->key+100);
4597 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4598 genIfxJump(ifx, "c");
4602 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4603 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4604 if((AOP_TYPE(right) == AOP_LIT) &&
4605 (AOP_TYPE(result) == AOP_CRY) &&
4606 (AOP_TYPE(left) != AOP_CRY)){
4610 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4612 continueIfTrue(ifx);
4615 // lit = 0, result = boolean(left)
4617 emitcode("setb","c");
4620 symbol *tlbl = newiTempLabel(NULL);
4621 emitcode("jnz","%05d$",tlbl->key+100);
4623 emitcode("","%05d$:",tlbl->key+100);
4625 genIfxJump (ifx,"a");
4633 /* if left is same as result */
4634 if(sameRegs(AOP(result),AOP(left))){
4635 for(;size--; offset++) {
4636 if(AOP_TYPE(right) == AOP_LIT){
4637 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4640 if (IS_AOP_PREG(left)) {
4641 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4642 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4643 aopPut(AOP(result),"a",offset);
4645 emitcode("orl","%s,%s",
4646 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4647 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4649 if (AOP_TYPE(left) == AOP_ACC)
4650 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4652 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4653 if (IS_AOP_PREG(left)) {
4654 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4655 aopPut(AOP(result),"a",offset);
4657 emitcode("orl","%s,a",
4658 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4663 // left & result in different registers
4664 if(AOP_TYPE(result) == AOP_CRY){
4666 // if(size), result in bit
4667 // if(!size && ifx), conditional oper: if(left | right)
4668 symbol *tlbl = newiTempLabel(NULL);
4669 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4671 emitcode("setb","c");
4673 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4674 emitcode("orl","a,%s",
4675 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4676 emitcode("jnz","%05d$",tlbl->key+100);
4681 emitcode("","%05d$:",tlbl->key+100);
4684 jmpTrueOrFalse(ifx, tlbl);
4685 } else for(;(size--);offset++){
4687 // result = left & right
4688 if(AOP_TYPE(right) == AOP_LIT){
4689 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4691 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4696 // faster than result <- left, anl result,right
4697 // and better if result is SFR
4698 if (AOP_TYPE(left) == AOP_ACC)
4699 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4701 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4702 emitcode("orl","a,%s",
4703 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4705 aopPut(AOP(result),"a",offset);
4710 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4711 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4712 freeAsmop(result,NULL,ic,TRUE);
4715 /*-----------------------------------------------------------------*/
4716 /* genXor - code for xclusive or */
4717 /*-----------------------------------------------------------------*/
4718 static void genXor (iCode *ic, iCode *ifx)
4720 operand *left, *right, *result;
4722 unsigned long lit = 0L;
4724 D(emitcode(";", "genXor "););
4729 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4730 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4731 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4735 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4737 AOP_TYPE(left), AOP_TYPE(right));
4738 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4740 AOP_SIZE(left), AOP_SIZE(right));
4743 /* if left is a literal & right is not ||
4744 if left needs acc & right does not */
4745 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4746 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4747 operand *tmp = right ;
4752 /* if result = right then exchange them */
4753 if(sameRegs(AOP(result),AOP(right))){
4754 operand *tmp = right ;
4759 /* if right is bit then exchange them */
4760 if (AOP_TYPE(right) == AOP_CRY &&
4761 AOP_TYPE(left) != AOP_CRY){
4762 operand *tmp = right ;
4766 if(AOP_TYPE(right) == AOP_LIT)
4767 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4769 size = AOP_SIZE(result);
4773 if (AOP_TYPE(left) == AOP_CRY){
4774 if(AOP_TYPE(right) == AOP_LIT){
4775 // c = bit & literal;
4777 // lit>>1 != 0 => result = 1
4778 if(AOP_TYPE(result) == AOP_CRY){
4780 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4782 continueIfTrue(ifx);
4785 emitcode("setb","c");
4789 // lit == 0, result = left
4790 if(size && sameRegs(AOP(result),AOP(left)))
4792 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4794 // lit == 1, result = not(left)
4795 if(size && sameRegs(AOP(result),AOP(left))){
4796 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4799 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4800 emitcode("cpl","c");
4807 symbol *tlbl = newiTempLabel(NULL);
4808 if (AOP_TYPE(right) == AOP_CRY){
4810 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4813 int sizer = AOP_SIZE(right);
4815 // if val>>1 != 0, result = 1
4816 emitcode("setb","c");
4818 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE,TRUE));
4820 // test the msb of the lsb
4821 emitcode("anl","a,#0xfe");
4822 emitcode("jnz","%05d$",tlbl->key+100);
4826 emitcode("rrc","a");
4828 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4829 emitcode("cpl","c");
4830 emitcode("","%05d$:",(tlbl->key+100));
4837 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4838 genIfxJump(ifx, "c");
4842 if(sameRegs(AOP(result),AOP(left))){
4843 /* if left is same as result */
4844 for(;size--; offset++) {
4845 if(AOP_TYPE(right) == AOP_LIT){
4846 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4849 if (IS_AOP_PREG(left)) {
4850 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4851 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4852 aopPut(AOP(result),"a",offset);
4854 emitcode("xrl","%s,%s",
4855 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4856 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4858 if (AOP_TYPE(left) == AOP_ACC)
4859 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4861 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4862 if (IS_AOP_PREG(left)) {
4863 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4864 aopPut(AOP(result),"a",offset);
4866 emitcode("xrl","%s,a",
4867 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4872 // left & result in different registers
4873 if(AOP_TYPE(result) == AOP_CRY){
4875 // if(size), result in bit
4876 // if(!size && ifx), conditional oper: if(left ^ right)
4877 symbol *tlbl = newiTempLabel(NULL);
4878 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4880 emitcode("setb","c");
4882 if((AOP_TYPE(right) == AOP_LIT) &&
4883 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4884 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4886 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4887 emitcode("xrl","a,%s",
4888 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4890 emitcode("jnz","%05d$",tlbl->key+100);
4895 emitcode("","%05d$:",tlbl->key+100);
4898 jmpTrueOrFalse(ifx, tlbl);
4899 } else for(;(size--);offset++){
4901 // result = left & right
4902 if(AOP_TYPE(right) == AOP_LIT){
4903 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4905 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4910 // faster than result <- left, anl result,right
4911 // and better if result is SFR
4912 if (AOP_TYPE(left) == AOP_ACC)
4913 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4915 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4916 emitcode("xrl","a,%s",
4917 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4919 aopPut(AOP(result),"a",offset);
4924 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4925 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4926 freeAsmop(result,NULL,ic,TRUE);
4929 /*-----------------------------------------------------------------*/
4930 /* genInline - write the inline code out */
4931 /*-----------------------------------------------------------------*/
4932 static void genInline (iCode *ic)
4934 char buffer[MAX_INLINEASM];
4938 D(emitcode(";", "genInline "););
4940 _G.inLine += (!options.asmpeep);
4941 strcpy(buffer,IC_INLINE(ic));
4943 /* emit each line as a code */
4962 /* emitcode("",buffer); */
4963 _G.inLine -= (!options.asmpeep);
4966 /*-----------------------------------------------------------------*/
4967 /* genRRC - rotate right with carry */
4968 /*-----------------------------------------------------------------*/
4969 static void genRRC (iCode *ic)
4971 operand *left , *result ;
4972 int size, offset = 0;
4975 D(emitcode(";", "genRRC "););
4977 /* rotate right with carry */
4979 result=IC_RESULT(ic);
4980 aopOp (left,ic,FALSE, FALSE);
4981 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
4983 /* move it to the result */
4984 size = AOP_SIZE(result);
4988 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
4990 emitcode("rrc","a");
4991 if (AOP_SIZE(result) > 1)
4992 aopPut(AOP(result),"a",offset--);
4994 /* now we need to put the carry into the
4995 highest order byte of the result */
4996 if (AOP_SIZE(result) > 1) {
4997 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE,TRUE);
5000 emitcode("mov","acc.7,c");
5001 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5002 freeAsmop(left,NULL,ic,TRUE);
5003 freeAsmop(result,NULL,ic,TRUE);
5006 /*-----------------------------------------------------------------*/
5007 /* genRLC - generate code for rotate left with carry */
5008 /*-----------------------------------------------------------------*/
5009 static void genRLC (iCode *ic)
5011 operand *left , *result ;
5012 int size, offset = 0;
5015 D(emitcode(";", "genRLC "););
5017 /* rotate right with carry */
5019 result=IC_RESULT(ic);
5020 aopOp (left,ic,FALSE, FALSE);
5021 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5023 /* move it to the result */
5024 size = AOP_SIZE(result);
5027 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5029 emitcode("add","a,acc");
5030 if (AOP_SIZE(result) > 1)
5031 aopPut(AOP(result),"a",offset++);
5033 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5035 emitcode("rlc","a");
5036 if (AOP_SIZE(result) > 1)
5037 aopPut(AOP(result),"a",offset++);
5040 /* now we need to put the carry into the
5041 highest order byte of the result */
5042 if (AOP_SIZE(result) > 1) {
5043 l = aopGet(AOP(result),0,FALSE,FALSE,TRUE);
5046 emitcode("mov","acc.0,c");
5047 aopPut(AOP(result),"a",0);
5048 freeAsmop(left,NULL,ic,TRUE);
5049 freeAsmop(result,NULL,ic,TRUE);
5052 /*-----------------------------------------------------------------*/
5053 /* genGetHbit - generates code get highest order bit */
5054 /*-----------------------------------------------------------------*/
5055 static void genGetHbit (iCode *ic)
5057 operand *left, *result;
5059 result=IC_RESULT(ic);
5060 aopOp (left,ic,FALSE, FALSE);
5061 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5063 D(emitcode(";", "genGetHbit "););
5065 /* get the highest order byte into a */
5066 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE,TRUE));
5067 if(AOP_TYPE(result) == AOP_CRY){
5068 emitcode("rlc","a");
5073 emitcode("anl","a,#0x01");
5078 freeAsmop(left,NULL,ic,TRUE);
5079 freeAsmop(result,NULL,ic,TRUE);
5082 /*-----------------------------------------------------------------*/
5083 /* AccRol - rotate left accumulator by known count */
5084 /*-----------------------------------------------------------------*/
5085 static void AccRol (int shCount)
5087 shCount &= 0x0007; // shCount : 0..7
5099 emitcode("swap","a");
5103 emitcode("swap","a");
5106 emitcode("swap","a");
5119 /*-----------------------------------------------------------------*/
5120 /* AccLsh - left shift accumulator by known count */
5121 /*-----------------------------------------------------------------*/
5122 static void AccLsh (int shCount)
5126 emitcode("add","a,acc");
5129 emitcode("add","a,acc");
5130 emitcode("add","a,acc");
5132 /* rotate left accumulator */
5134 /* and kill the lower order bits */
5135 emitcode("anl","a,#0x%02x", SLMask[shCount]);
5140 /*-----------------------------------------------------------------*/
5141 /* AccRsh - right shift accumulator by known count */
5142 /*-----------------------------------------------------------------*/
5143 static void AccRsh (int shCount)
5148 emitcode("rrc","a");
5150 /* rotate right accumulator */
5151 AccRol(8 - shCount);
5152 /* and kill the higher order bits */
5153 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5158 /*-----------------------------------------------------------------*/
5159 /* AccSRsh - signed right shift accumulator by known count */
5160 /*-----------------------------------------------------------------*/
5161 static void AccSRsh (int shCount)
5166 emitcode("mov","c,acc.7");
5167 emitcode("rrc","a");
5168 } else if(shCount == 2){
5169 emitcode("mov","c,acc.7");
5170 emitcode("rrc","a");
5171 emitcode("mov","c,acc.7");
5172 emitcode("rrc","a");
5174 tlbl = newiTempLabel(NULL);
5175 /* rotate right accumulator */
5176 AccRol(8 - shCount);
5177 /* and kill the higher order bits */
5178 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5179 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5180 emitcode("orl","a,#0x%02x",
5181 (unsigned char)~SRMask[shCount]);
5182 emitcode("","%05d$:",tlbl->key+100);
5187 /*-----------------------------------------------------------------*/
5188 /* shiftR1Left2Result - shift right one byte from left to result */
5189 /*-----------------------------------------------------------------*/
5190 static void shiftR1Left2Result (operand *left, int offl,
5191 operand *result, int offr,
5192 int shCount, int sign)
5194 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5195 /* shift right accumulator */
5200 aopPut(AOP(result),"a",offr);
5203 /*-----------------------------------------------------------------*/
5204 /* shiftL1Left2Result - shift left one byte from left to result */
5205 /*-----------------------------------------------------------------*/
5206 static void shiftL1Left2Result (operand *left, int offl,
5207 operand *result, int offr, int shCount)
5210 l = aopGet(AOP(left),offl,FALSE,FALSE,TRUE);
5212 /* shift left accumulator */
5214 aopPut(AOP(result),"a",offr);
5217 /*-----------------------------------------------------------------*/
5218 /* movLeft2Result - move byte from left to result */
5219 /*-----------------------------------------------------------------*/
5220 static void movLeft2Result (operand *left, int offl,
5221 operand *result, int offr, int sign)
5224 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5225 l = aopGet(AOP(left),offl,FALSE,FALSE,FALSE);
5227 if (*l == '@' && (IS_AOP_PREG(result))) {
5228 emitcode("mov","a,%s",l);
5229 aopPut(AOP(result),"a",offr);
5232 aopPut(AOP(result),l,offr);
5234 /* MSB sign in acc.7 ! */
5235 if(getDataSize(left) == offl+1){
5236 emitcode("mov","a,%s",l);
5237 aopPut(AOP(result),"a",offr);
5244 /*-----------------------------------------------------------------*/
5245 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5246 /*-----------------------------------------------------------------*/
5247 static void AccAXRrl1 (char *x)
5249 emitcode("rrc","a");
5250 emitcode("xch","a,%s", x);
5251 emitcode("rrc","a");
5252 emitcode("xch","a,%s", x);
5255 /*-----------------------------------------------------------------*/
5256 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5257 /*-----------------------------------------------------------------*/
5258 static void AccAXLrl1 (char *x)
5260 emitcode("xch","a,%s",x);
5261 emitcode("rlc","a");
5262 emitcode("xch","a,%s",x);
5263 emitcode("rlc","a");
5266 /*-----------------------------------------------------------------*/
5267 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5268 /*-----------------------------------------------------------------*/
5269 static void AccAXLsh1 (char *x)
5271 emitcode("xch","a,%s",x);
5272 emitcode("add","a,acc");
5273 emitcode("xch","a,%s",x);
5274 emitcode("rlc","a");
5277 /*-----------------------------------------------------------------*/
5278 /* AccAXLsh - left shift a:x by known count (0..7) */
5279 /*-----------------------------------------------------------------*/
5280 static void AccAXLsh (char *x, int shCount)
5294 case 5 : // AAAAABBB:CCCCCDDD
5295 AccRol(shCount); // BBBAAAAA:CCCCCDDD
5296 emitcode("anl","a,#0x%02x",
5297 SLMask[shCount]); // BBB00000:CCCCCDDD
5298 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
5299 AccRol(shCount); // DDDCCCCC:BBB00000
5300 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
5301 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
5302 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
5303 emitcode("anl","a,#0x%02x",
5304 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5305 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
5306 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
5308 case 6 : // AAAAAABB:CCCCCCDD
5309 emitcode("anl","a,#0x%02x",
5310 SRMask[shCount]); // 000000BB:CCCCCCDD
5311 emitcode("mov","c,acc.0"); // c = B
5312 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
5313 AccAXRrl1(x); // BCCCCCCD:D000000B
5314 AccAXRrl1(x); // BBCCCCCC:DD000000
5316 case 7 : // a:x <<= 7
5317 emitcode("anl","a,#0x%02x",
5318 SRMask[shCount]); // 0000000B:CCCCCCCD
5319 emitcode("mov","c,acc.0"); // c = B
5320 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
5321 AccAXRrl1(x); // BCCCCCCC:D0000000
5328 /*-----------------------------------------------------------------*/
5329 /* AccAXRsh - right shift a:x known count (0..7) */
5330 /*-----------------------------------------------------------------*/
5331 static void AccAXRsh (char *x, int shCount)
5338 AccAXRrl1(x); // 0->a:x
5342 AccAXRrl1(x); // 0->a:x
5344 AccAXRrl1(x); // 0->a:x
5348 case 5 : // AAAAABBB:CCCCCDDD = a:x
5349 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
5350 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5351 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5352 emitcode("anl","a,#0x%02x",
5353 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5354 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5355 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5356 emitcode("anl","a,#0x%02x",
5357 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5358 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5359 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5360 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
5362 case 6 : // AABBBBBB:CCDDDDDD
5363 emitcode("mov","c,acc.7");
5364 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5365 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5366 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5367 emitcode("anl","a,#0x%02x",
5368 SRMask[shCount]); // 000000AA:BBBBBBCC
5370 case 7 : // ABBBBBBB:CDDDDDDD
5371 emitcode("mov","c,acc.7"); // c = A
5372 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5373 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5374 emitcode("anl","a,#0x%02x",
5375 SRMask[shCount]); // 0000000A:BBBBBBBC
5382 /*-----------------------------------------------------------------*/
5383 /* AccAXRshS - right shift signed a:x known count (0..7) */
5384 /*-----------------------------------------------------------------*/
5385 static void AccAXRshS (char *x, int shCount)
5392 emitcode("mov","c,acc.7");
5393 AccAXRrl1(x); // s->a:x
5396 emitcode("mov","c,acc.7");
5397 AccAXRrl1(x); // s->a:x
5398 emitcode("mov","c,acc.7");
5399 AccAXRrl1(x); // s->a:x
5403 case 5 : // AAAAABBB:CCCCCDDD = a:x
5404 tlbl = newiTempLabel(NULL);
5405 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5406 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5407 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5408 emitcode("anl","a,#0x%02x",
5409 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5410 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5411 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5412 emitcode("anl","a,#0x%02x",
5413 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5414 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5415 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5416 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5417 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5418 emitcode("orl","a,#0x%02x",
5419 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5420 emitcode("","%05d$:",tlbl->key+100);
5421 break; // SSSSAAAA:BBBCCCCC
5422 case 6 : // AABBBBBB:CCDDDDDD
5423 tlbl = newiTempLabel(NULL);
5424 emitcode("mov","c,acc.7");
5425 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5426 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5427 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5428 emitcode("anl","a,#0x%02x",
5429 SRMask[shCount]); // 000000AA:BBBBBBCC
5430 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5431 emitcode("orl","a,#0x%02x",
5432 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5433 emitcode("","%05d$:",tlbl->key+100);
5435 case 7 : // ABBBBBBB:CDDDDDDD
5436 tlbl = newiTempLabel(NULL);
5437 emitcode("mov","c,acc.7"); // c = A
5438 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5439 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5440 emitcode("anl","a,#0x%02x",
5441 SRMask[shCount]); // 0000000A:BBBBBBBC
5442 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5443 emitcode("orl","a,#0x%02x",
5444 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5445 emitcode("","%05d$:",tlbl->key+100);
5452 /*-----------------------------------------------------------------*/
5453 /* shiftL2Left2Result - shift left two bytes from left to result */
5454 /*-----------------------------------------------------------------*/
5455 static void shiftL2Left2Result (operand *left, int offl,
5456 operand *result, int offr, int shCount)
5458 if(sameRegs(AOP(result), AOP(left)) &&
5459 ((offl + MSB16) == offr)){
5460 /* don't crash result[offr] */
5461 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5462 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5464 movLeft2Result(left,offl, result, offr, 0);
5465 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5467 /* ax << shCount (x = lsb(result))*/
5468 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE), shCount);
5469 aopPut(AOP(result),"a",offr+MSB16);
5473 /*-----------------------------------------------------------------*/
5474 /* shiftR2Left2Result - shift right two bytes from left to result */
5475 /*-----------------------------------------------------------------*/
5476 static void shiftR2Left2Result (operand *left, int offl,
5477 operand *result, int offr,
5478 int shCount, int sign)
5480 if(sameRegs(AOP(result), AOP(left)) &&
5481 ((offl + MSB16) == offr)){
5482 /* don't crash result[offr] */
5483 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5484 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5486 movLeft2Result(left,offl, result, offr, 0);
5487 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5489 /* a:x >> shCount (x = lsb(result))*/
5491 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5493 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5494 if(getDataSize(result) > 1)
5495 aopPut(AOP(result),"a",offr+MSB16);
5498 /*-----------------------------------------------------------------*/
5499 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5500 /*-----------------------------------------------------------------*/
5501 static void shiftLLeftOrResult (operand *left, int offl,
5502 operand *result, int offr, int shCount)
5504 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5505 /* shift left accumulator */
5507 /* or with result */
5508 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5509 /* back to result */
5510 aopPut(AOP(result),"a",offr);
5513 /*-----------------------------------------------------------------*/
5514 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5515 /*-----------------------------------------------------------------*/
5516 static void shiftRLeftOrResult (operand *left, int offl,
5517 operand *result, int offr, int shCount)
5519 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5520 /* shift right accumulator */
5522 /* or with result */
5523 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5524 /* back to result */
5525 aopPut(AOP(result),"a",offr);
5528 /*-----------------------------------------------------------------*/
5529 /* genlshOne - left shift a one byte quantity by known count */
5530 /*-----------------------------------------------------------------*/
5531 static void genlshOne (operand *result, operand *left, int shCount)
5533 D(emitcode(";", "genlshOne "););
5534 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5537 /*-----------------------------------------------------------------*/
5538 /* genlshTwo - left shift two bytes by known amount != 0 */
5539 /*-----------------------------------------------------------------*/
5540 static void genlshTwo (operand *result,operand *left, int shCount)
5544 D(emitcode(";", "genlshTwo "););
5546 size = getDataSize(result);
5548 /* if shCount >= 8 */
5554 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5556 movLeft2Result(left, LSB, result, MSB16, 0);
5558 aopPut(AOP(result),zero,LSB);
5561 /* 1 <= shCount <= 7 */
5564 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5566 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5570 /*-----------------------------------------------------------------*/
5571 /* shiftLLong - shift left one long from left to result */
5572 /* offl = LSB or MSB16 */
5573 /*-----------------------------------------------------------------*/
5574 static void shiftLLong (operand *left, operand *result, int offr )
5577 int size = AOP_SIZE(result);
5579 if(size >= LSB+offr){
5580 l = aopGet(AOP(left),LSB,FALSE,FALSE,TRUE);
5582 emitcode("add","a,acc");
5583 if (sameRegs(AOP(left),AOP(result)) &&
5584 size >= MSB16+offr && offr != LSB )
5585 emitcode("xch","a,%s",
5586 aopGet(AOP(left),LSB+offr,FALSE,FALSE,FALSE));
5588 aopPut(AOP(result),"a",LSB+offr);
5591 if(size >= MSB16+offr){
5592 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5593 l = aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE);
5596 emitcode("rlc","a");
5597 if (sameRegs(AOP(left),AOP(result)) &&
5598 size >= MSB24+offr && offr != LSB)
5599 emitcode("xch","a,%s",
5600 aopGet(AOP(left),MSB16+offr,FALSE,FALSE,FALSE));
5602 aopPut(AOP(result),"a",MSB16+offr);
5605 if(size >= MSB24+offr){
5606 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5607 l = aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE);
5610 emitcode("rlc","a");
5611 if (sameRegs(AOP(left),AOP(result)) &&
5612 size >= MSB32+offr && offr != LSB )
5613 emitcode("xch","a,%s",
5614 aopGet(AOP(left),MSB24+offr,FALSE,FALSE,FALSE));
5616 aopPut(AOP(result),"a",MSB24+offr);
5619 if(size > MSB32+offr){
5620 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5621 l = aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE);
5624 emitcode("rlc","a");
5625 aopPut(AOP(result),"a",MSB32+offr);
5628 aopPut(AOP(result),zero,LSB);
5631 /*-----------------------------------------------------------------*/
5632 /* genlshFour - shift four byte by a known amount != 0 */
5633 /*-----------------------------------------------------------------*/
5634 static void genlshFour (operand *result, operand *left, int shCount)
5638 D(emitcode(";", "genlshFour "););
5640 size = AOP_SIZE(result);
5642 /* if shifting more that 3 bytes */
5643 if (shCount >= 24 ) {
5646 /* lowest order of left goes to the highest
5647 order of the destination */
5648 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5650 movLeft2Result(left, LSB, result, MSB32, 0);
5651 aopPut(AOP(result),zero,LSB);
5652 aopPut(AOP(result),zero,MSB16);
5653 aopPut(AOP(result),zero,MSB32);
5657 /* more than two bytes */
5658 else if ( shCount >= 16 ) {
5659 /* lower order two bytes goes to higher order two bytes */
5661 /* if some more remaining */
5663 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5665 movLeft2Result(left, MSB16, result, MSB32, 0);
5666 movLeft2Result(left, LSB, result, MSB24, 0);
5668 aopPut(AOP(result),zero,MSB16);
5669 aopPut(AOP(result),zero,LSB);
5673 /* if more than 1 byte */
5674 else if ( shCount >= 8 ) {
5675 /* lower order three bytes goes to higher order three bytes */
5679 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5681 movLeft2Result(left, LSB, result, MSB16, 0);
5683 else{ /* size = 4 */
5685 movLeft2Result(left, MSB24, result, MSB32, 0);
5686 movLeft2Result(left, MSB16, result, MSB24, 0);
5687 movLeft2Result(left, LSB, result, MSB16, 0);
5688 aopPut(AOP(result),zero,LSB);
5690 else if(shCount == 1)
5691 shiftLLong(left, result, MSB16);
5693 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5694 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5695 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5696 aopPut(AOP(result),zero,LSB);
5701 /* 1 <= shCount <= 7 */
5702 else if(shCount <= 2){
5703 shiftLLong(left, result, LSB);
5705 shiftLLong(result, result, LSB);
5707 /* 3 <= shCount <= 7, optimize */
5709 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5710 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5711 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5715 /*-----------------------------------------------------------------*/
5716 /* genLeftShiftLiteral - left shifting by known count */
5717 /*-----------------------------------------------------------------*/
5718 static void genLeftShiftLiteral (operand *left,
5723 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5726 D(emitcode(";","genLeftShiftLiteral (%d)", shCount););
5728 freeAsmop(right,NULL,ic,TRUE);
5730 aopOp(left,ic,FALSE, FALSE);
5731 aopOp(result,ic,FALSE, TRUE);
5733 size = getSize(operandType(result));
5736 emitcode("; shift left ","result %d, left %d",size,
5740 /* I suppose that the left size >= result size */
5743 movLeft2Result(left, size, result, size, 0);
5747 else if(shCount >= (size * 8))
5749 aopPut(AOP(result),zero,size);
5753 genlshOne (result,left,shCount);
5757 case 3: /* bug: this is for generic pointers, I bet. */
5758 genlshTwo (result,left,shCount);
5762 genlshFour (result,left,shCount);
5766 freeAsmop(left,NULL,ic,TRUE);
5767 freeAsmop(result,NULL,ic,TRUE);
5770 /*-----------------------------------------------------------------*/
5771 /* genLeftShift - generates code for left shifting */
5772 /*-----------------------------------------------------------------*/
5773 static void genLeftShift (iCode *ic)
5775 operand *left,*right, *result;
5778 symbol *tlbl , *tlbl1;
5780 D(emitcode(";", "genLeftShift "););
5782 right = IC_RIGHT(ic);
5784 result = IC_RESULT(ic);
5786 aopOp(right,ic,FALSE, FALSE);
5789 /* if the shift count is known then do it
5790 as efficiently as possible */
5791 if (AOP_TYPE(right) == AOP_LIT) {
5792 genLeftShiftLiteral (left,right,result,ic);
5797 /* shift count is unknown then we have to form
5798 a loop get the loop count in B : Note: we take
5799 only the lower order byte since shifting
5800 more that 32 bits make no sense anyway, ( the
5801 largest size of an object can be only 32 bits ) */
5803 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
5804 emitcode("inc","b");
5805 freeAsmop (right,NULL,ic,TRUE);
5806 aopOp(left,ic,FALSE, FALSE);
5807 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5809 /* now move the left to the result if they are not the
5811 if (!sameRegs(AOP(left),AOP(result)) &&
5812 AOP_SIZE(result) > 1) {
5814 size = AOP_SIZE(result);
5817 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
5818 if (*l == '@' && (IS_AOP_PREG(result))) {
5820 emitcode("mov","a,%s",l);
5821 aopPut(AOP(result),"a",offset);
5823 aopPut(AOP(result),l,offset);
5828 tlbl = newiTempLabel(NULL);
5829 size = AOP_SIZE(result);
5831 tlbl1 = newiTempLabel(NULL);
5833 /* if it is only one byte then */
5835 symbol *tlbl1 = newiTempLabel(NULL);
5837 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
5839 emitcode("sjmp","%05d$",tlbl1->key+100);
5840 emitcode("","%05d$:",tlbl->key+100);
5841 emitcode("add","a,acc");
5842 emitcode("","%05d$:",tlbl1->key+100);
5843 emitcode("djnz","b,%05d$",tlbl->key+100);
5844 aopPut(AOP(result),"a",0);
5848 reAdjustPreg(AOP(result));
5850 emitcode("sjmp","%05d$",tlbl1->key+100);
5851 emitcode("","%05d$:",tlbl->key+100);
5852 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
5854 emitcode("add","a,acc");
5855 aopPut(AOP(result),"a",offset++);
5857 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
5859 emitcode("rlc","a");
5860 aopPut(AOP(result),"a",offset++);
5862 reAdjustPreg(AOP(result));
5864 emitcode("","%05d$:",tlbl1->key+100);
5865 emitcode("djnz","b,%05d$",tlbl->key+100);
5867 freeAsmop(left,NULL,ic,TRUE);
5868 freeAsmop(result,NULL,ic,TRUE);
5871 /*-----------------------------------------------------------------*/
5872 /* genrshOne - right shift a one byte quantity by known count */
5873 /*-----------------------------------------------------------------*/
5874 static void genrshOne (operand *result, operand *left,
5875 int shCount, int sign)
5877 D(emitcode(";", "genrshOne"););
5878 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
5881 /*-----------------------------------------------------------------*/
5882 /* genrshTwo - right shift two bytes by known amount != 0 */
5883 /*-----------------------------------------------------------------*/
5884 static void genrshTwo (operand *result,operand *left,
5885 int shCount, int sign)
5887 D(emitcode(";", "genrshTwo"););
5889 /* if shCount >= 8 */
5893 shiftR1Left2Result(left, MSB16, result, LSB,
5896 movLeft2Result(left, MSB16, result, LSB, sign);
5897 addSign(result, MSB16, sign);
5900 /* 1 <= shCount <= 7 */
5902 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
5905 /*-----------------------------------------------------------------*/
5906 /* shiftRLong - shift right one long from left to result */
5907 /* offl = LSB or MSB16 */
5908 /*-----------------------------------------------------------------*/
5909 static void shiftRLong (operand *left, int offl,
5910 operand *result, int sign)
5913 emitcode("clr","c");
5914 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE));
5916 emitcode("mov","c,acc.7");
5917 emitcode("rrc","a");
5918 aopPut(AOP(result),"a",MSB32-offl);
5920 /* add sign of "a" */
5921 addSign(result, MSB32, sign);
5923 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE));
5924 emitcode("rrc","a");
5925 aopPut(AOP(result),"a",MSB24-offl);
5927 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE));
5928 emitcode("rrc","a");
5929 aopPut(AOP(result),"a",MSB16-offl);
5932 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE,TRUE));
5933 emitcode("rrc","a");
5934 aopPut(AOP(result),"a",LSB);
5938 /*-----------------------------------------------------------------*/
5939 /* genrshFour - shift four byte by a known amount != 0 */
5940 /*-----------------------------------------------------------------*/
5941 static void genrshFour (operand *result, operand *left,
5942 int shCount, int sign)
5944 D(emitcode(";", "genrshFour"););
5946 /* if shifting more that 3 bytes */
5947 if(shCount >= 24 ) {
5950 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
5952 movLeft2Result(left, MSB32, result, LSB, sign);
5953 addSign(result, MSB16, sign);
5955 else if(shCount >= 16){
5958 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
5960 movLeft2Result(left, MSB24, result, LSB, 0);
5961 movLeft2Result(left, MSB32, result, MSB16, sign);
5963 addSign(result, MSB24, sign);
5965 else if(shCount >= 8){
5968 shiftRLong(left, MSB16, result, sign);
5969 else if(shCount == 0){
5970 movLeft2Result(left, MSB16, result, LSB, 0);
5971 movLeft2Result(left, MSB24, result, MSB16, 0);
5972 movLeft2Result(left, MSB32, result, MSB24, sign);
5973 addSign(result, MSB32, sign);
5976 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
5977 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
5978 /* the last shift is signed */
5979 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
5980 addSign(result, MSB32, sign);
5983 else{ /* 1 <= shCount <= 7 */
5985 shiftRLong(left, LSB, result, sign);
5987 shiftRLong(result, LSB, result, sign);
5990 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
5991 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
5992 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
5997 /*-----------------------------------------------------------------*/
5998 /* genRightShiftLiteral - right shifting by known count */
5999 /*-----------------------------------------------------------------*/
6000 static void genRightShiftLiteral (operand *left,
6006 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6009 D(emitcode(";", "genRightShiftLiteral"););
6011 freeAsmop(right,NULL,ic,TRUE);
6013 aopOp(left,ic,FALSE, FALSE);
6014 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6017 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6021 size = getDataSize(left);
6022 /* test the LEFT size !!! */
6024 /* I suppose that the left size >= result size */
6026 size = getDataSize(result);
6028 movLeft2Result(left, size, result, size, 0);
6031 else if(shCount >= (size * 8)){
6033 /* get sign in acc.7 */
6034 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE,TRUE));
6035 addSign(result, LSB, sign);
6039 genrshOne (result,left,shCount,sign);
6043 genrshTwo (result,left,shCount,sign);
6047 genrshFour (result,left,shCount,sign);
6053 freeAsmop(left,NULL,ic,TRUE);
6054 freeAsmop(result,NULL,ic,TRUE);
6058 /*-----------------------------------------------------------------*/
6059 /* genSignedRightShift - right shift of signed number */
6060 /*-----------------------------------------------------------------*/
6061 static void genSignedRightShift (iCode *ic)
6063 operand *right, *left, *result;
6066 symbol *tlbl, *tlbl1 ;
6068 D(emitcode(";", "genSignedRightShift "););
6070 /* we do it the hard way put the shift count in b
6071 and loop thru preserving the sign */
6073 right = IC_RIGHT(ic);
6075 result = IC_RESULT(ic);
6077 aopOp(right,ic,FALSE, FALSE);
6080 if ( AOP_TYPE(right) == AOP_LIT) {
6081 genRightShiftLiteral (left,right,result,ic,1);
6085 /* shift count is unknown then we have to form
6086 a loop get the loop count in B : Note: we take
6087 only the lower order byte since shifting
6088 more that 32 bits make no sense anyway, ( the
6089 largest size of an object can be only 32 bits ) */
6091 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6092 emitcode("inc","b");
6093 freeAsmop (right,NULL,ic,TRUE);
6094 aopOp(left,ic,FALSE, FALSE);
6095 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6097 /* now move the left to the result if they are not the
6099 if (!sameRegs(AOP(left),AOP(result)) &&
6100 AOP_SIZE(result) > 1) {
6102 size = AOP_SIZE(result);
6105 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6106 if (*l == '@' && IS_AOP_PREG(result)) {
6108 emitcode("mov","a,%s",l);
6109 aopPut(AOP(result),"a",offset);
6111 aopPut(AOP(result),l,offset);
6116 /* mov the highest order bit to OVR */
6117 tlbl = newiTempLabel(NULL);
6118 tlbl1= newiTempLabel(NULL);
6120 size = AOP_SIZE(result);
6122 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
6123 emitcode("rlc","a");
6124 emitcode("mov","ov,c");
6125 /* if it is only one byte then */
6127 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6129 emitcode("sjmp","%05d$",tlbl1->key+100);
6130 emitcode("","%05d$:",tlbl->key+100);
6131 emitcode("mov","c,ov");
6132 emitcode("rrc","a");
6133 emitcode("","%05d$:",tlbl1->key+100);
6134 emitcode("djnz","b,%05d$",tlbl->key+100);
6135 aopPut(AOP(result),"a",0);
6139 reAdjustPreg(AOP(result));
6140 emitcode("sjmp","%05d$",tlbl1->key+100);
6141 emitcode("","%05d$:",tlbl->key+100);
6142 emitcode("mov","c,ov");
6144 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6146 emitcode("rrc","a");
6147 aopPut(AOP(result),"a",offset--);
6149 reAdjustPreg(AOP(result));
6150 emitcode("","%05d$:",tlbl1->key+100);
6151 emitcode("djnz","b,%05d$",tlbl->key+100);
6154 freeAsmop(left,NULL,ic,TRUE);
6155 freeAsmop(result,NULL,ic,TRUE);
6158 /*-----------------------------------------------------------------*/
6159 /* genRightShift - generate code for right shifting */
6160 /*-----------------------------------------------------------------*/
6161 static void genRightShift (iCode *ic)
6163 operand *right, *left, *result;
6167 symbol *tlbl, *tlbl1 ;
6169 D(emitcode(";", "genRightShift "););
6171 /* if signed then we do it the hard way preserve the
6172 sign bit moving it inwards */
6173 retype = getSpec(operandType(IC_RESULT(ic)));
6175 if (!SPEC_USIGN(retype)) {
6176 genSignedRightShift (ic);
6180 /* signed & unsigned types are treated the same : i.e. the
6181 signed is NOT propagated inwards : quoting from the
6182 ANSI - standard : "for E1 >> E2, is equivalent to division
6183 by 2**E2 if unsigned or if it has a non-negative value,
6184 otherwise the result is implementation defined ", MY definition
6185 is that the sign does not get propagated */
6187 right = IC_RIGHT(ic);
6189 result = IC_RESULT(ic);
6191 aopOp(right,ic,FALSE, FALSE);
6194 /* if the shift count is known then do it
6195 as efficiently as possible */
6196 if (AOP_TYPE(right) == AOP_LIT) {
6197 genRightShiftLiteral (left,right,result,ic, 0);
6202 /* shift count is unknown then we have to form
6203 a loop get the loop count in B : Note: we take
6204 only the lower order byte since shifting
6205 more that 32 bits make no sense anyway, ( the
6206 largest size of an object can be only 32 bits ) */
6208 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6209 emitcode("inc","b");
6210 freeAsmop (right,NULL,ic,TRUE);
6211 aopOp(left,ic,FALSE, FALSE);
6212 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6214 /* now move the left to the result if they are not the
6216 if (!sameRegs(AOP(left),AOP(result)) &&
6217 AOP_SIZE(result) > 1) {
6219 size = AOP_SIZE(result);
6222 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6223 if (*l == '@' && IS_AOP_PREG(result)) {
6225 emitcode("mov","a,%s",l);
6226 aopPut(AOP(result),"a",offset);
6228 aopPut(AOP(result),l,offset);
6233 tlbl = newiTempLabel(NULL);
6234 tlbl1= newiTempLabel(NULL);
6235 size = AOP_SIZE(result);
6238 /* if it is only one byte then */
6240 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6242 emitcode("sjmp","%05d$",tlbl1->key+100);
6243 emitcode("","%05d$:",tlbl->key+100);
6245 emitcode("rrc","a");
6246 emitcode("","%05d$:",tlbl1->key+100);
6247 emitcode("djnz","b,%05d$",tlbl->key+100);
6248 aopPut(AOP(result),"a",0);
6252 reAdjustPreg(AOP(result));
6253 emitcode("sjmp","%05d$",tlbl1->key+100);
6254 emitcode("","%05d$:",tlbl->key+100);
6257 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6259 emitcode("rrc","a");
6260 aopPut(AOP(result),"a",offset--);
6262 reAdjustPreg(AOP(result));
6264 emitcode("","%05d$:",tlbl1->key+100);
6265 emitcode("djnz","b,%05d$",tlbl->key+100);
6268 freeAsmop(left,NULL,ic,TRUE);
6269 freeAsmop(result,NULL,ic,TRUE);
6272 /*-----------------------------------------------------------------*/
6273 /* genUnpackBits - generates code for unpacking bits */
6274 /*-----------------------------------------------------------------*/
6275 static void genUnpackBits (operand *result, char *rname, int ptype)
6282 D(emitcode(";", "genUnpackBits "););
6284 etype = getSpec(operandType(result));
6286 /* read the first byte */
6291 emitcode("mov","a,@%s",rname);
6295 emitcode("movx","a,@%s",rname);
6299 emitcode("movx","a,@dptr");
6303 emitcode("clr","a");
6304 emitcode("movc","a","@a+dptr");
6308 emitcode("lcall","__gptrget");
6312 /* if we have bitdisplacement then it fits */
6313 /* into this byte completely or if length is */
6314 /* less than a byte */
6315 if ((shCnt = SPEC_BSTR(etype)) ||
6316 (SPEC_BLEN(etype) <= 8)) {
6318 /* shift right acc */
6321 emitcode("anl","a,#0x%02x",
6322 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6323 aopPut(AOP(result),"a",offset);
6327 /* bit field did not fit in a byte */
6328 rlen = SPEC_BLEN(etype) - 8;
6329 aopPut(AOP(result),"a",offset++);
6336 emitcode("inc","%s",rname);
6337 emitcode("mov","a,@%s",rname);
6341 emitcode("inc","%s",rname);
6342 emitcode("movx","a,@%s",rname);
6346 emitcode("inc","dptr");
6347 emitcode("movx","a,@dptr");
6351 emitcode("clr","a");
6352 emitcode("inc","dptr");
6353 emitcode("movc","a","@a+dptr");
6357 emitcode("inc","dptr");
6358 emitcode("lcall","__gptrget");
6363 /* if we are done */
6367 aopPut(AOP(result),"a",offset++);
6372 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
6373 aopPut(AOP(result),"a",offset);
6380 /*-----------------------------------------------------------------*/
6381 /* genDataPointerGet - generates code when ptr offset is known */
6382 /*-----------------------------------------------------------------*/
6383 static void genDataPointerGet (operand *left,
6389 int size , offset = 0;
6390 aopOp(result,ic,TRUE, FALSE);
6392 /* get the string representation of the name */
6393 l = aopGet(AOP(left),0,FALSE,TRUE,FALSE);
6394 size = AOP_SIZE(result);
6397 sprintf(buffer,"(%s + %d)",l+1,offset);
6399 sprintf(buffer,"%s",l+1);
6400 aopPut(AOP(result),buffer,offset++);
6403 freeAsmop(left,NULL,ic,TRUE);
6404 freeAsmop(result,NULL,ic,TRUE);
6407 /*-----------------------------------------------------------------*/
6408 /* genNearPointerGet - emitcode for near pointer fetch */
6409 /*-----------------------------------------------------------------*/
6410 static void genNearPointerGet (operand *left,
6417 link *rtype, *retype;
6418 link *ltype = operandType(left);
6421 rtype = operandType(result);
6422 retype= getSpec(rtype);
6424 aopOp(left,ic,FALSE, FALSE);
6426 /* if left is rematerialisable and
6427 result is not bit variable type and
6428 the left is pointer to data space i.e
6429 lower 128 bytes of space */
6430 if (AOP_TYPE(left) == AOP_IMMD &&
6431 !IS_BITVAR(retype) &&
6432 DCL_TYPE(ltype) == POINTER) {
6433 genDataPointerGet (left,result,ic);
6437 /* if the value is already in a pointer register
6438 then don't need anything more */
6439 if (!AOP_INPREG(AOP(left))) {
6440 /* otherwise get a free pointer register */
6442 preg = getFreePtr(ic,&aop,FALSE);
6443 emitcode("mov","%s,%s",
6445 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6446 rname = preg->name ;
6448 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6450 freeAsmop(left,NULL,ic,TRUE);
6451 aopOp (result,ic,FALSE, FALSE);
6453 /* if bitfield then unpack the bits */
6454 if (IS_BITVAR(retype))
6455 genUnpackBits (result,rname,POINTER);
6457 /* we have can just get the values */
6458 int size = AOP_SIZE(result);
6462 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6464 emitcode("mov","a,@%s",rname);
6465 aopPut(AOP(result),"a",offset);
6467 sprintf(buffer,"@%s",rname);
6468 aopPut(AOP(result),buffer,offset);
6472 emitcode("inc","%s",rname);
6476 /* now some housekeeping stuff */
6478 /* we had to allocate for this iCode */
6479 freeAsmop(NULL,aop,ic,TRUE);
6481 /* we did not allocate which means left
6482 already in a pointer register, then
6483 if size > 0 && this could be used again
6484 we have to point it back to where it
6486 if (AOP_SIZE(result) > 1 &&
6487 !OP_SYMBOL(left)->remat &&
6488 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6490 int size = AOP_SIZE(result) - 1;
6492 emitcode("dec","%s",rname);
6497 freeAsmop(result,NULL,ic,TRUE);
6501 /*-----------------------------------------------------------------*/
6502 /* genPagedPointerGet - emitcode for paged pointer fetch */
6503 /*-----------------------------------------------------------------*/
6504 static void genPagedPointerGet (operand *left,
6511 link *rtype, *retype;
6513 rtype = operandType(result);
6514 retype= getSpec(rtype);
6516 aopOp(left,ic,FALSE, FALSE);
6518 /* if the value is already in a pointer register
6519 then don't need anything more */
6520 if (!AOP_INPREG(AOP(left))) {
6521 /* otherwise get a free pointer register */
6523 preg = getFreePtr(ic,&aop,FALSE);
6524 emitcode("mov","%s,%s",
6526 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6527 rname = preg->name ;
6529 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6531 freeAsmop(left,NULL,ic,TRUE);
6532 aopOp (result,ic,FALSE, FALSE);
6534 /* if bitfield then unpack the bits */
6535 if (IS_BITVAR(retype))
6536 genUnpackBits (result,rname,PPOINTER);
6538 /* we have can just get the values */
6539 int size = AOP_SIZE(result);
6544 emitcode("movx","a,@%s",rname);
6545 aopPut(AOP(result),"a",offset);
6550 emitcode("inc","%s",rname);
6554 /* now some housekeeping stuff */
6556 /* we had to allocate for this iCode */
6557 freeAsmop(NULL,aop,ic,TRUE);
6559 /* we did not allocate which means left
6560 already in a pointer register, then
6561 if size > 0 && this could be used again
6562 we have to point it back to where it
6564 if (AOP_SIZE(result) > 1 &&
6565 !OP_SYMBOL(left)->remat &&
6566 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6568 int size = AOP_SIZE(result) - 1;
6570 emitcode("dec","%s",rname);
6575 freeAsmop(result,NULL,ic,TRUE);
6580 /*-----------------------------------------------------------------*/
6581 /* genFarPointerGet - gget value from far space */
6582 /*-----------------------------------------------------------------*/
6583 static void genFarPointerGet (operand *left,
6584 operand *result, iCode *ic)
6587 link *retype = getSpec(operandType(result));
6589 D(emitcode(";", "genFarPointerGet"););
6591 aopOp(left,ic,FALSE, FALSE);
6593 /* if the operand is already in dptr
6594 then we do nothing else we move the value to dptr */
6595 if (AOP_TYPE(left) != AOP_STR) {
6596 /* if this is remateriazable */
6597 if (AOP_TYPE(left) == AOP_IMMD)
6599 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6603 /* we need to get it byte by byte */
6604 if (AOP_TYPE(left) != AOP_DPTR)
6606 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6607 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6608 if (options.model == MODEL_FLAT24)
6610 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6615 /* We need to generate a load to DPTR indirect through DPTR. */
6616 D(emitcode(";", "genFarPointerGet -- indirection special case."););
6617 emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE,TRUE));
6618 emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE,TRUE));
6619 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6620 emitcode("pop", "dph");
6621 emitcode("pop", "dpl");
6625 /* so dptr know contains the address */
6626 freeAsmop(left,NULL,ic,TRUE);
6627 aopOp(result,ic,FALSE, TRUE);
6629 /* if bit then unpack */
6630 if (IS_BITVAR(retype))
6631 genUnpackBits(result,"dptr",FPOINTER);
6633 size = AOP_SIZE(result);
6637 emitcode("movx","a,@dptr");
6638 aopPut(AOP(result),"a",offset++);
6640 emitcode("inc","dptr");
6644 freeAsmop(result,NULL,ic,TRUE);
6647 /*-----------------------------------------------------------------*/
6648 /* emitcodePointerGet - gget value from code space */
6649 /*-----------------------------------------------------------------*/
6650 static void emitcodePointerGet (operand *left,
6651 operand *result, iCode *ic)
6654 link *retype = getSpec(operandType(result));
6656 aopOp(left,ic,FALSE, FALSE);
6658 /* if the operand is already in dptr
6659 then we do nothing else we move the value to dptr */
6660 if (AOP_TYPE(left) != AOP_STR) {
6661 /* if this is remateriazable */
6662 if (AOP_TYPE(left) == AOP_IMMD)
6663 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6664 else { /* we need to get it byte by byte */
6665 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6666 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6667 if (options.model == MODEL_FLAT24)
6669 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6673 /* so dptr know contains the address */
6674 freeAsmop(left,NULL,ic,TRUE);
6675 aopOp(result,ic,FALSE, FALSE);
6677 /* if bit then unpack */
6678 if (IS_BITVAR(retype))
6679 genUnpackBits(result,"dptr",CPOINTER);
6681 size = AOP_SIZE(result);
6685 emitcode("clr","a");
6686 emitcode("movc","a,@a+dptr");
6687 aopPut(AOP(result),"a",offset++);
6689 emitcode("inc","dptr");
6693 freeAsmop(result,NULL,ic,TRUE);
6696 /*-----------------------------------------------------------------*/
6697 /* genGenPointerGet - gget value from generic pointer space */
6698 /*-----------------------------------------------------------------*/
6699 static void genGenPointerGet (operand *left,
6700 operand *result, iCode *ic)
6703 link *retype = getSpec(operandType(result));
6705 aopOp(left,ic,FALSE, TRUE);
6707 /* if the operand is already in dptr
6708 then we do nothing else we move the value to dptr */
6709 if (AOP_TYPE(left) != AOP_STR) {
6710 /* if this is remateriazable */
6711 if (AOP_TYPE(left) == AOP_IMMD) {
6712 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6713 emitcode("mov","b,#%d",pointerCode(retype));
6715 else { /* we need to get it byte by byte */
6716 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6717 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6718 if (options.model == MODEL_FLAT24)
6720 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6721 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE,TRUE));
6725 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6729 /* so dptr know contains the address */
6730 freeAsmop(left,NULL,ic,TRUE);
6731 aopOp(result,ic,FALSE, TRUE);
6733 /* if bit then unpack */
6734 if (IS_BITVAR(retype))
6735 genUnpackBits(result,"dptr",GPOINTER);
6737 size = AOP_SIZE(result);
6741 emitcode("lcall","__gptrget");
6742 aopPut(AOP(result),"a",offset++);
6744 emitcode("inc","dptr");
6748 freeAsmop(result,NULL,ic,TRUE);
6751 /*-----------------------------------------------------------------*/
6752 /* genPointerGet - generate code for pointer get */
6753 /*-----------------------------------------------------------------*/
6754 static void genPointerGet (iCode *ic)
6756 operand *left, *result ;
6760 D(emitcode(";", "genPointerGet "););
6763 result = IC_RESULT(ic) ;
6765 /* depending on the type of pointer we need to
6766 move it to the correct pointer register */
6767 type = operandType(left);
6768 etype = getSpec(type);
6769 /* if left is of type of pointer then it is simple */
6770 if (IS_PTR(type) && !IS_FUNC(type->next))
6771 p_type = DCL_TYPE(type);
6773 /* we have to go by the storage class */
6774 p_type = PTR_TYPE(SPEC_OCLS(etype));
6776 /* if (SPEC_OCLS(etype)->codesp ) { */
6777 /* p_type = CPOINTER ; */
6780 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6781 /* p_type = FPOINTER ; */
6783 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6784 /* p_type = PPOINTER; */
6786 /* if (SPEC_OCLS(etype) == idata ) */
6787 /* p_type = IPOINTER; */
6789 /* p_type = POINTER ; */
6792 /* now that we have the pointer type we assign
6793 the pointer values */
6798 genNearPointerGet (left,result,ic);
6802 genPagedPointerGet(left,result,ic);
6806 genFarPointerGet (left,result,ic);
6810 emitcodePointerGet (left,result,ic);
6814 genGenPointerGet (left,result,ic);
6820 /*-----------------------------------------------------------------*/
6821 /* genPackBits - generates code for packed bit storage */
6822 /*-----------------------------------------------------------------*/
6823 static void genPackBits (link *etype ,
6825 char *rname, int p_type)
6833 blen = SPEC_BLEN(etype);
6834 bstr = SPEC_BSTR(etype);
6836 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
6839 /* if the bit lenth is less than or */
6840 /* it exactly fits a byte then */
6841 if (SPEC_BLEN(etype) <= 8 ) {
6842 shCount = SPEC_BSTR(etype) ;
6844 /* shift left acc */
6847 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6852 emitcode ("mov","b,a");
6853 emitcode("mov","a,@%s",rname);
6857 emitcode ("mov","b,a");
6858 emitcode("movx","a,@dptr");
6862 emitcode ("push","b");
6863 emitcode ("push","acc");
6864 emitcode ("lcall","__gptrget");
6865 emitcode ("pop","b");
6869 emitcode ("anl","a,#0x%02x",(unsigned char)
6870 ((unsigned char)(0xFF << (blen+bstr)) |
6871 (unsigned char)(0xFF >> (8-bstr)) ) );
6872 emitcode ("orl","a,b");
6873 if (p_type == GPOINTER)
6874 emitcode("pop","b");
6880 emitcode("mov","@%s,a",rname);
6884 emitcode("movx","@dptr,a");
6888 emitcode("lcall","__gptrput");
6893 if ( SPEC_BLEN(etype) <= 8 )
6896 emitcode("inc","%s",rname);
6897 rLen = SPEC_BLEN(etype) ;
6899 /* now generate for lengths greater than one byte */
6902 l = aopGet(AOP(right),offset++,FALSE,TRUE,FALSE);
6912 emitcode("mov","@%s,a",rname);
6914 emitcode("mov","@%s,%s",rname,l);
6919 emitcode("movx","@dptr,a");
6924 emitcode("lcall","__gptrput");
6927 emitcode ("inc","%s",rname);
6932 /* last last was not complete */
6934 /* save the byte & read byte */
6937 emitcode ("mov","b,a");
6938 emitcode("mov","a,@%s",rname);
6942 emitcode ("mov","b,a");
6943 emitcode("movx","a,@dptr");
6947 emitcode ("push","b");
6948 emitcode ("push","acc");
6949 emitcode ("lcall","__gptrget");
6950 emitcode ("pop","b");
6954 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
6955 emitcode ("orl","a,b");
6958 if (p_type == GPOINTER)
6959 emitcode("pop","b");
6964 emitcode("mov","@%s,a",rname);
6968 emitcode("movx","@dptr,a");
6972 emitcode("lcall","__gptrput");
6976 /*-----------------------------------------------------------------*/
6977 /* genDataPointerSet - remat pointer to data space */
6978 /*-----------------------------------------------------------------*/
6979 static void genDataPointerSet(operand *right,
6983 int size, offset = 0 ;
6984 char *l, buffer[256];
6986 aopOp(right,ic,FALSE, FALSE);
6988 l = aopGet(AOP(result),0,FALSE,TRUE,FALSE);
6989 size = AOP_SIZE(right);
6992 sprintf(buffer,"(%s + %d)",l+1,offset);
6994 sprintf(buffer,"%s",l+1);
6995 emitcode("mov","%s,%s",buffer,
6996 aopGet(AOP(right),offset++,FALSE,FALSE,FALSE));
6999 freeAsmop(right,NULL,ic,TRUE);
7000 freeAsmop(result,NULL,ic,TRUE);
7003 /*-----------------------------------------------------------------*/
7004 /* genNearPointerSet - emitcode for near pointer put */
7005 /*-----------------------------------------------------------------*/
7006 static void genNearPointerSet (operand *right,
7014 link *ptype = operandType(result);
7016 retype= getSpec(operandType(right));
7018 aopOp(result,ic,FALSE, FALSE);
7020 /* if the result is rematerializable &
7021 in data space & not a bit variable */
7022 if (AOP_TYPE(result) == AOP_IMMD &&
7023 DCL_TYPE(ptype) == POINTER &&
7024 !IS_BITVAR(retype)) {
7025 genDataPointerSet (right,result,ic);
7029 /* if the value is already in a pointer register
7030 then don't need anything more */
7031 if (!AOP_INPREG(AOP(result))) {
7032 /* otherwise get a free pointer register */
7034 preg = getFreePtr(ic,&aop,FALSE);
7035 emitcode("mov","%s,%s",
7037 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7038 rname = preg->name ;
7040 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7042 freeAsmop(result,NULL,ic,TRUE);
7043 aopOp (right,ic,FALSE, FALSE);
7045 /* if bitfield then unpack the bits */
7046 if (IS_BITVAR(retype))
7047 genPackBits (retype,right,rname,POINTER);
7049 /* we have can just get the values */
7050 int size = AOP_SIZE(right);
7054 l = aopGet(AOP(right),offset,FALSE,TRUE,FALSE);
7057 emitcode("mov","@%s,a",rname);
7059 emitcode("mov","@%s,%s",rname,l);
7061 emitcode("inc","%s",rname);
7066 /* now some housekeeping stuff */
7068 /* we had to allocate for this iCode */
7069 freeAsmop(NULL,aop,ic,TRUE);
7071 /* we did not allocate which means left
7072 already in a pointer register, then
7073 if size > 0 && this could be used again
7074 we have to point it back to where it
7076 if (AOP_SIZE(right) > 1 &&
7077 !OP_SYMBOL(result)->remat &&
7078 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7080 int size = AOP_SIZE(right) - 1;
7082 emitcode("dec","%s",rname);
7087 freeAsmop(right,NULL,ic,TRUE);
7092 /*-----------------------------------------------------------------*/
7093 /* genPagedPointerSet - emitcode for Paged pointer put */
7094 /*-----------------------------------------------------------------*/
7095 static void genPagedPointerSet (operand *right,
7104 retype= getSpec(operandType(right));
7106 aopOp(result,ic,FALSE, FALSE);
7108 /* if the value is already in a pointer register
7109 then don't need anything more */
7110 if (!AOP_INPREG(AOP(result))) {
7111 /* otherwise get a free pointer register */
7113 preg = getFreePtr(ic,&aop,FALSE);
7114 emitcode("mov","%s,%s",
7116 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7117 rname = preg->name ;
7119 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7121 freeAsmop(result,NULL,ic,TRUE);
7122 aopOp (right,ic,FALSE, FALSE);
7124 /* if bitfield then unpack the bits */
7125 if (IS_BITVAR(retype))
7126 genPackBits (retype,right,rname,PPOINTER);
7128 /* we have can just get the values */
7129 int size = AOP_SIZE(right);
7133 l = aopGet(AOP(right),offset,FALSE,TRUE,TRUE);
7136 emitcode("movx","@%s,a",rname);
7139 emitcode("inc","%s",rname);
7145 /* now some housekeeping stuff */
7147 /* we had to allocate for this iCode */
7148 freeAsmop(NULL,aop,ic,TRUE);
7150 /* we did not allocate which means left
7151 already in a pointer register, then
7152 if size > 0 && this could be used again
7153 we have to point it back to where it
7155 if (AOP_SIZE(right) > 1 &&
7156 !OP_SYMBOL(result)->remat &&
7157 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7159 int size = AOP_SIZE(right) - 1;
7161 emitcode("dec","%s",rname);
7166 freeAsmop(right,NULL,ic,TRUE);
7171 /*-----------------------------------------------------------------*/
7172 /* genFarPointerSet - set value from far space */
7173 /*-----------------------------------------------------------------*/
7174 static void genFarPointerSet (operand *right,
7175 operand *result, iCode *ic)
7178 link *retype = getSpec(operandType(right));
7180 aopOp(result,ic,FALSE, FALSE);
7182 /* if the operand is already in dptr
7183 then we do nothing else we move the value to dptr */
7184 if (AOP_TYPE(result) != AOP_STR) {
7185 /* if this is remateriazable */
7186 if (AOP_TYPE(result) == AOP_IMMD)
7187 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7190 /* we need to get it byte by byte */
7191 if (AOP_TYPE(result) != AOP_DPTR)
7193 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7194 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7195 if (options.model == MODEL_FLAT24)
7197 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7202 /* We need to generate a load to DPTR indirect through DPTR. */
7203 D(emitcode(";", "genFarPointerSet -- indirection special case."););
7204 emitcode("push", "%s", aopGet(AOP(result),0,FALSE,TRUE,TRUE));
7205 emitcode("push", "%s", aopGet(AOP(result),1,FALSE,TRUE,TRUE));
7206 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7207 emitcode("pop", "dph");
7208 emitcode("pop", "dpl");
7212 /* so dptr know contains the address */
7213 freeAsmop(result,NULL,ic,TRUE);
7214 aopOp(right,ic,FALSE, TRUE);
7216 /* if bit then unpack */
7217 if (IS_BITVAR(retype))
7218 genPackBits(retype,right,"dptr",FPOINTER);
7220 size = AOP_SIZE(right);
7224 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7226 emitcode("movx","@dptr,a");
7228 emitcode("inc","dptr");
7232 freeAsmop(right,NULL,ic,TRUE);
7235 /*-----------------------------------------------------------------*/
7236 /* genGenPointerSet - set value from generic pointer space */
7237 /*-----------------------------------------------------------------*/
7238 static void genGenPointerSet (operand *right,
7239 operand *result, iCode *ic)
7242 link *retype = getSpec(operandType(right));
7244 aopOp(result,ic,FALSE, TRUE);
7246 /* if the operand is already in dptr
7247 then we do nothing else we move the value to dptr */
7248 if (AOP_TYPE(result) != AOP_STR) {
7249 /* if this is remateriazable */
7250 if (AOP_TYPE(result) == AOP_IMMD) {
7251 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7252 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7254 else { /* we need to get it byte by byte */
7255 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7256 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7257 if (options.model == MODEL_FLAT24)
7259 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7260 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE,TRUE));
7264 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7268 /* so dptr know contains the address */
7269 freeAsmop(result,NULL,ic,TRUE);
7270 aopOp(right,ic,FALSE, TRUE);
7272 /* if bit then unpack */
7273 if (IS_BITVAR(retype))
7274 genPackBits(retype,right,"dptr",GPOINTER);
7276 size = AOP_SIZE(right);
7280 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7282 emitcode("lcall","__gptrput");
7284 emitcode("inc","dptr");
7288 freeAsmop(right,NULL,ic,TRUE);
7291 /*-----------------------------------------------------------------*/
7292 /* genPointerSet - stores the value into a pointer location */
7293 /*-----------------------------------------------------------------*/
7294 static void genPointerSet (iCode *ic)
7296 operand *right, *result ;
7300 D(emitcode(";", "genPointerSet "););
7302 right = IC_RIGHT(ic);
7303 result = IC_RESULT(ic) ;
7305 /* depending on the type of pointer we need to
7306 move it to the correct pointer register */
7307 type = operandType(result);
7308 etype = getSpec(type);
7309 /* if left is of type of pointer then it is simple */
7310 if (IS_PTR(type) && !IS_FUNC(type->next)) {
7311 p_type = DCL_TYPE(type);
7314 /* we have to go by the storage class */
7315 p_type = PTR_TYPE(SPEC_OCLS(etype));
7317 /* if (SPEC_OCLS(etype)->codesp ) { */
7318 /* p_type = CPOINTER ; */
7321 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7322 /* p_type = FPOINTER ; */
7324 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7325 /* p_type = PPOINTER ; */
7327 /* if (SPEC_OCLS(etype) == idata ) */
7328 /* p_type = IPOINTER ; */
7330 /* p_type = POINTER ; */
7333 /* now that we have the pointer type we assign
7334 the pointer values */
7339 genNearPointerSet (right,result,ic);
7343 genPagedPointerSet (right,result,ic);
7347 genFarPointerSet (right,result,ic);
7351 genGenPointerSet (right,result,ic);
7357 /*-----------------------------------------------------------------*/
7358 /* genIfx - generate code for Ifx statement */
7359 /*-----------------------------------------------------------------*/
7360 static void genIfx (iCode *ic, iCode *popIc)
7362 operand *cond = IC_COND(ic);
7365 D(emitcode(";", "genIfx "););
7367 aopOp(cond,ic,FALSE, FALSE);
7369 /* get the value into acc */
7370 if (AOP_TYPE(cond) != AOP_CRY)
7374 /* the result is now in the accumulator */
7375 freeAsmop(cond,NULL,ic,TRUE);
7377 /* if there was something to be popped then do it */
7381 /* if the condition is a bit variable */
7382 if (isbit && IS_ITEMP(cond) &&
7384 genIfxJump(ic,SPIL_LOC(cond)->rname);
7386 if (isbit && !IS_ITEMP(cond))
7387 genIfxJump(ic,OP_SYMBOL(cond)->rname);
7394 /*-----------------------------------------------------------------*/
7395 /* genAddrOf - generates code for address of */
7396 /*-----------------------------------------------------------------*/
7397 static void genAddrOf (iCode *ic)
7399 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7402 D(emitcode(";", "genAddrOf "););
7404 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7406 /* if the operand is on the stack then we
7407 need to get the stack offset of this
7410 /* if it has an offset then we need to compute
7413 emitcode("mov","a,_bp");
7414 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7415 aopPut(AOP(IC_RESULT(ic)),"a",0);
7417 /* we can just move _bp */
7418 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7420 /* fill the result with zero */
7421 size = AOP_SIZE(IC_RESULT(ic)) - 1;
7424 if (options.stack10bit && size < (FPTRSIZE - 1))
7427 "*** warning: pointer to stack var truncated.\n");
7434 if (options.stack10bit && offset == 2)
7436 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7440 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7447 /* object not on stack then we need the name */
7448 size = AOP_SIZE(IC_RESULT(ic));
7452 char s[SDCC_NAME_MAX];
7454 sprintf(s,"#(%s >> %d)",
7458 sprintf(s,"#%s",sym->rname);
7459 aopPut(AOP(IC_RESULT(ic)),s,offset++);
7463 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7467 /*-----------------------------------------------------------------*/
7468 /* genFarFarAssign - assignment when both are in far space */
7469 /*-----------------------------------------------------------------*/
7470 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7472 int size = AOP_SIZE(right);
7475 /* first push the right side on to the stack */
7477 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7479 emitcode ("push","acc");
7482 D(emitcode(";", "genFarFarAssign "););
7484 freeAsmop(right,NULL,ic,FALSE);
7485 /* now assign DPTR to result */
7486 aopOp(result,ic,FALSE, FALSE);
7487 size = AOP_SIZE(result);
7489 emitcode ("pop","acc");
7490 aopPut(AOP(result),"a",--offset);
7492 freeAsmop(result,NULL,ic,FALSE);
7496 /*-----------------------------------------------------------------*/
7497 /* genAssign - generate code for assignment */
7498 /*-----------------------------------------------------------------*/
7499 static void genAssign (iCode *ic)
7501 operand *result, *right;
7503 unsigned long lit = 0L;
7505 D(emitcode(";", "genAssign "););
7507 result = IC_RESULT(ic);
7508 right = IC_RIGHT(ic) ;
7510 /* if they are the same */
7511 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7514 aopOp(right,ic,FALSE, FALSE);
7516 emitcode(";", "genAssign: resultIsFar = %s",
7517 isOperandInFarSpace(result) ?
7520 /* special case both in far space */
7521 if ((AOP_TYPE(right) == AOP_DPTR ||
7522 AOP_TYPE(right) == AOP_DPTR2) &&
7523 /* IS_TRUE_SYMOP(result) && */
7524 isOperandInFarSpace(result)) {
7526 genFarFarAssign (result,right,ic);
7530 aopOp(result,ic,TRUE, FALSE);
7532 /* if they are the same registers */
7533 if (sameRegs(AOP(right),AOP(result)))
7536 /* if the result is a bit */
7537 if (AOP_TYPE(result) == AOP_CRY) {
7539 /* if the right size is a literal then
7540 we know what the value is */
7541 if (AOP_TYPE(right) == AOP_LIT) {
7542 if (((int) operandLitValue(right)))
7543 aopPut(AOP(result),one,0);
7545 aopPut(AOP(result),zero,0);
7549 /* the right is also a bit variable */
7550 if (AOP_TYPE(right) == AOP_CRY) {
7551 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7552 aopPut(AOP(result),"c",0);
7558 aopPut(AOP(result),"a",0);
7562 /* bit variables done */
7564 size = AOP_SIZE(result);
7566 if(AOP_TYPE(right) == AOP_LIT)
7567 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7569 (AOP_TYPE(result) != AOP_REG) &&
7570 (AOP_TYPE(right) == AOP_LIT) &&
7571 !IS_FLOAT(operandType(right)) &&
7573 emitcode("clr","a");
7575 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7576 aopPut(AOP(result),"a",size);
7579 aopGet(AOP(right),size,FALSE,FALSE,FALSE),
7585 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7592 freeAsmop (right,NULL,ic,FALSE);
7593 freeAsmop (result,NULL,ic,TRUE);
7596 /*-----------------------------------------------------------------*/
7597 /* genJumpTab - genrates code for jump table */
7598 /*-----------------------------------------------------------------*/
7599 static void genJumpTab (iCode *ic)
7604 D(emitcode(";", "genJumpTab "););
7606 aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
7607 /* get the condition into accumulator */
7608 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE,TRUE);
7610 /* multiply by four! */
7611 emitcode("add","a,acc");
7612 emitcode("add","a,acc");
7613 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7615 jtab = newiTempLabel(NULL);
7616 emitcode("mov","dptr,#%05d$",jtab->key+100);
7617 emitcode("jmp","@a+dptr");
7618 emitcode("","%05d$:",jtab->key+100);
7619 /* now generate the jump labels */
7620 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
7621 jtab = setNextItem(IC_JTLABELS(ic)))
7622 emitcode("ljmp","%05d$",jtab->key+100);
7626 /*-----------------------------------------------------------------*/
7627 /* genCast - gen code for casting */
7628 /*-----------------------------------------------------------------*/
7629 static void genCast (iCode *ic)
7631 operand *result = IC_RESULT(ic);
7632 link *ctype = operandType(IC_LEFT(ic));
7633 link *rtype = operandType(IC_RIGHT(ic));
7634 operand *right = IC_RIGHT(ic);
7637 D(emitcode(";", "genCast "););
7639 /* if they are equivalent then do nothing */
7640 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
7643 aopOp(right,ic,FALSE, FALSE) ;
7644 aopOp(result,ic,FALSE, AOP_TYPE(right) == AOP_DPTR);
7646 /* if the result is a bit */
7647 if (AOP_TYPE(result) == AOP_CRY) {
7648 /* if the right size is a literal then
7649 we know what the value is */
7650 if (AOP_TYPE(right) == AOP_LIT) {
7651 if (((int) operandLitValue(right)))
7652 aopPut(AOP(result),one,0);
7654 aopPut(AOP(result),zero,0);
7659 /* the right is also a bit variable */
7660 if (AOP_TYPE(right) == AOP_CRY) {
7661 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7662 aopPut(AOP(result),"c",0);
7668 aopPut(AOP(result),"a",0);
7672 /* if they are the same size : or less */
7673 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
7675 /* if they are in the same place */
7676 if (sameRegs(AOP(right),AOP(result)))
7679 /* if they in different places then copy */
7680 size = AOP_SIZE(result);
7684 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7692 /* if the result is of type pointer */
7693 if (IS_PTR(ctype)) {
7696 link *type = operandType(right);
7698 /* pointer to generic pointer */
7699 if (IS_GENPTR(ctype)) {
7704 p_type = DCL_TYPE(type);
7708 #if OLD_CAST_BEHAVIOR
7709 /* KV: we are converting a non-pointer type to
7710 * a generic pointer. This (ifdef'd out) code
7711 * says that the resulting generic pointer
7712 * should have the same class as the storage
7713 * location of the non-pointer variable.
7715 * For example, converting an int (which happens
7716 * to be stored in DATA space) to a pointer results
7717 * in a DATA generic pointer; if the original int
7718 * in XDATA space, so will be the resulting pointer.
7720 * I don't like that behavior, and thus this change:
7721 * all such conversions will be forced to XDATA and
7722 * throw a warning. If you want some non-XDATA
7723 * type, or you want to suppress the warning, you
7724 * must go through an intermediate cast, like so:
7726 * char _generic *gp = (char _xdata *)(intVar);
7728 link *etype = getSpec(type);
7730 /* we have to go by the storage class */
7731 if (SPEC_OCLS(etype) != generic)
7733 p_type = PTR_TYPE(SPEC_OCLS(etype));
7738 /* Converting unknown class (i.e. register variable)
7739 * to generic pointer. This is not good, but
7740 * we'll make a guess (and throw a warning).
7743 werror(W_INT_TO_GEN_PTR_CAST);
7747 /* the first two bytes are known */
7748 size = GPTRSIZE - 1;
7752 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7757 /* the last byte depending on type */
7774 /* this should never happen */
7775 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7776 "got unknown pointer type");
7779 aopPut(AOP(result),l, GPTRSIZE - 1);
7783 /* just copy the pointers */
7784 size = AOP_SIZE(result);
7788 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7795 /* so we now know that the size of destination is greater
7796 than the size of the source */
7797 /* we move to result for the size of source */
7798 size = AOP_SIZE(right);
7802 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7807 /* now depending on the sign of the source && destination */
7808 size = AOP_SIZE(result) - AOP_SIZE(right);
7809 /* if unsigned or not an integral type */
7810 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
7812 aopPut(AOP(result),zero,offset++);
7814 /* we need to extend the sign :{ */
7815 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
7818 emitcode("rlc","a");
7819 emitcode("subb","a,acc");
7821 aopPut(AOP(result),"a",offset++);
7824 /* we are done hurray !!!! */
7827 freeAsmop(right,NULL,ic,TRUE);
7828 freeAsmop(result,NULL,ic,TRUE);
7832 /*-----------------------------------------------------------------*/
7833 /* genDjnz - generate decrement & jump if not zero instrucion */
7834 /*-----------------------------------------------------------------*/
7835 static int genDjnz (iCode *ic, iCode *ifx)
7841 /* if the if condition has a false label
7842 then we cannot save */
7846 /* if the minus is not of the form
7848 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
7849 !IS_OP_LITERAL(IC_RIGHT(ic)))
7852 if (operandLitValue(IC_RIGHT(ic)) != 1)
7855 /* if the size of this greater than one then no
7857 if (getSize(operandType(IC_RESULT(ic))) > 1)
7860 /* otherwise we can save BIG */
7861 lbl = newiTempLabel(NULL);
7862 lbl1= newiTempLabel(NULL);
7864 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7866 if (IS_AOP_PREG(IC_RESULT(ic))) {
7867 emitcode("dec","%s",
7868 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
7869 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
7870 emitcode("jnz","%05d$",lbl->key+100);
7872 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE),
7875 emitcode ("sjmp","%05d$",lbl1->key+100);
7876 emitcode ("","%05d$:",lbl->key+100);
7877 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
7878 emitcode ("","%05d$:",lbl1->key+100);
7880 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7885 /*-----------------------------------------------------------------*/
7886 /* genReceive - generate code for a receive iCode */
7887 /*-----------------------------------------------------------------*/
7888 static void genReceive (iCode *ic)
7891 D(emitcode(";", "genReceive "););
7893 if (isOperandInFarSpace(IC_RESULT(ic)) &&
7894 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
7895 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
7896 int size = getSize(operandType(IC_RESULT(ic)));
7897 int offset = fReturnSize_390 - size;
7899 emitcode ("push","%s", (strcmp(fReturn[fReturnSize_390 - offset - 1],"a") ?
7900 fReturn[fReturnSize_390 - offset - 1] : "acc"));
7903 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7904 size = AOP_SIZE(IC_RESULT(ic));
7907 emitcode ("pop","acc");
7908 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
7913 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7915 assignResultValue(IC_RESULT(ic));
7918 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7921 /*-----------------------------------------------------------------*/
7922 /* gen390Code - generate code for 8051 based controllers */
7923 /*-----------------------------------------------------------------*/
7924 void gen390Code (iCode *lic)
7929 lineHead = lineCurr = NULL;
7931 /* print the allocation information */
7933 printAllocInfo( currFunc, codeOutFile);
7934 /* if debug information required */
7935 /* if (options.debug && currFunc) { */
7937 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
7939 if (IS_STATIC(currFunc->etype))
7940 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
7942 emitcode("","G$%s$0$0 ==.",currFunc->name);
7945 /* stack pointer name */
7946 if (options.useXstack)
7952 for (ic = lic ; ic ; ic = ic->next ) {
7954 if ( cln != ic->lineno ) {
7955 if ( options.debug ) {
7957 emitcode("","C$%s$%d$%d$%d ==.",
7958 ic->filename,ic->lineno,
7959 ic->level,ic->block);
7962 emitcode(";","%s %d",ic->filename,ic->lineno);
7965 /* if the result is marked as
7966 spilt and rematerializable or code for
7967 this has already been generated then
7969 if (resultRemat(ic) || ic->generated )
7972 /* depending on the operation */
7991 /* IPOP happens only when trying to restore a
7992 spilt live range, if there is an ifx statement
7993 following this pop then the if statement might
7994 be using some of the registers being popped which
7995 would destory the contents of the register so
7996 we need to check for this condition and handle it */
7998 ic->next->op == IFX &&
7999 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
8000 genIfx (ic->next,ic);
8018 genEndFunction (ic);
8038 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8055 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
8059 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8066 /* note these two are xlated by algebraic equivalence
8067 during parsing SDCC.y */
8068 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8069 "got '>=' or '<=' shouldn't have come here");
8073 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8085 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8089 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8093 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8120 case GET_VALUE_AT_ADDRESS:
8125 if (POINTER_SET(ic))
8152 addSet(&_G.sendSet,ic);
8157 /* piCode(ic,stdout); */
8163 /* now we are ready to call the
8164 peep hole optimizer */
8165 if (!options.nopeep)
8166 peepHole (&lineHead);
8168 /* now do the actual printing */
8169 printLine (lineHead,codeOutFile);